From 73127104a245052cd5cf29cdaaca3e5c32c70348 Mon Sep 17 00:00:00 2001 From: CoprDistGit Date: Fri, 28 Feb 2025 10:03:49 +0000 Subject: automatic import of gcc --- .gitignore | 1 + 0001-Version-Set-version-to-12.3.1.patch | 19 + ...CV-Backport-inline-subword-atomic-patches.patch | 2042 ++ 0003-CONFIG-Regenerate-configure-file.patch | 45 + ...libquadmath-Enable-libquadmath-on-kunpeng.patch | 197 + ...Add-A-B-op-CST-B-match-and-simplify-optim.patch | 89 + ...-2-3-Fold-series-of-instructions-into-mul.patch | 130 + ...-3-Fold-series-of-instructions-into-umulh.patch | 105 + ...-Disable-mull64-transformation-by-default.patch | 66 + 0010-Version-Clear-DATESTAMP_s.patch | 26 + ...te-hot-judgement-for-INLINE_HINT_known_ho.patch | 124 + 0012-Enable-small-loop-unrolling-for-O2.patch | 490 + ...nable-small-loop-unrolling-in-backend-PR-.patch | 230 + ...-compare-Add-a-new-optimization-for-array.patch | 1981 ++ ...ort-Structure-reorganization-optimization.patch | 6170 ++++ ...tructRelayout-Complete-Structure-Relayout.patch | 2056 ++ ...-Some-bugfix-for-structure-reorganization.patch | 489 + ...other-optimization-opportunity-for-ccmp-i.patch | 342 + 0019-fp-model-Enable-fp-model-on-kunpeng.patch | 405 + 0020-simdmath-Enable-simdmath-on-kunpeng.patch | 317 + ...uctReorderFields-Structure-reorder-fields.patch | 5739 ++++ ...dd-Dead-Field-Elimination-in-Struct-Reorg.patch | 1753 + ...Add-fkernel-pgo-option-to-support-PGO-ker.patch | 44 + ...g-Refactoring-and-merge-reorder-fields-in.patch | 1470 + 0025-AArch64-Rewrite-the-tsv110-option.patch | 114 + ...ng-moutline-atomics-improves-libgomp-perf.patch | 37 + ...m-Redundant-loop-elimination-optimization.patch | 503 + ...-compare-Fix-the-return-value-match-after.patch | 40 + ...rg-Add-Safe-Structure-Pointer-Compression.patch | 1191 + ...g-Add-unsafe-structure-pointer-compressio.patch | 1232 + ...pport-saving-feedback-count-info-to-ELF-s.patch | 550 + 0032-AutoBOLT-Add-bolt-linker-plugin-2-3.patch | 34094 +++++++++++++++++++ ...-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch | 345 + ...ble-discrimibator-and-MCF-algorithm-on-Au.patch | 312 + ...efs-and-correct-costs-for-cmlt-generation.patch | 194 + ...l-ifcvt-introduce-rtl-ifcvt-enchancements.patch | 560 + ...-early-if-conversion-of-simple-arithmetic.patch | 109 + ...to-allow-matching-uaddsub-overflow-for-wi.patch | 252 + 0039-Match-double-sized-mul-pattern.patch | 488 + 0040-Port-icp-patch-to-GCC-12.patch | 2387 ++ 0041-Port-fixes-in-icp-to-GCC-12.patch | 100 + 0042-Add-split-complex-instructions-pass.patch | 1245 + ...nd-refactoring-of-pass_split_complex_inst.patch | 1426 + 0044-Port-maxmin-patch-to-GCC-12.patch | 378 + ...oving-minmask-pattern-to-gimple-to-GCC-12.patch | 239 + ...-Add-new-pattern-to-pass-the-maxmin-tests.patch | 65 + 0047-AES-Implement-AES-pattern-matching.patch | 3968 +++ ...l-add-optimization-level-requirement-to-t.patch | 27 + ...exible-check-for-pointer-aliasing-during-.patch | 239 + 0050-Port-IPA-prefetch-to-GCC-12.patch | 2071 ++ 0051-Port-fixes-for-IPA-prefetch-to-GCC-12.patch | 2216 ++ ...-in-IPA-prefetch-src-openEuler-gcc-I96ID7.patch | 94 + 0053-struct-reorg-Add-Semi-Relayout.patch | 1366 + ...g-Bugfix-for-structure-pointer-compressio.patch | 28 + ...-Struct-Reorg-Port-bugfixes-to-GCC-12.3.1.patch | 420 + ...t-verifying-gimple-failed-when-reorg-leve.patch | 27 + 0057-AutoFdo-Fix-memory-leaks-in-autofdo.patch | 90 + ...t-calculation-for-dealing-with-equivalenc.patch | 321 + ...alculation-for-reg-equivalence-invariants.patch | 49 + 0088-BUGFIX-Fix-the-configure-file-of-BOLT.patch | 30102 ++++++++++++++++ ...orderFields-Fix-gimple-call-not-rewritten.patch | 48 + ...d-mul-testsuite-Add-march-armv8.2-a-for-d.patch | 40 + ...Fix-fails-in-IPA-prefetch-src-openEuler-g.patch | 34 + ...Change-set_of-to-reg_set_p-and-add-check-.patch | 29 + ...x-bugs-within-pointer-compression-and-DFE.patch | 26 + 0094-BUGFIX-AutoBOLT-function-miss-bind-type.patch | 28 + ...BS-remove-gstabs-and-gxcoff-functionality.patch | 9044 +++++ ...tofdo-use-PMU-sampling-set-num-eauals-den.patch | 45 + 0097-Improve-non-loop-disambiguation.patch | 101 + ...REC-multiplication-and-undefined-overflow.patch | 265 + 0099-Enable-Transposed-SLP.patch | 5624 +++ 0100-Add-hip09-machine-discribtion.patch | 882 + 0101-Add-hip11-CPU-pipeline-scheduling.patch | 755 + ...ptimization-in-Gzip-For-crc32-algorithm-i.patch | 2164 ++ ...hip09-and-hip11-in-aarch64-cores.def-to-b.patch | 34 + ...E-AArch64-Cleanup-CPU-option-processing-c.patch | 336 + ...ME-AArch64-Cleanup-option-processing-code.patch | 528 + ...E-aarch64-Add-march-support-for-Armv9.1-A.patch | 108 + ...E-Revert-aarch64-Define-__ARM_FEATURE_RCP.patch | 112 + ...E-Revert-Ampere-1-and-Ampere-1A-core-defi.patch | 39 + ...E-aarch64-Rename-AARCH64_ISA-architecture.patch | 157 + ...E-aarch64-Rename-AARCH64_FL-architecture-.patch | 220 + ...E-aarch64-Rename-AARCH64_FL_FOR_ARCH-macr.patch | 398 + ...E-aarch64-Add-V-to-aarch64-arches.def-nam.patch | 315 + ...ort-SME-aarch64-Small-config.gcc-cleanups.patch | 55 + ...E-aarch64-Avoid-redundancy-in-aarch64-cor.patch | 273 + ...E-aarch64-Remove-AARCH64_FL_RCPC8_4-PR107.patch | 83 + ...E-aarch64-Fix-transitive-closure-of-featu.patch | 154 + ...E-aarch64-Reorder-an-entry-in-aarch64-opt.patch | 194 + ...-SME-aarch64-Simplify-feature-definitions.patch | 1176 + ...E-aarch64-Simplify-generation-of-.arch-st.patch | 467 + ...E-aarch64-Avoid-std-string-in-static-data.patch | 43 + ...E-aarch64-Tweak-constness-of-option-relat.patch | 195 + ...E-aarch64-Make-more-use-of-aarch64_featur.patch | 394 + ...E-aarch64-Tweak-contents-of-flags_on-off-.patch | 70 + ...E-aarch64-Tweak-handling-of-mgeneral-regs.patch | 370 + ...E-aarch64-Remove-redundant-TARGET_-checks.patch | 453 + ...ort-SME-aarch64-Define-__ARM_FEATURE_RCPC.patch | 132 + ...E-Add-Ampere-1-and-Ampere-1A-core-definit.patch | 29 + ...E-aarch64-Fix-nosimd-handling-of-FPR-move.patch | 968 + ...t-SME-aarch64-Commonise-some-folding-code.patch | 83 + ...E-aarch64-Add-a-Z-operand-modifier-for-SV.patch | 49 + ...E-mode-switching-Remove-unused-bbnum-fiel.patch | 104 + ...E-mode-switching-Tweak-the-macro-hook-doc.patch | 311 + ...kport-SME-mode-switching-Add-note-problem.patch | 35 + ...E-mode-switching-Avoid-quadractic-list-op.patch | 90 + ...E-mode-switching-Fix-the-mode-passed-to-t.patch | 136 + ...E-mode-switching-Simplify-recording-of-tr.patch | 103 + ...E-mode-switching-Tweak-entry-exit-handlin.patch | 92 + ...E-mode-switching-Allow-targets-to-set-the.patch | 93 + ...E-mode-switching-Pass-set-of-live-registe.patch | 211 + ...E-mode-switching-Pass-the-set-of-live-reg.patch | 177 + ...E-mode-switching-Use-1-based-edge-aux-fie.patch | 56 + ...E-mode-switching-Add-a-target-configurabl.patch | 337 + ...rt-SME-mode-switching-Add-a-backprop-hook.patch | 483 + ...E-aarch64-Add-a-result_mode-helper-functi.patch | 81 + ...E-rtl-Try-to-remove-EH-edges-after-pro-ep.patch | 232 + ...E-Fix-PR-middle-end-107705-ICE-after-recl.patch | 71 + ...E-function-Change-return-type-of-predicat.patch | 351 + ...E-Allow-prologues-and-epilogues-to-be-ins.patch | 233 + ...E-Add-a-target-hook-for-sibcall-epilogues.patch | 239 + ...E-Add-a-new-target-hook-TARGET_START_CALL.patch | 461 + ...ort-SME-Allow-targets-to-add-USEs-to-asms.patch | 490 + ...E-New-compact-syntax-for-insn-and-insn_sp.patch | 998 + ...E-recog-Improve-parser-for-pattern-new-co.patch | 104 + ...-Backport-SME-recog-Support-space-in-cons.patch | 49 + ...E-aarch64-Generalise-require_immediate_la.patch | 164 + ...t-SME-aarch64-Add-backend-support-for-DFP.patch | 469 + ...-SME-aarch64-Vector-move-fixes-for-nosimd.patch | 1824 + ...E-aarch64-Simplify-output-template-emissi.patch | 213 + ...-SME-Improve-immediate-expansion-PR106583.patch | 631 + ...t-SME-AArch64-Cleanup-move-immediate-code.patch | 410 + ...E-AArch64-convert-some-patterns-to-compac.patch | 229 + ...rt-SME-aarch64-Use-SVE-s-RDVL-instruction.patch | 792 + ...E-aarch64-Make-AARCH64_FL_SVE-requirement.patch | 137 + ...E-aarch64-Add-group-suffixes-to-SVE-intri.patch | 562 + ...E-aarch64-Add-sve_type-to-SVE-builtins-co.patch | 230 + ...E-aarch64-Generalise-some-SVE-ACLE-error-.patch | 1474 + ...E-aarch64-Replace-vague-previous-argument.patch | 698 + ...E-aarch64-Make-more-use-of-sve_type-in-AC.patch | 368 + ...E-aarch64-Tweak-error-message-for-tuple-v.patch | 106 + ...E-aarch64-Add-tuple-forms-of-svreinterpre.patch | 1236 + ...E-attribs-Use-existing-traits-for-excl_ha.patch | 90 + ...E-Allow-target-attributes-in-non-gnu-name.patch | 2369 ++ ...ort-SME-aarch64-Fix-plugin-header-install.patch | 64 + ...E-aarch64-Add-arm_streaming-_compatible-a.patch | 1178 + 0175-Backport-SME-aarch64-Add-sme.patch | 330 + ...E-aarch64-Add-r-m-and-m-r-alternatives-to.patch | 168 + ...E-AArch64-Rewrite-simd-move-immediate-pat.patch | 167 + ...E-AArch64-remove-test-comment-from-mov-mo.patch | 34 + ...E-aarch64-Distinguish-streaming-compatibl.patch | 1552 + ...E-aarch64-Mark-relevant-SVE-instructions-.patch | 4506 +++ ...ort-SME-AArch64-Support-new-tbranch-optab.patch | 250 + ...E-aarch64-Use-local-frame-vars-in-shrink-.patch | 381 + ...-SME-aarch64-Avoid-a-use-of-callee_offset.patch | 103 + ...E-aarch64-Explicitly-handle-frames-with-n.patch | 51 + ...E-aarch64-Add-bytes_below_saved_regs-to-f.patch | 236 + ...E-aarch64-Add-bytes_below_hard_fp-to-fram.patch | 87 + ...-SME-aarch64-Robustify-stack-tie-handling.patch | 126 + ...E-aarch64-Tweak-aarch64_save-restore_call.patch | 228 + ...E-aarch64-Only-calculate-chain_offset-if-.patch | 47 + ...E-aarch64-Rename-locals_offset-to-bytes_a.patch | 94 + ...E-aarch64-Rename-hard_fp_offset-to-bytes_.patch | 151 + ...port-SME-aarch64-Tweak-frame_size-comment.patch | 37 + ...E-aarch64-Measure-reg_offset-from-the-bot.patch | 198 + ...E-aarch64-Simplify-top-of-frame-allocatio.patch | 58 + ...ME-aarch64-Minor-initial-adjustment-tweak.patch | 41 + ...E-aarch64-Tweak-stack-clash-boundary-cond.patch | 128 + ...E-aarch64-Put-LR-save-probe-in-first-16-b.patch | 409 + ...E-aarch64-Simplify-probe-of-final-frame-a.patch | 126 + ...E-aarch64-Explicitly-record-probe-registe.patch | 280 + ...E-aarch64-Remove-below_hard_fp_saved_regs.patch | 160 + ...E-aarch64-Make-stack-smash-canary-protect.patch | 301 + ...t-SME-Handle-epilogues-that-contain-jumps.patch | 201 + ...E-aarch64-Use-vecs-to-store-register-save.patch | 709 + ...E-aarch64-Put-LR-save-slot-first-in-more-.patch | 107 + ...SME-aarch64-Switch-PSTATE.SM-around-calls.patch | 3270 ++ ...E-aarch64-Add-support-for-SME-ZA-attribut.patch | 4324 +++ ...E-aarch64-Add-a-register-class-for-w12-w1.patch | 103 + 0208-Backport-SME-aarch64-Add-a-VNx1TI-mode.patch | 72 + ...E-aarch64-Generalise-unspec_based_functio.patch | 118 + ...E-aarch64-Generalise-_m-rules-for-SVE-int.patch | 117 + ...ort-SME-aarch64-Add-support-for-arm_sme.h.patch | 15955 +++++++++ ...E-aarch64-Add-support-for-__arm_locally_s.patch | 1748 + ...E-aarch64-Handle-PSTATE.SM-across-abnorma.patch | 708 + ...E-aarch64-Enforce-inlining-restrictions-f.patch | 913 + ...E-aarch64-Update-sibcall-handling-for-SME.patch | 424 + ...E-libgcc-aarch64-Configure-check-for-.var.patch | 117 + ...E-libgcc-aarch64-Configure-check-for-__ge.patch | 117 + ...ME-libgcc-aarch64-Add-SME-runtime-support.patch | 627 + ...E-libgcc-aarch64-Add-SME-unwinder-support.patch | 70 + 0220-Backport-SME-libgcc-Fix-config.in.patch | 51 + ...E-aarch64-Add-funwind-tables-to-some-test.patch | 54 + ...E-aarch64-Skip-some-SME-register-save-tes.patch | 106 + ...ckport-SME-Add-OPTIONS_H_EXTRA-to-GTFILES.patch | 37 + 0224-Backport-SME-aarch64-Add-V1DI-mode.patch | 177 + ...E-Allow-md-iterators-to-include-other-ite.patch | 217 + ...E-riscv-Add-support-for-strlen-inline-exp.patch | 142 + ...E-attribs-Add-overloads-with-namespace-na.patch | 189 + ...E-vec-Add-array_slice-constructors-from-n.patch | 47 + ...kport-SME-A-couple-of-va_gc_atomic-tweaks.patch | 140 + ...E-middle-end-Fix-issue-of-poly_uint16-1-1.patch | 34 + ...SME-Add-missing-header-file-in-aarch64.cc.patch | 24 + ...kport-SME-c-Add-support-for-__extension__.patch | 327 + ...E-lra-Updates-of-biggest-mode-for-hard-re.patch | 140 + ...ME-c-Support-C2x-empty-initializer-braces.patch | 672 + ...E-aarch64-Update-sizeless-tests-for-recen.patch | 115 + ...E-attribs-Namespace-aware-lookup_attribut.patch | 58 + ...E-c-family-ICE-with-gnu-nocf_check-PR1069.patch | 281 + ...E-AArch64-Fix-assert-in-aarch64_move_imm-.patch | 35 + ...E-testsuite-Only-run-fcf-protection-test-.patch | 37 + ...E-Fix-PRs-106764-106765-and-107307-all-IC.patch | 113 + ...E-aarch64-Remove-expected-error-for-compo.patch | 43 + ...ME-aarch64-Remove-redundant-builtins-code.patch | 264 + ...E-AArch64-Fix-Armv9-a-warnings-that-get-e.patch | 63 + ...E-Canonicalize-X-Y-as-X-Y-in-match.pd-whe.patch | 184 + ...E-middle-end-Add-new-tbranch-optab-to-add.patch | 417 + ...E-explow-Allow-dynamic-allocations-after-.patch | 110 + ...E-PR105169-Fix-references-to-discarded-se.patch | 225 + ...E-RISC-V-autovec-Verify-that-GET_MODE_NUN.patch | 53 + ...E-Add-operator-to-gimple_stmt_iterator-an.patch | 42 + ...E-tree-optimization-110221-SLP-and-loop-m.patch | 75 + 0251-SME-Adapt-some-testsuites.patch | 116 + ...or-by-backported-patches-and-IPA-prefetch.patch | 43 + ...-return-register-handling-in-untyped_call.patch | 66 + 0254-aarch64-Fix-loose-ldpstp-check.patch | 119 + ...ew-option-mdaz-ftz-to-enable-FTZ-and-DAZ-.patch | 135 + ...view_convert_expr-mask-to-signed-type-whe.patch | 65 + ...-mvzeroupper-independent-of-optimization-.patch | 138 + ...une_string-with-arch_string-for-target-at.patch | 68 + ...e-maskloadmn-pattern-with-UNSPEC_MASKLOAD.patch | 111 + ...ne-maskstore-patterns-with-UNSPEC_MASKMOV.patch | 126 + ...model-values-for-Alderlake-and-Rocketlake.patch | 38 + ...around-possible-CPUID-bug-in-Sandy-Bridge.patch | 78 + ...tigation-Disable-gather-generation-in-vec.patch | 220 + ...o-gather-m-no-scatter-to-enable-disable-v.patch | 187 + ...traint-modifier-for-fcmaddcph-fmaddcph-fc.patch | 129 + ...lightly-for-the-alternative-which-move-DF.patch | 106 + ...ode-due-to-vec_merge-pcmp-to-blendvb-spli.patch | 163 + ...e-it-s-AVX_U128_CLEAN-after-call_insn-who.patch | 151 + ...able-FMADD-in-chains-for-Zen4-and-generic.patch | 142 + 0270-Initial-Raptorlake-Support.patch | 47 + 0271-Initial-Meteorlake-Support.patch | 49 + 0272-Support-Intel-AMX-FP16-ISA.patch | 691 + 0273-Support-Intel-prefetchit0-t1.patch | 902 + 0274-Initial-Granite-Rapids-Support.patch | 277 + 0275-Support-Intel-AMX-COMPLEX.patch | 722 + 0276-i386-Add-AMX-COMPLEX-to-Granite-Rapids.patch | 30 + 0277-Initial-Granite-Rapids-D-Support.patch | 212 + 0278-Correct-Granite-Rapids-D-documentation.patch | 48 + 0279-i386-Remove-Meteorlake-s-family_model.patch | 30 + ...model-values-for-Alderlake-Rocketlake-and.patch | 33 + 0281-x86-Update-model-values-for-Raptorlake.patch | 32 + 0282-Fix-target_clone-arch-graniterapids-d.patch | 159 + 0283-i386-Change-prefetchi-output-template.patch | 62 + 0284-i386-Add-non-optimize-prefetchi-intrins.patch | 92 + ...over-hip09-and-hip11-in-aarch64-cores.def.patch | 32 + ...Try-to-use-AI-model-to-guide-optimization.patch | 671 + 0287-Add-dynamic-memory-access-checks.patch | 774 + 0288-Enable-macro-use-commandline.patch | 207 + ...op-crc.cc-TARGET_CRC32-may-be-not-defined.patch | 35 + 0290-Add-ipa-prefetch-test-for-gcc-s-case.patch | 209 + 0291-Fix-settings-for-wide-operations-tests.patch | 73 + ...-errors-in-ipa-prefetch-IAORPF-and-IAOSJ0.patch | 42 + ...ith-stmts-insertion-in-ipa-prefetch-for-I.patch | 51 + ...-errors-in-ipa-prefetch-IAO50J-and-IAO5H7.patch | 80 + ...ith-grouped_load-merge-in-slp-transpose-v.patch | 30 + ...ror-in-slp-transpose-vectorize-for-IAQFM3.patch | 28 + ...ging-error-in-SLP-transpose-vectorization.patch | 26 + 0298-Mark-prefetch-builtin-as-willreturn.patch | 99 + ...sallow-pointer-operands-for-and-partly-PR.patch | 156 + ...emove-erroneous-pattern-from-gimple-ifcvt.patch | 55 + ...required-check-for-iteration-through-uses.patch | 33 + ...-for-optimization-for-merging-bb-s-with-c.patch | 158 + ...ion-of-stream-in-functions-for-pre-versio.patch | 6263 ++++ ...ersion-lto-symbol-parse-cross-lto-units-i.patch | 963 + ...rasm-Handle-private-COMDAT-function-symbo.patch | 296 + ...all-libstdc-libcc1-etc-to-lib64-instead-o.patch | 65 + ...llback-value-for-print-multi-os-directory.patch | 105 + 0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch | 108 + 0309-CSPGO-Add-context-sensitive-PGO.patch | 1337 + 0310-CFGO-Add-cfgo-pgo-optimization.patch | 168 + 0311-PATCH-Add-if-split-optimization-pass.patch | 1203 + ...p-vectorization-pass-with-additional-chec.patch | 320 + ...r-transformation-for-static-probabilities.patch | 130 + 0314-bugfix-Modify-the-hip09-tune-flags.patch | 56 + ...no-var-recored-check-for-ssa_name-in-stru.patch | 234 + 0316-Use-ai-ability-to-guide-optimization.patch | 741 + ...et-default-value-when-tune_native-is-NULL.patch | 27 + 0318-add-flag-flto-try.patch | 221 + 0319-CSPGO-fix-bugs-when-using-cspgo.patch | 140 + 0320-if-split-fix-bugs.patch | 105 + ...g-Avoid-doing-struct-split-and-reorder_fi.patch | 192 + ...eate-POINTER_PLUS_EXPR-for-REFERENCE_TYPE.patch | 26 + 0323-Bugfix-replace-tmp-pattern-split.patch | 50 + 0324-bugfix-fix-vector-costs-for-hip09.patch | 52 + 0325-gcc-opts-common.cc-Fix-build-with-clang.patch | 54 + 0326-BUGFIX-Fix-build-error-on-risv_64.patch | 1005 + ...Adjust-the-same-gate-to-use-struct-option.patch | 81 + ...gfix-if-split-Added-checking-for-ssa_name.patch | 248 + ...d-work-with-loops-in-process_complex_cond.patch | 90 + 0330-bugfix-fix-typo-error.patch | 25 + 0331-fix-function-missing-return-value.patch | 25 + gcc.spec | 4485 +++ sources | 1 + 305 files changed, 228093 insertions(+) create mode 100644 0001-Version-Set-version-to-12.3.1.patch create mode 100644 0002-RISCV-Backport-inline-subword-atomic-patches.patch create mode 100644 0003-CONFIG-Regenerate-configure-file.patch create mode 100644 0004-libquadmath-Enable-libquadmath-on-kunpeng.patch create mode 100644 0006-MULL64-1-3-Add-A-B-op-CST-B-match-and-simplify-optim.patch create mode 100644 0007-MULL64-2-3-Fold-series-of-instructions-into-mul.patch create mode 100644 0008-MULL64-3-3-Fold-series-of-instructions-into-umulh.patch create mode 100644 0009-MULL64-Disable-mull64-transformation-by-default.patch create mode 100644 0010-Version-Clear-DATESTAMP_s.patch create mode 100644 0011-Add-attribute-hot-judgement-for-INLINE_HINT_known_ho.patch create mode 100644 0012-Enable-small-loop-unrolling-for-O2.patch create mode 100644 0013-i386-Only-enable-small-loop-unrolling-in-backend-PR-.patch create mode 100644 0014-Array-widen-compare-Add-a-new-optimization-for-array.patch create mode 100644 0015-Backport-Structure-reorganization-optimization.patch create mode 100644 0016-CompleteStructRelayout-Complete-Structure-Relayout.patch create mode 100644 0017-StructReorg-Some-bugfix-for-structure-reorganization.patch create mode 100644 0018-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch create mode 100644 0019-fp-model-Enable-fp-model-on-kunpeng.patch create mode 100644 0020-simdmath-Enable-simdmath-on-kunpeng.patch create mode 100644 0021-StructReorderFields-Structure-reorder-fields.patch create mode 100644 0022-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch create mode 100644 0023-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch create mode 100644 0024-Struct-Reorg-Refactoring-and-merge-reorder-fields-in.patch create mode 100644 0025-AArch64-Rewrite-the-tsv110-option.patch create mode 100644 0026-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch create mode 100644 0027-LoopElim-Redundant-loop-elimination-optimization.patch create mode 100644 0028-Array-widen-compare-Fix-the-return-value-match-after.patch create mode 100644 0029-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch create mode 100644 0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch create mode 100644 0031-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch create mode 100644 0032-AutoBOLT-Add-bolt-linker-plugin-2-3.patch create mode 100644 0033-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch create mode 100644 0034-Autofdo-Enable-discrimibator-and-MCF-algorithm-on-Au.patch create mode 100644 0035-Add-insn-defs-and-correct-costs-for-cmlt-generation.patch create mode 100644 0036-rtl-ifcvt-introduce-rtl-ifcvt-enchancements.patch create mode 100644 0037-Perform-early-if-conversion-of-simple-arithmetic.patch create mode 100644 0038-Add-option-to-allow-matching-uaddsub-overflow-for-wi.patch create mode 100644 0039-Match-double-sized-mul-pattern.patch create mode 100644 0040-Port-icp-patch-to-GCC-12.patch create mode 100644 0041-Port-fixes-in-icp-to-GCC-12.patch create mode 100644 0042-Add-split-complex-instructions-pass.patch create mode 100644 0043-Extending-and-refactoring-of-pass_split_complex_inst.patch create mode 100644 0044-Port-maxmin-patch-to-GCC-12.patch create mode 100644 0045-Port-moving-minmask-pattern-to-gimple-to-GCC-12.patch create mode 100644 0046-Add-new-pattern-to-pass-the-maxmin-tests.patch create mode 100644 0047-AES-Implement-AES-pattern-matching.patch create mode 100644 0048-crypto-accel-add-optimization-level-requirement-to-t.patch create mode 100644 0049-Add-more-flexible-check-for-pointer-aliasing-during-.patch create mode 100644 0050-Port-IPA-prefetch-to-GCC-12.patch create mode 100644 0051-Port-fixes-for-IPA-prefetch-to-GCC-12.patch create mode 100644 0052-Fix-fails-in-IPA-prefetch-src-openEuler-gcc-I96ID7.patch create mode 100644 0053-struct-reorg-Add-Semi-Relayout.patch create mode 100644 0054-Struct-Reorg-Bugfix-for-structure-pointer-compressio.patch create mode 100644 0055-Struct-Reorg-Port-bugfixes-to-GCC-12.3.1.patch create mode 100644 0056-Fix-bug-that-verifying-gimple-failed-when-reorg-leve.patch create mode 100644 0057-AutoFdo-Fix-memory-leaks-in-autofdo.patch create mode 100644 0086-Modfify-cost-calculation-for-dealing-with-equivalenc.patch create mode 100644 0087-Add-cost-calculation-for-reg-equivalence-invariants.patch create mode 100644 0088-BUGFIX-Fix-the-configure-file-of-BOLT.patch create mode 100644 0089-StructReorderFields-Fix-gimple-call-not-rewritten.patch create mode 100644 0090-double-sized-mul-testsuite-Add-march-armv8.2-a-for-d.patch create mode 100644 0091-IPA-Bugfix-Fix-fails-in-IPA-prefetch-src-openEuler-g.patch create mode 100644 0092-AES-Bugfix-Change-set_of-to-reg_set_p-and-add-check-.patch create mode 100644 0093-fix-bugs-within-pointer-compression-and-DFE.patch create mode 100644 0094-BUGFIX-AutoBOLT-function-miss-bind-type.patch create mode 100644 0095-STABS-remove-gstabs-and-gxcoff-functionality.patch create mode 100644 0096-Bugfix-Autofdo-use-PMU-sampling-set-num-eauals-den.patch create mode 100644 0097-Improve-non-loop-disambiguation.patch create mode 100644 0098-CHREC-multiplication-and-undefined-overflow.patch create mode 100644 0099-Enable-Transposed-SLP.patch create mode 100644 0100-Add-hip09-machine-discribtion.patch create mode 100644 0101-Add-hip11-CPU-pipeline-scheduling.patch create mode 100644 0102-Add-Crc32-Optimization-in-Gzip-For-crc32-algorithm-i.patch create mode 100644 0103-SME-Remove-hip09-and-hip11-in-aarch64-cores.def-to-b.patch create mode 100644 0104-Backport-SME-AArch64-Cleanup-CPU-option-processing-c.patch create mode 100644 0105-Backport-SME-AArch64-Cleanup-option-processing-code.patch create mode 100644 0106-Backport-SME-aarch64-Add-march-support-for-Armv9.1-A.patch create mode 100644 0107-Backport-SME-Revert-aarch64-Define-__ARM_FEATURE_RCP.patch create mode 100644 0108-Backport-SME-Revert-Ampere-1-and-Ampere-1A-core-defi.patch create mode 100644 0109-Backport-SME-aarch64-Rename-AARCH64_ISA-architecture.patch create mode 100644 0110-Backport-SME-aarch64-Rename-AARCH64_FL-architecture-.patch create mode 100644 0111-Backport-SME-aarch64-Rename-AARCH64_FL_FOR_ARCH-macr.patch create mode 100644 0112-Backport-SME-aarch64-Add-V-to-aarch64-arches.def-nam.patch create mode 100644 0113-Backport-SME-aarch64-Small-config.gcc-cleanups.patch create mode 100644 0114-Backport-SME-aarch64-Avoid-redundancy-in-aarch64-cor.patch create mode 100644 0115-Backport-SME-aarch64-Remove-AARCH64_FL_RCPC8_4-PR107.patch create mode 100644 0116-Backport-SME-aarch64-Fix-transitive-closure-of-featu.patch create mode 100644 0117-Backport-SME-aarch64-Reorder-an-entry-in-aarch64-opt.patch create mode 100644 0118-Backport-SME-aarch64-Simplify-feature-definitions.patch create mode 100644 0119-Backport-SME-aarch64-Simplify-generation-of-.arch-st.patch create mode 100644 0120-Backport-SME-aarch64-Avoid-std-string-in-static-data.patch create mode 100644 0121-Backport-SME-aarch64-Tweak-constness-of-option-relat.patch create mode 100644 0122-Backport-SME-aarch64-Make-more-use-of-aarch64_featur.patch create mode 100644 0123-Backport-SME-aarch64-Tweak-contents-of-flags_on-off-.patch create mode 100644 0124-Backport-SME-aarch64-Tweak-handling-of-mgeneral-regs.patch create mode 100644 0125-Backport-SME-aarch64-Remove-redundant-TARGET_-checks.patch create mode 100644 0126-Backport-SME-aarch64-Define-__ARM_FEATURE_RCPC.patch create mode 100644 0127-Backport-SME-Add-Ampere-1-and-Ampere-1A-core-definit.patch create mode 100644 0128-Backport-SME-aarch64-Fix-nosimd-handling-of-FPR-move.patch create mode 100644 0129-Backport-SME-aarch64-Commonise-some-folding-code.patch create mode 100644 0130-Backport-SME-aarch64-Add-a-Z-operand-modifier-for-SV.patch create mode 100644 0131-Backport-SME-mode-switching-Remove-unused-bbnum-fiel.patch create mode 100644 0132-Backport-SME-mode-switching-Tweak-the-macro-hook-doc.patch create mode 100644 0133-Backport-SME-mode-switching-Add-note-problem.patch create mode 100644 0134-Backport-SME-mode-switching-Avoid-quadractic-list-op.patch create mode 100644 0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch create mode 100644 0136-Backport-SME-mode-switching-Simplify-recording-of-tr.patch create mode 100644 0137-Backport-SME-mode-switching-Tweak-entry-exit-handlin.patch create mode 100644 0138-Backport-SME-mode-switching-Allow-targets-to-set-the.patch create mode 100644 0139-Backport-SME-mode-switching-Pass-set-of-live-registe.patch create mode 100644 0140-Backport-SME-mode-switching-Pass-the-set-of-live-reg.patch create mode 100644 0141-Backport-SME-mode-switching-Use-1-based-edge-aux-fie.patch create mode 100644 0142-Backport-SME-mode-switching-Add-a-target-configurabl.patch create mode 100644 0143-Backport-SME-mode-switching-Add-a-backprop-hook.patch create mode 100644 0144-Backport-SME-aarch64-Add-a-result_mode-helper-functi.patch create mode 100644 0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch create mode 100644 0146-Backport-SME-Fix-PR-middle-end-107705-ICE-after-recl.patch create mode 100644 0147-Backport-SME-function-Change-return-type-of-predicat.patch create mode 100644 0148-Backport-SME-Allow-prologues-and-epilogues-to-be-ins.patch create mode 100644 0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch create mode 100644 0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch create mode 100644 0151-Backport-SME-Allow-targets-to-add-USEs-to-asms.patch create mode 100644 0152-Backport-SME-New-compact-syntax-for-insn-and-insn_sp.patch create mode 100644 0153-Backport-SME-recog-Improve-parser-for-pattern-new-co.patch create mode 100644 0154-Backport-SME-recog-Support-space-in-cons.patch create mode 100644 0155-Backport-SME-aarch64-Generalise-require_immediate_la.patch create mode 100644 0156-Backport-SME-aarch64-Add-backend-support-for-DFP.patch create mode 100644 0157-Backport-SME-aarch64-Vector-move-fixes-for-nosimd.patch create mode 100644 0158-Backport-SME-aarch64-Simplify-output-template-emissi.patch create mode 100644 0159-Backport-SME-Improve-immediate-expansion-PR106583.patch create mode 100644 0160-Backport-SME-AArch64-Cleanup-move-immediate-code.patch create mode 100644 0161-Backport-SME-AArch64-convert-some-patterns-to-compac.patch create mode 100644 0162-Backport-SME-aarch64-Use-SVE-s-RDVL-instruction.patch create mode 100644 0163-Backport-SME-aarch64-Make-AARCH64_FL_SVE-requirement.patch create mode 100644 0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch create mode 100644 0165-Backport-SME-aarch64-Add-sve_type-to-SVE-builtins-co.patch create mode 100644 0166-Backport-SME-aarch64-Generalise-some-SVE-ACLE-error-.patch create mode 100644 0167-Backport-SME-aarch64-Replace-vague-previous-argument.patch create mode 100644 0168-Backport-SME-aarch64-Make-more-use-of-sve_type-in-AC.patch create mode 100644 0169-Backport-SME-aarch64-Tweak-error-message-for-tuple-v.patch create mode 100644 0170-Backport-SME-aarch64-Add-tuple-forms-of-svreinterpre.patch create mode 100644 0171-Backport-SME-attribs-Use-existing-traits-for-excl_ha.patch create mode 100644 0172-Backport-SME-Allow-target-attributes-in-non-gnu-name.patch create mode 100644 0173-Backport-SME-aarch64-Fix-plugin-header-install.patch create mode 100644 0174-Backport-SME-aarch64-Add-arm_streaming-_compatible-a.patch create mode 100644 0175-Backport-SME-aarch64-Add-sme.patch create mode 100644 0176-Backport-SME-aarch64-Add-r-m-and-m-r-alternatives-to.patch create mode 100644 0177-Backport-SME-AArch64-Rewrite-simd-move-immediate-pat.patch create mode 100644 0178-Backport-SME-AArch64-remove-test-comment-from-mov-mo.patch create mode 100644 0179-Backport-SME-aarch64-Distinguish-streaming-compatibl.patch create mode 100644 0180-Backport-SME-aarch64-Mark-relevant-SVE-instructions-.patch create mode 100644 0181-Backport-SME-AArch64-Support-new-tbranch-optab.patch create mode 100644 0182-Backport-SME-aarch64-Use-local-frame-vars-in-shrink-.patch create mode 100644 0183-Backport-SME-aarch64-Avoid-a-use-of-callee_offset.patch create mode 100644 0184-Backport-SME-aarch64-Explicitly-handle-frames-with-n.patch create mode 100644 0185-Backport-SME-aarch64-Add-bytes_below_saved_regs-to-f.patch create mode 100644 0186-Backport-SME-aarch64-Add-bytes_below_hard_fp-to-fram.patch create mode 100644 0187-Backport-SME-aarch64-Robustify-stack-tie-handling.patch create mode 100644 0188-Backport-SME-aarch64-Tweak-aarch64_save-restore_call.patch create mode 100644 0189-Backport-SME-aarch64-Only-calculate-chain_offset-if-.patch create mode 100644 0190-Backport-SME-aarch64-Rename-locals_offset-to-bytes_a.patch create mode 100644 0191-Backport-SME-aarch64-Rename-hard_fp_offset-to-bytes_.patch create mode 100644 0192-Backport-SME-aarch64-Tweak-frame_size-comment.patch create mode 100644 0193-Backport-SME-aarch64-Measure-reg_offset-from-the-bot.patch create mode 100644 0194-Backport-SME-aarch64-Simplify-top-of-frame-allocatio.patch create mode 100644 0195-Backport-SME-aarch64-Minor-initial-adjustment-tweak.patch create mode 100644 0196-Backport-SME-aarch64-Tweak-stack-clash-boundary-cond.patch create mode 100644 0197-Backport-SME-aarch64-Put-LR-save-probe-in-first-16-b.patch create mode 100644 0198-Backport-SME-aarch64-Simplify-probe-of-final-frame-a.patch create mode 100644 0199-Backport-SME-aarch64-Explicitly-record-probe-registe.patch create mode 100644 0200-Backport-SME-aarch64-Remove-below_hard_fp_saved_regs.patch create mode 100644 0201-Backport-SME-aarch64-Make-stack-smash-canary-protect.patch create mode 100644 0202-Backport-SME-Handle-epilogues-that-contain-jumps.patch create mode 100644 0203-Backport-SME-aarch64-Use-vecs-to-store-register-save.patch create mode 100644 0204-Backport-SME-aarch64-Put-LR-save-slot-first-in-more-.patch create mode 100644 0205-Backport-SME-aarch64-Switch-PSTATE.SM-around-calls.patch create mode 100644 0206-Backport-SME-aarch64-Add-support-for-SME-ZA-attribut.patch create mode 100644 0207-Backport-SME-aarch64-Add-a-register-class-for-w12-w1.patch create mode 100644 0208-Backport-SME-aarch64-Add-a-VNx1TI-mode.patch create mode 100644 0209-Backport-SME-aarch64-Generalise-unspec_based_functio.patch create mode 100644 0210-Backport-SME-aarch64-Generalise-_m-rules-for-SVE-int.patch create mode 100644 0211-Backport-SME-aarch64-Add-support-for-arm_sme.h.patch create mode 100644 0212-Backport-SME-aarch64-Add-support-for-__arm_locally_s.patch create mode 100644 0213-Backport-SME-aarch64-Handle-PSTATE.SM-across-abnorma.patch create mode 100644 0214-Backport-SME-aarch64-Enforce-inlining-restrictions-f.patch create mode 100644 0215-Backport-SME-aarch64-Update-sibcall-handling-for-SME.patch create mode 100644 0216-Backport-SME-libgcc-aarch64-Configure-check-for-.var.patch create mode 100644 0217-Backport-SME-libgcc-aarch64-Configure-check-for-__ge.patch create mode 100644 0218-Backport-SME-libgcc-aarch64-Add-SME-runtime-support.patch create mode 100644 0219-Backport-SME-libgcc-aarch64-Add-SME-unwinder-support.patch create mode 100644 0220-Backport-SME-libgcc-Fix-config.in.patch create mode 100644 0221-Backport-SME-aarch64-Add-funwind-tables-to-some-test.patch create mode 100644 0222-Backport-SME-aarch64-Skip-some-SME-register-save-tes.patch create mode 100644 0223-Backport-SME-Add-OPTIONS_H_EXTRA-to-GTFILES.patch create mode 100644 0224-Backport-SME-aarch64-Add-V1DI-mode.patch create mode 100644 0225-Backport-SME-Allow-md-iterators-to-include-other-ite.patch create mode 100644 0226-Backport-SME-riscv-Add-support-for-strlen-inline-exp.patch create mode 100644 0227-Backport-SME-attribs-Add-overloads-with-namespace-na.patch create mode 100644 0228-Backport-SME-vec-Add-array_slice-constructors-from-n.patch create mode 100644 0229-Backport-SME-A-couple-of-va_gc_atomic-tweaks.patch create mode 100644 0230-Backport-SME-middle-end-Fix-issue-of-poly_uint16-1-1.patch create mode 100644 0231-SME-Add-missing-header-file-in-aarch64.cc.patch create mode 100644 0232-Backport-SME-c-Add-support-for-__extension__.patch create mode 100644 0233-Backport-SME-lra-Updates-of-biggest-mode-for-hard-re.patch create mode 100644 0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch create mode 100644 0235-Backport-SME-aarch64-Update-sizeless-tests-for-recen.patch create mode 100644 0236-Backport-SME-attribs-Namespace-aware-lookup_attribut.patch create mode 100644 0237-Backport-SME-c-family-ICE-with-gnu-nocf_check-PR1069.patch create mode 100644 0238-Backport-SME-AArch64-Fix-assert-in-aarch64_move_imm-.patch create mode 100644 0239-Backport-SME-testsuite-Only-run-fcf-protection-test-.patch create mode 100644 0240-Backport-SME-Fix-PRs-106764-106765-and-107307-all-IC.patch create mode 100644 0241-Backport-SME-aarch64-Remove-expected-error-for-compo.patch create mode 100644 0242-Backport-SME-aarch64-Remove-redundant-builtins-code.patch create mode 100644 0243-Backport-SME-AArch64-Fix-Armv9-a-warnings-that-get-e.patch create mode 100644 0244-Backport-SME-Canonicalize-X-Y-as-X-Y-in-match.pd-whe.patch create mode 100644 0245-Backport-SME-middle-end-Add-new-tbranch-optab-to-add.patch create mode 100644 0246-Backport-SME-explow-Allow-dynamic-allocations-after-.patch create mode 100644 0247-Backport-SME-PR105169-Fix-references-to-discarded-se.patch create mode 100644 0248-Backport-SME-RISC-V-autovec-Verify-that-GET_MODE_NUN.patch create mode 100644 0249-Backport-SME-Add-operator-to-gimple_stmt_iterator-an.patch create mode 100644 0250-Backport-SME-tree-optimization-110221-SLP-and-loop-m.patch create mode 100644 0251-SME-Adapt-some-testsuites.patch create mode 100644 0252-SME-Fix-error-by-backported-patches-and-IPA-prefetch.patch create mode 100644 0253-aarch64-Fix-return-register-handling-in-untyped_call.patch create mode 100644 0254-aarch64-Fix-loose-ldpstp-check.patch create mode 100644 0255-x86-Add-a-new-option-mdaz-ftz-to-enable-FTZ-and-DAZ-.patch create mode 100644 0256-Explicitly-view_convert_expr-mask-to-signed-type-whe.patch create mode 100644 0257-Make-option-mvzeroupper-independent-of-optimization-.patch create mode 100644 0258-i386-Sync-tune_string-with-arch_string-for-target-at.patch create mode 100644 0259-Refine-maskloadmn-pattern-with-UNSPEC_MASKLOAD.patch create mode 100644 0260-Refine-maskstore-patterns-with-UNSPEC_MASKMOV.patch create mode 100644 0261-x86-Update-model-values-for-Alderlake-and-Rocketlake.patch create mode 100644 0262-Workaround-possible-CPUID-bug-in-Sandy-Bridge.patch create mode 100644 0263-Software-mitigation-Disable-gather-generation-in-vec.patch create mode 100644 0264-Support-m-no-gather-m-no-scatter-to-enable-disable-v.patch create mode 100644 0265-Remove-constraint-modifier-for-fcmaddcph-fmaddcph-fc.patch create mode 100644 0266-Disparage-slightly-for-the-alternative-which-move-DF.patch create mode 100644 0267-Fix-wrong-code-due-to-vec_merge-pcmp-to-blendvb-spli.patch create mode 100644 0268-Don-t-assume-it-s-AVX_U128_CLEAN-after-call_insn-who.patch create mode 100644 0269-Disable-FMADD-in-chains-for-Zen4-and-generic.patch create mode 100644 0270-Initial-Raptorlake-Support.patch create mode 100644 0271-Initial-Meteorlake-Support.patch create mode 100644 0272-Support-Intel-AMX-FP16-ISA.patch create mode 100644 0273-Support-Intel-prefetchit0-t1.patch create mode 100644 0274-Initial-Granite-Rapids-Support.patch create mode 100644 0275-Support-Intel-AMX-COMPLEX.patch create mode 100644 0276-i386-Add-AMX-COMPLEX-to-Granite-Rapids.patch create mode 100644 0277-Initial-Granite-Rapids-D-Support.patch create mode 100644 0278-Correct-Granite-Rapids-D-documentation.patch create mode 100644 0279-i386-Remove-Meteorlake-s-family_model.patch create mode 100644 0280-x86-Update-model-values-for-Alderlake-Rocketlake-and.patch create mode 100644 0281-x86-Update-model-values-for-Raptorlake.patch create mode 100644 0282-Fix-target_clone-arch-graniterapids-d.patch create mode 100644 0283-i386-Change-prefetchi-output-template.patch create mode 100644 0284-i386-Add-non-optimize-prefetchi-intrins.patch create mode 100644 0285-SME-Recover-hip09-and-hip11-in-aarch64-cores.def.patch create mode 100644 0286-Try-to-use-AI-model-to-guide-optimization.patch create mode 100644 0287-Add-dynamic-memory-access-checks.patch create mode 100644 0288-Enable-macro-use-commandline.patch create mode 100644 0289-tree-ssa-loop-crc.cc-TARGET_CRC32-may-be-not-defined.patch create mode 100644 0290-Add-ipa-prefetch-test-for-gcc-s-case.patch create mode 100644 0291-Fix-settings-for-wide-operations-tests.patch create mode 100644 0292-Fix-errors-in-ipa-prefetch-IAORPF-and-IAOSJ0.patch create mode 100644 0293-Fix-error-with-stmts-insertion-in-ipa-prefetch-for-I.patch create mode 100644 0294-Fix-errors-in-ipa-prefetch-IAO50J-and-IAO5H7.patch create mode 100644 0295-Fix-error-with-grouped_load-merge-in-slp-transpose-v.patch create mode 100644 0296-Fix-error-in-slp-transpose-vectorize-for-IAQFM3.patch create mode 100644 0297-Fix-grouped-load-merging-error-in-SLP-transpose-vectorization.patch create mode 100644 0298-Mark-prefetch-builtin-as-willreturn.patch create mode 100644 0299-Backport-Disallow-pointer-operands-for-and-partly-PR.patch create mode 100644 0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch create mode 100644 0301-Add-required-check-for-iteration-through-uses.patch create mode 100644 0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch create mode 100644 0303-Add-generation-of-stream-in-functions-for-pre-versio.patch create mode 100644 0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch create mode 100644 0305-Backport-varasm-Handle-private-COMDAT-function-symbo.patch create mode 100644 0306-RISC-V-Install-libstdc-libcc1-etc-to-lib64-instead-o.patch create mode 100644 0307-Set-fallback-value-for-print-multi-os-directory.patch create mode 100644 0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch create mode 100644 0309-CSPGO-Add-context-sensitive-PGO.patch create mode 100644 0310-CFGO-Add-cfgo-pgo-optimization.patch create mode 100644 0311-PATCH-Add-if-split-optimization-pass.patch create mode 100644 0312-Add-late-slp-vectorization-pass-with-additional-chec.patch create mode 100644 0313-Add-tracer-transformation-for-static-probabilities.patch create mode 100644 0314-bugfix-Modify-the-hip09-tune-flags.patch create mode 100644 0315-Bugfix-Add-no-var-recored-check-for-ssa_name-in-stru.patch create mode 100644 0316-Use-ai-ability-to-guide-optimization.patch create mode 100644 0317-Bugfix-set-default-value-when-tune_native-is-NULL.patch create mode 100644 0318-add-flag-flto-try.patch create mode 100644 0319-CSPGO-fix-bugs-when-using-cspgo.patch create mode 100644 0320-if-split-fix-bugs.patch create mode 100644 0321-Struct-reorg-Avoid-doing-struct-split-and-reorder_fi.patch create mode 100644 0322-Bugfix-Create-POINTER_PLUS_EXPR-for-REFERENCE_TYPE.patch create mode 100644 0323-Bugfix-replace-tmp-pattern-split.patch create mode 100644 0324-bugfix-fix-vector-costs-for-hip09.patch create mode 100644 0325-gcc-opts-common.cc-Fix-build-with-clang.patch create mode 100644 0326-BUGFIX-Fix-build-error-on-risv_64.patch create mode 100644 0327-Bugfix-Adjust-the-same-gate-to-use-struct-option.patch create mode 100644 0328-Bugfix-if-split-Added-checking-for-ssa_name.patch create mode 100644 0329-Fixed-work-with-loops-in-process_complex_cond.patch create mode 100644 0330-bugfix-fix-typo-error.patch create mode 100644 0331-fix-function-missing-return-value.patch create mode 100644 gcc.spec create mode 100644 sources diff --git a/.gitignore b/.gitignore index e69de29..36a7a48 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +/gcc-12.3.0.tar.xz diff --git a/0001-Version-Set-version-to-12.3.1.patch b/0001-Version-Set-version-to-12.3.1.patch new file mode 100644 index 0000000..e5e920e --- /dev/null +++ b/0001-Version-Set-version-to-12.3.1.patch @@ -0,0 +1,19 @@ +From 73ee6351353b036f466ba1aab9a9e7d7865bf972 Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Tue, 11 Jul 2023 16:07:51 +0800 +Subject: [PATCH 01/22] [Version] Set version to 12.3.1 + +--- + gcc/BASE-VER | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gcc/BASE-VER b/gcc/BASE-VER +index 4d23cb8e0..9c028e25d 100644 +--- a/gcc/BASE-VER ++++ b/gcc/BASE-VER +@@ -1 +1 @@ +-12.3.0 ++12.3.1 +-- +2.33.0 + diff --git a/0002-RISCV-Backport-inline-subword-atomic-patches.patch b/0002-RISCV-Backport-inline-subword-atomic-patches.patch new file mode 100644 index 0000000..d3d2c33 --- /dev/null +++ b/0002-RISCV-Backport-inline-subword-atomic-patches.patch @@ -0,0 +1,2042 @@ +From 123615a0aac59a731516ef11c1fe433d39b6573a Mon Sep 17 00:00:00 2001 +From: laokz +Date: Tue, 11 Jul 2023 21:03:14 +0800 +Subject: [PATCH 02/22] [RISCV] Backport inline subword atomic patches + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f797260adaf52bee0ec0e16190bbefbe1bfc3692 + +203f3060dd363361b172f7295f42bb6bf5ac0b3b +--- + gcc/config/riscv/linux.h | 10 - + gcc/config/riscv/riscv-protos.h | 2 + + gcc/config/riscv/riscv.cc | 49 ++ + gcc/config/riscv/riscv.opt | 4 + + gcc/config/riscv/sync.md | 301 +++++++++ + gcc/doc/invoke.texi | 10 +- + .../gcc.target/riscv/inline-atomics-1.c | 18 + + .../gcc.target/riscv/inline-atomics-2.c | 9 + + .../gcc.target/riscv/inline-atomics-3.c | 569 ++++++++++++++++++ + .../gcc.target/riscv/inline-atomics-4.c | 566 +++++++++++++++++ + .../gcc.target/riscv/inline-atomics-5.c | 87 +++ + .../gcc.target/riscv/inline-atomics-6.c | 87 +++ + .../gcc.target/riscv/inline-atomics-7.c | 69 +++ + .../gcc.target/riscv/inline-atomics-8.c | 69 +++ + libgcc/config/riscv/atomic.c | 2 + + 15 files changed, 1841 insertions(+), 11 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-1.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-2.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-3.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-4.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-5.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-6.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-7.c + create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-8.c + +diff --git a/gcc/config/riscv/linux.h b/gcc/config/riscv/linux.h +index 38803723b..b5c6c5027 100644 +--- a/gcc/config/riscv/linux.h ++++ b/gcc/config/riscv/linux.h +@@ -35,16 +35,6 @@ along with GCC; see the file COPYING3. If not see + #undef MUSL_DYNAMIC_LINKER + #define MUSL_DYNAMIC_LINKER "/lib/ld-musl-riscv" XLEN_SPEC MUSL_ABI_SUFFIX ".so.1" + +-/* Because RISC-V only has word-sized atomics, it requries libatomic where +- others do not. So link libatomic by default, as needed. */ +-#undef LIB_SPEC +-#ifdef LD_AS_NEEDED_OPTION +-#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC \ +- " %{pthread:" LD_AS_NEEDED_OPTION " -latomic " LD_NO_AS_NEEDED_OPTION "}" +-#else +-#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC " -latomic " +-#endif +- + #define ICACHE_FLUSH_FUNC "__riscv_flush_icache" + + #define CPP_SPEC "%{pthread:-D_REENTRANT}" +diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h +index 65bb85f55..3b039e00d 100644 +--- a/gcc/config/riscv/riscv-protos.h ++++ b/gcc/config/riscv/riscv-protos.h +@@ -74,6 +74,8 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx); + extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *); + extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *); + extern bool riscv_gpr_save_operation_p (rtx); ++extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *); ++extern void riscv_lshift_subword (machine_mode, rtx, rtx, rtx *); + + /* Routines implemented in riscv-c.cc. */ + void riscv_cpu_cpp_builtins (cpp_reader *); +diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc +index 4939d9964..9cf79beba 100644 +--- a/gcc/config/riscv/riscv.cc ++++ b/gcc/config/riscv/riscv.cc +@@ -5605,6 +5605,55 @@ riscv_asan_shadow_offset (void) + return TARGET_64BIT ? (HOST_WIDE_INT_1 << 29) : 0; + } + ++/* Given memory reference MEM, expand code to compute the aligned ++ memory address, shift and mask values and store them into ++ *ALIGNED_MEM, *SHIFT, *MASK and *NOT_MASK. */ ++ ++void ++riscv_subword_address (rtx mem, rtx *aligned_mem, rtx *shift, rtx *mask, ++ rtx *not_mask) ++{ ++ /* Align the memory address to a word. */ ++ rtx addr = force_reg (Pmode, XEXP (mem, 0)); ++ ++ rtx addr_mask = gen_int_mode (-4, Pmode); ++ ++ rtx aligned_addr = gen_reg_rtx (Pmode); ++ emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, addr_mask)); ++ ++ *aligned_mem = change_address (mem, SImode, aligned_addr); ++ ++ /* Calculate the shift amount. */ ++ emit_move_insn (*shift, gen_rtx_AND (SImode, gen_lowpart (SImode, addr), ++ gen_int_mode (3, SImode))); ++ emit_move_insn (*shift, gen_rtx_ASHIFT (SImode, *shift, ++ gen_int_mode (3, SImode))); ++ ++ /* Calculate the mask. */ ++ int unshifted_mask = GET_MODE_MASK (GET_MODE (mem)); ++ ++ emit_move_insn (*mask, gen_int_mode (unshifted_mask, SImode)); ++ ++ emit_move_insn (*mask, gen_rtx_ASHIFT (SImode, *mask, ++ gen_lowpart (QImode, *shift))); ++ ++ emit_move_insn (*not_mask, gen_rtx_NOT(SImode, *mask)); ++} ++ ++/* Leftshift a subword within an SImode register. */ ++ ++void ++riscv_lshift_subword (machine_mode mode, rtx value, rtx shift, ++ rtx *shifted_value) ++{ ++ rtx value_reg = gen_reg_rtx (SImode); ++ emit_move_insn (value_reg, simplify_gen_subreg (SImode, value, ++ mode, 0)); ++ ++ emit_move_insn(*shifted_value, gen_rtx_ASHIFT (SImode, value_reg, ++ gen_lowpart (QImode, shift))); ++} ++ + /* Initialize the GCC target structure. */ + #undef TARGET_ASM_ALIGNED_HI_OP + #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" +diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt +index 492aad123..328d848d6 100644 +--- a/gcc/config/riscv/riscv.opt ++++ b/gcc/config/riscv/riscv.opt +@@ -225,3 +225,7 @@ Enum(isa_spec_class) String(20191213) Value(ISA_SPEC_CLASS_20191213) + misa-spec= + Target RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC) + Set the version of RISC-V ISA spec. ++ ++minline-atomics ++Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1) ++Always inline subword atomic operations. +diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md +index 86b41e6b0..9c4fbabc6 100644 +--- a/gcc/config/riscv/sync.md ++++ b/gcc/config/riscv/sync.md +@@ -21,8 +21,11 @@ + + (define_c_enum "unspec" [ + UNSPEC_COMPARE_AND_SWAP ++ UNSPEC_COMPARE_AND_SWAP_SUBWORD + UNSPEC_SYNC_OLD_OP ++ UNSPEC_SYNC_OLD_OP_SUBWORD + UNSPEC_SYNC_EXCHANGE ++ UNSPEC_SYNC_EXCHANGE_SUBWORD + UNSPEC_ATOMIC_STORE + UNSPEC_MEMORY_BARRIER + ]) +@@ -92,6 +95,135 @@ + "%F3amo.%A3 %0,%z2,%1" + [(set (attr "length") (const_int 8))]) + ++(define_insn "subword_atomic_fetch_strong_" ++ [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem ++ (match_operand:SI 1 "memory_operand" "+A")) ;; mem location ++ (set (match_dup 1) ++ (unspec_volatile:SI ++ [(any_atomic:SI (match_dup 1) ++ (match_operand:SI 2 "register_operand" "rI")) ;; value for op ++ (match_operand:SI 3 "register_operand" "rI")] ;; mask ++ UNSPEC_SYNC_OLD_OP_SUBWORD)) ++ (match_operand:SI 4 "register_operand" "rI") ;; not_mask ++ (clobber (match_scratch:SI 5 "=&r")) ;; tmp_1 ++ (clobber (match_scratch:SI 6 "=&r"))] ;; tmp_2 ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++ { ++ return "1:\;" ++ "lr.w.aq\t%0, %1\;" ++ "\t%5, %0, %2\;" ++ "and\t%5, %5, %3\;" ++ "and\t%6, %0, %4\;" ++ "or\t%6, %6, %5\;" ++ "sc.w.rl\t%5, %6, %1\;" ++ "bnez\t%5, 1b"; ++ } ++ [(set (attr "length") (const_int 28))]) ++ ++(define_expand "atomic_fetch_nand" ++ [(match_operand:SHORT 0 "register_operand") ;; old value at mem ++ (not:SHORT (and:SHORT (match_operand:SHORT 1 "memory_operand") ;; mem location ++ (match_operand:SHORT 2 "reg_or_0_operand"))) ;; value for op ++ (match_operand:SI 3 "const_int_operand")] ;; model ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++{ ++ /* We have no QImode/HImode atomics, so form a mask, then use ++ subword_atomic_fetch_strong_nand to implement a LR/SC version of the ++ operation. */ ++ ++ /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining ++ is disabled */ ++ ++ rtx old = gen_reg_rtx (SImode); ++ rtx mem = operands[1]; ++ rtx value = operands[2]; ++ rtx aligned_mem = gen_reg_rtx (SImode); ++ rtx shift = gen_reg_rtx (SImode); ++ rtx mask = gen_reg_rtx (SImode); ++ rtx not_mask = gen_reg_rtx (SImode); ++ ++ riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask); ++ ++ rtx shifted_value = gen_reg_rtx (SImode); ++ riscv_lshift_subword (mode, value, shift, &shifted_value); ++ ++ emit_insn (gen_subword_atomic_fetch_strong_nand (old, aligned_mem, ++ shifted_value, ++ mask, not_mask)); ++ ++ emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old, ++ gen_lowpart (QImode, shift))); ++ ++ emit_move_insn (operands[0], gen_lowpart (mode, old)); ++ ++ DONE; ++}) ++ ++(define_insn "subword_atomic_fetch_strong_nand" ++ [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem ++ (match_operand:SI 1 "memory_operand" "+A")) ;; mem location ++ (set (match_dup 1) ++ (unspec_volatile:SI ++ [(not:SI (and:SI (match_dup 1) ++ (match_operand:SI 2 "register_operand" "rI"))) ;; value for op ++ (match_operand:SI 3 "register_operand" "rI")] ;; mask ++ UNSPEC_SYNC_OLD_OP_SUBWORD)) ++ (match_operand:SI 4 "register_operand" "rI") ;; not_mask ++ (clobber (match_scratch:SI 5 "=&r")) ;; tmp_1 ++ (clobber (match_scratch:SI 6 "=&r"))] ;; tmp_2 ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++ { ++ return "1:\;" ++ "lr.w.aq\t%0, %1\;" ++ "and\t%5, %0, %2\;" ++ "not\t%5, %5\;" ++ "and\t%5, %5, %3\;" ++ "and\t%6, %0, %4\;" ++ "or\t%6, %6, %5\;" ++ "sc.w.rl\t%5, %6, %1\;" ++ "bnez\t%5, 1b"; ++ } ++ [(set (attr "length") (const_int 32))]) ++ ++(define_expand "atomic_fetch_" ++ [(match_operand:SHORT 0 "register_operand") ;; old value at mem ++ (any_atomic:SHORT (match_operand:SHORT 1 "memory_operand") ;; mem location ++ (match_operand:SHORT 2 "reg_or_0_operand")) ;; value for op ++ (match_operand:SI 3 "const_int_operand")] ;; model ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++{ ++ /* We have no QImode/HImode atomics, so form a mask, then use ++ subword_atomic_fetch_strong_ to implement a LR/SC version of the ++ operation. */ ++ ++ /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining ++ is disabled */ ++ ++ rtx old = gen_reg_rtx (SImode); ++ rtx mem = operands[1]; ++ rtx value = operands[2]; ++ rtx aligned_mem = gen_reg_rtx (SImode); ++ rtx shift = gen_reg_rtx (SImode); ++ rtx mask = gen_reg_rtx (SImode); ++ rtx not_mask = gen_reg_rtx (SImode); ++ ++ riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask); ++ ++ rtx shifted_value = gen_reg_rtx (SImode); ++ riscv_lshift_subword (mode, value, shift, &shifted_value); ++ ++ emit_insn (gen_subword_atomic_fetch_strong_ (old, aligned_mem, ++ shifted_value, ++ mask, not_mask)); ++ ++ emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old, ++ gen_lowpart (QImode, shift))); ++ ++ emit_move_insn (operands[0], gen_lowpart (mode, old)); ++ ++ DONE; ++}) ++ + (define_insn "atomic_exchange" + [(set (match_operand:GPR 0 "register_operand" "=&r") + (unspec_volatile:GPR +@@ -104,6 +236,56 @@ + "%F3amoswap.%A3 %0,%z2,%1" + [(set (attr "length") (const_int 8))]) + ++(define_expand "atomic_exchange" ++ [(match_operand:SHORT 0 "register_operand") ;; old value at mem ++ (match_operand:SHORT 1 "memory_operand") ;; mem location ++ (match_operand:SHORT 2 "register_operand") ;; value ++ (match_operand:SI 3 "const_int_operand")] ;; model ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++{ ++ rtx old = gen_reg_rtx (SImode); ++ rtx mem = operands[1]; ++ rtx value = operands[2]; ++ rtx aligned_mem = gen_reg_rtx (SImode); ++ rtx shift = gen_reg_rtx (SImode); ++ rtx mask = gen_reg_rtx (SImode); ++ rtx not_mask = gen_reg_rtx (SImode); ++ ++ riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask); ++ ++ rtx shifted_value = gen_reg_rtx (SImode); ++ riscv_lshift_subword (mode, value, shift, &shifted_value); ++ ++ emit_insn (gen_subword_atomic_exchange_strong (old, aligned_mem, ++ shifted_value, not_mask)); ++ ++ emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old, ++ gen_lowpart (QImode, shift))); ++ ++ emit_move_insn (operands[0], gen_lowpart (mode, old)); ++ DONE; ++}) ++ ++(define_insn "subword_atomic_exchange_strong" ++ [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem ++ (match_operand:SI 1 "memory_operand" "+A")) ;; mem location ++ (set (match_dup 1) ++ (unspec_volatile:SI ++ [(match_operand:SI 2 "reg_or_0_operand" "rI") ;; value ++ (match_operand:SI 3 "reg_or_0_operand" "rI")] ;; not_mask ++ UNSPEC_SYNC_EXCHANGE_SUBWORD)) ++ (clobber (match_scratch:SI 4 "=&r"))] ;; tmp_1 ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++ { ++ return "1:\;" ++ "lr.w.aq\t%0, %1\;" ++ "and\t%4, %0, %3\;" ++ "or\t%4, %4, %2\;" ++ "sc.w.rl\t%4, %4, %1\;" ++ "bnez\t%4, 1b"; ++ } ++ [(set (attr "length") (const_int 20))]) ++ + (define_insn "atomic_cas_value_strong" + [(set (match_operand:GPR 0 "register_operand" "=&r") + (match_operand:GPR 1 "memory_operand" "+A")) +@@ -152,6 +334,125 @@ + DONE; + }) + ++(define_expand "atomic_compare_and_swap" ++ [(match_operand:SI 0 "register_operand") ;; bool output ++ (match_operand:SHORT 1 "register_operand") ;; val output ++ (match_operand:SHORT 2 "memory_operand") ;; memory ++ (match_operand:SHORT 3 "reg_or_0_operand") ;; expected value ++ (match_operand:SHORT 4 "reg_or_0_operand") ;; desired value ++ (match_operand:SI 5 "const_int_operand") ;; is_weak ++ (match_operand:SI 6 "const_int_operand") ;; mod_s ++ (match_operand:SI 7 "const_int_operand")] ;; mod_f ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++{ ++ emit_insn (gen_atomic_cas_value_strong (operands[1], operands[2], ++ operands[3], operands[4], ++ operands[6], operands[7])); ++ ++ rtx val = gen_reg_rtx (SImode); ++ if (operands[1] != const0_rtx) ++ emit_move_insn (val, gen_rtx_SIGN_EXTEND (SImode, operands[1])); ++ else ++ emit_move_insn (val, const0_rtx); ++ ++ rtx exp = gen_reg_rtx (SImode); ++ if (operands[3] != const0_rtx) ++ emit_move_insn (exp, gen_rtx_SIGN_EXTEND (SImode, operands[3])); ++ else ++ emit_move_insn (exp, const0_rtx); ++ ++ rtx compare = val; ++ if (exp != const0_rtx) ++ { ++ rtx difference = gen_rtx_MINUS (SImode, val, exp); ++ compare = gen_reg_rtx (SImode); ++ emit_move_insn (compare, difference); ++ } ++ ++ if (word_mode != SImode) ++ { ++ rtx reg = gen_reg_rtx (word_mode); ++ emit_move_insn (reg, gen_rtx_SIGN_EXTEND (word_mode, compare)); ++ compare = reg; ++ } ++ ++ emit_move_insn (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx)); ++ DONE; ++}) ++ ++(define_expand "atomic_cas_value_strong" ++ [(match_operand:SHORT 0 "register_operand") ;; val output ++ (match_operand:SHORT 1 "memory_operand") ;; memory ++ (match_operand:SHORT 2 "reg_or_0_operand") ;; expected value ++ (match_operand:SHORT 3 "reg_or_0_operand") ;; desired value ++ (match_operand:SI 4 "const_int_operand") ;; mod_s ++ (match_operand:SI 5 "const_int_operand") ;; mod_f ++ (match_scratch:SHORT 6)] ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++{ ++ /* We have no QImode/HImode atomics, so form a mask, then use ++ subword_atomic_cas_strong to implement a LR/SC version of the ++ operation. */ ++ ++ /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining ++ is disabled */ ++ ++ rtx old = gen_reg_rtx (SImode); ++ rtx mem = operands[1]; ++ rtx aligned_mem = gen_reg_rtx (SImode); ++ rtx shift = gen_reg_rtx (SImode); ++ rtx mask = gen_reg_rtx (SImode); ++ rtx not_mask = gen_reg_rtx (SImode); ++ ++ riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask); ++ ++ rtx o = operands[2]; ++ rtx n = operands[3]; ++ rtx shifted_o = gen_reg_rtx (SImode); ++ rtx shifted_n = gen_reg_rtx (SImode); ++ ++ riscv_lshift_subword (mode, o, shift, &shifted_o); ++ riscv_lshift_subword (mode, n, shift, &shifted_n); ++ ++ emit_move_insn (shifted_o, gen_rtx_AND (SImode, shifted_o, mask)); ++ emit_move_insn (shifted_n, gen_rtx_AND (SImode, shifted_n, mask)); ++ ++ emit_insn (gen_subword_atomic_cas_strong (old, aligned_mem, ++ shifted_o, shifted_n, ++ mask, not_mask)); ++ ++ emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old, ++ gen_lowpart (QImode, shift))); ++ ++ emit_move_insn (operands[0], gen_lowpart (mode, old)); ++ ++ DONE; ++}) ++ ++(define_insn "subword_atomic_cas_strong" ++ [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem ++ (match_operand:SI 1 "memory_operand" "+A")) ;; mem location ++ (set (match_dup 1) ++ (unspec_volatile:SI [(match_operand:SI 2 "reg_or_0_operand" "rJ") ;; expected value ++ (match_operand:SI 3 "reg_or_0_operand" "rJ")] ;; desired value ++ UNSPEC_COMPARE_AND_SWAP_SUBWORD)) ++ (match_operand:SI 4 "register_operand" "rI") ;; mask ++ (match_operand:SI 5 "register_operand" "rI") ;; not_mask ++ (clobber (match_scratch:SI 6 "=&r"))] ;; tmp_1 ++ "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC" ++ { ++ return "1:\;" ++ "lr.w.aq\t%0, %1\;" ++ "and\t%6, %0, %4\;" ++ "bne\t%6, %z2, 1f\;" ++ "and\t%6, %0, %5\;" ++ "or\t%6, %6, %3\;" ++ "sc.w.rl\t%6, %6, %1\;" ++ "bnez\t%6, 1b\;" ++ "1:"; ++ } ++ [(set (attr "length") (const_int 28))]) ++ + (define_expand "atomic_test_and_set" + [(match_operand:QI 0 "register_operand" "") ;; bool output + (match_operand:QI 1 "memory_operand" "+A") ;; memory +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index cb83dd8a1..ff8cd032f 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -1210,7 +1210,8 @@ See RS/6000 and PowerPC Options. + -malign-data=@var{type} @gol + -mbig-endian -mlittle-endian @gol + -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol +--mstack-protector-guard-offset=@var{offset}} ++-mstack-protector-guard-offset=@var{offset} ++-minline-atomics -mno-inline-atomics} + + @emph{RL78 Options} + @gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs @gol +@@ -28035,6 +28036,13 @@ Do or don't use smaller but slower prologue and epilogue code that uses + library function calls. The default is to use fast inline prologues and + epilogues. + ++@opindex minline-atomics ++@item -minline-atomics ++@itemx -mno-inline-atomics ++Do or don't use smaller but slower subword atomic emulation code that uses ++libatomic function calls. The default is to use fast inline subword atomics ++that do not require libatomic. ++ + @item -mshorten-memrefs + @itemx -mno-shorten-memrefs + @opindex mshorten-memrefs +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-1.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-1.c +new file mode 100644 +index 000000000..5c5623d9b +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-1.c +@@ -0,0 +1,18 @@ ++/* { dg-do compile } */ ++/* { dg-options "-mno-inline-atomics" } */ ++/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */ ++/* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_add_1" } } */ ++/* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_nand_1" } } */ ++/* { dg-final { scan-assembler "\tcall\t__sync_bool_compare_and_swap_1" } } */ ++ ++char foo; ++char bar; ++char baz; ++ ++int ++main () ++{ ++ __sync_fetch_and_add(&foo, 1); ++ __sync_fetch_and_nand(&bar, 1); ++ __sync_bool_compare_and_swap (&baz, 1, 2); ++} +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-2.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-2.c +new file mode 100644 +index 000000000..01b439086 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-2.c +@@ -0,0 +1,9 @@ ++/* { dg-do compile } */ ++/* Verify that subword atomics do not generate calls. */ ++/* { dg-options "-minline-atomics" } */ ++/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */ ++/* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_add_1" } } */ ++/* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_nand_1" } } */ ++/* { dg-final { scan-assembler-not "\tcall\t__sync_bool_compare_and_swap_1" } } */ ++ ++#include "inline-atomics-1.c" +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-3.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-3.c +new file mode 100644 +index 000000000..709f37343 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-3.c +@@ -0,0 +1,569 @@ ++/* Check all char alignments. */ ++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-op-1.c */ ++/* Test __atomic routines for existence and proper execution on 1 byte ++ values with each valid memory model. */ ++/* { dg-do run } */ ++/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */ ++ ++/* Test the execution of the __atomic_*OP builtin routines for a char. */ ++ ++extern void abort(void); ++ ++char count, res; ++const char init = ~0; ++ ++struct A ++{ ++ char a; ++ char b; ++ char c; ++ char d; ++} __attribute__ ((packed)) A; ++ ++/* The fetch_op routines return the original value before the operation. */ ++ ++void ++test_fetch_add (char* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0) ++ abort (); ++ ++ if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1) ++ abort (); ++ ++ if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2) ++ abort (); ++ ++ if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3) ++ abort (); ++ ++ if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4) ++ abort (); ++ ++ if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5) ++ abort (); ++} ++ ++ ++void ++test_fetch_sub (char* v) ++{ ++ *v = res = 20; ++ count = 0; ++ ++ if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) != res--) ++ abort (); ++} ++ ++void ++test_fetch_and (char* v) ++{ ++ *v = init; ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) != 0) ++ abort (); ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ *v = ~*v; ++ if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) != 0) ++ abort (); ++} ++ ++void ++test_fetch_nand (char* v) ++{ ++ *v = init; ++ ++ if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) != init) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) != 0 ) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) != 0) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) != init) ++ abort (); ++} ++ ++void ++test_fetch_xor (char* v) ++{ ++ *v = init; ++ count = 0; ++ ++ if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) != init) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) != 0) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) != init) ++ abort (); ++} ++ ++void ++test_fetch_or (char* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) != 0) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) != 1) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) != 3) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) != 7) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) != 15) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) != 31) ++ abort (); ++} ++ ++/* The OP_fetch routines return the new value after the operation. */ ++ ++void ++test_add_fetch (char* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1) ++ abort (); ++ ++ if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2) ++ abort (); ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3) ++ abort (); ++ ++ if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4) ++ abort (); ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5) ++ abort (); ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6) ++ abort (); ++} ++ ++ ++void ++test_sub_fetch (char* v) ++{ ++ *v = res = 20; ++ count = 0; ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) != --res) ++ abort (); ++} ++ ++void ++test_and_fetch (char* v) ++{ ++ *v = init; ++ ++ if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) != 0) ++ abort (); ++ ++ *v = init; ++ if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) != init) ++ abort (); ++ ++ if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ *v = ~*v; ++ if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) != 0) ++ abort (); ++ ++ *v = ~*v; ++ if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) != 0) ++ abort (); ++} ++ ++void ++test_nand_fetch (char* v) ++{ ++ *v = init; ++ ++ if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) != 0) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) != init) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) != 0) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) != init) ++ abort (); ++} ++ ++ ++ ++void ++test_xor_fetch (char* v) ++{ ++ *v = init; ++ count = 0; ++ ++ if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) != 0) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) != 0) ++ abort (); ++} ++ ++void ++test_or_fetch (char* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) != 1) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) != 3) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) != 7) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) != 15) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) != 31) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) != 63) ++ abort (); ++} ++ ++ ++/* Test the OP routines with a result which isn't used. Use both variations ++ within each function. */ ++ ++void ++test_add (char* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ __atomic_add_fetch (v, count, __ATOMIC_RELAXED); ++ if (*v != 1) ++ abort (); ++ ++ __atomic_fetch_add (v, count, __ATOMIC_CONSUME); ++ if (*v != 2) ++ abort (); ++ ++ __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE); ++ if (*v != 3) ++ abort (); ++ ++ __atomic_fetch_add (v, 1, __ATOMIC_RELEASE); ++ if (*v != 4) ++ abort (); ++ ++ __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL); ++ if (*v != 5) ++ abort (); ++ ++ __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST); ++ if (*v != 6) ++ abort (); ++} ++ ++ ++void ++test_sub (char* v) ++{ ++ *v = res = 20; ++ count = 0; ++ ++ __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST); ++ if (*v != --res) ++ abort (); ++} ++ ++void ++test_and (char* v) ++{ ++ *v = init; ++ ++ __atomic_and_fetch (v, 0, __ATOMIC_RELAXED); ++ if (*v != 0) ++ abort (); ++ ++ *v = init; ++ __atomic_fetch_and (v, init, __ATOMIC_CONSUME); ++ if (*v != init) ++ abort (); ++ ++ __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE); ++ if (*v != 0) ++ abort (); ++ ++ *v = ~*v; ++ __atomic_fetch_and (v, init, __ATOMIC_RELEASE); ++ if (*v != init) ++ abort (); ++ ++ __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL); ++ if (*v != 0) ++ abort (); ++ ++ *v = ~*v; ++ __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST); ++ if (*v != 0) ++ abort (); ++} ++ ++void ++test_nand (char* v) ++{ ++ *v = init; ++ ++ __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED); ++ if (*v != init) ++ abort (); ++ ++ __atomic_fetch_nand (v, init, __ATOMIC_CONSUME); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE); ++ if (*v != init) ++ abort (); ++ ++ __atomic_nand_fetch (v, init, __ATOMIC_RELEASE); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL); ++ if (*v != init) ++ abort (); ++ ++ __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST); ++ if (*v != init) ++ abort (); ++} ++ ++ ++ ++void ++test_xor (char* v) ++{ ++ *v = init; ++ count = 0; ++ ++ __atomic_xor_fetch (v, count, __ATOMIC_RELAXED); ++ if (*v != init) ++ abort (); ++ ++ __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE); ++ if (*v != init) ++ abort (); ++ ++ __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL); ++ if (*v != init) ++ abort (); ++ ++ __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST); ++ if (*v != 0) ++ abort (); ++} ++ ++void ++test_or (char* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ __atomic_or_fetch (v, count, __ATOMIC_RELAXED); ++ if (*v != 1) ++ abort (); ++ ++ count *= 2; ++ __atomic_fetch_or (v, count, __ATOMIC_CONSUME); ++ if (*v != 3) ++ abort (); ++ ++ count *= 2; ++ __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE); ++ if (*v != 7) ++ abort (); ++ ++ count *= 2; ++ __atomic_fetch_or (v, 8, __ATOMIC_RELEASE); ++ if (*v != 15) ++ abort (); ++ ++ count *= 2; ++ __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL); ++ if (*v != 31) ++ abort (); ++ ++ count *= 2; ++ __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST); ++ if (*v != 63) ++ abort (); ++} ++ ++int ++main () ++{ ++ char* V[] = {&A.a, &A.b, &A.c, &A.d}; ++ ++ for (int i = 0; i < 4; i++) { ++ test_fetch_add (V[i]); ++ test_fetch_sub (V[i]); ++ test_fetch_and (V[i]); ++ test_fetch_nand (V[i]); ++ test_fetch_xor (V[i]); ++ test_fetch_or (V[i]); ++ ++ test_add_fetch (V[i]); ++ test_sub_fetch (V[i]); ++ test_and_fetch (V[i]); ++ test_nand_fetch (V[i]); ++ test_xor_fetch (V[i]); ++ test_or_fetch (V[i]); ++ ++ test_add (V[i]); ++ test_sub (V[i]); ++ test_and (V[i]); ++ test_nand (V[i]); ++ test_xor (V[i]); ++ test_or (V[i]); ++ } ++ ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-4.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-4.c +new file mode 100644 +index 000000000..eecfaae5c +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-4.c +@@ -0,0 +1,566 @@ ++/* Check all short alignments. */ ++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-op-2.c */ ++/* Test __atomic routines for existence and proper execution on 2 byte ++ values with each valid memory model. */ ++/* { dg-do run } */ ++/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */ ++ ++/* Test the execution of the __atomic_*OP builtin routines for a short. */ ++ ++extern void abort(void); ++ ++short count, res; ++const short init = ~0; ++ ++struct A ++{ ++ short a; ++ short b; ++} __attribute__ ((packed)) A; ++ ++/* The fetch_op routines return the original value before the operation. */ ++ ++void ++test_fetch_add (short* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0) ++ abort (); ++ ++ if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1) ++ abort (); ++ ++ if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2) ++ abort (); ++ ++ if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3) ++ abort (); ++ ++ if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4) ++ abort (); ++ ++ if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5) ++ abort (); ++} ++ ++ ++void ++test_fetch_sub (short* v) ++{ ++ *v = res = 20; ++ count = 0; ++ ++ if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) != res--) ++ abort (); ++ ++ if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) != res--) ++ abort (); ++} ++ ++void ++test_fetch_and (short* v) ++{ ++ *v = init; ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) != 0) ++ abort (); ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ *v = ~*v; ++ if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) != 0) ++ abort (); ++} ++ ++void ++test_fetch_nand (short* v) ++{ ++ *v = init; ++ ++ if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) != init) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) != 0 ) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) != 0) ++ abort (); ++ ++ if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) != init) ++ abort (); ++} ++ ++void ++test_fetch_xor (short* v) ++{ ++ *v = init; ++ count = 0; ++ ++ if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) != init) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) != 0) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) != init) ++ abort (); ++} ++ ++void ++test_fetch_or (short* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) != 0) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) != 1) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) != 3) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) != 7) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) != 15) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) != 31) ++ abort (); ++} ++ ++/* The OP_fetch routines return the new value after the operation. */ ++ ++void ++test_add_fetch (short* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1) ++ abort (); ++ ++ if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2) ++ abort (); ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3) ++ abort (); ++ ++ if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4) ++ abort (); ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5) ++ abort (); ++ ++ if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6) ++ abort (); ++} ++ ++ ++void ++test_sub_fetch (short* v) ++{ ++ *v = res = 20; ++ count = 0; ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) != --res) ++ abort (); ++ ++ if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) != --res) ++ abort (); ++} ++ ++void ++test_and_fetch (short* v) ++{ ++ *v = init; ++ ++ if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) != 0) ++ abort (); ++ ++ *v = init; ++ if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) != init) ++ abort (); ++ ++ if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ *v = ~*v; ++ if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) != 0) ++ abort (); ++ ++ *v = ~*v; ++ if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) != 0) ++ abort (); ++} ++ ++void ++test_nand_fetch (short* v) ++{ ++ *v = init; ++ ++ if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) != 0) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) != init) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) != 0) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) != init) ++ abort (); ++} ++ ++ ++ ++void ++test_xor_fetch (short* v) ++{ ++ *v = init; ++ count = 0; ++ ++ if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) != init) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) != 0) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) != 0) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) != init) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) != init) ++ abort (); ++ ++ if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) != 0) ++ abort (); ++} ++ ++void ++test_or_fetch (short* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) != 1) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) != 3) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) != 7) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) != 15) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) != 31) ++ abort (); ++ ++ count *= 2; ++ if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) != 63) ++ abort (); ++} ++ ++ ++/* Test the OP routines with a result which isn't used. Use both variations ++ within each function. */ ++ ++void ++test_add (short* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ __atomic_add_fetch (v, count, __ATOMIC_RELAXED); ++ if (*v != 1) ++ abort (); ++ ++ __atomic_fetch_add (v, count, __ATOMIC_CONSUME); ++ if (*v != 2) ++ abort (); ++ ++ __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE); ++ if (*v != 3) ++ abort (); ++ ++ __atomic_fetch_add (v, 1, __ATOMIC_RELEASE); ++ if (*v != 4) ++ abort (); ++ ++ __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL); ++ if (*v != 5) ++ abort (); ++ ++ __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST); ++ if (*v != 6) ++ abort (); ++} ++ ++ ++void ++test_sub (short* v) ++{ ++ *v = res = 20; ++ count = 0; ++ ++ __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL); ++ if (*v != --res) ++ abort (); ++ ++ __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST); ++ if (*v != --res) ++ abort (); ++} ++ ++void ++test_and (short* v) ++{ ++ *v = init; ++ ++ __atomic_and_fetch (v, 0, __ATOMIC_RELAXED); ++ if (*v != 0) ++ abort (); ++ ++ *v = init; ++ __atomic_fetch_and (v, init, __ATOMIC_CONSUME); ++ if (*v != init) ++ abort (); ++ ++ __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE); ++ if (*v != 0) ++ abort (); ++ ++ *v = ~*v; ++ __atomic_fetch_and (v, init, __ATOMIC_RELEASE); ++ if (*v != init) ++ abort (); ++ ++ __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL); ++ if (*v != 0) ++ abort (); ++ ++ *v = ~*v; ++ __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST); ++ if (*v != 0) ++ abort (); ++} ++ ++void ++test_nand (short* v) ++{ ++ *v = init; ++ ++ __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED); ++ if (*v != init) ++ abort (); ++ ++ __atomic_fetch_nand (v, init, __ATOMIC_CONSUME); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE); ++ if (*v != init) ++ abort (); ++ ++ __atomic_nand_fetch (v, init, __ATOMIC_RELEASE); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL); ++ if (*v != init) ++ abort (); ++ ++ __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST); ++ if (*v != init) ++ abort (); ++} ++ ++ ++ ++void ++test_xor (short* v) ++{ ++ *v = init; ++ count = 0; ++ ++ __atomic_xor_fetch (v, count, __ATOMIC_RELAXED); ++ if (*v != init) ++ abort (); ++ ++ __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE); ++ if (*v != 0) ++ abort (); ++ ++ __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE); ++ if (*v != init) ++ abort (); ++ ++ __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL); ++ if (*v != init) ++ abort (); ++ ++ __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST); ++ if (*v != 0) ++ abort (); ++} ++ ++void ++test_or (short* v) ++{ ++ *v = 0; ++ count = 1; ++ ++ __atomic_or_fetch (v, count, __ATOMIC_RELAXED); ++ if (*v != 1) ++ abort (); ++ ++ count *= 2; ++ __atomic_fetch_or (v, count, __ATOMIC_CONSUME); ++ if (*v != 3) ++ abort (); ++ ++ count *= 2; ++ __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE); ++ if (*v != 7) ++ abort (); ++ ++ count *= 2; ++ __atomic_fetch_or (v, 8, __ATOMIC_RELEASE); ++ if (*v != 15) ++ abort (); ++ ++ count *= 2; ++ __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL); ++ if (*v != 31) ++ abort (); ++ ++ count *= 2; ++ __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST); ++ if (*v != 63) ++ abort (); ++} ++ ++int ++main () { ++ short* V[] = {&A.a, &A.b}; ++ ++ for (int i = 0; i < 2; i++) { ++ test_fetch_add (V[i]); ++ test_fetch_sub (V[i]); ++ test_fetch_and (V[i]); ++ test_fetch_nand (V[i]); ++ test_fetch_xor (V[i]); ++ test_fetch_or (V[i]); ++ ++ test_add_fetch (V[i]); ++ test_sub_fetch (V[i]); ++ test_and_fetch (V[i]); ++ test_nand_fetch (V[i]); ++ test_xor_fetch (V[i]); ++ test_or_fetch (V[i]); ++ ++ test_add (V[i]); ++ test_sub (V[i]); ++ test_and (V[i]); ++ test_nand (V[i]); ++ test_xor (V[i]); ++ test_or (V[i]); ++ } ++ ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-5.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-5.c +new file mode 100644 +index 000000000..52093894a +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-5.c +@@ -0,0 +1,87 @@ ++/* Test __atomic routines for existence and proper execution on 1 byte ++ values with each valid memory model. */ ++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-compare-exchange-1.c */ ++/* { dg-do run } */ ++/* { dg-options "-minline-atomics" } */ ++ ++/* Test the execution of the __atomic_compare_exchange_n builtin for a char. */ ++ ++extern void abort(void); ++ ++char v = 0; ++char expected = 0; ++char max = ~0; ++char desired = ~0; ++char zero = 0; ++ ++#define STRONG 0 ++#define WEAK 1 ++ ++int ++main () ++{ ++ ++ if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != max) ++ abort (); ++ ++ if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != max) ++ abort (); ++ if (v != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ if (v != max) ++ abort (); ++ ++ /* Now test the generic version. */ ++ ++ v = 0; ++ ++ if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != max) ++ abort (); ++ ++ if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != max) ++ abort (); ++ if (v != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ if (v != max) ++ abort (); ++ ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-6.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-6.c +new file mode 100644 +index 000000000..8fee8c448 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-6.c +@@ -0,0 +1,87 @@ ++/* Test __atomic routines for existence and proper execution on 2 byte ++ values with each valid memory model. */ ++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-compare-exchange-2.c */ ++/* { dg-do run } */ ++/* { dg-options "-minline-atomics" } */ ++ ++/* Test the execution of the __atomic_compare_exchange_n builtin for a short. */ ++ ++extern void abort(void); ++ ++short v = 0; ++short expected = 0; ++short max = ~0; ++short desired = ~0; ++short zero = 0; ++ ++#define STRONG 0 ++#define WEAK 1 ++ ++int ++main () ++{ ++ ++ if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != max) ++ abort (); ++ ++ if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != max) ++ abort (); ++ if (v != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ if (v != max) ++ abort (); ++ ++ /* Now test the generic version. */ ++ ++ v = 0; ++ ++ if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) ++ abort (); ++ if (expected != max) ++ abort (); ++ ++ if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != max) ++ abort (); ++ if (v != 0) ++ abort (); ++ ++ if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ ++ if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) ++ abort (); ++ if (expected != 0) ++ abort (); ++ if (v != max) ++ abort (); ++ ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-7.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-7.c +new file mode 100644 +index 000000000..24c344c0c +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-7.c +@@ -0,0 +1,69 @@ ++/* Test __atomic routines for existence and proper execution on 1 byte ++ values with each valid memory model. */ ++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-exchange-1.c */ ++/* { dg-do run } */ ++/* { dg-options "-minline-atomics" } */ ++ ++/* Test the execution of the __atomic_exchange_n builtin for a char. */ ++ ++extern void abort(void); ++ ++char v, count, ret; ++ ++int ++main () ++{ ++ v = 0; ++ count = 0; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count) ++ abort (); ++ count++; ++ ++ /* Now test the generic version. */ ++ ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.target/riscv/inline-atomics-8.c b/gcc/testsuite/gcc.target/riscv/inline-atomics-8.c +new file mode 100644 +index 000000000..edc212df0 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-8.c +@@ -0,0 +1,69 @@ ++/* Test __atomic routines for existence and proper execution on 2 byte ++ values with each valid memory model. */ ++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-exchange-2.c */ ++/* { dg-do run } */ ++/* { dg-options "-minline-atomics" } */ ++ ++/* Test the execution of the __atomic_X builtin for a short. */ ++ ++extern void abort(void); ++ ++short v, count, ret; ++ ++int ++main () ++{ ++ v = 0; ++ count = 0; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count) ++ abort (); ++ count++; ++ ++ if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count) ++ abort (); ++ count++; ++ ++ /* Now test the generic version. */ ++ ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST); ++ if (ret != count - 1 || v != count) ++ abort (); ++ count++; ++ ++ return 0; ++} +diff --git a/libgcc/config/riscv/atomic.c b/libgcc/config/riscv/atomic.c +index 7007e7a20..a29909b97 100644 +--- a/libgcc/config/riscv/atomic.c ++++ b/libgcc/config/riscv/atomic.c +@@ -30,6 +30,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + #define INVERT "not %[tmp1], %[tmp1]\n\t" + #define DONT_INVERT "" + ++/* Logic duplicated in gcc/gcc/config/riscv/sync.md for use when inlining is enabled */ ++ + #define GENERATE_FETCH_AND_OP(type, size, opname, insn, invert, cop) \ + type __sync_fetch_and_ ## opname ## _ ## size (type *p, type v) \ + { \ +-- +2.33.0 + diff --git a/0003-CONFIG-Regenerate-configure-file.patch b/0003-CONFIG-Regenerate-configure-file.patch new file mode 100644 index 0000000..c31c887 --- /dev/null +++ b/0003-CONFIG-Regenerate-configure-file.patch @@ -0,0 +1,45 @@ +From 37ef787e743d98f9f6e53005d99709fb8e284964 Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Fri, 14 Jul 2023 11:07:05 +0800 +Subject: [PATCH 03/22] [CONFIG] Regenerate configure file + +Regenerate configure file under libquadmath directory +since it is out of date. +--- + libquadmath/configure | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libquadmath/configure b/libquadmath/configure +index b3ee64f9c..603f2f131 100755 +--- a/libquadmath/configure ++++ b/libquadmath/configure +@@ -10806,7 +10806,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 10819 "configure" ++#line 10809 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -10912,7 +10912,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 10925 "configure" ++#line 10915 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -13031,7 +13031,7 @@ case "$host" in + case "$enable_cet" in + auto) + # Check if target supports multi-byte NOPs +- # and if assembler supports CET insn. ++ # and if compiler and assembler support CET insn. + cet_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fcf-protection" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-- +2.33.0 + diff --git a/0004-libquadmath-Enable-libquadmath-on-kunpeng.patch b/0004-libquadmath-Enable-libquadmath-on-kunpeng.patch new file mode 100644 index 0000000..0bd784e --- /dev/null +++ b/0004-libquadmath-Enable-libquadmath-on-kunpeng.patch @@ -0,0 +1,197 @@ +From 52a810b4d8a725a7edb2988f6c3813a9938362a5 Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Fri, 14 Jul 2023 11:10:24 +0800 +Subject: [PATCH 04/22] [libquadmath] Enable libquadmath on kunpeng + +This enable libquadmath on kunpeng platform to convenient +users that migrating from x86 platform. libquadmath uses "__float128" +as quad precision floating point type and with math functions with "q" +suffix like "cosq". For those who do not need to adapt to x86 platform, +you can use "long double" as quad precision floating point type and math +functions with "l" suffix like "cosl" in libm for quad precision math. +--- + libquadmath/Makefile.am | 4 ++++ + libquadmath/Makefile.in | 3 ++- + libquadmath/configure | 28 ++++++++++++++++++++++++++-- + libquadmath/configure.ac | 7 +++++++ + libquadmath/quadmath.h | 13 +++++++++++-- + 5 files changed, 50 insertions(+), 5 deletions(-) + +diff --git a/libquadmath/Makefile.am b/libquadmath/Makefile.am +index 35dffb46f..bf0398d9c 100644 +--- a/libquadmath/Makefile.am ++++ b/libquadmath/Makefile.am +@@ -2,6 +2,10 @@ + + AUTOMAKE_OPTIONS = foreign info-in-builddir + ++if ARCH_AARCH64 ++DEFS += -D__float128="long double" ++endif ++ + ## Skip over everything if the quadlib is not available: + if BUILD_LIBQUADMATH + ACLOCAL_AMFLAGS = -I .. -I ../config +diff --git a/libquadmath/Makefile.in b/libquadmath/Makefile.in +index 8c0112122..449cc8a06 100644 +--- a/libquadmath/Makefile.in ++++ b/libquadmath/Makefile.in +@@ -90,6 +90,7 @@ POST_UNINSTALL = : + build_triplet = @build@ + host_triplet = @host@ + target_triplet = @target@ ++@ARCH_AARCH64_TRUE@am__append_1 = -D__float128="long double" + @BUILD_LIBQUADMATH_FALSE@libquadmath_la_DEPENDENCIES = + subdir = . + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +@@ -337,7 +338,7 @@ CFLAGS = @CFLAGS@ + CPP = @CPP@ + CPPFLAGS = @CPPFLAGS@ + CYGPATH_W = @CYGPATH_W@ +-DEFS = @DEFS@ ++DEFS = @DEFS@ $(am__append_1) + DEPDIR = @DEPDIR@ + DSYMUTIL = @DSYMUTIL@ + DUMPBIN = @DUMPBIN@ +diff --git a/libquadmath/configure b/libquadmath/configure +index 603f2f131..13a9088fb 100755 +--- a/libquadmath/configure ++++ b/libquadmath/configure +@@ -633,6 +633,8 @@ am__EXEEXT_TRUE + LTLIBOBJS + LIBOBJS + get_gcc_base_ver ++ARCH_AARCH64_FALSE ++ARCH_AARCH64_TRUE + GENINSRC_FALSE + GENINSRC_TRUE + XCFLAGS +@@ -10806,7 +10808,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 10809 "configure" ++#line 10811 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -10912,7 +10914,7 @@ else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +-#line 10915 "configure" ++#line 10917 "configure" + #include "confdefs.h" + + #if HAVE_DLFCN_H +@@ -12705,6 +12707,11 @@ else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + ++ #if defined(__aarch64__) ++ typedef long double __float128; ++ #define __builtin_huge_valq() (__extension__ 0x1.0p32767Q) ++ #endif ++ + #if (!defined(_ARCH_PPC)) || defined(__LONG_DOUBLE_IEEE128__) + typedef _Complex float __attribute__((mode(TC))) __complex128; + #else +@@ -12756,6 +12763,11 @@ fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ + ++ #if defined(__aarch64__) ++ typedef long double __float128; ++ #define __builtin_huge_valq() (__extension__ 0x1.0p32767Q) ++ #endif ++ + #if (!defined(_ARCH_PPC)) || defined(__LONG_DOUBLE_IEEE128__) + typedef _Complex float __attribute__((mode(TC))) __complex128; + #else +@@ -13242,6 +13254,14 @@ else + GENINSRC_FALSE= + fi + ++ if expr "$target_cpu" : "aarch64.*" > /dev/null; then ++ ARCH_AARCH64_TRUE= ++ ARCH_AARCH64_FALSE='#' ++else ++ ARCH_AARCH64_TRUE='#' ++ ARCH_AARCH64_FALSE= ++fi ++ + + # Determine what GCC version number to use in filesystem paths. + +@@ -13425,6 +13445,10 @@ if test -z "${GENINSRC_TRUE}" && test -z "${GENINSRC_FALSE}"; then + as_fn_error $? "conditional \"GENINSRC\" was never defined. + Usually this means the macro was only invoked conditionally." "$LINENO" 5 + fi ++if test -z "${ARCH_AARCH64_TRUE}" && test -z "${ARCH_AARCH64_FALSE}"; then ++ as_fn_error $? "conditional \"ARCH_AARCH64\" was never defined. ++Usually this means the macro was only invoked conditionally." "$LINENO" 5 ++fi + + : "${CONFIG_STATUS=./config.status}" + ac_write_fail=0 +diff --git a/libquadmath/configure.ac b/libquadmath/configure.ac +index eec4084a4..507c247d6 100644 +--- a/libquadmath/configure.ac ++++ b/libquadmath/configure.ac +@@ -218,6 +218,11 @@ AM_CONDITIONAL(LIBQUAD_USE_SYMVER_SUN, [test "x$quadmath_use_symver" = xsun]) + + AC_CACHE_CHECK([whether __float128 is supported], [libquad_cv_have_float128], + [GCC_TRY_COMPILE_OR_LINK([ ++ #if defined(__aarch64__) ++ typedef long double __float128; ++ #define __builtin_huge_valq() (__extension__ 0x1.0p32767Q) ++ #endif ++ + #if (!defined(_ARCH_PPC)) || defined(__LONG_DOUBLE_IEEE128__) + typedef _Complex float __attribute__((mode(TC))) __complex128; + #else +@@ -393,6 +398,8 @@ AS_HELP_STRING([--enable-generated-files-in-srcdir], + [enable_generated_files_in_srcdir=no]) + AC_MSG_RESULT($enable_generated_files_in_srcdir) + AM_CONDITIONAL(GENINSRC, test "$enable_generated_files_in_srcdir" = yes) ++AM_CONDITIONAL(ARCH_AARCH64, ++ [expr "$target_cpu" : "aarch64.*" > /dev/null]) + + # Determine what GCC version number to use in filesystem paths. + GCC_BASE_VER +diff --git a/libquadmath/quadmath.h b/libquadmath/quadmath.h +index 81eb957d2..bb1b49df6 100644 +--- a/libquadmath/quadmath.h ++++ b/libquadmath/quadmath.h +@@ -27,6 +27,12 @@ Boston, MA 02110-1301, USA. */ + extern "C" { + #endif + ++#if defined(__aarch64__) ++#ifndef __float128 ++typedef long double __float128; ++#endif ++#endif ++ + /* Define the complex type corresponding to __float128 + ("_Complex __float128" is not allowed) */ + #if (!defined(_ARCH_PPC)) || defined(__LONG_DOUBLE_IEEE128__) +@@ -160,10 +166,13 @@ extern int quadmath_snprintf (char *str, size_t size, + #define FLT128_MAX_10_EXP 4932 + + +-#define HUGE_VALQ __builtin_huge_valq() ++#if defined(__aarch64__) + /* The following alternative is valid, but brings the warning: + (floating constant exceeds range of ‘__float128’) */ +-/* #define HUGE_VALQ (__extension__ 0x1.0p32767Q) */ ++# define HUGE_VALQ (__extension__ 0x1.0p32767Q) ++#else ++# define HUGE_VALQ __builtin_huge_valq() ++#endif + + #define M_Eq 2.718281828459045235360287471352662498Q /* e */ + #define M_LOG2Eq 1.442695040888963407359924681001892137Q /* log_2 e */ +-- +2.33.0 + diff --git a/0006-MULL64-1-3-Add-A-B-op-CST-B-match-and-simplify-optim.patch b/0006-MULL64-1-3-Add-A-B-op-CST-B-match-and-simplify-optim.patch new file mode 100644 index 0000000..35dc803 --- /dev/null +++ b/0006-MULL64-1-3-Add-A-B-op-CST-B-match-and-simplify-optim.patch @@ -0,0 +1,89 @@ +From e7013d2640d82e928ebdaf830b6833051ac65296 Mon Sep 17 00:00:00 2001 +From: zhongyunde +Date: Sat, 5 Nov 2022 13:22:33 +0800 +Subject: [PATCH 06/22] [MULL64 1/3] Add A ? B op CST : B match and simplify + optimizations + + Refer to commit b6bdd7a4, use pattern match to simple + A ? B op CST : B (where CST is power of 2) simplifications. + Fixes the 1st issue of https://gitee.com/openeuler/gcc/issues/I5TSG0?from=project-issue. + + gcc/ + * match.pd (A ? B op CST : B): Add simplifcations for A ? B op POW2 : B + + gcc/testsuite/ + * gcc.dg/pr107190.c: New test. +--- + gcc/match.pd | 21 +++++++++++++++++++++ + gcc/testsuite/gcc.dg/pr107190.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+) + create mode 100644 gcc/testsuite/gcc.dg/pr107190.c + +diff --git a/gcc/match.pd b/gcc/match.pd +index fc2833bbd..fd0857fc9 100644 +--- a/gcc/match.pd ++++ b/gcc/match.pd +@@ -4280,6 +4280,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) + ) + #endif + ++#if GIMPLE ++(if (canonicalize_math_p ()) ++/* These patterns are mostly used by PHIOPT to move some operations outside of ++ the if statements. They should be done late because it gives jump threading ++ and few other passes to reduce what is going on. */ ++/* a ? x op C : x -> x op (a << log2(C)) when C is power of 2. */ ++ (for op (plus minus bit_ior bit_xor lshift rshift lrotate rrotate) ++ (simplify ++ (cond @0 (op:s @1 integer_pow2p@2) @1) ++ /* powerof2cst */ ++ (if (INTEGRAL_TYPE_P (type)) ++ (with { ++ tree shift = build_int_cst (integer_type_node, tree_log2 (@2)); ++ } ++ (op @1 (lshift (convert (convert:boolean_type_node @0)) { shift; }))) ++ ) ++ ) ++ ) ++) ++#endif ++ + /* Simplification moved from fold_cond_expr_with_comparison. It may also + be extended. */ + /* This pattern implements two kinds simplification: +diff --git a/gcc/testsuite/gcc.dg/pr107190.c b/gcc/testsuite/gcc.dg/pr107190.c +new file mode 100644 +index 000000000..235b2761a +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/pr107190.c +@@ -0,0 +1,27 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -fexpensive-optimizations -fdump-tree-phiopt2-details" } */ ++ ++# define BN_BITS4 32 ++# define BN_MASK2 (0xffffffffffffffffL) ++# define BN_MASK2l (0xffffffffL) ++# define BN_MASK2h (0xffffffff00000000L) ++# define BN_MASK2h1 (0xffffffff80000000L) ++# define LBITS(a) ((a)&BN_MASK2l) ++# define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l) ++# define L2HBITS(a) (((a)< +Date: Wed, 9 Nov 2022 17:04:13 +0800 +Subject: [PATCH 07/22] [MULL64 2/3] Fold series of instructions into mul + + Merge the low part of series instructions into mul + + gcc/ + * match.pd: Add simplifcations for low part of mul + * common.opt: Add new option fmerge-mull enable with -O2 + * opts.c: default_options_table + + gcc/testsuite/ + * g++.dg/tree-ssa/mull64.C: New test. +--- + gcc/common.opt | 4 +++ + gcc/match.pd | 27 ++++++++++++++++++++ + gcc/opts.cc | 1 + + gcc/testsuite/g++.dg/tree-ssa/mull64.C | 34 ++++++++++++++++++++++++++ + 4 files changed, 66 insertions(+) + create mode 100644 gcc/testsuite/g++.dg/tree-ssa/mull64.C + +diff --git a/gcc/common.opt b/gcc/common.opt +index 8a0dafc52..e365a48bc 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -2126,6 +2126,10 @@ fmerge-debug-strings + Common Var(flag_merge_debug_strings) Init(1) + Attempt to merge identical debug strings across compilation units. + ++fmerge-mull ++Common Var(flag_merge_mull) Init(0) Optimization ++Attempt to merge series instructions into mul. ++ + fmessage-length= + Common RejectNegative Joined UInteger + -fmessage-length= Limit diagnostics to characters per line. 0 suppresses line-wrapping. +diff --git a/gcc/match.pd b/gcc/match.pd +index fd0857fc9..2092e6959 100644 +--- a/gcc/match.pd ++++ b/gcc/match.pd +@@ -4301,6 +4301,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) + ) + #endif + ++#if GIMPLE ++/* These patterns are mostly used by FORWPROP1 to fold some operations into more ++ simple IR. The following scenario should be matched: ++ In0Lo = In0(D) & 4294967295; ++ In0Hi = In0(D) >> 32; ++ In1Lo = In1(D) & 4294967295; ++ In1Hi = In1(D) >> 32; ++ Addc = In0Lo * In1Hi + In0Hi * In1Lo; ++ addc32 = Addc << 32; ++ ResLo = In0Lo * In1Lo + addc32 */ ++(simplify ++ (plus:c (mult @4 @5) ++ (lshift ++ (plus:c ++ (mult (bit_and@4 SSA_NAME@0 @2) (rshift SSA_NAME@1 @3)) ++ (mult (rshift SSA_NAME@0 @3) (bit_and@5 SSA_NAME@1 INTEGER_CST@2))) ++ INTEGER_CST@3 ++ ) ++ ) ++ (if (flag_merge_mull && INTEGRAL_TYPE_P (type) ++ && INTEGRAL_TYPE_P (TREE_TYPE (@0)) && types_match (@0, @1) ++ && TYPE_PRECISION (type) == 64) ++ (mult (convert:type @0) (convert:type @1)) ++ ) ++) ++#endif ++ + /* Simplification moved from fold_cond_expr_with_comparison. It may also + be extended. */ + /* This pattern implements two kinds simplification: +diff --git a/gcc/opts.cc b/gcc/opts.cc +index a97630d1c..eae71ed20 100644 +--- a/gcc/opts.cc ++++ b/gcc/opts.cc +@@ -647,6 +647,7 @@ static const struct default_options default_options_table[] = + 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 }, ++ { OPT_LEVELS_2_PLUS, OPT_fmerge_mull, NULL, 1 }, + + /* -O2 and above optimizations, but not -Os or -Og. */ + { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_functions, NULL, 1 }, +diff --git a/gcc/testsuite/g++.dg/tree-ssa/mull64.C b/gcc/testsuite/g++.dg/tree-ssa/mull64.C +new file mode 100644 +index 000000000..2a3b74604 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/tree-ssa/mull64.C +@@ -0,0 +1,34 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -Wno-psabi -fmerge-mull -fdump-tree-forwprop1-details" } */ ++ ++# define BN_BITS4 32 ++# define BN_MASK2 (0xffffffffffffffffL) ++# define BN_MASK2l (0xffffffffL) ++# define BN_MASK2h (0xffffffff00000000L) ++# define BN_MASK2h1 (0xffffffff80000000L) ++# define LBITS(a) ((a)&BN_MASK2l) ++# define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l) ++# define L2HBITS(a) (((a)< +Date: Fri, 11 Nov 2022 11:30:37 +0800 +Subject: [PATCH 08/22] [MULL64 3/3] Fold series of instructions into umulh + + Merge the high part of series instructions into umulh + + gcc/ + * match.pd: Add simplifcations for high part of umulh + + gcc/testsuite/ + * g++.dg/tree-ssa/mull64.C: Add checking of tree pass forwprop4 +--- + gcc/match.pd | 56 ++++++++++++++++++++++++++ + gcc/testsuite/g++.dg/tree-ssa/mull64.C | 5 ++- + 2 files changed, 59 insertions(+), 2 deletions(-) + +diff --git a/gcc/match.pd b/gcc/match.pd +index 2092e6959..b7e3588e8 100644 +--- a/gcc/match.pd ++++ b/gcc/match.pd +@@ -4301,6 +4301,62 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) + ) + #endif + ++#if GIMPLE ++/* These patterns are mostly used by FORWPROP4 to move some operations outside of ++ the if statements. They should be done late because it gives jump threading ++ and few other passes to reduce what is going on. */ ++/* Mul64 is defined as a multiplication algorithm which compute two 64-bit ++ integers to one 128-bit integer. Try to match the high part of mul pattern ++ after the low part of mul pattern is simplified. The following scenario ++ should be matched: ++ (i64 ResLo, i64 ResHi) = Mul64(i64 In0, i64 In1) { ++ In0Lo = In0(D) & 4294967295; -- bit_and@4 SSA_NAME@0 @2 ++ In0Hi = In0(D) >> 32; -- rshift@5 SSA_NAME@0 @3 ++ In1Lo = In1(D) & 4294967295; -- bit_and@6 SSA_NAME@1 INTEGER_CST@2 ++ In1Hi = In1(D) >> 32; -- rshift@7 SSA_NAME@1 INTEGER_CST@3 ++ Mull_01 = In0Hi * In1Lo; -- mult@8 @5 @6 ++ Addc = In0Lo * In1Hi + Mull_01; -- plus@9 (mult (@4 @7) @8 ++ AddH = (Addc >> 32) + In0Hi * In1Hi -- (plus@11 (rshift @9 @3) (mult @5 @7)) ++ addc32 = Addc << 32; -- lshift@10 @9 @3 ++ ResLo = In0(D) * In1(D); -- mult @0 @1 ++ ResHi = ((long unsigned int) (addc32 > ResLo)) + ++ (((long unsigned int) (Mull_01 > Addc)) << 32) + AddH; ++ } */ ++(simplify ++ (plus:c ++ (plus:c ++ (convert ++ (gt (lshift@10 @9 @3) ++ (mult:c @0 @1))) ++ (lshift ++ (convert ++ (gt @8 @9)) ++ @3)) ++ (plus:c@11 ++ (rshift ++ (plus:c@9 ++ (mult:c (bit_and@4 SSA_NAME@0 @2) @7) ++ (mult:c@8 @5 (bit_and@6 SSA_NAME@1 INTEGER_CST@2))) ++ @3) ++ (mult:c (rshift@5 SSA_NAME@0 @3) ++ (rshift@7 SSA_NAME@1 INTEGER_CST@3)) ++ ) ++ ) ++ (if (flag_merge_mull && INTEGRAL_TYPE_P (type) ++ && INTEGRAL_TYPE_P (TREE_TYPE (@0)) && types_match (@0, @1) ++ && TYPE_PRECISION (type) == 64) ++ (with { ++ tree i128_type = build_nonstandard_integer_type (128, TYPE_UNSIGNED (type)); ++ tree shift = build_int_cst (integer_type_node, 64); ++ } ++ (convert:type (rshift ++ (mult (convert:i128_type @0) ++ (convert:i128_type @1)) ++ { shift; }))) ++ ) ++) ++#endif ++ + #if GIMPLE + /* These patterns are mostly used by FORWPROP1 to fold some operations into more + simple IR. The following scenario should be matched: +diff --git a/gcc/testsuite/g++.dg/tree-ssa/mull64.C b/gcc/testsuite/g++.dg/tree-ssa/mull64.C +index 2a3b74604..f61cf5e6f 100644 +--- a/gcc/testsuite/g++.dg/tree-ssa/mull64.C ++++ b/gcc/testsuite/g++.dg/tree-ssa/mull64.C +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-O2 -Wno-psabi -fmerge-mull -fdump-tree-forwprop1-details" } */ ++/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1-details -fdump-tree-forwprop4-details" } */ + + # define BN_BITS4 32 + # define BN_MASK2 (0xffffffffffffffffL) +@@ -31,4 +31,5 @@ void mul64(unsigned long in0, unsigned long in1, + retHi = m11; + } + +-/* { dg-final { scan-tree-dump "gimple_simplified to low_18 = in0_4" "forwprop1" } } */ ++/* { dg-final { scan-tree-dump "gimple_simplified to" "forwprop1" } } */ ++/* { dg-final { scan-tree-dump-times "gimple_simplified to" 1 "forwprop4" } } */ +-- +2.33.0 + diff --git a/0009-MULL64-Disable-mull64-transformation-by-default.patch b/0009-MULL64-Disable-mull64-transformation-by-default.patch new file mode 100644 index 0000000..347ba0a --- /dev/null +++ b/0009-MULL64-Disable-mull64-transformation-by-default.patch @@ -0,0 +1,66 @@ +From 7c1f4425c680ea144d29bc55a1283d46444a2691 Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Wed, 7 Dec 2022 09:43:15 +0800 +Subject: [PATCH 09/22] [MULL64] Disable mull64 transformation by default + +This commit disables mull64 transformation by default since +it shows some runtime failure in workloads. + +This is a workaround fix for https://gitee.com/src-openeuler/gcc/issues/I64UQH +--- + gcc/match.pd | 2 +- + gcc/opts.cc | 1 - + gcc/testsuite/g++.dg/tree-ssa/mull64.C | 2 +- + gcc/testsuite/gcc.dg/pr107190.c | 2 +- + 4 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/gcc/match.pd b/gcc/match.pd +index b7e3588e8..6f24d5079 100644 +--- a/gcc/match.pd ++++ b/gcc/match.pd +@@ -4290,7 +4290,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) + (simplify + (cond @0 (op:s @1 integer_pow2p@2) @1) + /* powerof2cst */ +- (if (INTEGRAL_TYPE_P (type)) ++ (if (flag_merge_mull && INTEGRAL_TYPE_P (type)) + (with { + tree shift = build_int_cst (integer_type_node, tree_log2 (@2)); + } +diff --git a/gcc/opts.cc b/gcc/opts.cc +index eae71ed20..a97630d1c 100644 +--- a/gcc/opts.cc ++++ b/gcc/opts.cc +@@ -647,7 +647,6 @@ static const struct default_options default_options_table[] = + 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 }, +- { OPT_LEVELS_2_PLUS, OPT_fmerge_mull, NULL, 1 }, + + /* -O2 and above optimizations, but not -Os or -Og. */ + { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_functions, NULL, 1 }, +diff --git a/gcc/testsuite/g++.dg/tree-ssa/mull64.C b/gcc/testsuite/g++.dg/tree-ssa/mull64.C +index f61cf5e6f..cad891e62 100644 +--- a/gcc/testsuite/g++.dg/tree-ssa/mull64.C ++++ b/gcc/testsuite/g++.dg/tree-ssa/mull64.C +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1-details -fdump-tree-forwprop4-details" } */ ++/* { dg-options "-O2 -fmerge-mull -Wno-psabi -fdump-tree-forwprop1-details -fdump-tree-forwprop4-details" } */ + + # define BN_BITS4 32 + # define BN_MASK2 (0xffffffffffffffffL) +diff --git a/gcc/testsuite/gcc.dg/pr107190.c b/gcc/testsuite/gcc.dg/pr107190.c +index 235b2761a..d1e72e5df 100644 +--- a/gcc/testsuite/gcc.dg/pr107190.c ++++ b/gcc/testsuite/gcc.dg/pr107190.c +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-O2 -fexpensive-optimizations -fdump-tree-phiopt2-details" } */ ++/* { dg-options "-O2 -fmerge-mull -fexpensive-optimizations -fdump-tree-phiopt2-details" } */ + + # define BN_BITS4 32 + # define BN_MASK2 (0xffffffffffffffffL) +-- +2.33.0 + diff --git a/0010-Version-Clear-DATESTAMP_s.patch b/0010-Version-Clear-DATESTAMP_s.patch new file mode 100644 index 0000000..e4c480f --- /dev/null +++ b/0010-Version-Clear-DATESTAMP_s.patch @@ -0,0 +1,26 @@ +From 8e8f783b02df155e3aafa94af6cc1f66604e08eb Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Fri, 21 Jul 2023 14:45:27 +0800 +Subject: [PATCH 10/22] [Version] Clear DATESTAMP_s + +--- + gcc/Makefile.in | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 31ff95500..db2a0e1bd 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -897,8 +897,7 @@ PATCHLEVEL_c := \ + # significant - do not remove it. + BASEVER_s := "\"$(BASEVER_c)\"" + DEVPHASE_s := "\"$(if $(DEVPHASE_c), ($(DEVPHASE_c)))\"" +-DATESTAMP_s := \ +- "\"$(if $(DEVPHASE_c)$(filter-out 0,$(PATCHLEVEL_c)), $(DATESTAMP_c))\"" ++DATESTAMP_s := "\"\"" + PKGVERSION_s:= "\"@PKGVERSION@\"" + BUGURL_s := "\"@REPORT_BUGS_TO@\"" + +-- +2.33.0 + diff --git a/0011-Add-attribute-hot-judgement-for-INLINE_HINT_known_ho.patch b/0011-Add-attribute-hot-judgement-for-INLINE_HINT_known_ho.patch new file mode 100644 index 0000000..f3add4c --- /dev/null +++ b/0011-Add-attribute-hot-judgement-for-INLINE_HINT_known_ho.patch @@ -0,0 +1,124 @@ +From 355eb8e20327242442d139fb052d3a3befde3dd7 Mon Sep 17 00:00:00 2001 +From: "Cui,Lili" +Date: Tue, 1 Nov 2022 09:16:49 +0800 +Subject: [PATCH 11/22] Add attribute hot judgement for INLINE_HINT_known_hot + hint. + +We set up INLINE_HINT_known_hot hint only when we have profile feedback, +now add function attribute judgement for it, when both caller and callee +have __attribute__((hot)), we will also set up INLINE_HINT_known_hot hint +for it. + +With this patch applied, +ADL Multi-copy: 538.imagic_r 16.7% +ICX Multi-copy: 538.imagic_r 15.2% +CLX Multi-copy: 538.imagic_r 12.7% +Znver3 Multi-copy: 538.imagic_r 10.6% +Arm Multi-copy: 538.imagic_r 13.4% + +gcc/ChangeLog + + * ipa-inline-analysis.cc (do_estimate_edge_time): Add function attribute + judgement for INLINE_HINT_known_hot hint. + +gcc/testsuite/ChangeLog: + + * gcc.dg/ipa/inlinehint-6.c: New test. +--- + gcc/ipa-inline-analysis.cc | 13 ++++--- + gcc/testsuite/gcc.dg/ipa/inlinehint-6.c | 47 +++++++++++++++++++++++++ + 2 files changed, 56 insertions(+), 4 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/ipa/inlinehint-6.c + +diff --git a/gcc/ipa-inline-analysis.cc b/gcc/ipa-inline-analysis.cc +index 11d8d09ee..16ac24cfc 100644 +--- a/gcc/ipa-inline-analysis.cc ++++ b/gcc/ipa-inline-analysis.cc +@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see + #include "ipa-utils.h" + #include "cfgexpand.h" + #include "gimplify.h" ++#include "attribs.h" + + /* Cached node/edge growths. */ + fast_call_summary *edge_growth_cache = NULL; +@@ -249,15 +250,19 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) + hints = estimates.hints; + } + +- /* When we have profile feedback, we can quite safely identify hot +- edges and for those we disable size limits. Don't do that when +- probability that caller will call the callee is low however, since it ++ /* When we have profile feedback or function attribute, we can quite safely ++ identify hot edges and for those we disable size limits. Don't do that ++ when probability that caller will call the callee is low however, since it + may hurt optimization of the caller's hot path. */ +- if (edge->count.ipa ().initialized_p () && edge->maybe_hot_p () ++ if ((edge->count.ipa ().initialized_p () && edge->maybe_hot_p () + && (edge->count.ipa ().apply_scale (2, 1) + > (edge->caller->inlined_to + ? edge->caller->inlined_to->count.ipa () + : edge->caller->count.ipa ()))) ++ || (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl)) ++ != NULL ++ && lookup_attribute ("hot", DECL_ATTRIBUTES (edge->callee->decl)) ++ != NULL)) + hints |= INLINE_HINT_known_hot; + + gcc_checking_assert (size >= 0); +diff --git a/gcc/testsuite/gcc.dg/ipa/inlinehint-6.c b/gcc/testsuite/gcc.dg/ipa/inlinehint-6.c +new file mode 100644 +index 000000000..1f3be641c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/ipa/inlinehint-6.c +@@ -0,0 +1,47 @@ ++/* { dg-options "-O3 -c -fdump-ipa-inline-details -fno-early-inlining -fno-ipa-cp" } */ ++/* { dg-add-options bind_pic_locally } */ ++ ++#define size_t long long int ++ ++struct A ++{ ++ size_t f1, f2, f3, f4; ++}; ++struct C ++{ ++ struct A a; ++ size_t b; ++}; ++struct C x; ++ ++__attribute__((hot)) struct C callee (struct A *a, struct C *c) ++{ ++ c->a=(*a); ++ ++ if((c->b + 7) & 17) ++ { ++ c->a.f1 = c->a.f2 + c->a.f1; ++ c->a.f2 = c->a.f3 - c->a.f2; ++ c->a.f3 = c->a.f2 + c->a.f3; ++ c->a.f4 = c->a.f2 - c->a.f4; ++ c->b = c->a.f2; ++ ++ } ++ return *c; ++} ++ ++__attribute__((hot)) struct C caller (size_t d, size_t e, size_t f, size_t g, struct C *c) ++{ ++ struct A a; ++ a.f1 = 1 + d; ++ a.f2 = e; ++ a.f3 = 12 + f; ++ a.f4 = 68 + g; ++ if (c->b > 0) ++ return callee (&a, c); ++ else ++ return *c; ++} ++ ++/* { dg-final { scan-ipa-dump "known_hot" "inline" } } */ ++ +-- +2.33.0 + diff --git a/0012-Enable-small-loop-unrolling-for-O2.patch b/0012-Enable-small-loop-unrolling-for-O2.patch new file mode 100644 index 0000000..97ca890 --- /dev/null +++ b/0012-Enable-small-loop-unrolling-for-O2.patch @@ -0,0 +1,490 @@ +From 1070bc24f53e851cae55320e26715cc594efcd2f Mon Sep 17 00:00:00 2001 +From: Hongyu Wang +Date: Thu, 8 Sep 2022 16:52:02 +0800 +Subject: [PATCH 12/22] Enable small loop unrolling for O2 + +Modern processors has multiple way instruction decoders +For x86, icelake/zen3 has 5 uops, so for small loop with <= 4 +instructions (usually has 3 uops with a cmp/jmp pair that can be +macro-fused), the decoder would have 2 uops bubble for each iteration +and the pipeline could not be fully utilized. + +Therefore, this patch enables loop unrolling for small size loop at O2 +to fullfill the decoder as much as possible. It turns on rtl loop +unrolling when targetm.loop_unroll_adjust exists and O2 plus speed only. +In x86 backend the default behavior is to unroll small loops with less +than 4 insns by 1 time. + +This improves 548.exchange2 by 9% on icelake and 7.4% on zen3 with +0.9% codesize increment. For other benchmarks the variants are minor +and overall codesize increased by 0.2%. + +The kernel image size increased by 0.06%, and no impact on eembc. + +gcc/ChangeLog: + + * common/config/i386/i386-common.cc (ix86_optimization_table): + Enable small loop unroll at O2 by default. + * config/i386/i386.cc (ix86_loop_unroll_adjust): Adjust unroll + factor if -munroll-only-small-loops enabled and -funroll-loops/ + -funroll-all-loops are disabled. + * config/i386/i386.h (struct processor_costs): Add 2 field + small_unroll_ninsns and small_unroll_factor. + * config/i386/i386.opt: Add -munroll-only-small-loops. + * doc/invoke.texi: Document -munroll-only-small-loops. + * loop-init.cc (pass_rtl_unroll_loops::gate): Enable rtl + loop unrolling for -O2-speed and above if target hook + loop_unroll_adjust exists. + (pass_rtl_unroll_loops::execute): Set UAP_UNROLL flag + when target hook loop_unroll_adjust exists. + * config/i386/x86-tune-costs.h: Update all processor costs + with small_unroll_ninsns = 4 and small_unroll_factor = 2. + +gcc/testsuite/ChangeLog: + + * gcc.dg/guality/loop-1.c: Add additional option + -mno-unroll-only-small-loops. + * gcc.target/i386/pr86270.c: Add -mno-unroll-only-small-loops. + * gcc.target/i386/pr93002.c: Likewise. +--- + gcc/common/config/i386/i386-common.cc | 1 + + gcc/config/i386/i386.cc | 18 ++++++++ + gcc/config/i386/i386.h | 5 +++ + gcc/config/i386/i386.opt | 4 ++ + gcc/config/i386/x86-tune-costs.h | 58 +++++++++++++++++++++++++ + gcc/doc/invoke.texi | 11 ++++- + gcc/loop-init.cc | 10 +++-- + gcc/testsuite/gcc.dg/guality/loop-1.c | 2 + + gcc/testsuite/gcc.target/i386/pr86270.c | 2 +- + gcc/testsuite/gcc.target/i386/pr93002.c | 2 +- + 10 files changed, 107 insertions(+), 6 deletions(-) + +diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc +index e2594cae4..cdd5caa55 100644 +--- a/gcc/common/config/i386/i386-common.cc ++++ b/gcc/common/config/i386/i386-common.cc +@@ -1687,6 +1687,7 @@ static const struct default_options ix86_option_optimization_table[] = + /* The STC algorithm produces the smallest code at -Os, for x86. */ + { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_algorithm_, NULL, + REORDER_BLOCKS_ALGORITHM_STC }, ++ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_munroll_only_small_loops, NULL, 1 }, + /* Turn off -fschedule-insns by default. It tends to make the + problem with not enough registers even worse. */ + { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 }, +diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc +index 9a9ff3b34..e56004300 100644 +--- a/gcc/config/i386/i386.cc ++++ b/gcc/config/i386/i386.cc +@@ -23570,6 +23570,24 @@ ix86_loop_unroll_adjust (unsigned nunroll, class loop *loop) + unsigned i; + unsigned mem_count = 0; + ++ /* Unroll small size loop when unroll factor is not explicitly ++ specified. */ ++ if (!(flag_unroll_loops ++ || flag_unroll_all_loops ++ || loop->unroll)) ++ { ++ nunroll = 1; ++ ++ /* Any explicit -f{no-}unroll-{all-}loops turns off ++ -munroll-only-small-loops. */ ++ if (ix86_unroll_only_small_loops ++ && !OPTION_SET_P (flag_unroll_loops) ++ && loop->ninsns <= ix86_cost->small_unroll_ninsns) ++ nunroll = ix86_cost->small_unroll_factor; ++ ++ return nunroll; ++ } ++ + if (!TARGET_ADJUST_UNROLL) + return nunroll; + +diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h +index fce0b3564..688aaabd3 100644 +--- a/gcc/config/i386/i386.h ++++ b/gcc/config/i386/i386.h +@@ -219,6 +219,11 @@ struct processor_costs { + const char *const align_jump; /* Jump alignment. */ + const char *const align_label; /* Label alignment. */ + const char *const align_func; /* Function alignment. */ ++ ++ const unsigned small_unroll_ninsns; /* Insn count limit for small loop ++ to be unrolled. */ ++ const unsigned small_unroll_factor; /* Unroll factor for small loop to ++ be unrolled. */ + }; + + extern const struct processor_costs *ix86_cost; +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt +index a3675e515..fc1b944ac 100644 +--- a/gcc/config/i386/i386.opt ++++ b/gcc/config/i386/i386.opt +@@ -1214,3 +1214,7 @@ Do not use GOT to access external symbols. + -param=x86-stlf-window-ninsns= + Target Joined UInteger Var(x86_stlf_window_ninsns) Init(64) Param + Instructions number above which STFL stall penalty can be compensated. ++ ++munroll-only-small-loops ++Target Var(ix86_unroll_only_small_loops) Init(0) Save ++Enable conservative small loop unrolling. +diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h +index f105d57ca..db4c2da34 100644 +--- a/gcc/config/i386/x86-tune-costs.h ++++ b/gcc/config/i386/x86-tune-costs.h +@@ -135,6 +135,8 @@ struct processor_costs ix86_size_cost = {/* costs for tuning for size */ + NULL, /* Jump alignment. */ + NULL, /* Label alignment. */ + NULL, /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* Processor costs (relative to an add) */ +@@ -244,6 +246,8 @@ struct processor_costs i386_cost = { /* 386 specific costs */ + "4", /* Jump alignment. */ + NULL, /* Label alignment. */ + "4", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs i486_memcpy[2] = { +@@ -354,6 +358,8 @@ struct processor_costs i486_cost = { /* 486 specific costs */ + "16", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs pentium_memcpy[2] = { +@@ -462,6 +468,8 @@ struct processor_costs pentium_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static const +@@ -563,6 +571,8 @@ struct processor_costs lakemont_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* PentiumPro has optimized rep instructions for blocks aligned by 8 bytes +@@ -679,6 +689,8 @@ struct processor_costs pentiumpro_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs geode_memcpy[2] = { +@@ -786,6 +798,8 @@ struct processor_costs geode_cost = { + NULL, /* Jump alignment. */ + NULL, /* Label alignment. */ + NULL, /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs k6_memcpy[2] = { +@@ -896,6 +910,8 @@ struct processor_costs k6_cost = { + "32:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "32", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* For some reason, Athlon deals better with REP prefix (relative to loops) +@@ -1007,6 +1023,8 @@ struct processor_costs athlon_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* K8 has optimized REP instruction for medium sized blocks, but for very +@@ -1127,6 +1145,8 @@ struct processor_costs k8_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* AMDFAM10 has optimized REP instruction for medium sized blocks, but for +@@ -1255,6 +1275,8 @@ struct processor_costs amdfam10_cost = { + "32:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "32", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* BDVER has optimized REP instruction for medium sized blocks, but for +@@ -1376,6 +1398,8 @@ const struct processor_costs bdver_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "11", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + +@@ -1529,6 +1553,8 @@ struct processor_costs znver1_cost = { + "16", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* ZNVER2 has optimized REP instruction for medium sized blocks, but for +@@ -1686,6 +1712,8 @@ struct processor_costs znver2_cost = { + "16", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + struct processor_costs znver3_cost = { +@@ -1818,6 +1846,8 @@ struct processor_costs znver3_cost = { + "16", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* This table currently replicates znver3_cost table. */ +@@ -1952,6 +1982,8 @@ struct processor_costs znver4_cost = { + "16", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* skylake_cost should produce code tuned for Skylake familly of CPUs. */ +@@ -2076,6 +2108,8 @@ struct processor_costs skylake_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* icelake_cost should produce code tuned for Icelake family of CPUs. +@@ -2202,6 +2236,8 @@ struct processor_costs icelake_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* alderlake_cost should produce code tuned for alderlake family of CPUs. */ +@@ -2322,6 +2358,8 @@ struct processor_costs alderlake_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* BTVER1 has optimized REP instruction for medium sized blocks, but for +@@ -2435,6 +2473,8 @@ const struct processor_costs btver1_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "11", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs btver2_memcpy[2] = { +@@ -2545,6 +2585,8 @@ const struct processor_costs btver2_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "11", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs pentium4_memcpy[2] = { +@@ -2654,6 +2696,8 @@ struct processor_costs pentium4_cost = { + NULL, /* Jump alignment. */ + NULL, /* Label alignment. */ + NULL, /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs nocona_memcpy[2] = { +@@ -2766,6 +2810,8 @@ struct processor_costs nocona_cost = { + NULL, /* Jump alignment. */ + NULL, /* Label alignment. */ + NULL, /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs atom_memcpy[2] = { +@@ -2876,6 +2922,8 @@ struct processor_costs atom_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs slm_memcpy[2] = { +@@ -2986,6 +3034,8 @@ struct processor_costs slm_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs tremont_memcpy[2] = { +@@ -3110,6 +3160,8 @@ struct processor_costs tremont_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + static stringop_algs intel_memcpy[2] = { +@@ -3220,6 +3272,8 @@ struct processor_costs intel_cost = { + "16:8:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* Generic should produce code tuned for Core-i7 (and newer chips) +@@ -3339,6 +3393,8 @@ struct processor_costs generic_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + + /* core_cost should produce code tuned for Core familly of CPUs. */ +@@ -3465,5 +3521,7 @@ struct processor_costs core_cost = { + "16:11:8", /* Jump alignment. */ + "0:0:8", /* Label alignment. */ + "16", /* Func alignment. */ ++ 4, /* Small unroll limit. */ ++ 2, /* Small unroll factor. */ + }; + +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index ff8cd032f..16f4b367e 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -1449,7 +1449,8 @@ See RS/6000 and PowerPC Options. + -mgeneral-regs-only -mcall-ms2sysv-xlogues -mrelax-cmpxchg-loop @gol + -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol + -mindirect-branch-register -mharden-sls=@var{choice} @gol +--mindirect-branch-cs-prefix -mneeded -mno-direct-extern-access} ++-mindirect-branch-cs-prefix -mneeded -mno-direct-extern-access @gol ++-munroll-only-small-loops} + + @emph{x86 Windows Options} + @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol +@@ -33183,6 +33184,14 @@ treat access to protected symbols as local symbols. The default is + @option{-mno-direct-extern-access} and executable compiled with + @option{-mdirect-extern-access} may not be binary compatible if + protected symbols are used in shared libraries and executable. ++ ++@item -munroll-only-small-loops ++@opindex munroll-only-small-loops ++@opindex mno-unroll-only-small-loops ++Controls conservative small loop unrolling. It is default enabled by ++O2, and unrolls loop with less than 4 insns by 1 time. Explicit ++-f[no-]unroll-[all-]loops would disable this flag to avoid any ++unintended unrolling behavior that user does not want. + @end table + + @node x86 Windows Options +diff --git a/gcc/loop-init.cc b/gcc/loop-init.cc +index 1e4f6cfd7..f1c717041 100644 +--- a/gcc/loop-init.cc ++++ b/gcc/loop-init.cc +@@ -565,9 +565,12 @@ public: + {} + + /* opt_pass methods: */ +- virtual bool gate (function *) ++ virtual bool gate (function *fun) + { +- return (flag_unroll_loops || flag_unroll_all_loops || cfun->has_unroll); ++ return (flag_unroll_loops || flag_unroll_all_loops || cfun->has_unroll ++ || (targetm.loop_unroll_adjust ++ && optimize >= 2 ++ && optimize_function_for_speed_p (fun))); + } + + virtual unsigned int execute (function *); +@@ -583,7 +586,8 @@ pass_rtl_unroll_loops::execute (function *fun) + if (dump_file) + df_dump (dump_file); + +- if (flag_unroll_loops) ++ if (flag_unroll_loops ++ || targetm.loop_unroll_adjust) + flags |= UAP_UNROLL; + if (flag_unroll_all_loops) + flags |= UAP_UNROLL_ALL; +diff --git a/gcc/testsuite/gcc.dg/guality/loop-1.c b/gcc/testsuite/gcc.dg/guality/loop-1.c +index 1b1f6d322..a32ea445a 100644 +--- a/gcc/testsuite/gcc.dg/guality/loop-1.c ++++ b/gcc/testsuite/gcc.dg/guality/loop-1.c +@@ -1,5 +1,7 @@ + /* { dg-do run } */ + /* { dg-options "-fno-tree-scev-cprop -fno-tree-vectorize -g" } */ ++/* { dg-additional-options "-mno-unroll-only-small-loops" { target ia32 } } */ ++ + + #include "../nop.h" + +diff --git a/gcc/testsuite/gcc.target/i386/pr86270.c b/gcc/testsuite/gcc.target/i386/pr86270.c +index 81841ef5b..cbc9fbb04 100644 +--- a/gcc/testsuite/gcc.target/i386/pr86270.c ++++ b/gcc/testsuite/gcc.target/i386/pr86270.c +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-O2" } */ ++/* { dg-options "-O2 -mno-unroll-only-small-loops" } */ + + int *a; + long len; +diff --git a/gcc/testsuite/gcc.target/i386/pr93002.c b/gcc/testsuite/gcc.target/i386/pr93002.c +index 0248fcc00..f75a847f7 100644 +--- a/gcc/testsuite/gcc.target/i386/pr93002.c ++++ b/gcc/testsuite/gcc.target/i386/pr93002.c +@@ -1,6 +1,6 @@ + /* PR target/93002 */ + /* { dg-do compile } */ +-/* { dg-options "-O2" } */ ++/* { dg-options "-O2 -mno-unroll-only-small-loops" } */ + /* { dg-final { scan-assembler-not "cmp\[^\n\r]*-1" } } */ + + volatile int sink; +-- +2.33.0 + diff --git a/0013-i386-Only-enable-small-loop-unrolling-in-backend-PR-.patch b/0013-i386-Only-enable-small-loop-unrolling-in-backend-PR-.patch new file mode 100644 index 0000000..6f89af0 --- /dev/null +++ b/0013-i386-Only-enable-small-loop-unrolling-in-backend-PR-.patch @@ -0,0 +1,230 @@ +From 96898a9cd8c159625848247bd2f3a09e5c12fcfa Mon Sep 17 00:00:00 2001 +From: Hongyu Wang +Date: Sat, 19 Nov 2022 09:38:00 +0800 +Subject: [PATCH 13/22] i386: Only enable small loop unrolling in backend [PR + 107692] + +Followed by the discussion in pr107692, -munroll-only-small-loops +Does not turns on/off -funroll-loops, and current check in +pass_rtl_unroll_loops::gate would cause -fno-unroll-loops do not take +effect. Revert the change about targetm.loop_unroll_adjust and apply +the backend option change to strictly follow the rule that +-funroll-loops takes full control of loop unrolling, and +munroll-only-small-loops just change its behavior to unroll small size +loops. + +gcc/ChangeLog: + + PR target/107692 + * common/config/i386/i386-common.cc (ix86_optimization_table): + Enable loop unroll O2, disable -fweb and -frename-registers + by default. + * config/i386/i386-options.cc + (ix86_override_options_after_change): + Disable small loop unroll when funroll-loops enabled, reset + cunroll_grow_size when it is not explicitly enabled. + (ix86_option_override_internal): Call + ix86_override_options_after_change instead of calling + ix86_recompute_optlev_based_flags and ix86_default_align + separately. + * config/i386/i386.cc (ix86_loop_unroll_adjust): Adjust unroll + factor if -munroll-only-small-loops enabled. + * loop-init.cc (pass_rtl_unroll_loops::gate): Do not enable + loop unrolling for -O2-speed. + (pass_rtl_unroll_loops::execute): Rmove + targetm.loop_unroll_adjust check. + +gcc/testsuite/ChangeLog: + + PR target/107692 + * gcc.dg/guality/loop-1.c: Remove additional option for ia32. + * gcc.target/i386/pr86270.c: Add -fno-unroll-loops. + * gcc.target/i386/pr93002.c: Likewise. +--- + gcc/common/config/i386/i386-common.cc | 8 ++++++ + gcc/config/i386/i386-options.cc | 34 ++++++++++++++++++++++--- + gcc/config/i386/i386.cc | 18 ++++--------- + gcc/loop-init.cc | 10 +++----- + gcc/testsuite/gcc.dg/guality/loop-1.c | 2 -- + gcc/testsuite/gcc.target/i386/pr86270.c | 2 +- + gcc/testsuite/gcc.target/i386/pr93002.c | 2 +- + 7 files changed, 48 insertions(+), 28 deletions(-) + +diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc +index cdd5caa55..f650e255f 100644 +--- a/gcc/common/config/i386/i386-common.cc ++++ b/gcc/common/config/i386/i386-common.cc +@@ -1687,7 +1687,15 @@ static const struct default_options ix86_option_optimization_table[] = + /* The STC algorithm produces the smallest code at -Os, for x86. */ + { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_algorithm_, NULL, + REORDER_BLOCKS_ALGORITHM_STC }, ++ ++ /* Turn on -funroll-loops with -munroll-only-small-loops to enable small ++ loop unrolling at -O2. */ ++ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_funroll_loops, NULL, 1 }, + { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_munroll_only_small_loops, NULL, 1 }, ++ /* Turns off -frename-registers and -fweb which are enabled by ++ funroll-loops. */ ++ { OPT_LEVELS_ALL, OPT_frename_registers, NULL, 0 }, ++ { OPT_LEVELS_ALL, OPT_fweb, NULL, 0 }, + /* Turn off -fschedule-insns by default. It tends to make the + problem with not enough registers even worse. */ + { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 }, +diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc +index 099cec4b6..ff44ad4e0 100644 +--- a/gcc/config/i386/i386-options.cc ++++ b/gcc/config/i386/i386-options.cc +@@ -1816,8 +1816,37 @@ ix86_recompute_optlev_based_flags (struct gcc_options *opts, + void + ix86_override_options_after_change (void) + { ++ /* Default align_* from the processor table. */ + ix86_default_align (&global_options); ++ + ix86_recompute_optlev_based_flags (&global_options, &global_options_set); ++ ++ /* Disable unrolling small loops when there's explicit ++ -f{,no}unroll-loop. */ ++ if ((OPTION_SET_P (flag_unroll_loops)) ++ || (OPTION_SET_P (flag_unroll_all_loops) ++ && flag_unroll_all_loops)) ++ { ++ if (!OPTION_SET_P (ix86_unroll_only_small_loops)) ++ ix86_unroll_only_small_loops = 0; ++ /* Re-enable -frename-registers and -fweb if funroll-loops ++ enabled. */ ++ if (!OPTION_SET_P (flag_web)) ++ flag_web = flag_unroll_loops; ++ if (!OPTION_SET_P (flag_rename_registers)) ++ flag_rename_registers = flag_unroll_loops; ++ /* -fcunroll-grow-size default follws -f[no]-unroll-loops. */ ++ if (!OPTION_SET_P (flag_cunroll_grow_size)) ++ flag_cunroll_grow_size = flag_unroll_loops ++ || flag_peel_loops ++ || optimize >= 3; ++ } ++ else ++ { ++ if (!OPTION_SET_P (flag_cunroll_grow_size)) ++ flag_cunroll_grow_size = flag_peel_loops || optimize >= 3; ++ } ++ + } + + /* Clear stack slot assignments remembered from previous functions. +@@ -2329,7 +2358,7 @@ ix86_option_override_internal (bool main_args_p, + + set_ix86_tune_features (opts, ix86_tune, opts->x_ix86_dump_tunes); + +- ix86_recompute_optlev_based_flags (opts, opts_set); ++ ix86_override_options_after_change (); + + ix86_tune_cost = processor_cost_table[ix86_tune]; + /* TODO: ix86_cost should be chosen at instruction or function granuality +@@ -2360,9 +2389,6 @@ ix86_option_override_internal (bool main_args_p, + || TARGET_64BIT_P (opts->x_ix86_isa_flags)) + opts->x_ix86_regparm = REGPARM_MAX; + +- /* Default align_* from the processor table. */ +- ix86_default_align (opts); +- + /* Provide default for -mbranch-cost= value. */ + SET_OPTION_IF_UNSET (opts, opts_set, ix86_branch_cost, + ix86_tune_cost->branch_cost); +diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc +index e56004300..462dce10e 100644 +--- a/gcc/config/i386/i386.cc ++++ b/gcc/config/i386/i386.cc +@@ -23572,20 +23572,12 @@ ix86_loop_unroll_adjust (unsigned nunroll, class loop *loop) + + /* Unroll small size loop when unroll factor is not explicitly + specified. */ +- if (!(flag_unroll_loops +- || flag_unroll_all_loops +- || loop->unroll)) ++ if (ix86_unroll_only_small_loops && !loop->unroll) + { +- nunroll = 1; +- +- /* Any explicit -f{no-}unroll-{all-}loops turns off +- -munroll-only-small-loops. */ +- if (ix86_unroll_only_small_loops +- && !OPTION_SET_P (flag_unroll_loops) +- && loop->ninsns <= ix86_cost->small_unroll_ninsns) +- nunroll = ix86_cost->small_unroll_factor; +- +- return nunroll; ++ if (loop->ninsns <= ix86_cost->small_unroll_ninsns) ++ return MIN (nunroll, ix86_cost->small_unroll_factor); ++ else ++ return 1; + } + + if (!TARGET_ADJUST_UNROLL) +diff --git a/gcc/loop-init.cc b/gcc/loop-init.cc +index f1c717041..1e4f6cfd7 100644 +--- a/gcc/loop-init.cc ++++ b/gcc/loop-init.cc +@@ -565,12 +565,9 @@ public: + {} + + /* opt_pass methods: */ +- virtual bool gate (function *fun) ++ virtual bool gate (function *) + { +- return (flag_unroll_loops || flag_unroll_all_loops || cfun->has_unroll +- || (targetm.loop_unroll_adjust +- && optimize >= 2 +- && optimize_function_for_speed_p (fun))); ++ return (flag_unroll_loops || flag_unroll_all_loops || cfun->has_unroll); + } + + virtual unsigned int execute (function *); +@@ -586,8 +583,7 @@ pass_rtl_unroll_loops::execute (function *fun) + if (dump_file) + df_dump (dump_file); + +- if (flag_unroll_loops +- || targetm.loop_unroll_adjust) ++ if (flag_unroll_loops) + flags |= UAP_UNROLL; + if (flag_unroll_all_loops) + flags |= UAP_UNROLL_ALL; +diff --git a/gcc/testsuite/gcc.dg/guality/loop-1.c b/gcc/testsuite/gcc.dg/guality/loop-1.c +index a32ea445a..1b1f6d322 100644 +--- a/gcc/testsuite/gcc.dg/guality/loop-1.c ++++ b/gcc/testsuite/gcc.dg/guality/loop-1.c +@@ -1,7 +1,5 @@ + /* { dg-do run } */ + /* { dg-options "-fno-tree-scev-cprop -fno-tree-vectorize -g" } */ +-/* { dg-additional-options "-mno-unroll-only-small-loops" { target ia32 } } */ +- + + #include "../nop.h" + +diff --git a/gcc/testsuite/gcc.target/i386/pr86270.c b/gcc/testsuite/gcc.target/i386/pr86270.c +index cbc9fbb04..98b012caf 100644 +--- a/gcc/testsuite/gcc.target/i386/pr86270.c ++++ b/gcc/testsuite/gcc.target/i386/pr86270.c +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-O2 -mno-unroll-only-small-loops" } */ ++/* { dg-options "-O2 -fno-unroll-loops" } */ + + int *a; + long len; +diff --git a/gcc/testsuite/gcc.target/i386/pr93002.c b/gcc/testsuite/gcc.target/i386/pr93002.c +index f75a847f7..7e2d869e1 100644 +--- a/gcc/testsuite/gcc.target/i386/pr93002.c ++++ b/gcc/testsuite/gcc.target/i386/pr93002.c +@@ -1,6 +1,6 @@ + /* PR target/93002 */ + /* { dg-do compile } */ +-/* { dg-options "-O2 -mno-unroll-only-small-loops" } */ ++/* { dg-options "-O2 -fno-unroll-loops" } */ + /* { dg-final { scan-assembler-not "cmp\[^\n\r]*-1" } } */ + + volatile int sink; +-- +2.33.0 + diff --git a/0014-Array-widen-compare-Add-a-new-optimization-for-array.patch b/0014-Array-widen-compare-Add-a-new-optimization-for-array.patch new file mode 100644 index 0000000..182560e --- /dev/null +++ b/0014-Array-widen-compare-Add-a-new-optimization-for-array.patch @@ -0,0 +1,1981 @@ +From 5ef5f6c4ae806f56ff81450c759f36d59b5b23db Mon Sep 17 00:00:00 2001 +From: dingguangya +Date: Sat, 29 Jul 2023 17:45:01 +0800 +Subject: [PATCH 14/22] [Array-widen-compare] Add a new optimization for array + comparison scenarios + +Add option farray-widen-compare. +For an array pointer whose element is a single-byte type, +by changing the pointer type to a long-byte type, the elements +can be combined and compared after loading. +--- + gcc/Makefile.in | 1 + + gcc/common.opt | 5 + + gcc/doc/invoke.texi | 13 +- + gcc/passes.def | 1 + + .../gcc.dg/tree-ssa/awiden-compare-1.c | 19 + + .../gcc.dg/tree-ssa/awiden-compare-2.c | 90 + + .../gcc.dg/tree-ssa/awiden-compare-3.c | 22 + + .../gcc.dg/tree-ssa/awiden-compare-4.c | 22 + + .../gcc.dg/tree-ssa/awiden-compare-5.c | 19 + + .../gcc.dg/tree-ssa/awiden-compare-6.c | 19 + + .../gcc.dg/tree-ssa/awiden-compare-7.c | 22 + + .../gcc.dg/tree-ssa/awiden-compare-8.c | 24 + + gcc/timevar.def | 1 + + gcc/tree-pass.h | 1 + + gcc/tree-ssa-loop-array-widen-compare.cc | 1555 +++++++++++++++++ + 15 files changed, 1813 insertions(+), 1 deletion(-) + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-1.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-2.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-3.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-4.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-5.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-6.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-7.c + create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-8.c + create mode 100644 gcc/tree-ssa-loop-array-widen-compare.cc + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 31ff95500..0aabc6ea3 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -1653,6 +1653,7 @@ OBJS = \ + tree-ssa-loop-ivopts.o \ + tree-ssa-loop-manip.o \ + tree-ssa-loop-niter.o \ ++ tree-ssa-loop-array-widen-compare.o \ + tree-ssa-loop-prefetch.o \ + tree-ssa-loop-split.o \ + tree-ssa-loop-unswitch.o \ +diff --git a/gcc/common.opt b/gcc/common.opt +index e365a48bc..4d91ce8cf 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1116,6 +1116,11 @@ fasynchronous-unwind-tables + Common Var(flag_asynchronous_unwind_tables) Optimization + Generate unwind tables that are exact at each instruction boundary. + ++farray-widen-compare ++Common Var(flag_array_widen_compare) Optimization ++Extends types for pointers to arrays to improve array comparsion performance. ++In some extreme situations this may result in unsafe behavior. ++ + fauto-inc-dec + Common Var(flag_auto_inc_dec) Init(1) Optimization + Generate auto-inc/dec instructions. +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index ff8cd032f..a11e2c24b 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -507,7 +507,7 @@ Objective-C and Objective-C++ Dialects}. + -falign-loops[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol + -fno-allocation-dce -fallow-store-data-races @gol + -fassociative-math -fauto-profile -fauto-profile[=@var{path}] @gol +--fauto-inc-dec -fbranch-probabilities @gol ++-farray-widen-compare -fauto-inc-dec -fbranch-probabilities @gol + -fcaller-saves @gol + -fcombine-stack-adjustments -fconserve-stack @gol + -fcompare-elim -fcprop-registers -fcrossjumping @gol +@@ -11387,6 +11387,17 @@ This pass is always skipped on architectures that do not have + instructions to support this. Enabled by default at @option{-O1} and + higher on architectures that support this. + ++@item -farray-widen-compare ++@opindex farray-widen-compare ++In the narrow-byte array comparison scenario, the types of pointers ++pointing to array are extended so that elements of multiple bytes can ++be loaded at a time when a wide type is used to dereference an array, ++thereby improving the performance of this comparison scenario. In some ++extreme situations this may result in unsafe behavior. ++ ++This option may generate better or worse code; results are highly dependent ++on the structure of loops within the source code. ++ + @item -fdce + @opindex fdce + Perform dead code elimination (DCE) on RTL@. +diff --git a/gcc/passes.def b/gcc/passes.def +index 375d3d62d..8dbb7983e 100644 +--- a/gcc/passes.def ++++ b/gcc/passes.def +@@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. If not see + NEXT_PASS (pass_dse); + NEXT_PASS (pass_cd_dce, false /* update_address_taken_p */); + NEXT_PASS (pass_phiopt, true /* early_p */); ++ NEXT_PASS (pass_array_widen_compare); + NEXT_PASS (pass_tail_recursion); + NEXT_PASS (pass_if_to_switch); + NEXT_PASS (pass_convert_switch); +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-1.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-1.c +new file mode 100644 +index 000000000..e18ef5ec1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-1.c +@@ -0,0 +1,19 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (++len != len_limit) ++ if (pb[len] != cur[len]) ++ break; ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 1 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-2.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-2.c +new file mode 100644 +index 000000000..f4b20b43c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-2.c +@@ -0,0 +1,90 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define EMPTY_HASH_VALUE 0 ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++#define true 1 ++ ++typedef struct { ++ uint32_t len; ++ uint32_t dist; ++} lzma_match; ++ ++ ++lzma_match * ++func ( ++ const uint32_t len_limit, ++ const uint32_t pos, ++ const uint8_t *const cur, ++ uint32_t cur_match, ++ uint32_t depth, ++ uint32_t *const son, ++ const uint32_t cyclic_pos, ++ const uint32_t cyclic_size, ++ lzma_match *matches, ++ uint32_t len_best) ++{ ++ uint32_t *ptr0 = son + (cyclic_pos << 1) + 1; ++ uint32_t *ptr1 = son + (cyclic_pos << 1); ++ ++ uint32_t len0 = 0; ++ uint32_t len1 = 0; ++ ++ while (true) ++ { ++ const uint32_t delta = pos - cur_match; ++ if (depth-- == 0 || delta >= cyclic_size) ++ { ++ *ptr0 = EMPTY_HASH_VALUE; ++ *ptr1 = EMPTY_HASH_VALUE; ++ return matches; ++ } ++ ++ uint32_t *const pair = son + ((cyclic_pos - delta + (delta > cyclic_pos ? cyclic_size : 0)) << 1); ++ ++ const uint8_t *const pb = cur -delta; ++ uint32_t len = my_min(len0, len1); ++ ++ if (pb[len] == cur[len]) ++ { ++ while (++len != len_limit) ++ if (pb[len] != cur[len]) ++ break; ++ ++ if (len_best < len) ++ { ++ len_best = len; ++ matches->len = len; ++ matches->dist = delta - 1; ++ ++matches; ++ ++ if (len == len_limit) ++ { ++ *ptr1 = pair[0]; ++ *ptr0 = pair[1]; ++ return matches; ++ } ++ } ++ } ++ ++ if (pb[len] < cur[len]) ++ { ++ *ptr1 = cur_match; ++ ptr1 = pair + 1; ++ cur_match = *ptr1; ++ len1 = len; ++ } ++ else ++ { ++ *ptr0 = cur_match; ++ ptr0 = pair; ++ cur_match = *ptr0; ++ len0 = len; ++ } ++ } ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 1 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-3.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-3.c +new file mode 100644 +index 000000000..86f5e7a1e +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-3.c +@@ -0,0 +1,22 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (len != len_limit) ++ { ++ if (pb[len] != cur[len]) ++ break; ++ len = len + 1; ++ } ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 1 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-4.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-4.c +new file mode 100644 +index 000000000..d66558699 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-4.c +@@ -0,0 +1,22 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (len != len_limit) ++ { ++ if (pb[len] != cur[len]) ++ break; ++ len = len + 2; ++ } ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 0 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-5.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-5.c +new file mode 100644 +index 000000000..e3e12bca4 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-5.c +@@ -0,0 +1,19 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (++len != len_limit) ++ if (pb[len] != cur[len-1]) ++ break; ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 0 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-6.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-6.c +new file mode 100644 +index 000000000..b8500735e +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-6.c +@@ -0,0 +1,19 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (len++ != len_limit) ++ if (pb[len] != cur[len]) ++ break; ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 0 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-7.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-7.c +new file mode 100644 +index 000000000..977bf5685 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-7.c +@@ -0,0 +1,22 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (len != len_limit) ++ { ++ len = len + 1; ++ if (pb[len] != cur[len]) ++ break; ++ } ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 0 "awiden_compare"} } */ +diff --git a/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-8.c b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-8.c +new file mode 100644 +index 000000000..386784c92 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/tree-ssa/awiden-compare-8.c +@@ -0,0 +1,24 @@ ++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */ ++/* { dg-options "-O3 -mabi=lp64 -farray-widen-compare -fdump-tree-awiden_compare-details" } */ ++ ++#include ++#include ++ ++#define my_min(x, y) ((x) < (y) ? (x) : (y)) ++ ++uint32_t ++func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur) ++{ ++ uint32_t len = my_min(len0, len1); ++ while (++len != len_limit) ++ { ++ if (pb[len] != cur[len]) ++ { ++ len = len - 1; ++ break; ++ } ++ } ++ return len; ++} ++ ++/* { dg-final { scan-tree-dump-times "loop form is success" 0 "awiden_compare"} } */ +diff --git a/gcc/timevar.def b/gcc/timevar.def +index 2dae5e1c7..794b8017d 100644 +--- a/gcc/timevar.def ++++ b/gcc/timevar.def +@@ -216,6 +216,7 @@ DEFTIMEVAR (TV_TREE_NRV , "tree NRV optimization") + DEFTIMEVAR (TV_TREE_COPY_RENAME , "tree rename SSA copies") + DEFTIMEVAR (TV_TREE_SSA_VERIFY , "tree SSA verifier") + DEFTIMEVAR (TV_TREE_STMT_VERIFY , "tree STMT verifier") ++DEFTIMEVAR (TV_TREE_ARRAY_WIDEN_COMPARE, "tree array widen compare") + DEFTIMEVAR (TV_TREE_SWITCH_CONVERSION, "tree switch conversion") + DEFTIMEVAR (TV_TREE_SWITCH_LOWERING, "tree switch lowering") + DEFTIMEVAR (TV_TREE_RECIP , "gimple CSE reciprocals") +diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h +index 606d1d60b..55ee2fe7f 100644 +--- a/gcc/tree-pass.h ++++ b/gcc/tree-pass.h +@@ -453,6 +453,7 @@ extern gimple_opt_pass *make_pass_cselim (gcc::context *ctxt); + extern gimple_opt_pass *make_pass_phiopt (gcc::context *ctxt); + extern gimple_opt_pass *make_pass_forwprop (gcc::context *ctxt); + extern gimple_opt_pass *make_pass_phiprop (gcc::context *ctxt); ++extern gimple_opt_pass *make_pass_array_widen_compare (gcc::context *ctxt); + extern gimple_opt_pass *make_pass_tree_ifcombine (gcc::context *ctxt); + extern gimple_opt_pass *make_pass_dse (gcc::context *ctxt); + extern gimple_opt_pass *make_pass_nrv (gcc::context *ctxt); +diff --git a/gcc/tree-ssa-loop-array-widen-compare.cc b/gcc/tree-ssa-loop-array-widen-compare.cc +new file mode 100644 +index 000000000..ba6170fa0 +--- /dev/null ++++ b/gcc/tree-ssa-loop-array-widen-compare.cc +@@ -0,0 +1,1555 @@ ++/* Array widen compare. ++ Copyright (C) 2022-2023 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 ++. */ ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "backend.h" ++#include "target.h" ++#include "tree.h" ++#include "gimple.h" ++#include "tree-pass.h" ++#include "gimple-ssa.h" ++#include "tree-pretty-print.h" ++#include "fold-const.h" ++#include "gimplify.h" ++#include "gimple-iterator.h" ++#include "tree-ssa-loop-manip.h" ++#include "tree-ssa-loop.h" ++#include "ssa.h" ++#include "tree-into-ssa.h" ++#include "cfganal.h" ++#include "cfgloop.h" ++#include "gimple-pretty-print.h" ++#include "tree-cfg.h" ++#include "cgraph.h" ++#include "print-tree.h" ++#include "cfghooks.h" ++#include "gimple-fold.h" ++ ++/* This pass handles scenarios similar to the following: ++ ++ uint32_t ++ func (uint32_t len0, uint32_t len1, const uint32_t len_limit, ++ const uint8_t *const pb, const uint8_t *const cur) ++ { ++ uint32_t len = my_min (len0, len1); ++ while (++len != len_limit) ++ if (pb[len] != cur[len]) ++ break; ++ return len; ++ } ++ ++ Features of this type of loop: ++ 1) the loop has two exits; ++ 2) One of the exits comes from the comparison result of the array; ++ ++ From the source code point of view, the pass completes the conversion of the ++ above scenario into: ++ ++ uint32_t ++ func (uint32_t len0, uint32_t len1, const uint32_t len_limit, ++ const uint8_t *const pb, const uint8_t *const cur) ++ { ++ uint32_t len = my_min (len0, len1); ++ // align_loop ++ for(++len; len + sizeof(uint64_t) <= len_limit; len += sizeof (uint64_t)) ++ { ++ uint64_t a = *((uint64_t*)(cur+len)); ++ uint64_t b = *((uint64_t*)(pb+len)); ++ if (a != b) ++ { ++ int lz = __builtin_ctzll (a ^ b); ++ len += lz / 8; ++ return len; ++ } ++ } ++ // epilogue_loop ++ for (;len != len_limit; ++len) ++ if (pb[len] != cur[len]) ++ break; ++ return len; ++ } ++ ++ This pass is to complete the conversion of such scenarios from the internal ++ perspective of the compiler: ++ 1) determine_loop_form: The function completes the screening of such ++ scenarios; ++ 2) convert_to_new_loop: The function completes the conversion of ++ origin_loop to new loops, and removes origin_loop; ++ 3) origin_loop_info: The structure is used to record important information ++ of origin_loop: such as loop exit, growth step size ++ of loop induction variable, initial value ++ of induction variable, etc; ++ 4) create_new_loops: The function is used as the key content of the pass ++ to complete the creation of new loops. */ ++ ++/* The useful information of origin loop. */ ++ ++struct origin_loop_info ++{ ++ tree base; /* The initial index of the array in the old loop. */ ++ tree limit; /* The limit index of the array in the old loop. */ ++ tree arr1; /* Array 1 in the old loop. */ ++ tree arr2; /* Array 2 in the old loop. */ ++ edge entry_edge; /* The edge into the old loop. */ ++ basic_block exit_bb1; ++ basic_block exit_bb2; ++ edge exit_e1; ++ edge exit_e2; ++ gimple *cond_stmt1; ++ gimple *cond_stmt2; ++ gimple *update_stmt; ++ bool exist_prolog_assgin; ++ /* Whether the marker has an initial value assigned ++ to the array index. */ ++ unsigned HOST_WIDE_INT step; ++ /* The growth step of the loop induction variable. */ ++}; ++ ++typedef struct origin_loop_info origin_loop_info; ++ ++static origin_loop_info origin_loop; ++hash_map defs_map; ++ ++/* Dump the bb information in a loop. */ ++ ++static void ++dump_loop_bb (struct loop *loop) ++{ ++ basic_block *body = get_loop_body_in_dom_order (loop); ++ basic_block bb = NULL; ++ ++ for (unsigned i = 0; i < loop->num_nodes; i++) ++ { ++ bb = body[i]; ++ if (bb->loop_father != loop) ++ { ++ continue; ++ } ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "===== the %dth bb of loop ==========:\n", i); ++ gimple_dump_bb (dump_file, bb, 0, dump_flags); ++ fprintf (dump_file, "\n"); ++ } ++ } ++ free (body); ++} ++ ++/* Return true if the loop has precisely one backedge. */ ++ ++static bool ++loop_single_backedge_p (class loop *loop) ++{ ++ basic_block latch = loop->latch; ++ if (!single_succ_p (latch)) ++ return false; ++ ++ edge e = single_succ_edge (latch); ++ edge backedge = find_edge (latch, loop->header); ++ ++ if (e != backedge) ++ return false; ++ ++ return true; ++} ++ ++/* Return true if the loop has precisely one preheader BB. */ ++ ++static bool ++loop_single_preheader_bb (class loop *loop) ++{ ++ basic_block header = loop->header; ++ if (EDGE_COUNT (header->preds) != 2) ++ return false; ++ ++ edge e1 = EDGE_PRED (header, 0); ++ edge e2 = EDGE_PRED (header, 1); ++ ++ if ((e1->src == loop->latch && e2->src->loop_father != loop) ++ || (e2->src == loop->latch && e1->src->loop_father != loop)) ++ return true; ++ ++ return false; ++} ++ ++/* Initialize the origin_loop structure. */ ++static void ++init_origin_loop_structure () ++{ ++ origin_loop.base = NULL; ++ origin_loop.limit = NULL; ++ origin_loop.arr1 = NULL; ++ origin_loop.arr2 = NULL; ++ origin_loop.exit_e1 = NULL; ++ origin_loop.exit_e2 = NULL; ++ origin_loop.exit_bb1 = NULL; ++ origin_loop.exit_bb2 =NULL; ++ origin_loop.entry_edge = NULL; ++ origin_loop.cond_stmt1 = NULL; ++ origin_loop.cond_stmt2 = NULL; ++ origin_loop.update_stmt = NULL; ++ origin_loop.exist_prolog_assgin = false; ++ origin_loop.step = 0; ++} ++ ++/* Get the edge that first entered the loop. */ ++ ++static edge ++get_loop_preheader_edge (class loop *loop) ++{ ++ edge e; ++ edge_iterator ei; ++ ++ FOR_EACH_EDGE (e, ei, loop->header->preds) ++ if (e->src != loop->latch) ++ break; ++ ++ if (!e) ++ { ++ gcc_assert (!loop_outer (loop)); ++ return single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); ++ } ++ ++ return e; ++} ++ ++/* Make sure the exit condition stmt satisfies a specific form. */ ++ ++static bool ++check_cond_stmt (gimple *stmt) ++{ ++ if (!stmt) ++ return false; ++ if (gimple_code (stmt) != GIMPLE_COND) ++ return false; ++ ++ if (gimple_cond_code (stmt) != NE_EXPR && gimple_cond_code (stmt) != EQ_EXPR) ++ return false; ++ ++ tree lhs = gimple_cond_lhs (stmt); ++ tree rhs = gimple_cond_rhs (stmt); ++ ++ /* The parameter that does not support the cond statement is not SSA_NAME. ++ eg: if (len_1 != 100). */ ++ if (TREE_CODE (lhs) != SSA_NAME || TREE_CODE (rhs) != SSA_NAME) ++ return false; ++ ++ return true; ++} ++ ++/* Record the exit information in the original loop including exit edge, ++ exit bb block, exit condition stmt, ++ eg: exit_eX origin_exit_bbX cond_stmtX. */ ++ ++static bool ++record_origin_loop_exit_info (class loop *loop) ++{ ++ bool found = false; ++ edge e = NULL; ++ unsigned i = 0; ++ gimple *stmt; ++ ++ if (origin_loop.exit_e1 != NULL || origin_loop.exit_bb1 != NULL ++ || origin_loop.exit_e2 != NULL || origin_loop.exit_bb2 != NULL ++ || origin_loop.cond_stmt1 != NULL || origin_loop.cond_stmt2 != NULL) ++ return false; ++ ++ vec exit_edges = get_loop_exit_edges (loop); ++ if (exit_edges == vNULL) ++ return false; ++ ++ if (exit_edges.length () != 2) ++ goto fail; ++ ++ FOR_EACH_VEC_ELT (exit_edges, i, e) ++ { ++ if (e->src == loop->header) ++ { ++ origin_loop.exit_e1 = e; ++ origin_loop.exit_bb1 = e->dest; ++ stmt = gsi_stmt (gsi_last_bb (e->src)); ++ if (check_cond_stmt (stmt)) ++ origin_loop.cond_stmt1 = stmt; ++ } ++ else ++ { ++ origin_loop.exit_e2 = e; ++ origin_loop.exit_bb2 = e->dest; ++ stmt = gsi_stmt (gsi_last_bb (e->src)); ++ if (check_cond_stmt (stmt)) ++ origin_loop.cond_stmt2 = stmt; ++ } ++ } ++ ++ if (origin_loop.exit_e1 != NULL && origin_loop.exit_bb1 != NULL ++ && origin_loop.exit_e2 != NULL && origin_loop.exit_bb2 != NULL ++ && origin_loop.cond_stmt1 != NULL && origin_loop.cond_stmt2 != NULL) ++ found = true; ++ ++fail: ++ exit_edges.release (); ++ return found; ++} ++ ++/* Returns true if t is SSA_NAME and user variable exists. */ ++ ++static bool ++ssa_name_var_p (tree t) ++{ ++ if (!t || TREE_CODE (t) != SSA_NAME) ++ return false; ++ if (SSA_NAME_VAR (t)) ++ return true; ++ return false; ++} ++ ++/* Returns true if t1 and t2 are SSA_NAME and belong to the same variable. */ ++ ++static bool ++same_ssa_name_var_p (tree t1, tree t2) ++{ ++ if (!ssa_name_var_p (t1) || !ssa_name_var_p (t2)) ++ return false; ++ if (SSA_NAME_VAR (t1) == SSA_NAME_VAR (t2)) ++ return true; ++ return false; ++} ++ ++/* Get origin loop induction variable upper bound. */ ++ ++static bool ++get_iv_upper_bound (gimple *stmt) ++{ ++ if (origin_loop.limit != NULL) ++ return false; ++ ++ tree lhs = gimple_cond_lhs (stmt); ++ tree rhs = gimple_cond_rhs (stmt); ++ ++ if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE ++ || TREE_CODE (TREE_TYPE (rhs)) != INTEGER_TYPE) ++ return false; ++ ++ gimple *g = SSA_NAME_DEF_STMT (rhs); ++ ++ /* TODO: Currently, the input restrictions on lhs and rhs are implemented ++ through PARM_DECL. We may consider releasing the restrictions later, and ++ we need to consider the overall adaptation scenario and adding test ++ cases. */ ++ if (ssa_name_var_p (rhs) && TREE_CODE (SSA_NAME_VAR (rhs)) == PARM_DECL ++ && g && gimple_code (g) == GIMPLE_NOP ++ && (ssa_name_var_p (lhs) && TREE_CODE (SSA_NAME_VAR (lhs)) != PARM_DECL)) ++ { ++ origin_loop.limit = rhs; ++ } ++ else ++ return false; ++ ++ if (origin_loop.limit != NULL) ++ return true; ++ ++ return false; ++} ++ ++/* Returns true only when the expression on the rhs code of stmt is PLUS_EXPR, ++ rhs1 is SSA_NAME with the same var as origin_loop base, and rhs2 is ++ INTEGER_CST. */ ++ ++static bool ++check_update_stmt (gimple *stmt) ++{ ++ if (!stmt) ++ return false; ++ ++ if (gimple_assign_rhs_code (stmt) == PLUS_EXPR) ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ if (TREE_CODE (rhs1) == SSA_NAME && TREE_CODE (rhs2) == INTEGER_CST ++ && same_ssa_name_var_p (rhs1, origin_loop.base)) ++ { ++ origin_loop.step = tree_to_uhwi (rhs2); ++ if (origin_loop.step == 1) ++ return true; ++ } ++ } ++ return false; ++} ++ ++/* Get origin loop induction variable initial value. */ ++ ++static bool ++get_iv_base (gimple *stmt) ++{ ++ tree lhs = gimple_cond_lhs (stmt); ++ if (origin_loop.base != NULL || origin_loop.update_stmt != NULL) ++ return false; ++ ++ basic_block header = gimple_bb (stmt); ++ ++ gphi_iterator gsi; ++ edge e; ++ edge_iterator ei; ++ tree iv_after; ++ ++ for (gsi = gsi_start_phis (header); !gsi_end_p (gsi); gsi_next (&gsi)) ++ { ++ gphi *phi = gsi.phi (); ++ tree res = gimple_phi_result (phi); ++ if (!same_ssa_name_var_p (res, lhs)) ++ continue; ++ tree base = PHI_ARG_DEF_FROM_EDGE (phi, origin_loop.entry_edge); ++ if (!same_ssa_name_var_p (base, lhs)) ++ return false; ++ origin_loop.base = base; ++ FOR_EACH_EDGE (e, ei, header->preds) ++ { ++ if (e != origin_loop.entry_edge) ++ { ++ iv_after = PHI_ARG_DEF_FROM_EDGE (phi, e); ++ gimple *update = SSA_NAME_DEF_STMT (iv_after); ++ if (!check_update_stmt (update)) ++ return false; ++ origin_loop.update_stmt = update; ++ if (gimple_bb (update) == header && iv_after == lhs) ++ origin_loop.exist_prolog_assgin = true; ++ } ++ } ++ } ++ ++ if (origin_loop.base != NULL && origin_loop.update_stmt != NULL) ++ return true; ++ ++ return false; ++} ++ ++/* Record the upper bound and initial value of the induction variable in the ++ original loop; When prolog_assign is present, make sure loop header is in ++ simple form; And the interpretation of prolog_assign is as follows: ++ eg: while (++len != limit) ++ ...... ++ For such a loop, ++len will be processed before entering header_bb, and the ++ assign is regarded as the prolog_assign of the loop. */ ++ ++static bool ++record_origin_loop_header (class loop *loop) ++{ ++ basic_block header = loop->header; ++ ++ if (origin_loop.entry_edge != NULL || origin_loop.base != NULL ++ || origin_loop.update_stmt != NULL || origin_loop.limit != NULL) ++ return false; ++ origin_loop.entry_edge = get_loop_preheader_edge (loop); ++ ++ gimple_stmt_iterator gsi; ++ gimple *stmt; ++ ++ for (gsi = gsi_last_bb (header); !gsi_end_p (gsi); gsi_prev (&gsi)) ++ { ++ stmt = gsi_stmt (gsi); ++ if (stmt && is_gimple_debug (stmt)) ++ continue; ++ if (stmt && gimple_code (stmt) == GIMPLE_COND) ++ { ++ if (!get_iv_upper_bound (stmt)) ++ return false; ++ if (!get_iv_base (stmt)) ++ return false; ++ } ++ else if (stmt && gimple_code (stmt) == GIMPLE_ASSIGN) ++ { ++ if (stmt != origin_loop.update_stmt || !origin_loop.exist_prolog_assgin) ++ return false; ++ } ++ else ++ return false; ++ } ++ ++ if (origin_loop.entry_edge != NULL && origin_loop.base != NULL ++ && origin_loop.update_stmt != NULL && origin_loop.limit != NULL) ++ return true; ++ ++ return false; ++} ++ ++/* When prolog_assign does not exist, make sure that update_stmt exists in the ++ loop latch, and its form is a specific form, eg: ++ len_2 = len_1 + 1. */ ++ ++static bool ++record_origin_loop_latch (class loop *loop) ++{ ++ basic_block latch = loop->latch; ++ gimple_stmt_iterator gsi; ++ gimple *stmt; ++ ++ gsi = gsi_start_bb (latch); ++ ++ if (origin_loop.exist_prolog_assgin) ++ { ++ if (gsi_end_p (gsi)) ++ return true; ++ } ++ else ++ { ++ if (gsi_one_before_end_p (gsi)) ++ { ++ stmt = gsi_stmt (gsi); ++ if (stmt == origin_loop.update_stmt) ++ return true; ++ } ++ } ++ return false; ++} ++ ++/* Returns true when the DEF_STMT corresponding to arg0 of the mem_ref tree ++ satisfies the POINTER_PLUS_EXPR type. */ ++ ++static bool ++check_body_mem_ref (tree mem_ref) ++{ ++ tree arg0 = TREE_OPERAND (mem_ref , 0); ++ tree arg1 = TREE_OPERAND (mem_ref , 1); ++ ++ if (TREE_CODE (TREE_TYPE (arg0)) == POINTER_TYPE ++ && TREE_CODE (arg1) == INTEGER_CST ++ && tree_to_uhwi (arg1) == 0) ++ { ++ gimple *tmp_g = SSA_NAME_DEF_STMT (arg0); ++ if (tmp_g && gimple_assign_rhs_code (tmp_g) == POINTER_PLUS_EXPR) ++ return true; ++ } ++ return false; ++} ++ ++/* Returns true if the rh2 of the current stmt comes from the base in the ++ original loop. */ ++ ++static bool ++check_body_pointer_plus (gimple *stmt, tree &tmp_index) ++{ ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ if (TREE_CODE (TREE_TYPE (rhs1)) == POINTER_TYPE) ++ { ++ gimple *g = SSA_NAME_DEF_STMT (rhs2); ++ if (g && gimple_assign_rhs_code (g) == NOP_EXPR) ++ { ++ tree nop_rhs = gimple_assign_rhs1 (g); ++ if (same_ssa_name_var_p (nop_rhs, origin_loop.base)) ++ { ++ if (!origin_loop.arr1) ++ { ++ origin_loop.arr1 = rhs1; ++ tmp_index = rhs2; ++ } ++ else if (!origin_loop.arr2) ++ { ++ origin_loop.arr2 = rhs1; ++ if (tmp_index != rhs2) ++ return false; ++ } ++ else ++ return false; ++ return true; ++ } ++ } ++ } ++ return false; ++} ++ ++/* Record the array comparison information in the original loop, while ensuring ++ that there are only statements related to cont_stmt in the loop body. */ ++ ++static bool ++record_origin_loop_body (class loop *loop) ++{ ++ basic_block body = gimple_bb (origin_loop.cond_stmt2); ++ ++ if (origin_loop.arr1 != NULL || origin_loop.arr2 != NULL) ++ return false; ++ ++ gimple_stmt_iterator gsi; ++ for (gsi = gsi_start_bb (body); !gsi_end_p (gsi); gsi_next (&gsi)) ++ { ++ gimple_set_visited (gsi_stmt (gsi), false); ++ } ++ ++ tree cond_lhs = gimple_cond_lhs (origin_loop.cond_stmt2); ++ tree cond_rhs = gimple_cond_rhs (origin_loop.cond_stmt2); ++ if (TREE_CODE (TREE_TYPE (cond_lhs)) != INTEGER_TYPE ++ || TREE_CODE (TREE_TYPE (cond_rhs)) != INTEGER_TYPE) ++ return false; ++ ++ auto_vec stack; ++ tree tmp_index = NULL; ++ stack.safe_push (cond_lhs); ++ stack.safe_push (cond_rhs); ++ gimple_set_visited (origin_loop.cond_stmt2, true); ++ ++ while (!stack.is_empty ()) ++ { ++ tree op = stack.pop (); ++ gimple *g = SSA_NAME_DEF_STMT (op); ++ if (!g || gimple_bb (g) != body || !is_gimple_assign (g)) ++ continue; ++ gimple_set_visited (g, true); ++ if (gimple_assign_rhs_code (g) == MEM_REF) ++ { ++ tree mem_ref = gimple_assign_rhs1 (g); ++ if (!check_body_mem_ref (mem_ref)) ++ return false; ++ stack.safe_push (TREE_OPERAND (mem_ref , 0)); ++ } ++ else if (gimple_assign_rhs_code (g) == POINTER_PLUS_EXPR) ++ { ++ tree rhs2 = gimple_assign_rhs2 (g); ++ if (!check_body_pointer_plus (g, tmp_index)) ++ return false; ++ stack.safe_push (rhs2); ++ } ++ else if (gimple_assign_rhs_code (g) == NOP_EXPR) ++ { ++ tree rhs = gimple_assign_rhs1 (g); ++ if (!same_ssa_name_var_p (rhs, origin_loop.base)) ++ return false; ++ stack.safe_push (rhs); ++ } ++ else ++ return false; ++ } ++ bool allvisited = true; ++ for (gsi = gsi_start_bb (body); !gsi_end_p (gsi); gsi_next (&gsi)) ++ { ++ if (!gimple_visited_p (gsi_stmt (gsi)) ++ && !is_gimple_debug (gsi_stmt (gsi))) ++ allvisited = false; ++ } ++ if (allvisited) ++ { ++ if (origin_loop.arr1 != NULL && origin_loop.arr2 != NULL) ++ return true; ++ } ++ return false; ++} ++ ++/* Dump the original loop information to see if the origin loop ++ form matches. */ ++ ++static void ++dump_origin_loop_info () ++{ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nThe origin loop info:\n"); ++ fprintf (dump_file, "\n the origin_loop.limit is:\n"); ++ print_node (dump_file, "", origin_loop.limit, 0); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "\n the origin_loop.base is:\n"); ++ print_node (dump_file, "", origin_loop.base, 0); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "\n the origin_loop.arr1 is:\n"); ++ print_node (dump_file, "", origin_loop.arr1, 0); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "\n the origin_loop.arr2 is:\n"); ++ print_node (dump_file, "", origin_loop.arr2, 0); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "\n the origin_loop.cond_stmt1 is:\n"); ++ print_gimple_stmt (dump_file, origin_loop.cond_stmt1, 0); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "\n the origin_loop.cond_stmt2 is:\n"); ++ print_gimple_stmt (dump_file, origin_loop.cond_stmt2, 0); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "\n the origin_loop.update_stmt is:\n"); ++ print_gimple_stmt (dump_file, origin_loop.update_stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++} ++ ++/* Returns true only if the exit bb of the original loop is unique and its phi ++ node parameter comes from the same variable. */ ++ ++static bool ++check_exit_bb (class loop *loop) ++{ ++ if (origin_loop.exit_bb1 != origin_loop.exit_bb2 ++ || flow_bb_inside_loop_p (loop, origin_loop.exit_bb1)) ++ return false; ++ ++ gphi_iterator gsi; ++ for (gsi = gsi_start_phis (origin_loop.exit_bb1); !gsi_end_p (gsi); ++ gsi_next (&gsi)) ++ { ++ gphi *phi = gsi.phi (); ++ tree res = gimple_phi_result (phi); ++ if (!same_ssa_name_var_p (res, origin_loop.base)) ++ continue; ++ if (gimple_phi_num_args (phi) == 2) ++ { ++ tree arg0 = gimple_phi_arg_def (phi, 0); ++ tree arg1 = gimple_phi_arg_def (phi, 1); ++ if (arg0 == arg1) ++ return true; ++ } ++ } ++ return false; ++} ++ ++/* Make sure that the recorded origin_loop information meets the ++ relative requirements. */ ++ ++static bool ++check_origin_loop_info (class loop *loop) ++{ ++ dump_origin_loop_info (); ++ tree arr1_elem_size, arr2_elem_size; ++ ++ if (!check_exit_bb (loop)) ++ return false; ++ ++ if (TREE_CODE (origin_loop.base) != SSA_NAME) ++ return false; ++ ++ if (!TYPE_READONLY (TREE_TYPE (origin_loop.limit))) ++ return false; ++ ++ if (!TYPE_READONLY (TREE_TYPE (TREE_TYPE (origin_loop.arr1)))) ++ return false; ++ ++ if (!TYPE_READONLY (TREE_TYPE (TREE_TYPE (origin_loop.arr2)))) ++ return false; ++ ++ if (TREE_CODE (TREE_TYPE (origin_loop.arr1)) != POINTER_TYPE ++ || TREE_CODE (TREE_TYPE (origin_loop.arr2)) != POINTER_TYPE ++ || TREE_CODE (TREE_TYPE (TREE_TYPE (origin_loop.arr1))) != INTEGER_TYPE ++ || TREE_CODE (TREE_TYPE (TREE_TYPE (origin_loop.arr2))) != INTEGER_TYPE) ++ return false; ++ ++ arr1_elem_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (origin_loop.arr1))); ++ arr2_elem_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (origin_loop.arr2))); ++ ++ if (tree_to_uhwi (arr1_elem_size) != 8 || tree_to_uhwi (arr2_elem_size) != 8) ++ return false; ++ ++ return true; ++} ++ ++/* Record the useful information of the original loop and judge whether the ++ information meets the specified conditions. */ ++ ++static bool ++check_record_loop_form (class loop *loop) ++{ ++ if (!record_origin_loop_exit_info (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nFailed to record loop exit information.\n"); ++ } ++ return false; ++ } ++ ++ if (!record_origin_loop_header (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nFailed to record loop header information.\n"); ++ } ++ return false; ++ } ++ ++ if (!record_origin_loop_latch (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nFailed to record loop latch information.\n"); ++ } ++ return false; ++ } ++ ++ if (!record_origin_loop_body (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nFailed to record loop body information.\n"); ++ } ++ return false; ++ } ++ ++ if (!check_origin_loop_info (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nFailed to check origin loop information.\n"); ++ } ++ return false; ++ } ++ ++ return true; ++} ++ ++/* The main entry for judging whether the loop meets some conditions. */ ++ ++static bool ++determine_loop_form (class loop *loop) ++{ ++ /* Currently only standard loops are processed, that is, only loop_header, ++ loop_latch, loop_body 3 bb blocks are included. */ ++ if (loop->inner || loop->num_nodes != 3) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nWrong loop form, there is inner loop or" ++ "redundant bb.\n"); ++ } ++ return false; ++ } ++ ++ if (single_exit (loop) || !loop->latch) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nWrong loop form, only one exit or loop_latch" ++ "does not exist.\n"); ++ } ++ return false; ++ } ++ ++ /* Support loop with only one backedge. */ ++ if (!loop_single_backedge_p (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nWrong loop form, loop back edges are not" ++ "unique.\n"); ++ } ++ return false; ++ } ++ ++ /* Support loop with only one preheader BB. */ ++ if (!loop_single_preheader_bb (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nWrong loop form, loop preheader bb are not" ++ "unique.\n"); ++ } ++ return false; ++ } ++ ++ init_origin_loop_structure (); ++ if (!check_record_loop_form (loop)) ++ return false; ++ ++ return true; ++} ++ ++/* Create prolog bb for newly constructed loop; When prolog_assign exists in ++ the original loop, the corresponding assign needs to be added to prolog_bb; ++ eg: ++ len_16 = len_10 + 1 ++ Create simple copy statement when prolog_assign does not exist; ++ eg: ++ len_16 = len_10 ++ ++ The IR of bb is as above. */ ++ ++static void ++create_prolog_bb (basic_block &prolog_bb, basic_block after_bb, ++ basic_block dominator_bb, class loop *outer, edge entry_edge) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gimple *g; ++ tree lhs1; ++ ++ prolog_bb = create_empty_bb (after_bb); ++ add_bb_to_loop (prolog_bb, outer); ++ redirect_edge_and_branch (entry_edge, prolog_bb); ++ set_immediate_dominator (CDI_DOMINATORS, prolog_bb, dominator_bb); ++ gsi = gsi_last_bb (prolog_bb); ++ lhs1 = copy_ssa_name (origin_loop.base); ++ ++ if (origin_loop.exist_prolog_assgin) ++ g = gimple_build_assign (lhs1, PLUS_EXPR, origin_loop.base, ++ build_int_cst (TREE_TYPE (origin_loop.base), origin_loop.step)); ++ else ++ g = gimple_build_assign (lhs1, NOP_EXPR, origin_loop.base); ++ gimple_seq_add_stmt (&stmts, g); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ set_current_def (origin_loop.base, lhs1); ++ defs_map.put (prolog_bb, lhs1); ++} ++ ++/* Create preheader bb for new loop; In order to ensure the standard form of ++ the loop, add a preheader_bb before loop_header. */ ++ ++static void ++create_loop_pred_bb (basic_block &loop_pred_bb, basic_block after_bb, ++ basic_block dominator_bb, class loop *outer) ++{ ++ loop_pred_bb = create_empty_bb (after_bb); ++ add_bb_to_loop (loop_pred_bb, outer); ++ set_immediate_dominator (CDI_DOMINATORS, loop_pred_bb, dominator_bb); ++ defs_map.put (loop_pred_bb, get_current_def (origin_loop.base)); ++} ++ ++/* Add phi_arg for bb with phi node. */ ++ ++static void ++rewrite_add_phi_arg (basic_block bb) ++{ ++ edge e; ++ edge_iterator ei; ++ gphi *phi; ++ gphi_iterator gsi; ++ tree res; ++ location_t loc; ++ ++ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) ++ { ++ phi = gsi.phi (); ++ res = gimple_phi_result (phi); ++ ++ FOR_EACH_EDGE (e, ei, bb->preds) ++ { ++ if (PHI_ARG_DEF_FROM_EDGE (phi, e)) ++ continue; ++ tree var = *(defs_map.get (e->src)); ++ if (!same_ssa_name_var_p (var, res)) ++ continue; ++ if (virtual_operand_p (var)) ++ loc = UNKNOWN_LOCATION; ++ else ++ loc = gimple_location (SSA_NAME_DEF_STMT (var)); ++ add_phi_arg (phi, var, e, loc); ++ } ++ } ++} ++ ++/* Create loop_header BB for align_loop. ++ eg: ++ _18 = (long unsigned int) len_17; ++ _19 = _18 + 8; ++ _20 = (long unsigned int) len_limit_12 (D); ++ if (_19 <= _20) ++ ++ The IR of bb is as above. */ ++ ++static void ++create_align_loop_header (basic_block &align_loop_header, basic_block after_bb, ++ basic_block dominator_bb, class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gcond *cond_stmt; ++ gphi *phi; ++ tree res; ++ ++ tree entry_node = get_current_def (origin_loop.base); ++ align_loop_header = create_empty_bb (after_bb); ++ add_bb_to_loop (align_loop_header, outer); ++ make_single_succ_edge (after_bb, align_loop_header, EDGE_FALLTHRU); ++ set_immediate_dominator (CDI_DOMINATORS, align_loop_header, dominator_bb); ++ gsi = gsi_last_bb (align_loop_header); ++ phi = create_phi_node (NULL_TREE, align_loop_header); ++ create_new_def_for (entry_node, phi, gimple_phi_result_ptr (phi)); ++ res = gimple_phi_result (phi); ++ ++ tree lhs1 = gimple_build (&stmts, NOP_EXPR, long_unsigned_type_node, res); ++ tree lhs2 = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (lhs1), lhs1, ++ build_int_cst (TREE_TYPE (lhs1), 8)); ++ tree lhs3 = gimple_build (&stmts, NOP_EXPR, long_unsigned_type_node, ++ origin_loop.limit); ++ cond_stmt = gimple_build_cond (LE_EXPR, lhs2, lhs3, NULL_TREE, NULL_TREE); ++ gimple_seq_add_stmt (&stmts, cond_stmt); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ ++ set_current_def (origin_loop.base, res); ++ defs_map.put (align_loop_header, res); ++} ++ ++/* Create loop body BB for align_loop. ++ eg: ++ _21 = (sizetype) len_17; ++ _22 = cur_15 (D) + _21; ++ _23 = MEM[(long unsigned int *)_22]; ++ _24 = pb_13 (D) + _21; ++ _25 = MEM[(long unsigned int *)_24]; ++ if (_23 != _25) ++ ++ The IR of bb is as above. */ ++ ++static void ++create_align_loop_body_bb (basic_block &align_loop_body_bb, ++ basic_block after_bb, basic_block dominator_bb, ++ class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gimple *g; ++ gcond *cond_stmt; ++ tree lhs1, lhs2; ++ ++ align_loop_body_bb = create_empty_bb (after_bb); ++ add_bb_to_loop (align_loop_body_bb, outer); ++ make_edge (after_bb, align_loop_body_bb, EDGE_TRUE_VALUE); ++ set_immediate_dominator (CDI_DOMINATORS, align_loop_body_bb, dominator_bb); ++ gsi = gsi_last_bb (align_loop_body_bb); ++ ++ tree var = gimple_build (&stmts, NOP_EXPR, sizetype, ++ get_current_def (origin_loop.base)); ++ lhs1 = gimple_build (&stmts, POINTER_PLUS_EXPR, TREE_TYPE (origin_loop.arr2), ++ origin_loop.arr2, var); ++ g = gimple_build_assign (make_ssa_name (long_unsigned_type_node), ++ fold_build2 (MEM_REF, long_unsigned_type_node, lhs1, ++ build_int_cst (build_pointer_type (long_unsigned_type_node), 0))); ++ gimple_seq_add_stmt (&stmts, g); ++ lhs1 = gimple_assign_lhs (g); ++ lhs2 = gimple_build (&stmts, POINTER_PLUS_EXPR, TREE_TYPE (origin_loop.arr1), ++ origin_loop.arr1, var); ++ g = gimple_build_assign (make_ssa_name (long_unsigned_type_node), ++ fold_build2 (MEM_REF, long_unsigned_type_node, lhs2, ++ build_int_cst (build_pointer_type (long_unsigned_type_node), 0))); ++ gimple_seq_add_stmt (&stmts, g); ++ lhs2 = gimple_assign_lhs (g); ++ cond_stmt = gimple_build_cond (gimple_cond_code (origin_loop.cond_stmt2), ++ lhs1, lhs2, NULL_TREE, NULL_TREE); ++ gimple_seq_add_stmt (&stmts, cond_stmt); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++} ++ ++/* Create loop_latch BB for align_loop. ++ eg: ++ len_26 = len_17 + 8; ++ ++ The IR of bb is as above. */ ++ ++static void ++create_align_loop_latch (basic_block &align_loop_latch, basic_block after_bb, ++ basic_block dominator_bb, class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gimple *g; ++ tree res; ++ ++ tree entry_node = get_current_def (origin_loop.base); ++ align_loop_latch = create_empty_bb (after_bb); ++ add_bb_to_loop (align_loop_latch, outer); ++ make_edge (after_bb, align_loop_latch, EDGE_FALSE_VALUE); ++ set_immediate_dominator (CDI_DOMINATORS, align_loop_latch, dominator_bb); ++ gsi = gsi_last_bb (align_loop_latch); ++ res = copy_ssa_name (entry_node); ++ g = gimple_build_assign (res, PLUS_EXPR, entry_node, ++ build_int_cst (TREE_TYPE (entry_node), 8)); ++ gimple_seq_add_stmt (&stmts, g); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ defs_map.put (align_loop_latch, res); ++} ++ ++/* Create a new loop and add it to outer_loop and return. */ ++ ++static class loop * ++init_new_loop (class loop *outer_loop, basic_block header, basic_block latch) ++{ ++ class loop *new_loop; ++ new_loop = alloc_loop (); ++ new_loop->header = header; ++ new_loop->latch = latch; ++ add_loop (new_loop, outer_loop); ++ ++ return new_loop; ++} ++ ++/* Create necessary exit BB for align_loop. ++ eg: ++ _27 = _23 ^ _25; ++ _28 = __builtin_ctzll (_27); ++ _29 = _28 >> 3; ++ len_30 = _29 + len_17; ++ ++ The IR of bb is as above. */ ++ ++static void ++create_align_loop_exit_bb (basic_block &align_loop_exit_bb, ++ basic_block after_bb, basic_block dominator_bb, ++ class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gimple *g; ++ gimple *cond_stmt; ++ tree lhs1, lhs2; ++ tree cond_lhs, cond_rhs; ++ gcall *build_ctzll; ++ ++ tree entry_node = get_current_def (origin_loop.base); ++ align_loop_exit_bb = create_empty_bb (after_bb); ++ add_bb_to_loop (align_loop_exit_bb, outer); ++ make_edge (after_bb, align_loop_exit_bb, EDGE_TRUE_VALUE); ++ set_immediate_dominator (CDI_DOMINATORS, align_loop_exit_bb, dominator_bb); ++ gsi = gsi_last_bb (align_loop_exit_bb); ++ ++ cond_stmt = gsi_stmt (gsi_last_bb (after_bb)); ++ cond_lhs = gimple_cond_lhs (cond_stmt); ++ cond_rhs = gimple_cond_rhs (cond_stmt); ++ ++ lhs1 = gimple_build (&stmts, BIT_XOR_EXPR, TREE_TYPE (cond_lhs), cond_lhs, ++ cond_rhs); ++ build_ctzll = gimple_build_call (builtin_decl_explicit (BUILT_IN_CTZLL), 1, ++ lhs1); ++ lhs1 = make_ssa_name (integer_type_node); ++ gimple_call_set_lhs (build_ctzll, lhs1); ++ gimple_seq_add_stmt (&stmts, build_ctzll); ++ lhs2 = copy_ssa_name (lhs1); ++ g = gimple_build_assign (lhs2, RSHIFT_EXPR, lhs1, ++ build_int_cst (TREE_TYPE (lhs1), 3)); ++ gimple_seq_add_stmt (&stmts, g); ++ lhs1 = gimple_build (&stmts, NOP_EXPR, TREE_TYPE (entry_node), lhs2); ++ lhs2 = copy_ssa_name (entry_node); ++ g = gimple_build_assign (lhs2, PLUS_EXPR, lhs1, entry_node); ++ gimple_seq_add_stmt (&stmts, g); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ defs_map.put (align_loop_exit_bb, lhs2); ++} ++ ++/* Create loop_header BB for epilogue_loop. ++ eg: ++ # len_31 = PHI ++ if (len_31 != len_limit_12 (D)) ++ ++ The IR of bb is as above. */ ++ ++static void ++create_epilogue_loop_header (basic_block &epilogue_loop_header, ++ basic_block after_bb, basic_block dominator_bb, ++ class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gcond *cond_stmt; ++ tree res; ++ gphi *phi; ++ ++ tree entry_node = get_current_def (origin_loop.base); ++ epilogue_loop_header = create_empty_bb (after_bb); ++ add_bb_to_loop (epilogue_loop_header, outer); ++ make_single_succ_edge (after_bb, epilogue_loop_header, EDGE_FALLTHRU); ++ set_immediate_dominator (CDI_DOMINATORS, epilogue_loop_header, dominator_bb); ++ gsi = gsi_last_bb (epilogue_loop_header); ++ phi = create_phi_node (NULL_TREE, epilogue_loop_header); ++ create_new_def_for (entry_node, phi, gimple_phi_result_ptr (phi)); ++ res = gimple_phi_result (phi); ++ cond_stmt = gimple_build_cond (gimple_cond_code (origin_loop.cond_stmt1), res, ++ origin_loop.limit, NULL_TREE, NULL_TREE); ++ gimple_seq_add_stmt (&stmts, cond_stmt); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ ++ set_current_def (origin_loop.base, res); ++ defs_map.put (epilogue_loop_header, res); ++} ++ ++/* Create loop body BB for epilogue_loop. ++ eg: ++ _32 = (sizetype) len_31; ++ _33 = pb_13 (D) + _32; ++ _34 = *_33; ++ _35 = cur_15 (D) + _32; ++ _36 = *_35; ++ if (_34 != _36) ++ ++ The IR of bb is as above. */ ++ ++static void ++create_epilogue_loop_body_bb (basic_block &epilogue_loop_body_bb, ++ basic_block after_bb, basic_block dominator_bb, ++ class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gimple *g; ++ gcond *cond_stmt; ++ tree lhs1, lhs2, lhs3; ++ ++ tree entry_node = get_current_def (origin_loop.base); ++ epilogue_loop_body_bb = create_empty_bb (after_bb); ++ add_bb_to_loop (epilogue_loop_body_bb, outer); ++ make_edge (after_bb, epilogue_loop_body_bb, EDGE_TRUE_VALUE); ++ set_immediate_dominator (CDI_DOMINATORS, epilogue_loop_body_bb, dominator_bb); ++ gsi = gsi_last_bb (epilogue_loop_body_bb); ++ lhs1 = gimple_build (&stmts, NOP_EXPR, sizetype, entry_node); ++ lhs2 = gimple_build (&stmts, POINTER_PLUS_EXPR, TREE_TYPE (origin_loop.arr1), ++ origin_loop.arr1, lhs1); ++ g = gimple_build_assign (make_ssa_name (unsigned_char_type_node), ++ fold_build2 (MEM_REF, unsigned_char_type_node, lhs2, ++ build_int_cst (TREE_TYPE (lhs2), 0))); ++ gimple_seq_add_stmt (&stmts, g); ++ lhs2 = gimple_assign_lhs (g); ++ lhs3 = gimple_build (&stmts, POINTER_PLUS_EXPR, TREE_TYPE (origin_loop.arr2), ++ origin_loop.arr2, lhs1); ++ g = gimple_build_assign (make_ssa_name (unsigned_char_type_node), ++ fold_build2 (MEM_REF, unsigned_char_type_node, lhs3, ++ build_int_cst (TREE_TYPE (lhs3), 0))); ++ gimple_seq_add_stmt (&stmts, g); ++ lhs3 = gimple_assign_lhs (g); ++ cond_stmt = gimple_build_cond (gimple_cond_code (origin_loop.cond_stmt2), lhs2, ++ lhs3, NULL_TREE, NULL_TREE); ++ gimple_seq_add_stmt (&stmts, cond_stmt); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ defs_map.put (epilogue_loop_body_bb, get_current_def (origin_loop.base)); ++} ++ ++/* Create loop_latch BB for epilogue_loop. ++ eg: ++ len_37 = len_31 + 1; ++ ++ The IR of bb is as above. */ ++ ++static void ++create_epilogue_loop_latch (basic_block &epilogue_loop_latch, ++ basic_block after_bb, basic_block dominator_bb, ++ class loop *outer) ++{ ++ gimple_seq stmts = NULL; ++ gimple_stmt_iterator gsi; ++ gimple *g; ++ tree res; ++ ++ tree entry_node = get_current_def (origin_loop.base); ++ epilogue_loop_latch = create_empty_bb (after_bb); ++ add_bb_to_loop (epilogue_loop_latch, outer); ++ make_edge (after_bb, epilogue_loop_latch, EDGE_FALSE_VALUE); ++ set_immediate_dominator (CDI_DOMINATORS, epilogue_loop_latch, dominator_bb); ++ gsi = gsi_last_bb (epilogue_loop_latch); ++ res = copy_ssa_name (entry_node); ++ g = gimple_build_assign (res, PLUS_EXPR, entry_node, ++ build_int_cst (TREE_TYPE (entry_node), origin_loop.step)); ++ gimple_seq_add_stmt (&stmts, g); ++ gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); ++ defs_map.put (epilogue_loop_latch, res); ++} ++ ++/* convert_to_new_loop ++ | | ++ | | ++ | | entry_edge ++ | ______ | ++ | / V V ++ | | -----origin_loop_header--- ++ | | | | ++ | | -------------------------\ ++ | | | \ ++ | | V \___ ___ ___ ___ ___ ___ ___ ++ | | -----origin_loop_body----- | ++ | | | | | ++ | | -------------------------\ | ++ | | | \___ ___ ___ ___ | ++ | | V V V ++ | | -----origin_loop_latch---- -----exit_bb------ ++ | | | | | | ++ | | /-------------------------- ------------------ ++ | \ __ / ++ | ++ | | ++ | ====> |entry_edge ++ | V ++ | -------prolog_bb----- ++ | | | ++ | --------------------- ++ | | ++ | V ++ | -----align_loop_header---- ++ | /-----------------> | | ++ |/ -------------------------- ++ || / \ ++ || V V ++ || ---align_loop_body--- ---epilogue_loop_header-- ++ || | | -------| |<---| ++ || --------------------\ / ------------------------- | ++ || | \____ | | | ++ || V | | V | ++ || ---align_loop_latch--- | | ---epilogue_loop_body---- | ++ || | | | | ----| | | ++ || ---------------------- | | / ------------------------- | ++ || / __________/ | | | | ++ || / | | | V | ++ | \ __________/ | | | ---epilogue_loop_latch--- | ++ | | | | | | | ++ | | | | ------------------------- / ++ | V | | | / ++ | -align_loop_exit_bb- | | \______________/ ++ | | | | | ++ | -------------------- | | ++ | | | | ++ | | V V ++ | | -----exit_bb------ ++ | |---->| | ++ | ------------------ ++ ++ The origin_loop conversion process starts from entry_edge and ends at ++ exit_bb; The execution logic of origin_loop is completely replaced by ++ align_loop + epilogue_loop: ++ 1) align_loop mainly implements the idea of ​​using wide-type dereference ++ and comparison on array elements, so as to achieve the effect of ++ acceleration; For the corresponding source code understanding, please ++ refer to the description of the pass at the beginning; ++ 2) epilogue_loop processes the previous loop remaining array element ++ comparison. */ ++ ++static void ++create_new_loops (edge entry_edge) ++{ ++ basic_block prolog_bb; ++ basic_block align_loop_header, align_loop_latch, align_loop_body_bb; ++ basic_block align_pred_bb, align_loop_exit_bb; ++ basic_block epilogue_loop_header, epilogue_loop_latch, epilogue_loop_body_bb; ++ basic_block epilogue_loop_pred_bb; ++ class loop *align_loop; ++ class loop *epilogue_loop; ++ ++ class loop *outer = entry_edge->src->loop_father; ++ ++ create_prolog_bb (prolog_bb, entry_edge->src, entry_edge->src, outer, ++ entry_edge); ++ ++ create_loop_pred_bb (align_pred_bb, prolog_bb, prolog_bb, outer); ++ make_single_succ_edge (prolog_bb, align_pred_bb, EDGE_FALLTHRU); ++ ++ create_align_loop_header (align_loop_header, align_pred_bb, ++ align_pred_bb, outer); ++ ++ create_align_loop_body_bb (align_loop_body_bb, align_loop_header, ++ align_loop_header, outer); ++ ++ create_align_loop_latch (align_loop_latch, align_loop_body_bb, ++ align_loop_body_bb, outer); ++ make_edge (align_loop_latch, align_loop_header, EDGE_FALLTHRU); ++ rewrite_add_phi_arg (align_loop_header); ++ ++ align_loop = init_new_loop (outer, align_loop_header, align_loop_latch); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nPrint byte align loop %d:\n", align_loop->num); ++ flow_loop_dump (align_loop, dump_file, NULL, 1); ++ fprintf (dump_file, "\n\n"); ++ } ++ ++ create_align_loop_exit_bb (align_loop_exit_bb, align_loop_body_bb, ++ align_loop_body_bb, outer); ++ ++ create_loop_pred_bb (epilogue_loop_pred_bb, align_loop_header, ++ align_loop_header, outer); ++ make_edge (align_loop_header, epilogue_loop_pred_bb, EDGE_FALSE_VALUE); ++ ++ create_epilogue_loop_header (epilogue_loop_header, epilogue_loop_pred_bb, ++ epilogue_loop_pred_bb, outer); ++ ++ create_epilogue_loop_body_bb (epilogue_loop_body_bb, epilogue_loop_header, ++ epilogue_loop_header, outer); ++ ++ create_epilogue_loop_latch (epilogue_loop_latch, epilogue_loop_body_bb, ++ epilogue_loop_body_bb, outer); ++ make_single_succ_edge (epilogue_loop_latch, epilogue_loop_header, ++ EDGE_FALLTHRU); ++ rewrite_add_phi_arg (epilogue_loop_header); ++ ++ epilogue_loop = init_new_loop (outer, epilogue_loop_header, ++ epilogue_loop_latch); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nPrint epilogue loop %d:\n", epilogue_loop->num); ++ flow_loop_dump (epilogue_loop, dump_file, NULL, 1); ++ fprintf (dump_file, "\n\n"); ++ } ++ make_single_succ_edge (align_loop_exit_bb, origin_loop.exit_bb1, ++ EDGE_FALLTHRU); ++ set_immediate_dominator (CDI_DOMINATORS, origin_loop.exit_bb1, ++ entry_edge->src); ++ make_edge (epilogue_loop_body_bb, origin_loop.exit_bb1, EDGE_TRUE_VALUE); ++ ++ make_edge (epilogue_loop_header, origin_loop.exit_bb2, EDGE_FALSE_VALUE); ++ set_immediate_dominator (CDI_DOMINATORS, origin_loop.exit_bb2, ++ entry_edge->src); ++ ++ rewrite_add_phi_arg (origin_loop.exit_bb1); ++ rewrite_add_phi_arg (origin_loop.exit_bb2); ++ ++ remove_edge (origin_loop.exit_e1); ++ remove_edge (origin_loop.exit_e2); ++} ++ ++/* Make sure that the dominance relationship of the newly inserted cfg ++ is not missing. */ ++ ++static void ++update_loop_dominator (cdi_direction dir) ++{ ++ gcc_assert (dom_info_available_p (dir)); ++ ++ basic_block bb; ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ basic_block imm_bb = get_immediate_dominator (dir, bb); ++ if (!imm_bb || bb == origin_loop.exit_bb1) ++ { ++ set_immediate_dominator (CDI_DOMINATORS, bb, ++ recompute_dominator (CDI_DOMINATORS, bb)); ++ continue; ++ } ++ } ++} ++ ++/* Clear information about the original loop. */ ++ ++static void ++remove_origin_loop (class loop *loop) ++{ ++ basic_block *body; ++ ++ body = get_loop_body_in_dom_order (loop); ++ unsigned n = loop->num_nodes; ++ for (unsigned i = 0; i < n; i++) ++ { ++ delete_basic_block (body[i]); ++ } ++ free (body); ++ delete_loop (loop); ++} ++ ++/* Perform the conversion of origin_loop to new_loop. */ ++ ++static void ++convert_to_new_loop (class loop *loop) ++{ ++ create_new_loops (origin_loop.entry_edge); ++ remove_origin_loop (loop); ++ update_loop_dominator (CDI_DOMINATORS); ++ update_ssa (TODO_update_ssa); ++} ++ ++/* The main entry of array-widen-compare optimizes. */ ++ ++static unsigned int ++tree_ssa_array_widen_compare () ++{ ++ unsigned int todo = 0; ++ class loop *loop; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ flow_loops_dump (dump_file, NULL, 1); ++ fprintf (dump_file, "\nConfirm which loop can be optimized using" ++ " array-widen-compare\n"); ++ } ++ ++ enum li_flags LI = LI_FROM_INNERMOST; ++ for (auto loop : loops_list (cfun, LI)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "======================================\n"); ++ fprintf (dump_file, "Processing loop %d:\n", loop->num); ++ fprintf (dump_file, "======================================\n"); ++ flow_loop_dump (loop, dump_file, NULL, 1); ++ fprintf (dump_file, "\n\n"); ++ } ++ ++ if (determine_loop_form (loop)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "The %dth loop form is success matched," ++ "and the loop can be optimized.\n", ++ loop->num); ++ dump_loop_bb (loop); ++ } ++ ++ convert_to_new_loop (loop); ++ } ++ } ++ ++ todo |= (TODO_update_ssa); ++ return todo; ++} ++ ++/* Array widen compare. */ ++ ++namespace { ++ ++const pass_data pass_data_tree_array_widen_compare = ++{ ++ GIMPLE_PASS, ++ "awiden_compare", ++ OPTGROUP_LOOP, ++ TV_TREE_ARRAY_WIDEN_COMPARE, ++ (PROP_cfg | PROP_ssa), ++ 0, ++ 0, ++ 0, ++ (TODO_update_ssa | TODO_verify_all) ++}; ++ ++class pass_array_widen_compare : public gimple_opt_pass ++{ ++public: ++ pass_array_widen_compare (gcc::context *ctxt) ++ : gimple_opt_pass (pass_data_tree_array_widen_compare, ctxt) ++ {} ++ ++ /* opt_pass methods: */ ++ virtual bool gate (function *); ++ virtual unsigned int execute (function *); ++ ++}; // class pass_array_widen_compare ++ ++bool ++pass_array_widen_compare::gate (function *) ++{ ++ return (flag_array_widen_compare > 0 && optimize >= 3); ++} ++ ++unsigned int ++pass_array_widen_compare::execute (function *fun) ++{ ++ if (number_of_loops (fun) <= 1) ++ return 0; ++ ++ /* Only supports LP64 data mode. */ ++ if (TYPE_PRECISION (long_integer_type_node) != 64 ++ || POINTER_SIZE != 64 || TYPE_PRECISION (integer_type_node) != 32) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "The current data mode is not supported," ++ "only the LP64 date mode is supported.\n"); ++ return 0; ++ } ++ ++ return tree_ssa_array_widen_compare (); ++} ++ ++} // anon namespace ++ ++gimple_opt_pass * ++make_pass_array_widen_compare (gcc::context *ctxt) ++{ ++ return new pass_array_widen_compare (ctxt); ++} +-- +2.33.0 + diff --git a/0015-Backport-Structure-reorganization-optimization.patch b/0015-Backport-Structure-reorganization-optimization.patch new file mode 100644 index 0000000..d380916 --- /dev/null +++ b/0015-Backport-Structure-reorganization-optimization.patch @@ -0,0 +1,6170 @@ +From 8631d4a39453bb262675bea9abb5c1b7d52af624 Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Wed, 19 Jul 2023 10:28:04 +0800 +Subject: [PATCH 15/22] [Backport] Structure reorganization optimization + +Reference: https://gcc.gnu.org/git/?p=gcc-old.git;a=commit;h=6e1bd1c900533c627b5e4fbbecb41dcd7974b522 + +Introduce structure reorganization optimization, that change C-like +structures layout in order to better utilize spatial locality. This +transformation is affective for programs containing arrays of structures. +--- + gcc/Makefile.in | 1 + + gcc/common.opt | 4 +- + gcc/configure | 2 +- + gcc/configure.ac | 2 +- + gcc/doc/invoke.texi | 23 + + gcc/gimple-ssa-warn-access.cc | 8 + + gcc/ipa-param-manipulation.cc | 3 +- + gcc/ipa-param-manipulation.h | 3 +- + gcc/ipa-struct-reorg/escapes.def | 60 + + gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 4015 +++++++++++++++++ + gcc/ipa-struct-reorg/ipa-struct-reorg.h | 235 + + gcc/params.opt | 4 + + gcc/passes.def | 2 + + gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 35 + + gcc/testsuite/gcc.dg/struct/struct_reorg-1.c | 24 + + gcc/testsuite/gcc.dg/struct/struct_reorg-2.c | 29 + + gcc/testsuite/gcc.dg/struct/struct_reorg-3.c | 23 + + gcc/testsuite/gcc.dg/struct/struct_reorg-4.c | 59 + + .../gcc.dg/struct/w_prof_global_array.c | 29 + + .../gcc.dg/struct/w_prof_global_var.c | 42 + + .../gcc.dg/struct/w_prof_local_array.c | 37 + + .../gcc.dg/struct/w_prof_local_var.c | 40 + + .../gcc.dg/struct/w_prof_single_str_global.c | 31 + + gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c | 64 + + .../gcc.dg/struct/w_ratio_cold_str.c | 43 + + .../gcc.dg/struct/wo_prof_array_field.c | 26 + + .../struct/wo_prof_array_through_pointer.c | 38 + + .../gcc.dg/struct/wo_prof_double_malloc.c | 29 + + .../gcc.dg/struct/wo_prof_empty_str.c | 44 + + .../struct/wo_prof_escape_arg_to_local.c | 44 + + .../gcc.dg/struct/wo_prof_escape_return-1.c | 33 + + .../gcc.dg/struct/wo_prof_escape_return.c | 32 + + .../gcc.dg/struct/wo_prof_escape_str_init.c | 31 + + .../struct/wo_prof_escape_substr_array.c | 33 + + .../struct/wo_prof_escape_substr_pointer.c | 48 + + .../struct/wo_prof_escape_substr_value.c | 45 + + .../gcc.dg/struct/wo_prof_global_array.c | 32 + + .../gcc.dg/struct/wo_prof_global_var.c | 45 + + .../gcc.dg/struct/wo_prof_local_array.c | 40 + + .../gcc.dg/struct/wo_prof_local_var.c | 43 + + .../gcc.dg/struct/wo_prof_malloc_size_var-1.c | 47 + + .../gcc.dg/struct/wo_prof_malloc_size_var.c | 47 + + .../struct/wo_prof_mult_field_peeling.c | 42 + + .../gcc.dg/struct/wo_prof_single_str_global.c | 34 + + .../gcc.dg/struct/wo_prof_single_str_local.c | 34 + + .../struct/wo_prof_single_str_pointer.c | 38 + + .../gcc.dg/struct/wo_prof_two_strs.c | 67 + + gcc/timevar.def | 1 + + gcc/tree-pass.h | 1 + + 49 files changed, 5686 insertions(+), 6 deletions(-) + create mode 100644 gcc/ipa-struct-reorg/escapes.def + create mode 100644 gcc/ipa-struct-reorg/ipa-struct-reorg.cc + create mode 100644 gcc/ipa-struct-reorg/ipa-struct-reorg.h + create mode 100644 gcc/testsuite/gcc.dg/struct/struct-reorg.exp + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-1.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-2.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-3.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-4.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_prof_global_array.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_prof_global_var.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_prof_local_array.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_prof_local_var.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_prof_two_strs.c + create mode 100644 gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_array_field.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_array_through_pointer.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_double_malloc.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_return-1.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_array.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_value.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_global_var.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_local_array.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_local_var.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var-1.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_single_str_global.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_single_str_local.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_single_str_pointer.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_two_strs.c + +diff --git a/gcc/Makefile.in b/gcc/Makefile.in +index 31ff95500..c863ad992 100644 +--- a/gcc/Makefile.in ++++ b/gcc/Makefile.in +@@ -1451,6 +1451,7 @@ OBJS = \ + incpath.o \ + init-regs.o \ + internal-fn.o \ ++ ipa-struct-reorg/ipa-struct-reorg.o \ + ipa-cp.o \ + ipa-sra.o \ + ipa-devirt.o \ +diff --git a/gcc/common.opt b/gcc/common.opt +index e365a48bc..b48fa3228 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1950,8 +1950,8 @@ Common Ignore + Does nothing. Preserved for backward compatibility. + + fipa-struct-reorg +-Common Ignore +-Does nothing. Preserved for backward compatibility. ++Common Var(flag_ipa_struct_reorg) Init(0) Optimization ++Perform structure layout optimizations. + + fipa-vrp + Common Var(flag_ipa_vrp) Optimization +diff --git a/gcc/configure b/gcc/configure +index c749ace01..98bbf0f85 100755 +--- a/gcc/configure ++++ b/gcc/configure +@@ -34191,7 +34191,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} + "depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;; + "gccdepdir":C) + ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR +- for lang in $subdirs c-family common analyzer rtl-ssa ++ for lang in $subdirs c-family common analyzer rtl-ssa ipa-struct-reorg + do + ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR + done ;; +diff --git a/gcc/configure.ac b/gcc/configure.ac +index 992a50e7b..c74f4b555 100644 +--- a/gcc/configure.ac ++++ b/gcc/configure.ac +@@ -1340,7 +1340,7 @@ AC_CHECK_HEADERS(ext/hash_map) + ZW_CREATE_DEPDIR + AC_CONFIG_COMMANDS([gccdepdir],[ + ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR +- for lang in $subdirs c-family common analyzer rtl-ssa ++ for lang in $subdirs c-family common analyzer rtl-ssa ipa-struct-reorg + do + ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR + done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR]) +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index ff8cd032f..e37bae5b1 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -526,6 +526,7 @@ Objective-C and Objective-C++ Dialects}. + -finline-functions -finline-functions-called-once -finline-limit=@var{n} @gol + -finline-small-functions -fipa-modref -fipa-cp -fipa-cp-clone @gol + -fipa-bit-cp -fipa-vrp -fipa-pta -fipa-profile -fipa-pure-const @gol ++-fipa-struct-reorg @gol + -fipa-reference -fipa-reference-addressable @gol + -fipa-stack-alignment -fipa-icf -fira-algorithm=@var{algorithm} @gol + -flive-patching=@var{level} @gol +@@ -11886,6 +11887,19 @@ higher. + Discover which functions are pure or constant. + Enabled by default at @option{-O1} and higher. + ++@item -fipa-struct-reorg ++@opindex fipa-struct-reorg ++Perform structure reorganization optimization, that change C-like structures ++layout in order to better utilize spatial locality. This transformation is ++affective for programs containing arrays of structures. Available in two ++compilation modes: profile-based (enabled with @option{-fprofile-generate}) ++or static (which uses built-in heuristics). It works only in whole program ++mode, so it requires @option{-fwhole-program} to be ++enabled. Structures considered @samp{cold} by this transformation are not ++affected (see @option{--param struct-reorg-cold-struct-ratio=@var{value}}). ++ ++With this flag, the program debug info reflects a new structure layout. ++ + @item -fipa-reference + @opindex fipa-reference + Discover which static variables do not escape the +@@ -13772,6 +13786,15 @@ In each case, the @var{value} is an integer. The following choices + of @var{name} are recognized for all targets: + + @table @gcctabopt ++@item struct-reorg-cold-struct-ratio ++The threshold ratio (as a percentage) between a structure frequency ++and the frequency of the hottest structure in the program. This parameter ++is used by struct-reorg optimization enabled by @option{-fipa-struct-reorg}. ++We say that if the ratio of a structure frequency, calculated by profiling, ++to the hottest structure frequency in the program is less than this ++parameter, then structure reorganization is not applied to this structure. ++The default is 10. ++ + @item predictable-branch-outcome + When branch is predicted to be taken with probability lower than this threshold + (in percent), then it is considered well predictable. +diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc +index 8d088ad33..a24645783 100644 +--- a/gcc/gimple-ssa-warn-access.cc ++++ b/gcc/gimple-ssa-warn-access.cc +@@ -2193,6 +2193,14 @@ pass_waccess::set_pass_param (unsigned int n, bool early) + bool + pass_waccess::gate (function *) + { ++ /* FIXME: In structure optimizations, some statements will be ++ rewritten and removed from the BB, leaving some unused SSA. ++ In pass waccess, it will traverse all SSA and cause ICE ++ when handling these unused SSA. So temporarily disable ++ pass waccess when enable structure optimizations. */ ++ if (flag_ipa_struct_reorg) ++ return false; ++ + return (warn_free_nonheap_object + || warn_mismatched_alloc + || warn_mismatched_new_delete); +diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc +index 38328c3e8..f9e956008 100644 +--- a/gcc/ipa-param-manipulation.cc ++++ b/gcc/ipa-param-manipulation.cc +@@ -55,7 +55,8 @@ static const char *ipa_param_prefixes[IPA_PARAM_PREFIX_COUNT] + = {"SYNTH", + "ISRA", + "simd", +- "mask"}; ++ "mask", ++ "struct_reorg"}; + + /* Names of parameters for dumping. Keep in sync with enum ipa_parm_op. */ + +diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h +index a9ad2b216..71f4a0a2f 100644 +--- a/gcc/ipa-param-manipulation.h ++++ b/gcc/ipa-param-manipulation.h +@@ -126,6 +126,7 @@ enum ipa_param_name_prefix_indices + IPA_PARAM_PREFIX_ISRA, + IPA_PARAM_PREFIX_SIMD, + IPA_PARAM_PREFIX_MASK, ++ IPA_PARAM_PREFIX_REORG, + IPA_PARAM_PREFIX_COUNT + }; + +@@ -189,7 +190,7 @@ struct GTY(()) ipa_adjusted_param + + /* Index into ipa_param_prefixes specifying a prefix to be used with + DECL_NAMEs of newly synthesized parameters. */ +- unsigned param_prefix_index : 2; ++ unsigned param_prefix_index : 3; + + /* Storage order of the original parameter (for the cases when the new + parameter is a component of an original one). */ +diff --git a/gcc/ipa-struct-reorg/escapes.def b/gcc/ipa-struct-reorg/escapes.def +new file mode 100644 +index 000000000..c4c8e0739 +--- /dev/null ++++ b/gcc/ipa-struct-reorg/escapes.def +@@ -0,0 +1,60 @@ ++/* Copyright (C) 2016-2023 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 ++. */ ++ ++/* Before including this file, you should define a macro: ++ DEF_ESCAPE (ENUM, TEXT) ++ ++ This macro will be called once for each escape reason. The ++ ENUM will be of type "escape_type". The TEXT is describing ++ the reason for the escape. ++*/ ++DEF_ESCAPE (escape_marked_as_used, "Type used in variable marked as used") ++DEF_ESCAPE (escape_via_global_var, "Type used via a external visible variable") ++DEF_ESCAPE (escape_via_global_init, "Type used via a global init of a variable") ++DEF_ESCAPE (escape_non_supported_allocator, "Type used by allocation which is not currently supported") ++DEF_ESCAPE (escape_dependent_type_escapes, "Type uses a type which escapes or is used by a type which escapes") ++DEF_ESCAPE (escape_var_arg_function, "Types escapes via a variable argument function") ++DEF_ESCAPE (escape_bitfields, "Types has bitfields") ++DEF_ESCAPE (escape_recusive_type, "Type has a recusive relationship") ++DEF_ESCAPE (escape_variable_sized_array, "Type has a variable sized type") ++DEF_ESCAPE (escape_external_function, "Type escapes via an external function call") ++DEF_ESCAPE (escape_visible_function, "Type escapes via expternally visible function call") ++DEF_ESCAPE (escape_pointer_function, "Type escapes via an function pointer call") ++DEF_ESCAPE (escape_unkown_field, "Type escapes via an unkown field accessed") ++DEF_ESCAPE (escape_union, "Type escapes via an union") ++DEF_ESCAPE (escape_inline_asm, "Type escapes via inline-asm") ++DEF_ESCAPE (escape_non_multiply_size, "Type escapes a pointer plus which is not a multiplicate of the size") ++DEF_ESCAPE (escape_cast_void, "Type escapes a cast to/from void*") ++DEF_ESCAPE (escape_cast_another_ptr, "Type escapes a cast to a different pointer") ++DEF_ESCAPE (escape_cast_int, "Type escapes a cast from/to intergral type") ++DEF_ESCAPE (escape_int_const, "Type escapes via integer constant") ++DEF_ESCAPE (escape_vce, "Type escapes via a VIEW_CONVERT_EXPR") ++DEF_ESCAPE (escape_array_access, "Type escapes via an array access") ++DEF_ESCAPE (escape_noclonable_function, "Type escapes via a non-clonable function") ++DEF_ESCAPE (escape_rescusive_type, "Recusive type") ++DEF_ESCAPE (escape_user_alignment, "Type has an user alignment set") ++DEF_ESCAPE (escape_volatile, "Type has an variable which is volatile") ++DEF_ESCAPE (escape_non_eq, "Type has a comparison other than equals or not equals") ++DEF_ESCAPE (escape_addr, "Type escapes via taking the address of field") ++DEF_ESCAPE (escape_cannot_change_signature, "Type used in a call that cannot change signature") ++DEF_ESCAPE (escape_non_optimize, "Type used by a function which turns off struct reorg") ++DEF_ESCAPE (escape_array, "Type is used in an array [not handled yet]") ++DEF_ESCAPE (escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]") ++DEF_ESCAPE (escape_return, "Type escapes via a return [not handled yet]") ++ ++#undef DEF_ESCAPE +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +new file mode 100644 +index 000000000..238530860 +--- /dev/null ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +@@ -0,0 +1,4015 @@ ++/* Struct-reorg optimizations. ++ Copyright (C) 2016-2023 Free Software Foundation, Inc. ++ Contributed by Andrew Pinski ++ ++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 ++. */ ++ ++/* This pass implements the structure reorganization organization ++ (struct-reorg). ++ ++ Right now it handles just splitting off the hottest fields for a struct ++ of 2 fields: ++ struct s { ++ type1 field1; // Hot field ++ type2 field2; ++ }; ++ s *v; ++ into: ++ struct s_hot { ++ type1 field1; ++ }; ++ struct c_cold { ++ type2 field2; ++ }; ++ s_hot *v_hot; ++ s_cold *v_cold; ++ ++ TODO: This pass can be extended to more fields, and other alogrothims ++ like reordering. ++ ++ This pass operate in four stages: ++ 1. All of the field accesses, declarations (struct types and pointers ++ to that type) and struct types are scanned and recorded. This includes ++ global declarations. Also record all allocation and freeing sites; ++ this is needed for the rewriting phase. ++ ++ FIXME: If there is a top-level inline-asm, the pass immediately returns. ++ ++ 2. Prune out the types which are considered escaping. ++ Examples of types which are considered escaping: ++ a. A declaration has been marked as having the attribute used or ++ has user defined alignment (type too). ++ b. Accesses are via a BIT_FIELD_REF. ++ FIXME: Handle VECTOR_TYPE for this case. ++ c. The "allocation" site is not a known builtin function. ++ d. Casting to/from an integer. ++ ++ 3. Analyze the types for which optimization to do. ++ a. Split the fields into two different structs. ++ (FIXME: two field case handled only) ++ Look at all structs which contain two fields, if one of the fields ++ is hotter then split it and put it on the rewritting for accesses. ++ Allocations and freeing are marked to split into two functions; ++ all uses of that type will now be considered as two. ++ b. Reorder fields hottest to the coldest. TODO: Implement. ++ ++ 4. Rewrite each access and allocation and free whichis marked as ++ rewriting. ++ ++*/ ++ ++#include "config.h" ++#include "system.h" ++#include "coretypes.h" ++#include "tm.h" ++#include "tree.h" ++#include "tree-pass.h" ++#include "cgraph.h" ++#include "diagnostic-core.h" ++#include "function.h" ++#include "basic-block.h" ++#include "gimple.h" ++#include "vec.h" ++#include "tree-pretty-print.h" ++#include "gimple-pretty-print.h" ++#include "gimple-iterator.h" ++#include "cfg.h" ++#include "ssa.h" ++#include "tree-dfa.h" ++#include "fold-const.h" ++#include "tree-inline.h" ++#include "stor-layout.h" ++#include "tree-into-ssa.h" ++#include "tree-cfg.h" ++#include "alloc-pool.h" ++#include "symbol-summary.h" ++#include "ipa-prop.h" ++#include "ipa-struct-reorg.h" ++#include "tree-eh.h" ++#include "bitmap.h" ++#include "tree-ssa-live.h" /* For remove_unused_locals. */ ++#include "ipa-param-manipulation.h" ++#include "gimplify-me.h" ++ ++namespace { ++ ++using namespace struct_reorg; ++ ++#define VOID_POINTER_P(type) \ ++ (POINTER_TYPE_P (type) && VOID_TYPE_P (TREE_TYPE (type))) ++ ++/* Return true iff TYPE is stdarg va_list type. */ ++ ++static inline bool ++is_va_list_type (tree type) ++{ ++ return TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node); ++} ++ ++static const char * ++get_type_name (tree type) ++{ ++ const char *tname = NULL; ++ ++ if (type == NULL) ++ return NULL; ++ ++ if (TYPE_NAME (type) != NULL) ++ { ++ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) ++ tname = IDENTIFIER_POINTER (TYPE_NAME (type)); ++ else if (DECL_NAME (TYPE_NAME (type)) != NULL) ++ tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); ++ } ++ return tname; ++} ++ ++/* Return the inner most type for arrays and pointers of TYPE. */ ++ ++static tree ++inner_type (tree type) ++{ ++ while (POINTER_TYPE_P (type) ++ || TREE_CODE (type) == ARRAY_TYPE) ++ type = TREE_TYPE (type); ++ return type; ++} ++ ++/* Return true if TYPE is a type which struct reorg should handled. */ ++ ++static bool ++handled_type (tree type) ++{ ++ type = inner_type (type); ++ if (TREE_CODE (type) == RECORD_TYPE) ++ return !is_va_list_type (type); ++ return false; ++} ++ ++/* The gimplify_buildN API is moved to tree-vect-generic.c locally ++ at commit b972e036f40c12b106f9070c3e8adea0eb8a45fa. ++ ++ The gimplify_buildN API is copied from gcc 10 implementation. ++*/ ++ ++/* Build a binary operation and gimplify it. Emit code before GSI. ++ Return the gimple_val holding the result. */ ++ ++static tree ++gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code, ++ tree type, tree a, tree b) ++{ ++ tree ret; ++ ++ ret = fold_build2_loc (gimple_location (gsi_stmt (*gsi)), code, type, a, b); ++ return force_gimple_operand_gsi (gsi, ret, true, NULL, true, ++ GSI_SAME_STMT); ++} ++ ++/* Build a unary operation and gimplify it. Emit code before GSI. ++ Return the gimple_val holding the result. */ ++ ++static tree ++gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type, ++ tree a) ++{ ++ tree ret; ++ ++ ret = fold_build1_loc (gimple_location (gsi_stmt (*gsi)), code, type, a); ++ return force_gimple_operand_gsi (gsi, ret, true, NULL, true, ++ GSI_SAME_STMT); ++} ++ ++} // anon namespace ++ ++ ++namespace struct_reorg { ++ ++/* Constructor of srfunction. */ ++ ++srfunction::srfunction (cgraph_node *n) ++ : node (n), ++ old (NULL), ++ newnode (NULL), ++ newf (NULL) ++{} ++ ++/* Add an ARG to the list of arguments for the function. */ ++ ++void ++srfunction::add_arg (srdecl *arg) ++{ ++ args.safe_push (arg); ++} ++ ++/* Dump the SRFUNCTION to the file FILE. */ ++ ++void ++srfunction::dump (FILE *file) ++{ ++ if (node) ++ { ++ fprintf (file, "function : "); ++ print_generic_expr (file, node->decl); ++ fprintf (file, " with arguments: "); ++ for (unsigned i = 0; i < args.length (); i++) ++ { ++ if (i == 0) ++ fprintf (file, "\n "); ++ else ++ fprintf (file, "\n, "); ++ args[i]->dump (file); ++ } ++ ++ fprintf (file, "\nuses globals: "); ++ for (unsigned i = 0; i < globals.length (); i++) ++ { ++ fprintf (file, "\n "); ++ globals[i]->dump (file); ++ } ++ ++ fprintf (file, "\ndecls: "); ++ } ++ else ++ fprintf (file, "globals : "); ++ ++ for (unsigned i = 0; i < decls.length (); i++) ++ { ++ fprintf (file, "\n "); ++ decls[i]->dump (file); ++ } ++} ++ ++/* Simple dump the SRFUNCTION to the file FILE; ++ used so it is not recusive. */ ++ ++void ++srfunction::simple_dump (FILE *file) ++{ ++ print_generic_expr (file, node->decl); ++} ++ ++/* Constructor of FIELD. */ ++ ++srfield::srfield (tree field, srtype *base) ++ : offset (int_byte_position (field)), ++ fieldtype (TREE_TYPE (field)), ++ fielddecl (field), ++ base (base), ++ type (NULL), ++ clusternum (0) ++{ ++ for (int i = 0; i < max_split; i++) ++ newfield[i] = NULL_TREE; ++} ++ ++/* Constructor of TYPE. */ ++ ++srtype::srtype (tree type) ++ : type (type), ++ chain_type (false), ++ escapes (does_not_escape), ++ visited (false) ++{ ++ for (int i = 0; i < max_split; i++) ++ newtype[i] = NULL_TREE; ++ ++ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL) ++ { ++ if (DECL_BIT_FIELD (field)) ++ { ++ escapes = escape_bitfields; ++ continue; ++ } ++ else if (!DECL_SIZE (field) ++ || TREE_CODE (DECL_SIZE (field)) != INTEGER_CST) ++ { ++ escapes = escape_variable_sized_array; ++ break; ++ } ++ srfield *t = new srfield (field, this); ++ fields.safe_push (t); ++ } ++ } ++} ++ ++/* Mark the type as escaping type E at statement STMT. */ ++ ++void ++srtype::mark_escape (escape_type e, gimple *stmt) ++{ ++ /* Once the type has escaped, it should never ++ change back to non escaping. */ ++ gcc_assert (e != does_not_escape); ++ if (has_escaped ()) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nO type: "); ++ simple_dump (dump_file); ++ fprintf (dump_file, " has already escaped."); ++ fprintf (dump_file, " old = \"%s\" ", ++ escape_type_string[escapes - 1]); ++ fprintf (dump_file, " new = \"%s\"\n", escape_type_string[e - 1]); ++ if (stmt) ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ return; ++ } ++ escapes = e; ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nN type: "); ++ simple_dump (dump_file); ++ fprintf (dump_file, " new = \"%s\"\n", escape_reason ()); ++ if (stmt) ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++} ++ ++/* Add FIELD to the list of fields that use this type. */ ++ ++void ++srtype::add_field_site (srfield *field) ++{ ++ field_sites.safe_push (field); ++} ++ ++/* Constructor of DECL. */ ++ ++srdecl::srdecl (srtype *tp, tree decl, int argnum) ++ : type (tp), ++ decl (decl), ++ func (NULL_TREE), ++ argumentnum (argnum), ++ visited (false) ++{ ++ if (TREE_CODE (decl) == SSA_NAME) ++ func = current_function_decl; ++ else if (!is_global_var (decl)) ++ func = DECL_CONTEXT (decl); ++ for (int i = 0; i < max_split; i++) ++ newdecl[i] = NULL_TREE; ++} ++ ++/* Find DECL in the function. */ ++ ++srdecl * ++srfunction::find_decl (tree decl) ++{ ++ for (unsigned i = 0; i < decls.length (); i++) ++ if (decls[i]->decl == decl) ++ return decls[i]; ++ return NULL; ++} ++ ++/* Record DECL of the TYPE with argument num ARG. */ ++ ++srdecl * ++srfunction::record_decl (srtype *type, tree decl, int arg) ++{ ++ // Search for the decl to see if it is already there. ++ srdecl *decl1 = find_decl (decl); ++ ++ if (decl1) ++ return decl1; ++ ++ gcc_assert (type); ++ ++ decl1 = new srdecl (type, decl, arg); ++ decls.safe_push (decl1); ++ return decl1; ++} ++ ++/* Find the field at OFF offset. */ ++ ++srfield * ++srtype::find_field (unsigned HOST_WIDE_INT off) ++{ ++ unsigned int i; ++ srfield *field; ++ ++ /* FIXME: handle array/struct field inside the current struct. */ ++ /* NOTE This does not need to be fixed to handle libquatumn. */ ++ FOR_EACH_VEC_ELT (fields, i, field) ++ { ++ if (off == field->offset) ++ return field; ++ } ++ return NULL; ++} ++ ++/* Add the function FN to the list of functions if it ++ is there not already. */ ++ ++void ++srtype::add_function (srfunction *fn) ++{ ++ unsigned decluid; ++ unsigned i; ++ decluid = DECL_UID (fn->node->decl); ++ ++ srfunction *fn1; ++ // Search for the decl to see if it is already there. ++ FOR_EACH_VEC_ELT (functions, i, fn1) ++ { ++ if (DECL_UID (fn1->node->decl) == decluid) ++ return; ++ } ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "Recording new function: %u.\n", decluid); ++ ++ functions.safe_push (fn); ++} ++ ++/* Dump out the type structure to FILE. */ ++ ++void ++srtype::dump (FILE *f) ++{ ++ unsigned int i; ++ srfield *field; ++ srfunction *fn; ++ sraccess *access; ++ ++ if (chain_type) ++ fprintf (f, "chain decl "); ++ ++ fprintf (f, "type : "); ++ print_generic_expr (f, type); ++ fprintf (f, "(%d) { ", TYPE_UID (type)); ++ if (escapes != does_not_escape) ++ fprintf (f, " escapes = \"%s\"\n", escape_reason ()); ++ fprintf (f, " fields = { "); ++ FOR_EACH_VEC_ELT (fields, i, field) ++ { ++ if (i == 0) ++ fprintf (f, "\n "); ++ else ++ fprintf (f, "\n, "); ++ field->dump (f); ++ } ++ fprintf (f, " }\n "); ++ fprintf (f, "\n accesses = {"); ++ FOR_EACH_VEC_ELT (accesses, i, access) ++ { ++ fprintf (f, "\n"); ++ access->dump (f); ++ } ++ fprintf (f, " }\n "); ++ fprintf (f, "\n functions = {"); ++ FOR_EACH_VEC_ELT (functions, i, fn) ++ { ++ fprintf (f, " \n"); ++ fn->simple_dump (f); ++ } ++ fprintf (f, "\n }\n"); ++ fprintf (f, "\n field_sites = {"); ++ FOR_EACH_VEC_ELT (field_sites, i, field) ++ { ++ fprintf (f, " \n"); ++ field->simple_dump (f); ++ } ++ fprintf (f, "\n }\n"); ++ fprintf (f, "}\n"); ++} ++ ++/* A simplified dump out the type structure to FILE. */ ++ ++void ++srtype::simple_dump (FILE *f) ++{ ++ print_generic_expr (f, type); ++} ++ ++/* Analyze the type and decide what to be done with it. */ ++ ++void ++srtype::analyze (void) ++{ ++ /* Chain decl types can't be split ++ so don't try. */ ++ if (chain_type) ++ return; ++ ++ /* If there is only one field then there is nothing ++ to be done. */ ++ if (fields.length () == 1) ++ return; ++ ++ /* For now we unconditionally split only structures with 2 fields ++ into 2 different structures. In future we intend to add profile ++ info and/or static heuristics to differentiate splitting process. */ ++ if (fields.length () == 2) ++ fields[1]->clusternum = 1; ++ ++ /* Otherwise we do nothing. */ ++ if (fields.length () >= 3) ++ return; ++} ++ ++/* Create the new fields for this field. */ ++ ++void ++srfield::create_new_fields (tree newtype[max_split], ++ tree newfields[max_split], ++ tree newlast[max_split]) ++{ ++ tree nt[max_split]; ++ ++ for (unsigned i = 0; i < max_split; i++) ++ nt[i] = NULL; ++ ++ if (type == NULL) ++ nt[0] = fieldtype; ++ else ++ memcpy (nt, type->newtype, sizeof (type->newtype)); ++ ++ for (unsigned i = 0; i < max_split && nt[i] != NULL; i++) ++ { ++ tree field = make_node (FIELD_DECL); ++ if (nt[1] != NULL && DECL_NAME (fielddecl)) ++ { ++ const char *tname = IDENTIFIER_POINTER (DECL_NAME (fielddecl)); ++ char id[10]; ++ char *name; ++ ++ sprintf (id, "%d", i); ++ name = concat (tname, ".reorg.", id, NULL); ++ DECL_NAME (field) = get_identifier (name); ++ free (name); ++ } ++ else ++ DECL_NAME (field) = DECL_NAME (fielddecl); ++ ++ TREE_TYPE (field) = reconstruct_complex_type ( ++ TREE_TYPE (fielddecl), nt[i]); ++ DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (fielddecl); ++ SET_DECL_ALIGN (field, DECL_ALIGN (fielddecl)); ++ DECL_USER_ALIGN (field) = DECL_USER_ALIGN (fielddecl); ++ TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (fielddecl); ++ DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (fielddecl); ++ TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (fielddecl); ++ DECL_CONTEXT (field) = newtype[clusternum]; ++ ++ if (newfields[clusternum] == NULL) ++ newfields[clusternum] = newlast[clusternum] = field; ++ else ++ { ++ DECL_CHAIN (newlast[clusternum]) = field; ++ newlast[clusternum] = field; ++ } ++ newfield[i] = field; ++ } ++} ++ ++/* Create the new TYPE corresponding to THIS type. */ ++ ++bool ++srtype::create_new_type (void) ++{ ++ /* If the type has been visited, ++ then return if a new type was ++ created or not. */ ++ if (visited) ++ return has_new_type (); ++ ++ visited = true; ++ ++ if (escapes != does_not_escape) ++ { ++ newtype[0] = type; ++ return false; ++ } ++ ++ bool createnewtype = false; ++ unsigned maxclusters = 0; ++ ++ /* Create a new type for each field. */ ++ for (unsigned i = 0; i < fields.length (); i++) ++ { ++ srfield *field = fields[i]; ++ if (field->type) ++ createnewtype |= field->type->create_new_type (); ++ if (field->clusternum > maxclusters) ++ maxclusters = field->clusternum; ++ } ++ ++ /* If the fields' types did have a change or ++ we are not splitting the struct into two clusters, ++ then just return false and don't change the type. */ ++ if (!createnewtype && maxclusters == 0) ++ { ++ newtype[0] = type; ++ return false; ++ } ++ ++ /* Should have at most max_split clusters. */ ++ gcc_assert (maxclusters < max_split); ++ ++ tree newfields[max_split]; ++ tree newlast[max_split]; ++ ++ maxclusters++; ++ ++ const char *tname = NULL; ++ ++ if (TYPE_NAME (type) != NULL) ++ { ++ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) ++ tname = IDENTIFIER_POINTER (TYPE_NAME (type)); ++ else if (DECL_NAME (TYPE_NAME (type)) != NULL) ++ tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); ++ } ++ ++ for (unsigned i = 0; i < maxclusters; i++) ++ { ++ newfields[i] = NULL_TREE; ++ newlast[i] = NULL_TREE; ++ newtype[i] = make_node (RECORD_TYPE); ++ ++ char *name = NULL; ++ char id[10]; ++ sprintf (id, "%d", i); ++ if (tname) ++ { ++ name = concat (tname, ".reorg.", id, NULL); ++ TYPE_NAME (newtype[i]) = get_identifier (name); ++ free (name); ++ } ++ } ++ ++ for (unsigned i = 0; i < fields.length (); i++) ++ { ++ srfield *f = fields[i]; ++ f->create_new_fields (newtype, newfields, newlast); ++ } ++ ++ /* No reason to warn about these structs since the warning would ++ have happened already. */ ++ int save_warn_padded = warn_padded; ++ warn_padded = 0; ++ ++ for (unsigned i = 0; i < maxclusters; i++) ++ { ++ TYPE_FIELDS (newtype[i]) = newfields[i]; ++ layout_type (newtype[i]); ++ } ++ ++ warn_padded = save_warn_padded; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Created %d types:\n", maxclusters); ++ for (unsigned i = 0; i < maxclusters; i++) ++ { ++ print_generic_expr (dump_file, newtype[i]); ++ fprintf (dump_file, "\n"); ++ } ++ } ++ ++ return true; ++} ++ ++/* Helper function to copy some attributes from ORIG_DECL to the NEW_DECL. */ ++ ++static inline void ++copy_var_attributes (tree new_decl, tree orig_decl) ++{ ++ DECL_ARTIFICIAL (new_decl) = 1; ++ DECL_EXTERNAL (new_decl) = DECL_EXTERNAL (orig_decl); ++ TREE_STATIC (new_decl) = TREE_STATIC (orig_decl); ++ TREE_PUBLIC (new_decl) = TREE_PUBLIC (orig_decl); ++ TREE_USED (new_decl) = TREE_USED (orig_decl); ++ DECL_CONTEXT (new_decl) = DECL_CONTEXT (orig_decl); ++ TREE_THIS_VOLATILE (new_decl) = TREE_THIS_VOLATILE (orig_decl); ++ TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (orig_decl); ++ TREE_READONLY (new_decl) = TREE_READONLY (orig_decl); ++ if (is_global_var (orig_decl)) ++ set_decl_tls_model (new_decl, DECL_TLS_MODEL (orig_decl)); ++} ++ ++/* Create all of the new decls (SSA_NAMES included) for THIS function. */ ++ ++void ++srfunction::create_new_decls (void) ++{ ++ /* If this function has been cloned, we don't need to ++ create the new decls. */ ++ if (newnode) ++ return; ++ ++ if (node) ++ set_cfun (DECL_STRUCT_FUNCTION (node->decl)); ++ ++ for (unsigned i = 0; i < decls.length (); i++) ++ { ++ srdecl *decl = decls[i]; ++ srtype *type = decl->type; ++ /* If the type of the decl does not change, ++ then don't create a new decl. */ ++ if (!type->has_new_type ()) ++ { ++ decl->newdecl[0] = decl->decl; ++ continue; ++ } ++ ++ /* Handle SSA_NAMEs. */ ++ if (TREE_CODE (decl->decl) == SSA_NAME) ++ { ++ tree newtype1[max_split]; ++ tree inner = SSA_NAME_VAR (decl->decl); ++ tree newinner[max_split]; ++ memset (newinner, 0, sizeof (newinner)); ++ for (unsigned j = 0; j < max_split && type->newtype[j]; j++) ++ newtype1[j] = reconstruct_complex_type (TREE_TYPE (decls[i]->decl), ++ type->newtype[j]); ++ if (inner) ++ { ++ srdecl *in = find_decl (inner); ++ gcc_assert (in); ++ memcpy (newinner, in->newdecl, sizeof (newinner)); ++ } ++ tree od = decls[i]->decl; ++ /* Create the new ssa names and copy some attributes ++ from the old one. */ ++ for (unsigned j = 0; j < max_split && type->newtype[j]; j++) ++ { ++ tree nd = make_ssa_name (newinner[j] ? newinner[j] ++ : newtype1[j]); ++ decl->newdecl[j] = nd; ++ /* If the old decl was a default definition, ++ handle it specially. */ ++ if (SSA_NAME_IS_DEFAULT_DEF (od)) ++ { ++ SSA_NAME_IS_DEFAULT_DEF (nd) = true; ++ SSA_NAME_DEF_STMT (nd) = gimple_build_nop (); ++ ++ /* Set the default definition for the ssaname if needed. */ ++ if (inner) ++ { ++ gcc_assert (newinner[j]); ++ set_ssa_default_def (cfun, newinner[j], nd); ++ } ++ } ++ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (nd) ++ = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (od); ++ statistics_counter_event (cfun, "Create new ssa_name", 1); ++ } ++ } ++ else if (TREE_CODE (decls[i]->decl) == VAR_DECL) ++ { ++ tree orig_var = decl->decl; ++ const char *tname = NULL; ++ if (DECL_NAME (orig_var)) ++ tname = IDENTIFIER_POINTER (DECL_NAME (orig_var)); ++ for (unsigned j = 0; j < max_split && type->newtype[j]; j++) ++ { ++ tree new_name = NULL; ++ char *name = NULL; ++ char id[10]; ++ sprintf (id, "%d", j); ++ if (tname) ++ { ++ name = concat (tname, ".reorg.", id, NULL); ++ new_name = get_identifier (name); ++ free (name); ++ } ++ tree newtype1 = reconstruct_complex_type (TREE_TYPE (orig_var), ++ type->newtype[j]); ++ decl->newdecl[j] = build_decl (DECL_SOURCE_LOCATION (orig_var), ++ VAR_DECL, new_name, newtype1); ++ copy_var_attributes (decl->newdecl[j], orig_var); ++ if (!is_global_var (orig_var)) ++ add_local_decl (cfun, decl->newdecl[j]); ++ else ++ varpool_node::add (decl->newdecl[j]); ++ statistics_counter_event (cfun, "Create new var decl", 1); ++ } ++ } ++ /* Paramater decls are already handled in create_new_functions. */ ++ else if (TREE_CODE (decls[i]->decl) == PARM_DECL) ++ ; ++ else ++ internal_error ("Unhandled declaration type stored"); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Created New decls for decl:\n"); ++ fprintf (dump_file, "\n"); ++ decls[i]->dump (dump_file); ++ fprintf (dump_file, "\n"); ++ for (unsigned j = 0; j < max_split && decls[i]->newdecl[j]; j++) ++ { ++ print_generic_expr (dump_file, decls[i]->newdecl[j]); ++ fprintf (dump_file, "\n"); ++ } ++ fprintf (dump_file, "\n"); ++ } ++ } ++ ++ set_cfun (NULL); ++} ++ ++/* Dump out the field structure to FILE. */ ++ ++void ++srfield::dump (FILE *f) ++{ ++ fprintf (f, "field (%d) { ", DECL_UID (fielddecl)); ++ fprintf (f, "base = "); ++ base->simple_dump (f); ++ fprintf (f, ", offset = " HOST_WIDE_INT_PRINT_DEC, offset); ++ fprintf (f, ", type = "); ++ print_generic_expr (f, fieldtype); ++ if (type) ++ { ++ fprintf (f, "( srtype = "); ++ type->simple_dump (f); ++ fprintf (f, ")"); ++ } ++ fprintf (f, "\n}\n"); ++} ++ ++/* A simplified dump out the field structure to FILE. */ ++ ++void ++srfield::simple_dump (FILE *f) ++{ ++ fprintf (f, "field (%d)", DECL_UID (fielddecl)); ++} ++ ++/* Dump out the access structure to FILE. */ ++ ++void ++sraccess::dump (FILE *f) ++{ ++ fprintf (f, "access { "); ++ fprintf (f, "type = '("); ++ type->simple_dump (f); ++ fprintf (f, ")'"); ++ if (field) ++ { ++ fprintf (f, ", field = '("); ++ field->simple_dump (f); ++ fprintf (f, ")'"); ++ } ++ else ++ fprintf (f, ", whole type"); ++ fprintf (f, " in function: %s/%d", node->name (), node->order); ++ fprintf (f, ", stmt:\n"); ++ print_gimple_stmt (f, stmt, 0); ++ fprintf (f, "\n }\n"); ++} ++ ++/* Dump out the decl structure to FILE. */ ++ ++void ++srdecl::dump (FILE *file) ++{ ++ if (!func) ++ fprintf (file, "global "); ++ if (argumentnum != -1) ++ fprintf (file, "argument(%d) ", argumentnum); ++ fprintf (file, "decl: "); ++ print_generic_expr (file, decl); ++ fprintf (file, " type: "); ++ type->simple_dump (file); ++} ++ ++} // namespace struct_reorg ++ ++ ++namespace { ++ ++struct ipa_struct_reorg ++{ ++public: ++ // Constructors ++ ipa_struct_reorg (void) ++ : current_function (NULL), ++ done_recording (false) ++ {} ++ ++ // Public methods ++ unsigned execute (void); ++ void mark_type_as_escape (tree type, escape_type, gimple *stmt = NULL); ++private: ++ // Fields ++ auto_vec_del types; ++ auto_vec_del functions; ++ srglobal globals; ++ srfunction *current_function; ++ ++ bool done_recording; ++ ++ // Private methods ++ void dump_types (FILE *f); ++ void dump_types_escaped (FILE *f); ++ void dump_functions (FILE *f); ++ void record_accesses (void); ++ void detect_cycles (void); ++ bool walk_field_for_cycles (srtype *); ++ void prune_escaped_types (void); ++ void propagate_escape (void); ++ void analyze_types (void); ++ void clear_visited (void); ++ bool create_new_types (void); ++ void restore_field_type (void); ++ void create_new_decls (void); ++ srdecl *find_decl (tree); ++ void create_new_functions (void); ++ void create_new_args (cgraph_node *new_node); ++ unsigned rewrite_functions (void); ++ srdecl *record_var (tree decl, ++ escape_type escapes = does_not_escape, ++ int arg = -1); ++ srfunction *record_function (cgraph_node *node); ++ srfunction *find_function (cgraph_node *node); ++ srtype *record_type (tree type); ++ void process_union (tree type); ++ srtype *find_type (tree type); ++ void maybe_record_stmt (cgraph_node *, gimple *); ++ void maybe_record_assign (cgraph_node *, gassign *); ++ void maybe_record_call (cgraph_node *, gcall *); ++ void maybe_record_allocation_site (cgraph_node *, gimple *); ++ void record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt); ++ void mark_expr_escape (tree, escape_type, gimple *stmt); ++ tree allocate_size (srtype *t, gimple *stmt); ++ ++ void mark_decls_in_as_not_needed (tree fn); ++ ++ bool rewrite_stmt (gimple *, gimple_stmt_iterator *); ++ bool rewrite_assign (gassign *, gimple_stmt_iterator *); ++ bool rewrite_call (gcall *, gimple_stmt_iterator *); ++ bool rewrite_cond (gcond *, gimple_stmt_iterator *); ++ bool rewrite_debug (gimple *, gimple_stmt_iterator *); ++ bool rewrite_phi (gphi *); ++ bool rewrite_expr (tree expr, ++ tree newexpr[max_split], ++ bool ignore_missing_decl = false); ++ bool rewrite_lhs_rhs (tree lhs, tree rhs, tree newlhs[max_split], ++ tree newrhs[max_split]); ++ bool get_type_field (tree expr, tree &base, bool &indirect, ++ srtype *&type, srfield *&field, ++ bool &realpart, bool &imagpart, ++ bool &address, bool should_create = false, ++ bool can_escape = false); ++ bool wholeaccess (tree expr, tree base, tree accesstype, srtype *t); ++ ++ void check_definition (srdecl *decl, vec &); ++ void check_uses (srdecl *decl, vec &); ++ void check_use (srdecl *decl, gimple *stmt, vec &); ++ void check_type_and_push (tree newdecl, srtype *type, ++ vec &worklist, gimple *stmt); ++ void check_other_side (srdecl *decl, tree other, gimple *stmt, ++ vec &worklist); ++ ++ void find_vars (gimple *stmt); ++ void find_var (tree expr, gimple *stmt); ++ void mark_types_asm (gasm *astmt); ++ ++ bool has_rewritten_type (srfunction *); ++ void maybe_mark_or_record_other_side (tree side, tree other, gimple *stmt); ++}; ++ ++/* Dump all of the recorded types to file F. */ ++ ++void ++ipa_struct_reorg::dump_types (FILE *f) ++{ ++ unsigned i; ++ srtype *type; ++ FOR_EACH_VEC_ELT (types, i, type) ++ { ++ type->dump (f); ++ } ++ fprintf (f, "\n"); ++} ++ ++/* Dump all of the recorded types to file F. */ ++ ++void ++ipa_struct_reorg::dump_types_escaped (FILE *f) ++{ ++ unsigned i; ++ srtype *type; ++ FOR_EACH_VEC_ELT (types, i, type) ++ { ++ if (type->has_escaped ()) ++ { ++ type->simple_dump (f); ++ fprintf (f, " has escaped: \"%s\"\n", type->escape_reason ()); ++ } ++ } ++ fprintf (f, "\n"); ++} ++ ++/* Dump all of the record functions to file F. */ ++ ++void ++ipa_struct_reorg::dump_functions (FILE *f) ++{ ++ unsigned i; ++ srfunction *fn; ++ ++ fprintf (f, "\n\n"); ++ globals.dump (f); ++ fprintf (f, "\n\n"); ++ FOR_EACH_VEC_ELT (functions, i, fn) ++ { ++ fn->dump (f); ++ fprintf (f, "\n"); ++ } ++ fprintf (f, "\n\n"); ++} ++ ++/* Find the recorded srtype corresponding to TYPE. */ ++ ++srtype * ++ipa_struct_reorg::find_type (tree type) ++{ ++ unsigned i; ++ /* Get the main variant as we are going ++ to find that type only. */ ++ type = TYPE_MAIN_VARIANT (type); ++ ++ srtype *type1; ++ // Search for the type to see if it is already there. ++ FOR_EACH_VEC_ELT (types, i, type1) ++ { ++ if (types_compatible_p (type1->type, type)) ++ return type1; ++ } ++ return NULL; ++} ++ ++/* Is TYPE a volatile type or one which points ++ to a volatile type. */ ++ ++static bool ++isvolatile_type (tree type) ++{ ++ if (TYPE_VOLATILE (type)) ++ return true; ++ while (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) ++ { ++ type = TREE_TYPE (type); ++ if (TYPE_VOLATILE (type)) ++ return true; ++ } ++ return false; ++} ++ ++/* Is TYPE an array type or points to an array type. */ ++ ++static bool ++isarraytype (tree type) ++{ ++ if (TREE_CODE (type) == ARRAY_TYPE) ++ return true; ++ while (POINTER_TYPE_P (type)) ++ { ++ type = TREE_TYPE (type); ++ if (TREE_CODE (type) == ARRAY_TYPE) ++ return true; ++ } ++ return false; ++} ++ ++/* Is TYPE a pointer to another pointer. */ ++ ++static bool ++isptrptr (tree type) ++{ ++ bool firstptr = false; ++ while (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) ++ { ++ if (POINTER_TYPE_P (type)) ++ { ++ if (firstptr) ++ return true; ++ firstptr = true; ++ } ++ type = TREE_TYPE (type); ++ } ++ return false; ++} ++ ++/* Return the escape type which corresponds to if ++ this is an volatile type, an array type or a pointer ++ to a pointer type. */ ++ ++static escape_type ++escape_type_volatile_array_or_ptrptr (tree type) ++{ ++ if (isvolatile_type (type)) ++ return escape_volatile; ++ if (isarraytype (type)) ++ return escape_array; ++ if (isptrptr (type)) ++ return escape_ptr_ptr; ++ return does_not_escape; ++} ++ ++/* Record TYPE if not already recorded. */ ++ ++srtype * ++ipa_struct_reorg::record_type (tree type) ++{ ++ unsigned typeuid; ++ ++ /* Get the main variant as we are going ++ to record that type only. */ ++ type = TYPE_MAIN_VARIANT (type); ++ typeuid = TYPE_UID (type); ++ ++ srtype *type1; ++ ++ type1 = find_type (type); ++ if (type1) ++ return type1; ++ ++ /* If already done recording just return NULL. */ ++ if (done_recording) ++ return NULL; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "Recording new type: %u.\n", typeuid); ++ ++ type1 = new srtype (type); ++ types.safe_push (type1); ++ ++ /* If the type has an user alignment set, ++ that means the user most likely already setup the type. */ ++ if (TYPE_USER_ALIGN (type)) ++ type1->mark_escape (escape_user_alignment, NULL); ++ ++ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL) ++ { ++ tree t = TREE_TYPE (field); ++ process_union (t); ++ if (TREE_CODE (inner_type (t)) == UNION_TYPE ++ || TREE_CODE (inner_type (t)) == QUAL_UNION_TYPE) ++ type1->mark_escape (escape_union, NULL); ++ if (isvolatile_type (t)) ++ type1->mark_escape (escape_volatile, NULL); ++ escape_type e = escape_type_volatile_array_or_ptrptr (t); ++ if (e != does_not_escape) ++ type1->mark_escape (e, NULL); ++ if (handled_type (t)) ++ { ++ srtype *t1 = record_type (inner_type (t)); ++ srfield *f = type1->find_field (int_byte_position (field)); ++ /* We might have an variable sized type which ++ we don't set the handle. */ ++ if (f) ++ { ++ f->type = t1; ++ t1->add_field_site (f); ++ } ++ if (t1 == type1) ++ type1->mark_escape (escape_rescusive_type, NULL); ++ } ++ } ++ } ++ ++ return type1; ++} ++ ++/* Mark TYPE as escaping with ESCAPES as the reason. */ ++ ++void ++ipa_struct_reorg::mark_type_as_escape (tree type, ++ escape_type escapes, ++ gimple *stmt) ++{ ++ if (handled_type (type)) ++ { ++ srtype *stype = record_type (inner_type (type)); ++ ++ if (!stype) ++ return; ++ ++ stype->mark_escape (escapes, stmt); ++ } ++} ++ ++/* Maybe process the union of type TYPE, such that marking all of the fields' ++ types as being escaping. */ ++ ++void ++ipa_struct_reorg::process_union (tree type) ++{ ++ static hash_set unions_recorded; ++ ++ type = inner_type (type); ++ if (TREE_CODE (type) != UNION_TYPE ++ && TREE_CODE (type) != QUAL_UNION_TYPE) ++ return; ++ ++ type = TYPE_MAIN_VARIANT (type); ++ ++ /* We already processed this type. */ ++ if (unions_recorded.add (type)) ++ return; ++ ++ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL) ++ { ++ mark_type_as_escape (TREE_TYPE (field), escape_union); ++ process_union (TREE_TYPE (field)); ++ } ++ } ++} ++ ++/* Used by record_var function as a callback to walk_tree. ++ Mark the type as escaping if it has expressions which ++ cannot be converted for global initializations. */ ++ ++static tree ++record_init_types (tree *tp, int *walk_subtrees, void *data) ++{ ++ ipa_struct_reorg *c = (ipa_struct_reorg *)data; ++ switch (TREE_CODE (*tp)) ++ { ++ CASE_CONVERT: ++ case COMPONENT_REF: ++ case VIEW_CONVERT_EXPR: ++ case ARRAY_REF: ++ { ++ tree typeouter = TREE_TYPE (*tp); ++ tree typeinner = TREE_TYPE (TREE_OPERAND (*tp, 0)); ++ c->mark_type_as_escape (typeouter, escape_via_global_init); ++ c->mark_type_as_escape (typeinner, escape_via_global_init); ++ break; ++ } ++ case INTEGER_CST: ++ if (!integer_zerop (*tp)) ++ c->mark_type_as_escape (TREE_TYPE (*tp), escape_via_global_init); ++ break; ++ case VAR_DECL: ++ case PARM_DECL: ++ case FIELD_DECL: ++ c->mark_type_as_escape (TREE_TYPE (*tp), escape_via_global_init); ++ *walk_subtrees = false; ++ break; ++ default: ++ *walk_subtrees = true; ++ break; ++ } ++ return NULL_TREE; ++} ++ ++/* Record var DECL; optionally specify the escape reason and the argument ++ number in a function. */ ++ ++srdecl * ++ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) ++{ ++ srtype *type; ++ srdecl *sd = NULL; ++ ++ process_union (TREE_TYPE (decl)); ++ ++ if (handled_type (TREE_TYPE (decl))) ++ { ++ type = record_type (inner_type (TREE_TYPE (decl))); ++ escape_type e; ++ ++ if (done_recording && !type) ++ return NULL; ++ ++ gcc_assert (type); ++ if (TREE_CODE (decl) == VAR_DECL && is_global_var (decl)) ++ sd = globals.record_decl (type, decl, arg); ++ else ++ { ++ gcc_assert (current_function); ++ sd = current_function->record_decl (type, decl, arg); ++ } ++ ++ /* If the variable has the "used" attribute, ++ then treat the type as escaping. */ ++ if (escapes != does_not_escape) ++ e = escapes; ++ else if (TREE_CODE (decl) != SSA_NAME && DECL_PRESERVE_P (decl)) ++ e = escape_marked_as_used; ++ else if (TREE_THIS_VOLATILE (decl)) ++ e = escape_volatile; ++ else if (TREE_CODE (decl) != SSA_NAME && DECL_USER_ALIGN (decl)) ++ e = escape_user_alignment; ++ else if (TREE_CODE (decl) != SSA_NAME && TREE_STATIC (decl) ++ && TREE_PUBLIC (decl)) ++ e = escape_via_global_var; ++ /* We don't have an initlizer. */ ++ else if (TREE_CODE (decl) != SSA_NAME ++ && DECL_INITIAL (decl) == error_mark_node) ++ e = escape_via_global_var; ++ else ++ e = escape_type_volatile_array_or_ptrptr (TREE_TYPE (decl)); ++ ++ if (e != does_not_escape) ++ type->mark_escape (e, NULL); ++ } ++ ++ /* Record the initial usage of variables as types escapes. */ ++ if (TREE_CODE (decl) != SSA_NAME && TREE_STATIC (decl) ++ && DECL_INITIAL (decl)) ++ { ++ walk_tree_without_duplicates (&DECL_INITIAL (decl), ++ record_init_types, this); ++ if (!integer_zerop (DECL_INITIAL (decl)) ++ && DECL_INITIAL (decl) != error_mark_node) ++ mark_type_as_escape (TREE_TYPE (decl), escape_via_global_init); ++ } ++ return sd; ++} ++ ++/* Find void* ssa_names which are used inside MEM[] or if we have &a.c, ++ mark the type as escaping. */ ++ ++void ++ipa_struct_reorg::find_var (tree expr, gimple *stmt) ++{ ++ /* If we have VCE mark the outer type as escaping and the inner one ++ Also mark the inner most operand. */ ++ if (TREE_CODE (expr) == VIEW_CONVERT_EXPR) ++ { ++ mark_type_as_escape (TREE_TYPE (expr), escape_vce, stmt); ++ mark_type_as_escape (TREE_TYPE (TREE_OPERAND (expr, 0)), ++ escape_vce, stmt); ++ } ++ ++ /* If we have &b.c then we need to mark the type of b ++ as escaping as tracking a will be hard. */ ++ if (TREE_CODE (expr) == ADDR_EXPR ++ || TREE_CODE (expr) == VIEW_CONVERT_EXPR) ++ { ++ tree r = TREE_OPERAND (expr, 0); ++ if (handled_component_p (r) ++ || TREE_CODE (r) == MEM_REF) ++ { ++ while (handled_component_p (r) ++ || TREE_CODE (r) == MEM_REF) ++ { ++ if (TREE_CODE (r) == VIEW_CONVERT_EXPR) ++ { ++ mark_type_as_escape (TREE_TYPE (r), escape_vce, stmt); ++ mark_type_as_escape (TREE_TYPE (TREE_OPERAND (r, 0)), ++ escape_vce, stmt); ++ } ++ if (TREE_CODE (r) == MEM_REF) ++ mark_type_as_escape (TREE_TYPE (TREE_OPERAND (r, 1)), ++ escape_addr, stmt); ++ r = TREE_OPERAND (r, 0); ++ } ++ mark_expr_escape (r, escape_addr, stmt); ++ } ++ } ++ ++ tree base; ++ bool indirect; ++ srtype *type; ++ srfield *field; ++ bool realpart, imagpart, address; ++ get_type_field (expr, base, indirect, type, field, ++ realpart, imagpart, address, true, true); ++} ++ ++void ++ipa_struct_reorg::find_vars (gimple *stmt) ++{ ++ gasm *astmt; ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_ASSIGN: ++ if (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS ++ || gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs = gimple_assign_rhs1 (stmt); ++ find_var (gimple_assign_lhs (stmt), stmt); ++ find_var (gimple_assign_rhs1 (stmt), stmt); ++ if (TREE_CODE (lhs) == SSA_NAME ++ && VOID_POINTER_P (TREE_TYPE (lhs)) ++ && handled_type (TREE_TYPE (rhs))) ++ { ++ srtype *t = find_type (inner_type (TREE_TYPE (rhs))); ++ srdecl *d = find_decl (lhs); ++ if (!d && t) ++ current_function->record_decl (t, lhs, -1); ++ } ++ if (TREE_CODE (rhs) == SSA_NAME ++ && VOID_POINTER_P (TREE_TYPE (rhs)) ++ && handled_type (TREE_TYPE (lhs))) ++ { ++ srtype *t = find_type (inner_type (TREE_TYPE (lhs))); ++ srdecl *d = find_decl (rhs); ++ if (!d && t) ++ current_function->record_decl (t, rhs, -1); ++ } ++ } ++ break; ++ ++ case GIMPLE_CALL: ++ if (gimple_call_lhs (stmt)) ++ find_var (gimple_call_lhs (stmt), stmt); ++ ++ if (gimple_call_chain (stmt)) ++ find_var (gimple_call_chain (stmt), stmt); ++ ++ for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) ++ find_var (gimple_call_arg (stmt, i), stmt); ++ break; ++ ++ case GIMPLE_ASM: ++ astmt = as_a (stmt); ++ for (unsigned i = 0; i < gimple_asm_ninputs (astmt); i++) ++ find_var (TREE_VALUE (gimple_asm_input_op (astmt, i)), stmt); ++ for (unsigned i = 0; i < gimple_asm_noutputs (astmt); i++) ++ find_var (TREE_VALUE (gimple_asm_output_op (astmt, i)), stmt); ++ mark_types_asm (astmt); ++ break; ++ ++ case GIMPLE_RETURN: ++ { ++ tree expr = gimple_return_retval (as_a (stmt)); ++ if (expr) ++ find_var (expr, stmt); ++ /* return &a; should mark the type of a as escaping ++ through a return. */ ++ if (expr && TREE_CODE (expr) == ADDR_EXPR) ++ { ++ expr = TREE_OPERAND (expr, 0); ++ srdecl *d = find_decl (expr); ++ if (d) ++ d->type->mark_escape (escape_return, stmt); ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/* Maybe record access of statement for further analaysis. */ ++ ++void ++ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt) ++{ ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_ASSIGN: ++ maybe_record_assign (node, as_a (stmt)); ++ break; ++ case GIMPLE_CALL: ++ maybe_record_call (node, as_a (stmt)); ++ break; ++ case GIMPLE_DEBUG: ++ break; ++ case GIMPLE_GOTO: ++ case GIMPLE_SWITCH: ++ break; ++ default: ++ break; ++ } ++} ++ ++/* This function checks whether ARG is a result of multiplication ++ of some number by STRUCT_SIZE. If yes, the function returns true ++ and this number is filled into NUM. */ ++ ++static bool ++is_result_of_mult (tree arg, tree *num, tree struct_size) ++{ ++ if (!struct_size ++ || TREE_CODE (struct_size) != INTEGER_CST ++ || integer_zerop (struct_size)) ++ return false; ++ ++ /* If we have a integer, just check if it is a multiply of STRUCT_SIZE. */ ++ if (TREE_CODE (arg) == INTEGER_CST) ++ { ++ if (integer_zerop (size_binop (FLOOR_MOD_EXPR, arg, struct_size))) ++ { ++ *num = size_binop (FLOOR_DIV_EXPR, arg, struct_size); ++ return true; ++ } ++ return false; ++ } ++ gimple *size_def_stmt = SSA_NAME_DEF_STMT (arg); ++ ++ /* If the allocation statement was of the form ++ D.2229_10 = (D.2228_9); ++ then size_def_stmt can be D.2228_9 = num.3_8 * 8; */ ++ ++ while (size_def_stmt && is_gimple_assign (size_def_stmt)) ++ { ++ tree lhs = gimple_assign_lhs (size_def_stmt); ++ ++ /* We expect temporary here. */ ++ if (!is_gimple_reg (lhs)) ++ return false; ++ ++ // FIXME: this should handle SHIFT also. ++ if (gimple_assign_rhs_code (size_def_stmt) == PLUS_EXPR) ++ { ++ tree num1, num2; ++ tree arg0 = gimple_assign_rhs1 (size_def_stmt); ++ tree arg1 = gimple_assign_rhs2 (size_def_stmt); ++ if (!is_result_of_mult (arg0, &num1, struct_size)) ++ return false; ++ if (!is_result_of_mult (arg1, &num2, struct_size)) ++ return false; ++ *num = size_binop (PLUS_EXPR, num1, num2); ++ return true; ++ } ++ else if (gimple_assign_rhs_code (size_def_stmt) == MULT_EXPR) ++ { ++ tree arg0 = gimple_assign_rhs1 (size_def_stmt); ++ tree arg1 = gimple_assign_rhs2 (size_def_stmt); ++ tree num1; ++ ++ if (is_result_of_mult (arg0, &num1, struct_size)) ++ { ++ *num = size_binop (MULT_EXPR, arg1, num1); ++ return true; ++ } ++ if (is_result_of_mult (arg1, &num1, struct_size)) ++ { ++ *num = size_binop (MULT_EXPR, arg0, num1); ++ return true; ++ } ++ ++ *num = NULL_TREE; ++ return false; ++ } ++ else if (gimple_assign_rhs_code (size_def_stmt) == SSA_NAME) ++ { ++ arg = gimple_assign_rhs1 (size_def_stmt); ++ size_def_stmt = SSA_NAME_DEF_STMT (arg); ++ } ++ else ++ { ++ *num = NULL_TREE; ++ return false; ++ } ++ } ++ ++ *num = NULL_TREE; ++ return false; ++} ++ ++/* Return TRUE if STMT is an allocation statement that is handled. */ ++ ++static bool ++handled_allocation_stmt (gimple *stmt) ++{ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALIGNED_ALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN)) ++ return true; ++ return false; ++} ++ ++/* Returns the allocated size / T size for STMT. That is the number of ++ elements in the array allocated. */ ++ ++tree ++ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt) ++{ ++ if (!stmt ++ || gimple_code (stmt) != GIMPLE_CALL ++ || !handled_allocation_stmt (stmt)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nNot a allocate statment:\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ return NULL; ++ } ++ ++ if (type->has_escaped ()) ++ return NULL; ++ ++ tree struct_size = TYPE_SIZE_UNIT (type->type); ++ ++ tree size = gimple_call_arg (stmt, 0); ++ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALIGNED_ALLOC)) ++ size = gimple_call_arg (stmt, 1); ++ else if (gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) ++ { ++ tree arg1; ++ arg1 = gimple_call_arg (stmt, 1); ++ /* Check that second argument is a constant equal to ++ the size of structure. */ ++ if (operand_equal_p (arg1, struct_size, 0)) ++ return size; ++ /* Check that first argument is a constant equal to ++ the size of structure. */ ++ if (operand_equal_p (size, struct_size, 0)) ++ return arg1; ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\ncalloc the correct size:\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ return NULL; ++ } ++ ++ tree num; ++ if (!is_result_of_mult (size, &num, struct_size)) ++ return NULL; ++ ++ return num; ++} ++ ++void ++ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, ++ gimple *stmt) ++{ ++ gcc_assert (TREE_CODE (side) == SSA_NAME || TREE_CODE (side) == ADDR_EXPR); ++ srtype *type = NULL; ++ if (handled_type (TREE_TYPE (other))) ++ type = record_type (inner_type (TREE_TYPE (other))); ++ if (TREE_CODE (side) == ADDR_EXPR) ++ side = TREE_OPERAND (side, 0); ++ srdecl *d = find_decl (side); ++ if (!type) ++ { ++ if (!d) ++ return; ++ if (TREE_CODE (side) == SSA_NAME ++ && VOID_POINTER_P (TREE_TYPE (side))) ++ return; ++ d->type->mark_escape (escape_cast_another_ptr, stmt); ++ return; ++ } ++ ++ if (!d) ++ { ++ if (VOID_POINTER_P (TREE_TYPE (side)) ++ && TREE_CODE (side) == SSA_NAME) ++ current_function->record_decl (type, side, -1); ++ else ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ } ++ else if (type != d->type) ++ { ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ d->type->mark_escape (escape_cast_another_ptr, stmt); ++ } ++} ++ ++/* Record accesses in an assignment statement STMT. */ ++ ++void ++ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt) ++{ ++ if (gimple_clobber_p (stmt)) ++ { ++ record_stmt_expr (gimple_assign_lhs (stmt), node, stmt); ++ return; ++ } ++ ++ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree num; ++ if (!handled_type (TREE_TYPE (lhs))) ++ return; ++ /* Check if rhs2 is a multiplication of the size of the type. */ ++ if (is_result_of_mult (rhs2, &num, ++ TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs))))) ++ { ++ record_stmt_expr (lhs, node, stmt); ++ record_stmt_expr (rhs1, node, stmt); ++ } ++ else ++ { ++ mark_expr_escape (lhs, escape_non_multiply_size, stmt); ++ mark_expr_escape (rhs1, escape_non_multiply_size, stmt); ++ } ++ return; ++ } ++ /* Copies, References, Taking addresses. */ ++ if (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs = gimple_assign_rhs1 (stmt); ++ /* If we have a = &b.c then we need to mark the type of b ++ as escaping as tracking a will be hard. */ ++ if (TREE_CODE (rhs) == ADDR_EXPR) ++ { ++ tree r = TREE_OPERAND (rhs, 0); ++ if (handled_component_p (r)) ++ { ++ while (handled_component_p (r)) ++ r = TREE_OPERAND (r, 0); ++ mark_expr_escape (r, escape_addr, stmt); ++ return; ++ } ++ } ++ if ((TREE_CODE (rhs) == SSA_NAME || TREE_CODE (rhs) == ADDR_EXPR)) ++ maybe_mark_or_record_other_side (rhs, lhs, stmt); ++ if (TREE_CODE (lhs) == SSA_NAME) ++ maybe_mark_or_record_other_side (lhs, rhs, stmt); ++ } ++} ++ ++static tree ++get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, ++ bool &realpart, bool &imagpart, ++ tree &accesstype) ++{ ++ offset = 0; ++ realpart = false; ++ imagpart = false; ++ accesstype = NULL_TREE; ++ if (TREE_CODE (e) == REALPART_EXPR) ++ { ++ e = TREE_OPERAND (e, 0); ++ realpart = true; ++ } ++ if (TREE_CODE (e) == IMAGPART_EXPR) ++ { ++ e = TREE_OPERAND (e, 0); ++ imagpart = true; ++ } ++ tree expr = e; ++ while (true) ++ { ++ switch (TREE_CODE (expr)) ++ { ++ case COMPONENT_REF: ++ { ++ tree field = TREE_OPERAND (expr, 1); ++ tree field_off = byte_position (field); ++ if (TREE_CODE (field_off) != INTEGER_CST) ++ return NULL; ++ offset += tree_to_shwi (field_off); ++ expr = TREE_OPERAND (expr, 0); ++ accesstype = NULL; ++ break; ++ } ++ case MEM_REF: ++ { ++ tree field_off = TREE_OPERAND (expr, 1); ++ gcc_assert (TREE_CODE (field_off) == INTEGER_CST); ++ /* So we can mark the types as escaping if different. */ ++ accesstype = TREE_TYPE (field_off); ++ offset += tree_to_uhwi (field_off); ++ return TREE_OPERAND (expr, 0); ++ } ++ default: ++ return expr; ++ } ++ } ++} ++ ++/* Return true if EXPR was accessing the whole type T. */ ++ ++bool ++ipa_struct_reorg::wholeaccess (tree expr, tree base, ++ tree accesstype, srtype *t) ++{ ++ if (expr == base) ++ return true; ++ ++ if (TREE_CODE (expr) == ADDR_EXPR && TREE_OPERAND (expr, 0) == base) ++ return true; ++ ++ if (!accesstype) ++ return false; ++ ++ if (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (accesstype))) ++ return false; ++ ++ if (!handled_type (TREE_TYPE (expr))) ++ return false; ++ ++ srtype *other_type = find_type (inner_type (TREE_TYPE (expr))); ++ ++ if (t == other_type) ++ return true; ++ ++ return false; ++} ++ ++bool ++ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, ++ srtype *&type, srfield *&field, ++ bool &realpart, bool &imagpart, ++ bool &address, bool should_create, ++ bool can_escape) ++{ ++ HOST_WIDE_INT offset; ++ tree accesstype; ++ address = false; ++ bool mark_as_bit_field = false; ++ ++ if (TREE_CODE (expr) == BIT_FIELD_REF) ++ { ++ expr = TREE_OPERAND (expr, 0); ++ mark_as_bit_field = true; ++ } ++ ++ base = get_ref_base_and_offset (expr, offset, realpart, imagpart, ++ accesstype); ++ ++ /* Variable access, unkown type. */ ++ if (base == NULL) ++ return false; ++ ++ if (TREE_CODE (base) == ADDR_EXPR) ++ { ++ address = true; ++ base = TREE_OPERAND (base, 0); ++ } ++ ++ if (offset != 0 && accesstype) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Non zero offset (%d) with MEM.\n", (int)offset); ++ print_generic_expr (dump_file, expr); ++ fprintf (dump_file, "\n"); ++ print_generic_expr (dump_file, base); ++ fprintf (dump_file, "\n"); ++ } ++ } ++ ++ srdecl *d = find_decl (base); ++ srtype *t; ++ ++ if (integer_zerop (base)) ++ { ++ gcc_assert (!d); ++ if (!accesstype) ++ return false; ++ t = find_type (inner_type (inner_type (accesstype))); ++ if (!t && should_create && handled_type (accesstype)) ++ t = record_type (inner_type (accesstype)); ++ if (!t) ++ return false; ++ } ++ else if (!d && accesstype) ++ { ++ if (!should_create) ++ return false; ++ if (!handled_type (accesstype)) ++ return false; ++ t = find_type (inner_type (inner_type (accesstype))); ++ if (!t) ++ t = record_type (inner_type (accesstype)); ++ if (!t || t->has_escaped ()) ++ return false; ++ /* If base is not void* mark the type as escaping. */ ++ if (!VOID_POINTER_P (TREE_TYPE (base))) ++ { ++ gcc_assert (can_escape); ++ t->mark_escape (escape_cast_another_ptr, NULL); ++ return false; ++ } ++ if (TREE_CODE (base) == SSA_NAME) ++ current_function->record_decl (t, base, -1); ++ } ++ else if (!d) ++ return false; ++ else ++ t = d->type; ++ ++ if (t->has_escaped ()) ++ return false; ++ ++ if (mark_as_bit_field) ++ { ++ gcc_assert (can_escape); ++ t->mark_escape (escape_bitfields, NULL); ++ return false; ++ } ++ ++ if (wholeaccess (expr, base, accesstype, t)) ++ { ++ field = NULL; ++ type = t; ++ indirect = accesstype != NULL; ++ return true; ++ } ++ ++ srfield *f = t->find_field (offset); ++ if (!f) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nunkown field\n"); ++ print_generic_expr (dump_file, expr); ++ fprintf (dump_file, "\n"); ++ print_generic_expr (dump_file, base); ++ fprintf (dump_file, "\n"); ++ } ++ gcc_assert (can_escape); ++ t->mark_escape (escape_unkown_field, NULL); ++ return false; ++ } ++ if (!types_compatible_p (f->fieldtype, TREE_TYPE (expr))) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nfieldtype = "); ++ print_generic_expr (dump_file, f->fieldtype); ++ fprintf (dump_file, "\naccess type = "); ++ print_generic_expr (dump_file, TREE_TYPE (expr)); ++ fprintf (dump_file, "original expr = "); ++ print_generic_expr (dump_file, expr); ++ fprintf (dump_file, "\n"); ++ } ++ gcc_assert (can_escape); ++ t->mark_escape (escape_unkown_field, NULL); ++ return false; ++ } ++ field = f; ++ type = t; ++ indirect = accesstype != NULL; ++ return true; ++} ++ ++/* Mark the type used in EXPR as escaping. */ ++ ++void ++ipa_struct_reorg::mark_expr_escape (tree expr, escape_type escapes, ++ gimple *stmt) ++{ ++ tree base; ++ bool indirect; ++ srtype *type; ++ srfield *field; ++ bool realpart, imagpart, address; ++ if (!get_type_field (expr, base, indirect, type, field, ++ realpart, imagpart, address)) ++ return; ++ ++ type->mark_escape (escapes, stmt); ++} ++ ++/* Record accesses in a call statement STMT. */ ++ ++void ++ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt) ++{ ++ tree argtype; ++ tree fndecl; ++ escape_type escapes = does_not_escape; ++ bool free_or_realloc = gimple_call_builtin_p (stmt, BUILT_IN_FREE) ++ || gimple_call_builtin_p (stmt, BUILT_IN_REALLOC); ++ ++ /* We check allocation sites in a different location. */ ++ if (handled_allocation_stmt (stmt)) ++ return; ++ ++ /* A few cases here: ++ 1) assigned from the lhs ++ 2) Used in argument ++ If a function being called is global (or indirect) ++ then we reject the types as being escaping. */ ++ ++ if (tree chain = gimple_call_chain (stmt)) ++ record_stmt_expr (chain, node, stmt); ++ ++ /* Assigned from LHS. */ ++ if (tree lhs = gimple_call_lhs (stmt)) ++ { ++ /* FIXME: handle return types. */ ++ mark_type_as_escape (TREE_TYPE (lhs), escape_return); ++ } ++ ++ /* If we have an internal call, just record the stmt. */ ++ if (gimple_call_internal_p (stmt)) ++ { ++ for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) ++ record_stmt_expr (gimple_call_arg (stmt, i), node, stmt); ++ return; ++ } ++ ++ fndecl = gimple_call_fndecl (stmt); ++ ++ /* If we have an indrect call, just mark the types as escape. */ ++ if (!fndecl) ++ escapes = escape_pointer_function; ++ /* Non local functions cause escape except for calls to free ++ and realloc. ++ FIXME: should support function annotations too. */ ++ else if (!free_or_realloc ++ && !cgraph_node::local_info_node (fndecl)->local) ++ escapes = escape_external_function; ++ else if (!free_or_realloc ++ && !cgraph_node::local_info_node (fndecl)->can_change_signature) ++ escapes = escape_cannot_change_signature; ++ /* FIXME: we should be able to handle functions in other partitions. */ ++ else if (symtab_node::get (fndecl)->in_other_partition) ++ escapes = escape_external_function; ++ ++ if (escapes != does_not_escape) ++ { ++ for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) ++ mark_type_as_escape (TREE_TYPE (gimple_call_arg (stmt, i)), ++ escapes); ++ return; ++ } ++ ++ argtype = TYPE_ARG_TYPES (gimple_call_fntype (stmt)); ++ for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) ++ { ++ tree arg = gimple_call_arg (stmt, i); ++ if (argtype) ++ { ++ tree argtypet = TREE_VALUE (argtype); ++ if (!free_or_realloc ++ && VOID_POINTER_P (argtypet)) ++ mark_type_as_escape (TREE_TYPE (arg), escape_cast_void); ++ else ++ record_stmt_expr (arg, node, stmt); ++ } ++ else ++ mark_type_as_escape (TREE_TYPE (arg), escape_var_arg_function); ++ ++ argtype = argtype ? TREE_CHAIN (argtype) : NULL_TREE; ++ } ++} ++ ++void ++ipa_struct_reorg::record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt) ++{ ++ tree base; ++ bool indirect; ++ srtype *type; ++ srfield *field; ++ bool realpart, imagpart, address; ++ if (!get_type_field (expr, base, indirect, type, field, ++ realpart, imagpart, address)) ++ return; ++ ++ if (!opt_for_fn (current_function_decl, flag_ipa_struct_reorg)) ++ type->mark_escape (escape_non_optimize, stmt); ++ ++ /* Record it. */ ++ type->add_access (new sraccess (stmt, node, type, field)); ++} ++ ++/* Find function corresponding to NODE. */ ++ ++srfunction * ++ipa_struct_reorg::find_function (cgraph_node *node) ++{ ++ for (unsigned i = 0; i < functions.length (); i++) ++ if (functions[i]->node == node) ++ return functions[i]; ++ return NULL; ++} ++ ++void ++ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, ++ vec &worklist, ++ gimple *stmt) ++{ ++ if (integer_zerop (newdecl)) ++ return; ++ ++ if (TREE_CODE (newdecl) == ADDR_EXPR) ++ { ++ srdecl *d = find_decl (TREE_OPERAND (newdecl, 0)); ++ if (!d) ++ { ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ return; ++ } ++ if (d->type == type) ++ return; ++ ++ srtype *type1 = d->type; ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ type1->mark_escape (escape_cast_another_ptr, stmt); ++ return; ++ } ++ ++ srdecl *d = find_decl (newdecl); ++ if (!d) ++ { ++ if (TREE_CODE (newdecl) == INTEGER_CST) ++ { ++ type->mark_escape (escape_int_const, stmt); ++ return; ++ } ++ /* If we have a non void* or a decl (which is hard to track), ++ then mark the type as escaping. */ ++ if (!VOID_POINTER_P (TREE_TYPE (newdecl)) ++ || DECL_P (newdecl)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nunkown decl: "); ++ print_generic_expr (dump_file, newdecl); ++ fprintf (dump_file, " in type:\n"); ++ print_generic_expr (dump_file, TREE_TYPE (newdecl)); ++ fprintf (dump_file, "\n"); ++ } ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ return; ++ } ++ /* At this point there should only be unkown void* ssa names. */ ++ gcc_assert (TREE_CODE (newdecl) == SSA_NAME); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nrecording unkown decl: "); ++ print_generic_expr (dump_file, newdecl); ++ fprintf (dump_file, " as type:\n"); ++ type->simple_dump (dump_file); ++ fprintf (dump_file, "\n"); ++ } ++ d = current_function->record_decl (type, newdecl, -1); ++ worklist.safe_push (d); ++ return; ++ } ++ ++ /* Only add to the worklist if the decl is a SSA_NAME. */ ++ if (TREE_CODE (newdecl) == SSA_NAME) ++ worklist.safe_push (d); ++ if (d->type == type) ++ return; ++ ++ srtype *type1 = d->type; ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ type1->mark_escape (escape_cast_another_ptr, stmt); ++} ++ ++/* ++ 2) Check SSA_NAMEs for non type usages (source or use) (worlist of srdecl) ++ a) if the SSA_NAME is sourced from a pointer plus, record the pointer and ++ check to make sure the addition was a multiple of the size. ++ check the pointer type too. ++ b) If the name is sourced from an allocation check the allocation ++ i) Add SSA_NAME (void*) to the worklist if allocated from realloc ++ c) if the name is from a param, make sure the param type was of the ++ original type ++ d) if the name is from a cast/assignment, make sure it is used as that ++ type or void* ++ i) If void* then push the ssa_name into worklist ++*/ ++void ++ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) ++{ ++ tree ssa_name = decl->decl; ++ srtype *type = decl->type; ++ ++ /* ++ c) if the name is from a param, make sure the param type was of the ++ original type. ++ */ ++ if (SSA_NAME_IS_DEFAULT_DEF (ssa_name)) ++ { ++ tree var = SSA_NAME_VAR (ssa_name); ++ if (var ++ && TREE_CODE (var) == PARM_DECL ++ && VOID_POINTER_P (TREE_TYPE (ssa_name))) ++ type->mark_escape (escape_cast_void, NULL); ++ return; ++ } ++ gimple *stmt = SSA_NAME_DEF_STMT (ssa_name); ++ ++ /* ++ b) If the name is sourced from an allocation check the allocation ++ i) Add SSA_NAME (void*) to the worklist if allocated from realloc ++ */ ++ if (gimple_code (stmt) == GIMPLE_CALL) ++ { ++ /* For realloc, check the type of the argument. */ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)) ++ check_type_and_push (gimple_call_arg (stmt, 0), type, worklist, stmt); ++ ++ if (!handled_allocation_stmt (stmt) ++ || !allocate_size (type, stmt)) ++ type->mark_escape (escape_return, stmt); ++ return; ++ } ++ /* If the SSA_NAME is sourced from an inline-asm, ++ just mark the type as escaping. */ ++ if (gimple_code (stmt) == GIMPLE_ASM) ++ { ++ type->mark_escape (escape_inline_asm, stmt); ++ return; ++ } ++ ++ /* If the SSA_NAME is sourced from a PHI check add ++ each name to the worklist and check to make sure ++ they are used correctly. */ ++ if (gimple_code (stmt) == GIMPLE_PHI) ++ { ++ for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++) ++ check_type_and_push (gimple_phi_arg_def (stmt, i), ++ type, worklist, stmt); ++ return; ++ } ++ ++ gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN); ++ /* ++ a) if the SSA_NAME is sourced from a pointer plus, record the pointer and ++ check to make sure the addition was a multiple of the size. ++ check the pointer type too. ++ */ ++ ++ tree rhs = gimple_assign_rhs1 (stmt); ++ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree num; ++ if (!is_result_of_mult (rhs2, &num, TYPE_SIZE_UNIT (type->type))) ++ type->mark_escape (escape_non_multiply_size, stmt); ++ ++ if (TREE_CODE (rhs) == SSA_NAME) ++ check_type_and_push (rhs, type, worklist, stmt); ++ return; ++ } ++ ++ /* Casts between pointers and integer are escaping. */ ++ if (gimple_assign_cast_p (stmt)) ++ { ++ type->mark_escape (escape_cast_int, stmt); ++ return; ++ } ++ ++ /* ++ d) if the name is from a cast/assignment, make sure it is used as that ++ type or void* ++ i) If void* then push the ssa_name into worklist ++ */ ++ gcc_assert (gimple_assign_single_p (stmt)); ++ check_other_side (decl, rhs, stmt, worklist); ++} ++ ++/* Mark the types used by the inline-asm as escaping. ++ It is unkown what happens inside an inline-asm. */ ++ ++void ++ipa_struct_reorg::mark_types_asm (gasm *astmt) ++{ ++ for (unsigned i = 0; i < gimple_asm_ninputs (astmt); i++) ++ { ++ tree v = TREE_VALUE (gimple_asm_input_op (astmt, i)); ++ /* If we have &b, just strip the & here. */ ++ if (TREE_CODE (v) == ADDR_EXPR) ++ v = TREE_OPERAND (v, 0); ++ mark_expr_escape (v, escape_inline_asm, astmt); ++ } ++ for (unsigned i = 0; i < gimple_asm_noutputs (astmt); i++) ++ { ++ tree v = TREE_VALUE (gimple_asm_output_op (astmt, i)); ++ /* If we have &b, just strip the & here. */ ++ if (TREE_CODE (v) == ADDR_EXPR) ++ v = TREE_OPERAND (v, 0); ++ mark_expr_escape (v, escape_inline_asm, astmt); ++ } ++} ++ ++void ++ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, ++ vec &worklist) ++{ ++ srtype *type = decl->type; ++ ++ if (TREE_CODE (other) == SSA_NAME ++ || DECL_P (other) ++ || TREE_CODE (other) == INTEGER_CST) ++ { ++ check_type_and_push (other, type, worklist, stmt); ++ return; ++ } ++ ++ tree t = TREE_TYPE (other); ++ if (!handled_type (t)) ++ { ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ return; ++ } ++ ++ srtype *t1 = find_type (inner_type (t)); ++ if (t1 == type) ++ { ++ tree base; ++ bool indirect; ++ srtype *type1; ++ srfield *field; ++ bool realpart, imagpart, address; ++ if (!get_type_field (other, base, indirect, type1, field, ++ realpart, imagpart, address)) ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ ++ return; ++ } ++ ++ if (t1) ++ t1->mark_escape (escape_cast_another_ptr, stmt); ++ ++ type->mark_escape (escape_cast_another_ptr, stmt); ++} ++ ++void ++ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, ++ vec &worklist) ++{ ++ srtype *type = decl->type; ++ ++ if (gimple_code (stmt) == GIMPLE_RETURN) ++ { ++ type->mark_escape (escape_return, stmt); ++ return; ++ } ++ /* If the SSA_NAME PHI check and add the src to the worklist and ++ check to make sure they are used correctly. */ ++ if (gimple_code (stmt) == GIMPLE_PHI) ++ { ++ check_type_and_push (gimple_phi_result (stmt), type, worklist, stmt); ++ return; ++ } ++ ++ if (gimple_code (stmt) == GIMPLE_ASM) ++ { ++ mark_types_asm (as_a (stmt)); ++ return; ++ } ++ ++ if (gimple_code (stmt) == GIMPLE_COND) ++ { ++ tree rhs1 = gimple_cond_lhs (stmt); ++ tree rhs2 = gimple_cond_rhs (stmt); ++ tree orhs = rhs1; ++ if (gimple_cond_code (stmt) != EQ_EXPR ++ && gimple_cond_code (stmt) != NE_EXPR) ++ { ++ mark_expr_escape (rhs1, escape_non_eq, stmt); ++ mark_expr_escape (rhs2, escape_non_eq, stmt); ++ } ++ if (rhs1 == decl->decl) ++ orhs = rhs2; ++ if (integer_zerop (orhs)) ++ return; ++ if (TREE_CODE (orhs) != SSA_NAME) ++ mark_expr_escape (rhs1, escape_non_eq, stmt); ++ check_type_and_push (orhs, type, worklist, stmt); ++ return; ++ } ++ ++ /* Casts between pointers and integer are escaping. */ ++ if (gimple_assign_cast_p (stmt)) ++ { ++ type->mark_escape (escape_cast_int, stmt); ++ return; ++ } ++ ++ /* We might have a_1 = ptr_2 == ptr_3; */ ++ if (is_gimple_assign (stmt) ++ && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison) ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree orhs = rhs1; ++ if (gimple_assign_rhs_code (stmt) != EQ_EXPR ++ && gimple_assign_rhs_code (stmt) != NE_EXPR) ++ { ++ mark_expr_escape (rhs1, escape_non_eq, stmt); ++ mark_expr_escape (rhs2, escape_non_eq, stmt); ++ } ++ if (rhs1 == decl->decl) ++ orhs = rhs2; ++ if (integer_zerop (orhs)) ++ return; ++ if (TREE_CODE (orhs) != SSA_NAME) ++ mark_expr_escape (rhs1, escape_non_eq, stmt); ++ check_type_and_push (orhs, type, worklist, stmt); ++ return; ++ } ++ ++ if (gimple_assign_single_p (stmt)) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs = gimple_assign_rhs1 (stmt); ++ /* Check if we have a_1 = b_2; that a_1 is in the correct type. */ ++ if (decl->decl == rhs) ++ { ++ check_other_side (decl, lhs, stmt, worklist); ++ return; ++ } ++ } ++ ++ if (is_gimple_assign (stmt) ++ && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree lhs = gimple_assign_lhs (stmt); ++ tree num; ++ check_other_side (decl, lhs, stmt, worklist); ++ if (!is_result_of_mult (rhs2, &num, TYPE_SIZE_UNIT (type->type))) ++ type->mark_escape (escape_non_multiply_size, stmt); ++ } ++} ++ ++/* ++ 2) Check SSA_NAMEs for non type usages (source or use) (worlist of srdecl) ++ d) if the name is from a cast/assignment, make sure it is used as that ++ type or void* ++ i) If void* then push the ssa_name into worklist ++ e) if used in conditional check the other side ++ i) If the conditional is non NE/EQ then mark the type as non rejecting ++ f) Check if the use in a Pointer PLUS EXPR Is used by mulitplication ++ of its size ++ */ ++void ++ipa_struct_reorg::check_uses (srdecl *decl, vec &worklist) ++{ ++ tree ssa_name = decl->decl; ++ imm_use_iterator imm_iter; ++ use_operand_p use_p; ++ ++ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ssa_name) ++ { ++ gimple *stmt = USE_STMT (use_p); ++ ++ if (is_gimple_debug (stmt)) ++ continue; ++ ++ check_use (decl, stmt, worklist); ++ } ++} ++ ++/* Record function corresponding to NODE. */ ++ ++srfunction * ++ipa_struct_reorg::record_function (cgraph_node *node) ++{ ++ function *fn; ++ tree parm, var; ++ unsigned int i; ++ srfunction *sfn; ++ escape_type escapes = does_not_escape; ++ ++ sfn = new srfunction (node); ++ functions.safe_push (sfn); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, ++ "\nRecording accesses and types from function: %s/%u\n", ++ node->name (), node->order); ++ ++ /* Nodes without a body are not interesting. Especially do not ++ visit clones at this point for now - we get duplicate decls ++ there for inline clones at least. */ ++ if (!node->has_gimple_body_p () || node->inlined_to) ++ return sfn; ++ ++ node->get_body (); ++ fn = DECL_STRUCT_FUNCTION (node->decl); ++ ++ if (!fn) ++ return sfn; ++ ++ current_function = sfn; ++ ++ if (DECL_PRESERVE_P (node->decl)) ++ escapes = escape_marked_as_used; ++ else if (!node->local) ++ escapes = escape_visible_function; ++ else if (!node->can_change_signature) ++ escapes = escape_cannot_change_signature; ++ else if (!tree_versionable_function_p (node->decl)) ++ escapes = escape_noclonable_function; ++ else if (!opt_for_fn (node->decl, flag_ipa_struct_reorg)) ++ escapes = escape_non_optimize; ++ ++ basic_block bb; ++ gimple_stmt_iterator si; ++ ++ /* Record the static chain decl. */ ++ if (fn->static_chain_decl) ++ { ++ srdecl *sd = record_var (fn->static_chain_decl, ++ escapes, -2); ++ if (sd) ++ { ++ /* Specify that this type is used by the static ++ chain so it cannot be split. */ ++ sd->type->chain_type = true; ++ sfn->add_arg (sd); ++ sd->type->add_function (sfn); ++ } ++ } ++ ++ /* Record the arguments. */ ++ for (parm = DECL_ARGUMENTS (node->decl), i = 0; ++ parm; ++ parm = DECL_CHAIN (parm), i++) ++ { ++ srdecl *sd = record_var (parm, escapes, i); ++ if (sd) ++ { ++ sfn->add_arg (sd); ++ sd->type->add_function (sfn); ++ } ++ } ++ ++ /* Mark the return type as escaping. */ ++ { ++ tree return_type = TREE_TYPE (TREE_TYPE (node->decl)); ++ mark_type_as_escape (return_type, escape_return, NULL); ++ } ++ ++ /* If the cfg does not exist for the function, ++ don't process the function. */ ++ if (!fn->cfg) ++ { ++ current_function = NULL; ++ return sfn; ++ } ++ ++ /* The following order is done for recording stage: ++ 0) Record all variables/SSA_NAMES that are of struct type ++ 1) Record MEM_REF/COMPONENT_REFs ++ a) Record SSA_NAMEs (void*) and record that as the accessed type. ++ */ ++ ++ push_cfun (fn); ++ ++ FOR_EACH_LOCAL_DECL (cfun, i, var) ++ { ++ if (TREE_CODE (var) != VAR_DECL) ++ continue; ++ ++ record_var (var); ++ } ++ ++ for (i = 1; i < num_ssa_names; ++i) ++ { ++ tree name = ssa_name (i); ++ if (!name ++ || has_zero_uses (name) ++ || virtual_operand_p (name)) ++ continue; ++ ++ record_var (name); ++ } ++ ++ /* Find the variables which are used via MEM_REF and are void* types. */ ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) ++ { ++ gimple *stmt = gsi_stmt (si); ++ find_vars (stmt); ++ } ++ } ++ ++ auto_vec worklist; ++ for (unsigned i = 0; i < current_function->decls.length (); i++) ++ { ++ srdecl *decl = current_function->decls[i]; ++ if (TREE_CODE (decl->decl) == SSA_NAME) ++ { ++ decl->visited = false; ++ worklist.safe_push (decl); ++ } ++ } ++ ++/* ++ 2) Check SSA_NAMEs for non type usages (source or use) (worlist of srdecl) ++ a) if the SSA_NAME is sourced from a pointer plus, record the pointer and ++ check to make sure the addition was a multiple of the size. ++ check the pointer type too. ++ b) If the name is sourced from an allocation check the allocation ++ i) Add SSA_NAME (void*) to the worklist if allocated from realloc ++ c) if the name is from a param, make sure the param type was of the ++ original type ++ d) if the name is used in a cast/assignment, make sure it is used as that ++ type or void* ++ i) If void* then push the ssa_name into worklist ++ e) if used in conditional check the other side ++ i) If the conditional is non NE/EQ then mark the type as non rejecting ++ f) Check if the use in a POinter PLUS EXPR Is used by mulitplication ++ of its size ++*/ ++ ++ while (!worklist.is_empty ()) ++ { ++ srdecl *decl = worklist.pop (); ++ if (decl->visited) ++ continue; ++ decl->visited = true; ++ check_definition (decl, worklist); ++ check_uses (decl, worklist); ++ } ++ ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) ++ { ++ gimple *stmt = gsi_stmt (si); ++ maybe_record_stmt (node, stmt); ++ } ++ } ++ ++ pop_cfun (); ++ current_function = NULL; ++ return sfn; ++} ++ ++/* Record all accesses for all types including global variables. */ ++ ++void ++ipa_struct_reorg::record_accesses (void) ++{ ++ varpool_node *var; ++ cgraph_node *cnode; ++ ++ /* Record global (non-auto) variables first. */ ++ FOR_EACH_VARIABLE (var) ++ { ++ if (!var->real_symbol_p ()) ++ continue; ++ ++ /* Record all variables including the accesses inside a variable. */ ++ escape_type escapes = does_not_escape; ++ if (var->externally_visible || !var->definition) ++ escapes = escape_via_global_var; ++ if (var->in_other_partition) ++ escapes = escape_via_global_var; ++ if (!var->externally_visible && var->definition) ++ var->get_constructor (); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Recording global variable: "); ++ print_generic_expr (dump_file, var->decl); ++ fprintf (dump_file, "\n"); ++ } ++ record_var (var->decl, escapes); ++ } ++ ++ FOR_EACH_FUNCTION (cnode) ++ { ++ if (!cnode->real_symbol_p ()) ++ continue; ++ ++ /* Record accesses inside a function. */ ++ if (cnode->definition) ++ record_function (cnode); ++ } ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "all types (before pruning):\n"); ++ dump_types (dump_file); ++ fprintf (dump_file, "all functions (before pruning):\n"); ++ dump_functions (dump_file); ++ } ++ done_recording = true; ++} ++ ++/* A helper function to detect cycles (recusive) types. ++ Return TRUE if TYPE was a rescusive type. */ ++ ++bool ++ipa_struct_reorg::walk_field_for_cycles (srtype *type) ++{ ++ unsigned i; ++ srfield *field; ++ ++ type->visited = true; ++ if (type->escaped_rescusive ()) ++ return true; ++ ++ if (type->has_escaped ()) ++ return false; ++ ++ FOR_EACH_VEC_ELT (type->fields, i, field) ++ { ++ if (!field->type) ++ ; ++ else if (field->type->visited ++ || walk_field_for_cycles (field->type)) ++ { ++ type->mark_escape (escape_rescusive_type, NULL); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++/* Clear visited on all types. */ ++ ++void ++ipa_struct_reorg::clear_visited (void) ++{ ++ for (unsigned i = 0; i < types.length (); i++) ++ types[i]->visited = false; ++} ++ ++/* Detect recusive types and mark them as escaping. */ ++ ++void ++ipa_struct_reorg::detect_cycles (void) ++{ ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ if (types[i]->has_escaped ()) ++ continue; ++ ++ clear_visited (); ++ walk_field_for_cycles (types[i]); ++ } ++} ++ ++/* Propagate escaping to depdenent types. */ ++ ++void ++ipa_struct_reorg::propagate_escape (void) ++{ ++ unsigned i; ++ srtype *type; ++ bool changed = false; ++ ++ do ++ { ++ changed = false; ++ FOR_EACH_VEC_ELT (types, i, type) ++ { ++ for (tree field = TYPE_FIELDS (type->type); ++ field; ++ field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL ++ && handled_type (TREE_TYPE (field))) ++ { ++ tree t = inner_type (TREE_TYPE (field)); ++ srtype *type1 = find_type (t); ++ if (!type1) ++ continue; ++ if (type1->has_escaped () ++ && !type->has_escaped ()) ++ { ++ type->mark_escape (escape_dependent_type_escapes, NULL); ++ changed = true; ++ } ++ if (type->has_escaped () ++ && !type1->has_escaped ()) ++ { ++ type1->mark_escape (escape_dependent_type_escapes, NULL); ++ changed = true; ++ } ++ } ++ } ++ } ++ } while (changed); ++} ++ ++/* Prune the escaped types and their decls from what was recorded. */ ++ ++void ++ipa_struct_reorg::prune_escaped_types (void) ++{ ++ detect_cycles (); ++ propagate_escape (); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "all types (after prop but before pruning):\n"); ++ dump_types (dump_file); ++ fprintf (dump_file, "all functions (after prop but before pruning):\n"); ++ dump_functions (dump_file); ++ } ++ ++ if (dump_file) ++ dump_types_escaped (dump_file); ++ ++ /* Prune the function arguments which escape ++ and functions which have no types as arguments. */ ++ for (unsigned i = 0; i < functions.length ();) ++ { ++ srfunction *function = functions[i]; ++ ++ /* Prune function arguments of types that escape. */ ++ for (unsigned j = 0; j < function->args.length ();) ++ { ++ if (function->args[j]->type->has_escaped ()) ++ function->args.ordered_remove (j); ++ else ++ j++; ++ } ++ ++ /* Prune global variables that the function uses of types ++ that escape. */ ++ for (unsigned j = 0; j < function->globals.length ();) ++ { ++ if (function->globals[j]->type->has_escaped ()) ++ function->globals.ordered_remove (j); ++ else ++ j++; ++ } ++ ++ /* Prune variables that the function uses of types that escape. */ ++ for (unsigned j = 0; j < function->decls.length ();) ++ { ++ srdecl *decl = function->decls[j]; ++ if (decl->type->has_escaped ()) ++ { ++ function->decls.ordered_remove (j); ++ delete decl; ++ } ++ else ++ j++; ++ } ++ ++ /* Prune functions which don't refer to any variables any more. */ ++ if (function->args.is_empty () ++ && function->decls.is_empty () ++ && function->globals.is_empty ()) ++ { ++ delete function; ++ functions.ordered_remove (i); ++ } ++ else ++ i++; ++ } ++ ++ /* Prune globals of types that escape, all references to those decls ++ will have been removed in the first loop. */ ++ for (unsigned j = 0; j < globals.decls.length ();) ++ { ++ srdecl *decl = globals.decls[j]; ++ if (decl->type->has_escaped ()) ++ { ++ globals.decls.ordered_remove (j); ++ delete decl; ++ } ++ else ++ j++; ++ } ++ ++ /* Prune types that escape, all references to those types ++ will have been removed in the above loops. */ ++ for (unsigned i = 0; i < types.length ();) ++ { ++ srtype *type = types[i]; ++ if (type->has_escaped ()) ++ { ++ /* All references to this type should have been removed now. */ ++ delete type; ++ types.ordered_remove (i); ++ } ++ else ++ i++; ++ } ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "all types (after pruning):\n"); ++ dump_types (dump_file); ++ fprintf (dump_file, "all functions (after pruning):\n"); ++ dump_functions (dump_file); ++ } ++} ++ ++/* Analyze all of the types. */ ++ ++void ++ipa_struct_reorg::analyze_types (void) ++{ ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ if (!types[i]->has_escaped ()) ++ types[i]->analyze (); ++ } ++} ++ ++/* When struct A has a struct B member, B's type info ++ is not stored in ++ TYPE_FIELDS (TREE_TYPE (TYPE_FIELDS (typeA))) ++ Try to restore B's type information. */ ++ ++void ++ipa_struct_reorg::restore_field_type (void) ++{ ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ for (unsigned j = 0; j < types[i]->fields.length (); j++) ++ { ++ srfield *field = types[i]->fields[j]; ++ if (TREE_CODE (inner_type (field->fieldtype)) == RECORD_TYPE) ++ { ++ /* If field type has TYPE_FIELDS information, ++ we do not need to do this. */ ++ if (TYPE_FIELDS (field->type->type) != NULL) ++ continue; ++ for (unsigned k = 0; k < types.length (); k++) ++ { ++ if (i == k) ++ continue; ++ const char *type1 = get_type_name (field->type->type); ++ const char *type2 = get_type_name (types[k]->type); ++ if (type1 == NULL || type2 == NULL) ++ continue; ++ if (type1 == type2 ++ && TYPE_FIELDS (types[k]->type)) ++ field->type = types[k]; ++ } ++ } ++ } ++ } ++} ++ ++/* Create all new types we want to create. */ ++ ++bool ++ipa_struct_reorg::create_new_types (void) ++{ ++ int newtypes = 0; ++ clear_visited (); ++ for (unsigned i = 0; i < types.length (); i++) ++ newtypes += types[i]->create_new_type (); ++ ++ if (dump_file) ++ { ++ if (newtypes) ++ fprintf (dump_file, "\nNumber of structures to transform is %d\n", ++ newtypes); ++ else ++ fprintf (dump_file, "\nNo structures to transform.\n"); ++ } ++ ++ return newtypes != 0; ++} ++ ++/* Create all the new decls except for the new arguments ++ which create_new_functions would have created. */ ++ ++void ++ipa_struct_reorg::create_new_decls (void) ++{ ++ globals.create_new_decls (); ++ for (unsigned i = 0; i < functions.length (); i++) ++ functions[i]->create_new_decls (); ++} ++ ++/* Create the new arguments for the function corresponding to NODE. */ ++ ++void ++ipa_struct_reorg::create_new_args (cgraph_node *new_node) ++{ ++ tree decl = new_node->decl; ++ auto_vec params; ++ push_function_arg_decls (¶ms, decl); ++ vec *adjs = NULL; ++ vec_safe_reserve (adjs, params.length ()); ++ for (unsigned i = 0; i < params.length (); i++) ++ { ++ struct ipa_adjusted_param adj; ++ tree parm = params[i]; ++ memset (&adj, 0, sizeof (adj)); ++ adj.base_index = i; ++ adj.prev_clone_index = i; ++ srtype *t = find_type (inner_type (TREE_TYPE (parm))); ++ if (!t ++ || t->has_escaped () ++ || !t->has_new_type ()) ++ { ++ adj.op = IPA_PARAM_OP_COPY; ++ vec_safe_push (adjs, adj); ++ continue; ++ } ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Creating a new argument for: "); ++ print_generic_expr (dump_file, params[i]); ++ fprintf (dump_file, " in function: "); ++ print_generic_expr (dump_file, decl); ++ fprintf (dump_file, "\n"); ++ } ++ adj.op = IPA_PARAM_OP_NEW; ++ adj.param_prefix_index = IPA_PARAM_PREFIX_REORG; ++ for (unsigned j = 0; j < max_split && t->newtype[j]; j++) ++ { ++ adj.type = reconstruct_complex_type (TREE_TYPE (parm), ++ t->newtype[j]); ++ vec_safe_push (adjs, adj); ++ } ++ } ++ ipa_param_body_adjustments *adjustments ++ = new ipa_param_body_adjustments (adjs, decl); ++ adjustments->modify_formal_parameters (); ++ auto_vec new_params; ++ push_function_arg_decls (&new_params, decl); ++ unsigned veclen = vec_safe_length (adjs); ++ for (unsigned i = 0; i < veclen; i++) ++ { ++ if ((*adjs)[i].op != IPA_PARAM_OP_NEW) ++ continue; ++ tree decl = params[(*adjs)[i].base_index]; ++ srdecl *d = find_decl (decl); ++ if (!d) ++ continue; ++ unsigned j = 0; ++ while (j < max_split && d->newdecl[j]) ++ j++; ++ d->newdecl[j] = new_params[i]; ++ } ++ ++ function *fn = DECL_STRUCT_FUNCTION (decl); ++ ++ if (!fn->static_chain_decl) ++ return; ++ srdecl *chain = find_decl (fn->static_chain_decl); ++ if (!chain) ++ return; ++ ++ srtype *type = chain->type; ++ tree orig_var = chain->decl; ++ const char *tname = NULL; ++ if (DECL_NAME (orig_var)) ++ tname = IDENTIFIER_POINTER (DECL_NAME (orig_var)); ++ gcc_assert (!type->newtype[1]); ++ tree new_name = NULL; ++ char *name = NULL; ++ if (tname) ++ { ++ name = concat (tname, ".reorg.0", NULL); ++ new_name = get_identifier (name); ++ free (name); ++ } ++ tree newtype1 = reconstruct_complex_type (TREE_TYPE (orig_var), ++ type->newtype[0]); ++ chain->newdecl[0] = build_decl (DECL_SOURCE_LOCATION (orig_var), ++ PARM_DECL, new_name, newtype1); ++ copy_var_attributes (chain->newdecl[0], orig_var); ++ fn->static_chain_decl = chain->newdecl[0]; ++} ++ ++/* Find the refered DECL in the current function or globals. ++ If this is a global decl, record that as being used ++ in the current function. */ ++ ++srdecl * ++ipa_struct_reorg::find_decl (tree decl) ++{ ++ srdecl *d; ++ d = globals.find_decl (decl); ++ if (d) ++ { ++ /* Record the global usage in the current function. */ ++ if (!done_recording && current_function) ++ { ++ bool add = true; ++ /* No reason to add it to the current function if it is ++ already recorded as such. */ ++ for (unsigned i = 0; i < current_function->globals.length (); i++) ++ { ++ if (current_function->globals[i] == d) ++ { ++ add = false; ++ break; ++ } ++ } ++ if (add) ++ current_function->globals.safe_push (d); ++ } ++ return d; ++ } ++ if (current_function) ++ return current_function->find_decl (decl); ++ return NULL; ++} ++ ++/* Create new function clones for the cases where the arguments ++ need to be changed. */ ++ ++void ++ipa_struct_reorg::create_new_functions (void) ++{ ++ for (unsigned i = 0; i < functions.length (); i++) ++ { ++ srfunction *f = functions[i]; ++ bool anyargchanges = false; ++ cgraph_node *new_node; ++ cgraph_node *node = f->node; ++ int newargs = 0; ++ if (f->old) ++ continue; ++ ++ if (f->args.length () == 0) ++ continue; ++ ++ for (unsigned j = 0; j < f->args.length (); j++) ++ { ++ srdecl *d = f->args[j]; ++ srtype *t = d->type; ++ if (t->has_new_type ()) ++ { ++ newargs += t->newtype[1] != NULL; ++ anyargchanges = true; ++ } ++ } ++ if (!anyargchanges) ++ continue; ++ ++ if (dump_file) ++ { ++ fprintf (dump_file, "Creating a clone of function: "); ++ f->simple_dump (dump_file); ++ fprintf (dump_file, "\n"); ++ } ++ statistics_counter_event (NULL, "Create new function", 1); ++ new_node = node->create_version_clone_with_body (vNULL, NULL, ++ NULL, NULL, NULL, ++ "struct_reorg"); ++ new_node->can_change_signature = node->can_change_signature; ++ new_node->make_local (); ++ f->newnode = new_node; ++ srfunction *n = record_function (new_node); ++ current_function = n; ++ n->old = f; ++ f->newf = n; ++ /* Create New arguments. */ ++ create_new_args (new_node); ++ current_function = NULL; ++ } ++} ++ ++bool ++ipa_struct_reorg::rewrite_lhs_rhs (tree lhs, tree rhs, ++ tree newlhs[max_split], ++ tree newrhs[max_split]) ++{ ++ bool l = rewrite_expr (lhs, newlhs); ++ bool r = rewrite_expr (rhs, newrhs); ++ ++ /* Handle NULL pointer specially. */ ++ if (l && !r && integer_zerop (rhs)) ++ { ++ r = true; ++ for (unsigned i = 0; i < max_split && newlhs[i]; i++) ++ newrhs[i] = fold_convert (TREE_TYPE (newlhs[i]), rhs); ++ } ++ ++ return l || r; ++} ++ ++bool ++ipa_struct_reorg::rewrite_expr (tree expr, ++ tree newexpr[max_split], ++ bool ignore_missing_decl) ++{ ++ tree base; ++ bool indirect; ++ srtype *t; ++ srfield *f; ++ bool realpart, imagpart; ++ bool address; ++ ++ tree newbase[max_split]; ++ memset (newexpr, 0, sizeof (tree[max_split])); ++ ++ if (TREE_CODE (expr) == CONSTRUCTOR) ++ { ++ srtype *t = find_type (TREE_TYPE (expr)); ++ if (!t) ++ return false; ++ gcc_assert (CONSTRUCTOR_NELTS (expr) == 0); ++ if (!t->has_new_type ()) ++ return false; ++ for (unsigned i = 0; i < max_split && t->newtype[i]; i++) ++ newexpr[i] = build_constructor (t->newtype[i], NULL); ++ return true; ++ } ++ ++ if (!get_type_field (expr, base, indirect, t, f, ++ realpart, imagpart, address)) ++ return false; ++ ++ /* If the type is not changed, then just return false. */ ++ if (!t->has_new_type ()) ++ return false; ++ ++ /* NULL pointer handling is "special". */ ++ if (integer_zerop (base)) ++ { ++ gcc_assert (indirect && !address); ++ for (unsigned i = 0; i < max_split && t->newtype[i]; i++) ++ { ++ tree newtype1 = reconstruct_complex_type (TREE_TYPE (base), ++ t->newtype[i]); ++ newbase[i] = fold_convert (newtype1, base); ++ } ++ } ++ else ++ { ++ srdecl *d = find_decl (base); ++ ++ if (!d && dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Can't find decl:\n"); ++ print_generic_expr (dump_file, base); ++ fprintf (dump_file, "\ntype:\n"); ++ t->dump (dump_file); ++ } ++ if (!d && ignore_missing_decl) ++ return true; ++ gcc_assert (d); ++ memcpy (newbase, d->newdecl, sizeof (d->newdecl)); ++ } ++ ++ if (f == NULL) ++ { ++ memcpy (newexpr, newbase, sizeof (newbase)); ++ for (unsigned i = 0; i < max_split && newexpr[i]; i++) ++ { ++ if (address) ++ newexpr[i] = build_fold_addr_expr (newexpr[i]); ++ if (indirect) ++ newexpr[i] = build_simple_mem_ref (newexpr[i]); ++ if (imagpart) ++ newexpr[i] = build1 (IMAGPART_EXPR, ++ TREE_TYPE (TREE_TYPE (newexpr[i])), ++ newexpr[i]); ++ if (realpart) ++ newexpr[i] = build1 (REALPART_EXPR, ++ TREE_TYPE (TREE_TYPE (newexpr[i])), ++ newexpr[i]); ++ } ++ return true; ++ } ++ ++ tree newdecl = newbase[f->clusternum]; ++ for (unsigned i = 0; i < max_split && f->newfield[i]; i++) ++ { ++ tree newbase1 = newdecl; ++ if (address) ++ newbase1 = build_fold_addr_expr (newbase1); ++ if (indirect) ++ newbase1 = build_simple_mem_ref (newbase1); ++ newexpr[i] = build3 (COMPONENT_REF, TREE_TYPE (f->newfield[i]), ++ newbase1, f->newfield[i], NULL_TREE); ++ if (imagpart) ++ newexpr[i] = build1 (IMAGPART_EXPR, ++ TREE_TYPE (TREE_TYPE (newexpr[i])), ++ newexpr[i]); ++ if (realpart) ++ newexpr[i] = build1 (REALPART_EXPR, ++ TREE_TYPE (TREE_TYPE (newexpr[i])), ++ newexpr[i]); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "cluster: %d. decl = ", (int)f->clusternum); ++ print_generic_expr (dump_file, newbase1); ++ fprintf (dump_file, "\nnewexpr = "); ++ print_generic_expr (dump_file, newexpr[i]); ++ fprintf (dump_file, "\n"); ++ } ++ } ++ return true; ++} ++ ++bool ++ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) ++{ ++ bool remove = false; ++ if (gimple_clobber_p (stmt)) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree newlhs[max_split]; ++ if (!rewrite_expr (lhs, newlhs)) ++ return false; ++ for (unsigned i = 0; i < max_split && newlhs[i]; i++) ++ { ++ tree clobber = build_constructor (TREE_TYPE (newlhs[i]), NULL); ++ TREE_THIS_VOLATILE (clobber) = true; ++ gimple *newstmt = gimple_build_assign (newlhs[i], clobber); ++ gsi_insert_before (gsi, newstmt, GSI_SAME_STMT); ++ remove = true; ++ } ++ return remove; ++ } ++ ++ if (gimple_assign_rhs_code (stmt) == EQ_EXPR ++ || gimple_assign_rhs_code (stmt) == NE_EXPR) ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree newrhs1[max_split]; ++ tree newrhs2[max_split]; ++ tree_code rhs_code = gimple_assign_rhs_code (stmt); ++ tree_code code = rhs_code == EQ_EXPR ? BIT_AND_EXPR : BIT_IOR_EXPR; ++ if (!rewrite_lhs_rhs (rhs1, rhs2, newrhs1, newrhs2)) ++ return false; ++ tree newexpr = NULL_TREE; ++ for (unsigned i = 0; i < max_split && newrhs1[i]; i++) ++ { ++ tree expr = gimplify_build2 (gsi, rhs_code, boolean_type_node, ++ newrhs1[i], newrhs2[i]); ++ if (!newexpr) ++ newexpr = expr; ++ else ++ newexpr = gimplify_build2 (gsi, code, boolean_type_node, ++ newexpr, expr); ++ } ++ ++ if (newexpr) ++ { ++ newexpr = fold_convert (TREE_TYPE (gimple_assign_lhs (stmt)), ++ newexpr); ++ gimple_assign_set_rhs_from_tree (gsi, newexpr); ++ update_stmt (stmt); ++ } ++ return false; ++ } ++ ++ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree newlhs[max_split]; ++ tree newrhs[max_split]; ++ ++ if (!rewrite_lhs_rhs (lhs, rhs1, newlhs, newrhs)) ++ return false; ++ tree size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs))); ++ tree num; ++ /* Check if rhs2 is a multiplication of the size of the type. */ ++ if (!is_result_of_mult (rhs2, &num, size)) ++ internal_error ( ++ "The rhs of pointer is not a multiplicate and it slips through"); ++ ++ num = gimplify_build1 (gsi, NOP_EXPR, sizetype, num); ++ for (unsigned i = 0; i < max_split && newlhs[i]; i++) ++ { ++ gimple *new_stmt; ++ ++ tree newsize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (newlhs[i]))); ++ newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype, num, newsize); ++ new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR, ++ newrhs[i], newsize); ++ gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); ++ remove = true; ++ } ++ return remove; ++ } ++ if (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs = gimple_assign_rhs1 (stmt); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "rewriting statement:\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ tree newlhs[max_split]; ++ tree newrhs[max_split]; ++ if (!rewrite_lhs_rhs (lhs, rhs, newlhs, newrhs)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "\nDid nothing to statement.\n"); ++ return false; ++ } ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "\nreplaced with:\n"); ++ for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++) ++ { ++ gimple *newstmt = gimple_build_assign (newlhs[i] ? newlhs[i] : lhs, ++ newrhs[i] ? newrhs[i] : rhs); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ print_gimple_stmt (dump_file, newstmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ gsi_insert_before (gsi, newstmt, GSI_SAME_STMT); ++ remove = true; ++ } ++ return remove; ++ } ++ ++ return remove; ++} ++ ++/* Rewrite function call statement STMT. Return TRUE if the statement ++ is to be removed. */ ++ ++bool ++ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) ++{ ++ /* Handled allocation calls are handled seperately from normal ++ function calls. */ ++ if (handled_allocation_stmt (stmt)) ++ { ++ tree lhs = gimple_call_lhs (stmt); ++ tree newrhs1[max_split]; ++ srdecl *decl = find_decl (lhs); ++ if (!decl || !decl->type) ++ return false; ++ srtype *type = decl->type; ++ tree num = allocate_size (type, stmt); ++ gcc_assert (num); ++ memset (newrhs1, 0, sizeof (newrhs1)); ++ ++ /* The realloc call needs to have its first argument rewritten. */ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)) ++ { ++ tree rhs1 = gimple_call_arg (stmt, 0); ++ if (integer_zerop (rhs1)) ++ { ++ for (unsigned i = 0; i < max_split; i++) ++ newrhs1[i] = rhs1; ++ } ++ else if (!rewrite_expr (rhs1, newrhs1)) ++ internal_error ("Rewrite failed for realloc"); ++ } ++ ++ /* Go through each new lhs. */ ++ for (unsigned i = 0; i < max_split && decl->newdecl[i]; i++) ++ { ++ tree newsize = TYPE_SIZE_UNIT (type->type); ++ gimple *g; ++ /* Every allocation except for calloc needs ++ the size multiplied out. */ ++ if (!gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) ++ newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype, num, newsize); ++ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA)) ++ g = gimple_build_call (gimple_call_fndecl (stmt), ++ 1, newsize); ++ else if (gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) ++ g = gimple_build_call (gimple_call_fndecl (stmt), ++ 2, num, newsize); ++ else if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)) ++ g = gimple_build_call (gimple_call_fndecl (stmt), ++ 2, newrhs1[i], newsize); ++ else ++ gcc_assert (false); ++ gimple_call_set_lhs (g, decl->newdecl[i]); ++ gsi_insert_before (gsi, g, GSI_SAME_STMT); ++ } ++ return true; ++ } ++ ++ /* The function call free needs to be handled special. */ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_FREE)) ++ { ++ tree expr = gimple_call_arg (stmt, 0); ++ tree newexpr[max_split]; ++ if (!rewrite_expr (expr, newexpr)) ++ return false; ++ ++ if (newexpr[1] == NULL) ++ { ++ gimple_call_set_arg (stmt, 0, newexpr[0]); ++ update_stmt (stmt); ++ return false; ++ } ++ ++ for (unsigned i = 0; i < max_split && newexpr[i]; i++) ++ { ++ gimple *g = gimple_build_call (gimple_call_fndecl (stmt), ++ 1, newexpr[i]); ++ gsi_insert_before (gsi, g, GSI_SAME_STMT); ++ } ++ return true; ++ } ++ ++ /* Otherwise, look up the function to see if we have cloned it ++ and rewrite the arguments. */ ++ tree fndecl = gimple_call_fndecl (stmt); ++ ++ /* Indirect calls are already marked as escaping so ignore. */ ++ if (!fndecl) ++ return false; ++ ++ cgraph_node *node = cgraph_node::get (fndecl); ++ gcc_assert (node); ++ srfunction *f = find_function (node); ++ ++ /* Did not find the function or had not cloned it return saying don't ++ change the function call. */ ++ if (!f || !f->newf) ++ return false; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Changing arguments for function call :\n"); ++ print_gimple_expr (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ ++ /* Move over to the new function. */ ++ f = f->newf; ++ ++ tree chain = gimple_call_chain (stmt); ++ unsigned nargs = gimple_call_num_args (stmt); ++ auto_vec vargs (nargs); ++ ++ if (chain) ++ { ++ tree newchains[max_split]; ++ if (rewrite_expr (chain, newchains)) ++ { ++ /* Chain decl's type cannot be split and but it can change. */ ++ gcc_assert (newchains[1] == NULL); ++ chain = newchains[0]; ++ } ++ } ++ ++ for (unsigned i = 0; i < nargs; i++) ++ vargs.quick_push (gimple_call_arg (stmt, i)); ++ ++ int extraargs = 0; ++ ++ for (unsigned i = 0; i < f->args.length (); i++) ++ { ++ srdecl *d = f->args[i]; ++ if (d->argumentnum == -2) ++ continue; ++ gcc_assert (d->argumentnum != -1); ++ tree arg = vargs[d->argumentnum + extraargs]; ++ tree newargs[max_split]; ++ if (!rewrite_expr (arg, newargs)) ++ continue; ++ ++ /* If this ARG has a replacement handle the replacement. */ ++ for (unsigned j = 0; j < max_split && d->newdecl[j]; j++) ++ { ++ gcc_assert (newargs[j]); ++ /* If this is the first replacement of the arugment, ++ then just replace it. */ ++ if (j == 0) ++ vargs[d->argumentnum + extraargs] = newargs[j]; ++ else ++ { ++ /* More than one replacement, ++ we need to insert into the array. */ ++ extraargs++; ++ vargs.safe_insert (d->argumentnum + extraargs, newargs[j]); ++ } ++ } ++ } ++ ++ gcall *new_stmt; ++ ++ new_stmt = gimple_build_call_vec (f->node->decl, vargs); ++ ++ if (gimple_call_lhs (stmt)) ++ gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); ++ ++ gimple_set_vuse (new_stmt, gimple_vuse (stmt)); ++ gimple_set_vdef (new_stmt, gimple_vdef (stmt)); ++ ++ if (gimple_has_location (stmt)) ++ gimple_set_location (new_stmt, gimple_location (stmt)); ++ gimple_call_copy_flags (new_stmt, stmt); ++ gimple_call_set_chain (new_stmt, chain); ++ ++ gimple_set_modified (new_stmt, true); ++ ++ if (gimple_vdef (new_stmt) ++ && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME) ++ SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; ++ ++ gsi_replace (gsi, new_stmt, false); ++ ++ /* We need to defer cleaning EH info on the new statement to ++ fixup-cfg. We may not have dominator information at this point ++ and thus would end up with unreachable blocks and have no way ++ to communicate that we need to run CFG cleanup then. */ ++ int lp_nr = lookup_stmt_eh_lp (stmt); ++ if (lp_nr != 0) ++ { ++ remove_stmt_from_eh_lp (stmt); ++ add_stmt_to_eh_lp (new_stmt, lp_nr); ++ } ++ ++ return false; ++} ++ ++/* Rewrite the conditional statement STMT. Return TRUE if the ++ old statement is to be removed. */ ++ ++bool ++ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi) ++{ ++ tree_code rhs_code = gimple_cond_code (stmt); ++ ++ /* Handle only equals or not equals conditionals. */ ++ if (rhs_code != EQ_EXPR ++ && rhs_code != NE_EXPR) ++ return false; ++ tree rhs1 = gimple_cond_lhs (stmt); ++ tree rhs2 = gimple_cond_rhs (stmt); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "COND: Rewriting\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ print_generic_expr (dump_file, rhs1); ++ fprintf (dump_file, "\n"); ++ print_generic_expr (dump_file, rhs2); ++ fprintf (dump_file, "\n"); ++ } ++ ++ tree newrhs1[max_split]; ++ tree newrhs2[max_split]; ++ tree_code code = rhs_code == EQ_EXPR ? BIT_AND_EXPR : BIT_IOR_EXPR; ++ if (!rewrite_lhs_rhs (rhs1, rhs2, newrhs1, newrhs2)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "\nDid nothing to statement.\n"); ++ return false; ++ } ++ ++ tree newexpr = NULL_TREE; ++ for (unsigned i = 0; i < max_split && newrhs1[i]; i++) ++ { ++ tree expr = gimplify_build2 (gsi, rhs_code, boolean_type_node, ++ newrhs1[i], newrhs2[i]); ++ if (!newexpr) ++ newexpr = expr; ++ else ++ newexpr = gimplify_build2 (gsi, code, boolean_type_node, ++ newexpr, expr); ++ } ++ ++ if (newexpr) ++ { ++ gimple_cond_set_lhs (stmt, newexpr); ++ gimple_cond_set_rhs (stmt, boolean_true_node); ++ update_stmt (stmt); ++ } ++ return false; ++} ++ ++/* Rewrite debug statments if possible. Return TRUE if the statement ++ should be removed. */ ++ ++bool ++ipa_struct_reorg::rewrite_debug (gimple *stmt, gimple_stmt_iterator *) ++{ ++ bool remove = false; ++ if (gimple_debug_bind_p (stmt)) ++ { ++ tree var = gimple_debug_bind_get_var (stmt); ++ tree newvar[max_split]; ++ if (rewrite_expr (var, newvar, true)) ++ remove = true; ++ if (gimple_debug_bind_has_value_p (stmt)) ++ { ++ var = gimple_debug_bind_get_value (stmt); ++ if (TREE_CODE (var) == POINTER_PLUS_EXPR) ++ var = TREE_OPERAND (var, 0); ++ if (rewrite_expr (var, newvar, true)) ++ remove = true; ++ } ++ } ++ else if (gimple_debug_source_bind_p (stmt)) ++ { ++ tree var = gimple_debug_source_bind_get_var (stmt); ++ tree newvar[max_split]; ++ if (rewrite_expr (var, newvar, true)) ++ remove = true; ++ var = gimple_debug_source_bind_get_value (stmt); ++ if (TREE_CODE (var) == POINTER_PLUS_EXPR) ++ var = TREE_OPERAND (var, 0); ++ if (rewrite_expr (var, newvar, true)) ++ remove = true; ++ } ++ ++ return remove; ++} ++ ++/* Rewrite PHI nodes, return true if the PHI was replaced. */ ++ ++bool ++ipa_struct_reorg::rewrite_phi (gphi *phi) ++{ ++ tree newlhs[max_split]; ++ gphi *newphi[max_split]; ++ tree result = gimple_phi_result (phi); ++ gphi_iterator gsi; ++ ++ memset (newphi, 0, sizeof (newphi)); ++ ++ if (!rewrite_expr (result, newlhs)) ++ return false; ++ ++ if (newlhs[0] == NULL) ++ return false; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nrewriting PHI:"); ++ print_gimple_stmt (dump_file, phi, 0); ++ } ++ ++ for (unsigned i = 0; i < max_split && newlhs[i]; i++) ++ newphi[i] = create_phi_node (newlhs[i], gimple_bb (phi)); ++ ++ for (unsigned i = 0; i < gimple_phi_num_args (phi); i++) ++ { ++ tree newrhs[max_split]; ++ phi_arg_d rhs = *gimple_phi_arg (phi, i); ++ rewrite_expr (rhs.def, newrhs); ++ for (unsigned j = 0; j < max_split && newlhs[j]; j++) ++ { ++ SET_PHI_ARG_DEF (newphi[j], i, newrhs[j]); ++ gimple_phi_arg_set_location (newphi[j], i, rhs.locus); ++ update_stmt (newphi[j]); ++ } ++ } ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\ninto\n:"); ++ for (unsigned i = 0; i < max_split && newlhs[i]; i++) ++ { ++ print_gimple_stmt (dump_file, newphi[i], 0); ++ fprintf (dump_file, "\n"); ++ } ++ } ++ ++ gsi = gsi_for_phi (phi); ++ remove_phi_node (&gsi, false); ++ ++ return true; ++} ++ ++/* Rewrite gimple statement STMT, return true if the STATEMENT ++ is to be removed. */ ++ ++bool ++ipa_struct_reorg::rewrite_stmt (gimple *stmt, gimple_stmt_iterator *gsi) ++{ ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_ASSIGN: ++ return rewrite_assign (as_a (stmt), gsi); ++ case GIMPLE_CALL: ++ return rewrite_call (as_a (stmt), gsi); ++ case GIMPLE_COND: ++ return rewrite_cond (as_a (stmt), gsi); ++ break; ++ case GIMPLE_GOTO: ++ case GIMPLE_SWITCH: ++ break; ++ case GIMPLE_DEBUG: ++ case GIMPLE_ASM: ++ break; ++ default: ++ break; ++ } ++ return false; ++} ++ ++/* Does the function F uses any decl which has changed. */ ++ ++bool ++ipa_struct_reorg::has_rewritten_type (srfunction *f) ++{ ++ for (unsigned i = 0; i < f->decls.length (); i++) ++ { ++ srdecl *d = f->decls[i]; ++ if (d->newdecl[0] != d->decl) ++ return true; ++ } ++ ++ for (unsigned i = 0; i < f->globals.length (); i++) ++ { ++ srdecl *d = f->globals[i]; ++ if (d->newdecl[0] != d->decl) ++ return true; ++ } ++ return false; ++} ++ ++/* Rewrite the functions if needed, return ++ the TODOs requested. */ ++ ++unsigned ++ipa_struct_reorg::rewrite_functions (void) ++{ ++ unsigned retval = 0; ++ ++ restore_field_type (); ++ /* Create new types, if we did not create any new types, ++ then don't rewrite any accesses. */ ++ if (!create_new_types ()) ++ return 0; ++ ++ if (functions.length ()) ++ { ++ retval = TODO_remove_functions; ++ create_new_functions (); ++ } ++ ++ create_new_decls (); ++ ++ for (unsigned i = 0; i < functions.length (); i++) ++ { ++ srfunction *f = functions[i]; ++ if (f->newnode) ++ continue; ++ ++ /* Function uses no rewriten types so don't cause a rewrite. */ ++ if (!has_rewritten_type (f)) ++ continue; ++ ++ cgraph_node *node = f->node; ++ basic_block bb; ++ ++ push_cfun (DECL_STRUCT_FUNCTION (node->decl)); ++ current_function = f; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nBefore rewrite:\n"); ++ dump_function_to_file (current_function_decl, dump_file, ++ dump_flags | TDF_VOPS); ++ } ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);) ++ { ++ if (rewrite_phi (si.phi ())) ++ si = gsi_start_phis (bb); ++ else ++ gsi_next (&si); ++ } ++ ++ for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);) ++ { ++ gimple *stmt = gsi_stmt (si); ++ if (rewrite_stmt (stmt, &si)) ++ gsi_remove (&si, true); ++ else ++ gsi_next (&si); ++ } ++ } ++ ++ /* Debug statements need to happen after all other statements ++ have changed. */ ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);) ++ { ++ gimple *stmt = gsi_stmt (si); ++ if (gimple_code (stmt) == GIMPLE_DEBUG ++ && rewrite_debug (stmt, &si)) ++ gsi_remove (&si, true); ++ else ++ gsi_next (&si); ++ } ++ } ++ ++ /* Release the old SSA_NAMES for old arguments. */ ++ if (f->old) ++ { ++ for (unsigned i = 0; i < f->args.length (); i++) ++ { ++ srdecl *d = f->args[i]; ++ if (d->newdecl[0] != d->decl) ++ { ++ tree ssa_name = ssa_default_def (cfun, d->decl); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Found "); ++ print_generic_expr (dump_file, ssa_name); ++ fprintf (dump_file, " to be released.\n"); ++ } ++ release_ssa_name (ssa_name); ++ } ++ } ++ } ++ ++ update_ssa (TODO_update_ssa_only_virtuals); ++ ++ if (flag_tree_pta) ++ compute_may_aliases (); ++ ++ remove_unused_locals (); ++ ++ cgraph_edge::rebuild_edges (); ++ ++ free_dominance_info (CDI_DOMINATORS); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nAfter rewrite:\n"); ++ dump_function_to_file (current_function_decl, dump_file, ++ dump_flags | TDF_VOPS); ++ } ++ ++ pop_cfun (); ++ current_function = NULL; ++ } ++ ++ return retval | TODO_verify_all; ++} ++ ++unsigned int ++ipa_struct_reorg::execute (void) ++{ ++ /* FIXME: If there is a top-level inline-asm, ++ the pass immediately returns. */ ++ if (symtab->first_asm_symbol ()) ++ return 0; ++ record_accesses (); ++ prune_escaped_types (); ++ analyze_types (); ++ ++ return rewrite_functions (); ++} ++ ++const pass_data pass_data_ipa_struct_reorg = ++{ ++ SIMPLE_IPA_PASS, // type ++ "struct_reorg", // name ++ OPTGROUP_NONE, // optinfo_flags ++ TV_IPA_STRUCT_REORG, // tv_id ++ 0, // properties_required ++ 0, // properties_provided ++ 0, // properties_destroyed ++ 0, // todo_flags_start ++ 0, // todo_flags_finish ++}; ++ ++class pass_ipa_struct_reorg : public simple_ipa_opt_pass ++{ ++public: ++ pass_ipa_struct_reorg (gcc::context *ctxt) ++ : simple_ipa_opt_pass (pass_data_ipa_struct_reorg, ctxt) ++ {} ++ ++ /* opt_pass methods: */ ++ virtual bool gate (function *); ++ virtual unsigned int execute (function *) ++ { ++ return ipa_struct_reorg ().execute (); ++ } ++ ++}; // class pass_ipa_struct_reorg ++ ++bool ++pass_ipa_struct_reorg::gate (function *) ++{ ++ return (optimize ++ && flag_ipa_struct_reorg ++ /* Don't bother doing anything if the program has errors. */ ++ && !seen_error ()); ++} ++ ++} // anon namespace ++ ++ ++simple_ipa_opt_pass * ++make_pass_ipa_struct_reorg (gcc::context *ctxt) ++{ ++ return new pass_ipa_struct_reorg (ctxt); ++} +\ No newline at end of file +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +new file mode 100644 +index 000000000..a58794070 +--- /dev/null ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +@@ -0,0 +1,235 @@ ++/* Struct-reorg optimizations. ++ Copyright (C) 2016-2023 Free Software Foundation, Inc. ++ Contributed by Andrew Pinski ++ ++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 ++. */ ++ ++#ifndef IPA_STRUCT_REORG_H ++#define IPA_STRUCT_REORG_H ++ ++namespace struct_reorg { ++ ++const int max_split = 2; ++ ++template ++struct auto_vec_del : auto_vec ++{ ++ ~auto_vec_del (); ++}; ++ ++template ++auto_vec_del::~auto_vec_del (void) ++{ ++ unsigned i; ++ T *t; ++ FOR_EACH_VEC_ELT (*this, i, t) ++ { ++ delete t; ++ } ++} ++ ++enum escape_type ++{ ++ does_not_escape, ++#define DEF_ESCAPE(ENUM, TEXT) ENUM, ++#include "escapes.def" ++ escape_max_escape ++}; ++ ++const char *escape_type_string[escape_max_escape - 1] = ++{ ++#define DEF_ESCAPE(ENUM, TEXT) TEXT, ++#include "escapes.def" ++}; ++ ++struct srfield; ++struct srtype; ++struct sraccess; ++struct srdecl; ++struct srfunction; ++ ++struct srfunction ++{ ++ cgraph_node *node; ++ auto_vec args; ++ auto_vec globals; ++ auto_vec_del decls; ++ srdecl *record_decl (srtype *, tree, int arg); ++ ++ srfunction *old; ++ cgraph_node *newnode; ++ srfunction *newf; ++ ++ // Constructors ++ srfunction (cgraph_node *n); ++ ++ // Methods ++ void add_arg (srdecl *arg); ++ void dump (FILE *file); ++ void simple_dump (FILE *file); ++ ++ bool check_args (void); ++ void create_new_decls (void); ++ srdecl *find_decl (tree); ++}; ++ ++struct srglobal : private srfunction ++{ ++ srglobal () ++ : srfunction (NULL) ++ {} ++ ++ using srfunction::dump; ++ using srfunction::create_new_decls; ++ using srfunction::find_decl; ++ using srfunction::record_decl; ++ using srfunction::decls; ++}; ++ ++struct srtype ++{ ++ tree type; ++ auto_vec_del fields; ++ ++ // array of fields that use this type. ++ auto_vec field_sites; ++ ++ // array of functions which use directly the type ++ auto_vec functions; ++ ++ auto_vec_del accesses; ++ bool chain_type; ++ ++private: ++ escape_type escapes; ++ ++public: ++ tree newtype[max_split]; ++ bool visited; ++ ++ // Constructors ++ srtype (tree type); ++ ++ // Methods ++ void dump (FILE *file); ++ void simple_dump (FILE *file); ++ void add_function (srfunction *); ++ void add_access (sraccess *a) ++ { ++ accesses.safe_push (a); ++ } ++ void add_field_site (srfield *); ++ ++ srfield *find_field (unsigned HOST_WIDE_INT offset); ++ ++ bool create_new_type (void); ++ void analyze (void); ++ void mark_escape (escape_type, gimple *stmt); ++ bool has_escaped (void) ++ { ++ return escapes != does_not_escape; ++ } ++ const char *escape_reason (void) ++ { ++ if (!has_escaped ()) ++ return NULL; ++ return escape_type_string[escapes - 1]; ++ } ++ bool escaped_rescusive (void) ++ { ++ return escapes == escape_rescusive_type; ++ } ++ bool has_new_type (void) ++ { ++ return newtype[0] && newtype[0] != type; ++ } ++}; ++ ++struct srfield ++{ ++ unsigned HOST_WIDE_INT offset; ++ tree fieldtype; ++ tree fielddecl; ++ srtype *base; ++ srtype *type; ++ ++ unsigned clusternum; ++ ++ tree newfield[max_split]; ++ ++ // Constructors ++ srfield (tree field, srtype *base); ++ ++ // Methods ++ void dump (FILE *file); ++ void simple_dump (FILE *file); ++ ++ void create_new_fields (tree newtype[max_split], ++ tree newfields[max_split], ++ tree newlast[max_split]); ++}; ++ ++struct sraccess ++{ ++ gimple *stmt; ++ cgraph_node *node; ++ ++ srtype *type; ++ // NULL field means the whole type is accessed ++ srfield *field; ++ ++ // Constructors ++ sraccess (gimple *s, cgraph_node *n, srtype *t, srfield *f = NULL) ++ : stmt (s), ++ node (n), ++ type (t), ++ field (f) ++ {} ++ ++ // Methods ++ void dump (FILE *file); ++}; ++ ++struct srdecl ++{ ++ srtype *type; ++ tree decl; ++ tree func; ++ /* -1 : not an argument ++ -2 : static chain ++ */ ++ int argumentnum; ++ ++ bool visited; ++ ++ tree newdecl[max_split]; ++ ++ // Constructors ++ srdecl (srtype *type, tree decl, int argumentnum = -1); ++ ++ // Methods ++ void dump (FILE *file); ++ bool has_new_decl (void) ++ { ++ return newdecl[0] && newdecl[0] != decl; ++ } ++}; ++ ++ ++} // namespace struct_reorg ++ ++#endif +diff --git a/gcc/params.opt b/gcc/params.opt +index e0ff9e210..1ddf1343f 100644 +--- a/gcc/params.opt ++++ b/gcc/params.opt +@@ -865,6 +865,10 @@ Enum(parloops_schedule_type) String(runtime) Value(PARLOOPS_SCHEDULE_RUNTIME) + Common Joined UInteger Var(param_partial_inlining_entry_probability) Init(70) Optimization IntegerRange(0, 100) Param + Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen. + ++-param=struct-reorg-cold-struct-ratio= ++Common Joined UInteger Var(param_struct_reorg_cold_struct_ratio) Init(10) IntegerRange(0, 100) Param Optimization ++The threshold ratio between current and hottest structure counts. ++ + -param=predictable-branch-outcome= + Common Joined UInteger Var(param_predictable_branch_outcome) Init(2) IntegerRange(0, 50) Param Optimization + Maximal estimated outcome of branch considered predictable. +diff --git a/gcc/passes.def b/gcc/passes.def +index 375d3d62d..1c1658c4a 100644 +--- a/gcc/passes.def ++++ b/gcc/passes.def +@@ -177,6 +177,8 @@ along with GCC; see the file COPYING3. If not see + compiled unit. */ + INSERT_PASSES_AFTER (all_late_ipa_passes) + NEXT_PASS (pass_ipa_pta); ++ /* FIXME: this should be a normal IP pass. */ ++ NEXT_PASS (pass_ipa_struct_reorg); + NEXT_PASS (pass_omp_simd_clone); + TERMINATE_PASS_LIST (all_late_ipa_passes) + +diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +new file mode 100644 +index 000000000..43913104e +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +@@ -0,0 +1,35 @@ ++# Copyright (C) 1997-2023 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 ++# . ++ ++load_lib gcc-dg.exp ++load_lib torture-options.exp ++ ++# Initialize `dg'. ++dg-init ++torture-init ++ ++set STRUCT_REORG_TORTURE_OPTIONS [list \ ++ { -O3 } \ ++ { -Ofast } ] ++ ++set-torture-options $STRUCT_REORG_TORTURE_OPTIONS {{}} ++ ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \ ++ "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" ++ ++# All done. ++torture-finish ++dg-finish +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c +new file mode 100644 +index 000000000..6565fe8dd +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c +@@ -0,0 +1,24 @@ ++// { dg-do compile } ++// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all" } ++ ++struct a ++{ ++ int t, t1; ++}; ++ ++static struct a *b; ++ ++void *xmalloc(int); ++ ++ ++void f(void) ++{ ++ b = xmalloc (sizeof(*b)); ++} ++ ++int g(void) ++{ ++ return b->t; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c +new file mode 100644 +index 000000000..44babd35b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-2.c +@@ -0,0 +1,29 @@ ++// { dg-do run } ++ ++#include ++ ++struct a ++{ ++ int t; ++ int t1; ++}; ++ ++__attribute__((noinline)) int f(int i, int j) ++{ ++ struct a *t; ++ struct a t1 = {i, j}; ++ t = &t1; ++ auto int g(void) __attribute__((noinline)); ++ int g(void) ++ { ++ return t->t + t->t1; ++ } ++ return g(); ++} ++ ++int main() ++{ ++ assert (f(1, 2) == 3); ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c +new file mode 100644 +index 000000000..5864ad46f +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c +@@ -0,0 +1,23 @@ ++// { dg-do compile } ++// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all" } ++ ++#include ++typedef struct { ++ long laststart_offset; ++ unsigned regnum; ++} compile_stack_elt_t; ++typedef struct { ++ compile_stack_elt_t *stack; ++ unsigned size; ++} compile_stack_type; ++void f (const char *p, const char *pend, int c) ++{ ++ compile_stack_type compile_stack; ++ while (p != pend) ++ if (c) ++ compile_stack.stack = realloc (compile_stack.stack, ++ (compile_stack.size << 1) ++ * sizeof (compile_stack_elt_t)); ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c +new file mode 100644 +index 000000000..e5a8a6c84 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-4.c +@@ -0,0 +1,59 @@ ++/* { dg-do run } */ ++ ++extern void abort (void); ++ ++struct S ++{ ++ int b; ++ int *c; ++}; ++static int d, e; ++ ++static struct S s; ++ ++static int * ++__attribute__((noinline, const)) ++foo (void) ++{ ++ return &s.b; ++} ++ ++int * ++__attribute__((noinline)) ++bar (int **f) ++{ ++ s.c = &d; ++ *f = &e; ++ /* As nothing ever takes the address of any int * field in struct S, ++ the write to *f can't alias with the s.c field. */ ++ return s.c; ++} ++ ++int ++__attribute__((noinline)) ++baz (int *x) ++{ ++ s.b = 1; ++ *x = 4; ++ /* Function foo takes address of an int field in struct S, ++ so *x can alias with the s.b field (and it does in this testcase). */ ++ return s.b; ++} ++ ++int ++__attribute__((noinline)) ++t (void) ++{ ++ int *f = (int *) 0; ++ return 10 * (bar (&f) != &d) + baz (foo ()); ++} ++ ++int ++main (void) ++{ ++ if (t () != 4) ++ abort (); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c b/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c +new file mode 100644 +index 000000000..733413a94 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/w_prof_global_array.c +@@ -0,0 +1,29 @@ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#define N 1000 ++str_t A[N]; ++ ++int ++main () ++{ ++ int i; ++ ++ for (i = 0; i < N; i++) ++ { ++ A[i].a = 0; ++ } ++ ++ for (i = 0; i < N; i++) ++ if (A[i].a != 0) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c b/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c +new file mode 100644 +index 000000000..0ef686e74 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/w_prof_global_var.c +@@ -0,0 +1,42 @@ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++str_t *p; ++ ++int ++main () ++{ ++ int i, sum; ++ ++ p = malloc (N * sizeof (str_t)); ++ if (p == NULL) ++ return 0; ++ for (i = 0; i < N; i++) ++ p[i].b = i; ++ ++ for (i = 0; i < N; i++) ++ p[i].a = p[i].b + 1; ++ ++ for (i = 0; i < N; i++) ++ if (p[i].a != p[i].b + 1) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c b/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c +new file mode 100644 +index 000000000..23a53be53 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/w_prof_local_array.c +@@ -0,0 +1,37 @@ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ int i; ++ str_t A[N]; ++ ++ for (i = 0; i < N; i++) ++ { ++ A[i].a = 0; ++ } ++ ++ for (i = 0; i < N; i++) ++ if (A[i].a != 0) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c b/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c +new file mode 100644 +index 000000000..0cbb172f2 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/w_prof_local_var.c +@@ -0,0 +1,40 @@ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ int i, sum; ++ ++ str_t * p = malloc (N * sizeof (str_t)); ++ if (p == NULL) ++ return 0; ++ for (i = 0; i < N; i++) ++ p[i].b = i; ++ ++ for (i = 0; i < N; i++) ++ p[i].a = p[i].b + 1; ++ ++ for (i = 0; i < N; i++) ++ if (p[i].a != p[i].b + 1) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c b/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c +new file mode 100644 +index 000000000..f900b1349 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/w_prof_single_str_global.c +@@ -0,0 +1,31 @@ ++#include ++typedef struct ++{ ++ int a; ++ int b; ++}str_t; ++ ++#define N 3 ++ ++str_t str; ++ ++int ++main () ++{ ++ int i; ++ int res = 1<<(1< ++ ++typedef struct ++{ ++ int a; ++ float b; ++}str_t1; ++ ++typedef struct ++{ ++ int c; ++ float d; ++}str_t2; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 16000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/16) ++#endif ++#else ++#define N 1000 ++#endif ++ ++str_t1 *p1; ++str_t2 *p2; ++int num; ++ ++void ++foo (void) ++{ ++ int i; ++ ++ for (i=0; i < num; i++) ++ p2[i].c = 2; ++} ++ ++int ++main () ++{ ++ int i, r; ++ ++ r = rand (); ++ num = r > N ? N : r; ++ p1 = malloc (num * sizeof (str_t1)); ++ p2 = malloc (num * sizeof (str_t2)); ++ ++ if (p1 == NULL || p2 == NULL) ++ return 0; ++ ++ for (i = 0; i < num; i++) ++ p1[i].a = 1; ++ ++ foo (); ++ ++ for (i = 0; i < num; i++) ++ if (p1[i].a != 1 || p2[i].c != 2) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c b/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c +new file mode 100644 +index 000000000..dcc545964 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/w_ratio_cold_str.c +@@ -0,0 +1,43 @@ ++#include ++typedef struct ++{ ++ int a; ++ int b; ++}str_t1; ++ ++typedef struct ++{ ++ float a; ++ float b; ++}str_t2; ++ ++#define N1 1000 ++#define N2 100 ++str_t1 A1[N1]; ++str_t2 A2[N2]; ++ ++int ++main () ++{ ++ int i; ++ ++ for (i = 0; i < N1; i++) ++ A1[i].a = 0; ++ ++ for (i = 0; i < N2; i++) ++ A2[i].a = 0; ++ ++ for (i = 0; i < N1; i++) ++ if (A1[i].a != 0) ++ abort (); ++ ++ for (i = 0; i < N2; i++) ++ if (A2[i].a != 0) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* Arrays are not handled. */ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_array_field.c b/gcc/testsuite/gcc.dg/struct/wo_prof_array_field.c +new file mode 100644 +index 000000000..6d6375fc1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_array_field.c +@@ -0,0 +1,26 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct basic ++{ ++ int a; ++ int b[10]; ++} type_struct; ++ ++type_struct *str1; ++ ++int main() ++{ ++ int i; ++ ++ str1 = malloc (10 * sizeof (type_struct)); ++ ++ for (i=0; i<=9; i++) ++ str1[i].a = str1[i].b[0]; ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_array_through_pointer.c b/gcc/testsuite/gcc.dg/struct/wo_prof_array_through_pointer.c +new file mode 100644 +index 000000000..9d3213408 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_array_through_pointer.c +@@ -0,0 +1,38 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ int i; ++ str_t A[N]; ++ str_t *p = A; ++ ++ for (i = 0; i < N; i++) ++ p[i].a = 0; ++ ++ for (i = 0; i < N; i++) ++ if (p[i].a != 0) ++ abort (); ++ ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_double_malloc.c b/gcc/testsuite/gcc.dg/struct/wo_prof_double_malloc.c +new file mode 100644 +index 000000000..d79992a53 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_double_malloc.c +@@ -0,0 +1,29 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++ ++typedef struct test_struct ++{ ++ int a; ++ int b; ++} type_struct; ++ ++typedef type_struct **struct_pointer2; ++ ++struct_pointer2 str1; ++ ++int main() ++{ ++ int i, j; ++ ++ str1 = malloc (2 * sizeof (type_struct *)); ++ ++ for (i = 0; i <= 1; i++) ++ str1[i] = malloc (2 * sizeof (type_struct)); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c b/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c +new file mode 100644 +index 000000000..ee9b0d765 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c +@@ -0,0 +1,44 @@ ++/* { dg-do run } */ ++ ++#include ++ ++struct S { int a; struct V *b; }; ++typedef struct { int c; } T; ++typedef struct { int d; int e; } U; ++ ++void * ++fn (void *x) ++{ ++ return x; ++} ++ ++int ++foo (struct S *s) ++{ ++ T x; ++ ++ T y = *(T *)fn (&x); ++ return y.c; ++} ++ ++int ++bar (struct S *s) ++{ ++ U x; ++ ++ U y = *(U *)fn (&x); ++ return y.d + s->a; ++} ++ ++int ++main () ++{ ++ struct S s; ++ ++ foo(&s) + bar (&s); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c +new file mode 100644 +index 000000000..9ebb2b4cc +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c +@@ -0,0 +1,44 @@ ++/* { dg-do run } */ ++ ++#include ++struct str ++{ ++ int a; ++ float b; ++}; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++foo (struct str * p_str) ++{ ++ static int sum = 0; ++ ++ sum = sum + p_str->a; ++ return sum; ++} ++ ++int ++main () ++{ ++ int i, sum; ++ struct str * p = malloc (N * sizeof (struct str)); ++ if (p == NULL) ++ return 0; ++ for (i = 0; i < N; i++) ++ sum = foo (p+i); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ ++ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return-1.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return-1.c +new file mode 100644 +index 000000000..d0dce8b53 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return-1.c +@@ -0,0 +1,33 @@ ++/* { dg-do run } */ ++/* { dg-additional-options "-fno-ipa-sra" } */ ++ ++#include ++ ++struct A { ++ int d; ++ int d1; ++}; ++ ++struct A a; ++ ++struct A *foo () __attribute__((noinline)); ++struct A *foo () ++{ ++ a.d = 5; ++ return &a; ++} ++ ++int ++main () ++{ ++ a.d = 0; ++ foo (); ++ ++ if (a.d != 5) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "has escaped. .Type escapes via a return" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c +new file mode 100644 +index 000000000..71167182d +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c +@@ -0,0 +1,32 @@ ++/* { dg-do run } */ ++/* { dg-additional-options "-fno-ipa-sra" } */ ++ ++#include ++ ++struct A { ++ int d; ++}; ++ ++struct A a; ++ ++struct A foo () __attribute__((noinline)); ++struct A foo () ++{ ++ a.d = 5; ++ return a; ++} ++ ++int ++main () ++{ ++ a.d = 0; ++ foo (); ++ ++ if (a.d != 5) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "has escaped: \"Type escapes via a return" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c +new file mode 100644 +index 000000000..74fa11f39 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_str_init.c +@@ -0,0 +1,31 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ int b; ++}str_t; ++ ++#define N 2 ++ ++str_t A[2] = {{1,1},{2,2}}; ++ ++int ++main () ++{ ++ int i; ++ ++ for (i = 0; i < N; i++) ++ A[i].b = A[i].a; ++ ++ for (i = 0; i < N; i++) ++ if (A[i].b != A[i].a) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_array.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_array.c +new file mode 100644 +index 000000000..60d2466e1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_array.c +@@ -0,0 +1,33 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#define N 1000 ++ ++typedef struct ++{ ++ str_t A[N]; ++ int c; ++}str_with_substr_t; ++ ++str_with_substr_t a; ++ ++int ++main () ++{ ++ int i; ++ ++ for (i = 0; i < N; i++) ++ a.A[i].b = 0; ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c +new file mode 100644 +index 000000000..baf617816 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c +@@ -0,0 +1,48 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 16000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/16) ++#endif ++#else ++#define N 1000 ++#endif ++ ++typedef struct ++{ ++ str_t * sub_str; ++ int c; ++}str_with_substr_t; ++ ++int foo; ++ ++int ++main (void) ++{ ++ int i; ++ str_with_substr_t A[N]; ++ str_t a[N]; ++ ++ for (i=0; i < N; i++) ++ A[i].sub_str = &(a[i]); ++ ++ for (i=0; i < N; i++) ++ A[i].sub_str->a = 5; ++ ++ foo = A[56].sub_str->a; ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "has escaped...Type is used in an array" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_value.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_value.c +new file mode 100644 +index 000000000..33fce3b23 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_value.c +@@ -0,0 +1,45 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++ ++typedef struct ++{ ++ str_t sub_str; ++ int c; ++}str_with_substr_t; ++ ++int ++main () ++{ ++ int i; ++ str_with_substr_t A[N]; ++ ++ for (i = 0; i < N; i++) ++ A[i].sub_str.a = 5; ++ ++ for (i = 0; i < N; i++) ++ if (A[i].sub_str.a != 5) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "has escaped...Type is used in an array" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c b/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c +new file mode 100644 +index 000000000..1c5a3aa15 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_global_array.c +@@ -0,0 +1,32 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#define N 1000 ++str_t A[N]; ++ ++int ++main () ++{ ++ int i; ++ ++ for (i = 0; i < N; i++) ++ { ++ A[i].a = 0; ++ } ++ ++ for (i = 0; i < N; i++) ++ if (A[i].a != 0) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_global_var.c b/gcc/testsuite/gcc.dg/struct/wo_prof_global_var.c +new file mode 100644 +index 000000000..a0d1467fe +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_global_var.c +@@ -0,0 +1,45 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++str_t *p; ++ ++int ++main () ++{ ++ int i, sum; ++ ++ p = malloc (N * sizeof (str_t)); ++ if (p == NULL) ++ return 0; ++ for (i = 0; i < N; i++) ++ p[i].b = i; ++ ++ for (i = 0; i < N; i++) ++ p[i].b = p[i].a + 1; ++ ++ for (i = 0; i < N; i++) ++ if (p[i].b != p[i].a + 1) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_local_array.c b/gcc/testsuite/gcc.dg/struct/wo_prof_local_array.c +new file mode 100644 +index 000000000..6c24e1c8b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_local_array.c +@@ -0,0 +1,40 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ int i; ++ str_t A[N]; ++ ++ for (i = 0; i < N; i++) ++ { ++ A[i].a = 0; ++ } ++ ++ for (i = 0; i < N; i++) ++ if (A[i].a != 0) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" { xfail *-*-* } } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_local_var.c b/gcc/testsuite/gcc.dg/struct/wo_prof_local_var.c +new file mode 100644 +index 000000000..8f2f8143f +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_local_var.c +@@ -0,0 +1,43 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ int i, sum; ++ ++ str_t * p = malloc (N * sizeof (str_t)); ++ if (p == NULL) ++ return 0; ++ for (i = 0; i < N; i++) ++ p[i].b = i; ++ ++ for (i = 0; i < N; i++) ++ p[i].b = p[i].a + 1; ++ ++ for (i = 0; i < N; i++) ++ if (p[i].b != p[i].a + 1) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var-1.c b/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var-1.c +new file mode 100644 +index 000000000..98bf01a6d +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var-1.c +@@ -0,0 +1,47 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ long i, num; ++ ++ num = rand(); ++ num = num > N ? N : num; ++ str_t * p = malloc (num * sizeof (str_t)); ++ ++ if (p == 0) ++ return 0; ++ ++ for (i = 1; i <= num; i++) ++ p[i-1].b = i; ++ ++ for (i = 1; i <= num; i++) ++ p[i-1].a = p[i-1].b + 1; ++ ++ for (i = 0; i < num; i++) ++ if (p[i].a != p[i].b + 1) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var.c b/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var.c +new file mode 100644 +index 000000000..66b0f967c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_malloc_size_var.c +@@ -0,0 +1,47 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 8000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/8) ++#endif ++#else ++#define N 1000 ++#endif ++ ++int ++main () ++{ ++ int i, num; ++ ++ num = rand(); ++ num = num > N ? N : num; ++ str_t * p = malloc (num * sizeof (str_t)); ++ ++ if (p == 0) ++ return 0; ++ ++ for (i = 0; i < num; i++) ++ p[i].b = i; ++ ++ for (i = 0; i < num; i++) ++ p[i].a = p[i].b + 1; ++ ++ for (i = 0; i < num; i++) ++ if (p[i].a != p[i].b + 1) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c b/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c +new file mode 100644 +index 000000000..d28bcfb02 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_mult_field_peeling.c +@@ -0,0 +1,42 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ float b; ++ int c; ++ float d; ++}str_t; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 1600 ++#define N 100 ++#else ++#define N (STACK_SIZE/16) ++#endif ++#else ++#define N 100 ++#endif ++ ++int ++main () ++{ ++ int i; ++ str_t *p = malloc (N * sizeof (str_t)); ++ if (p == NULL) ++ return 0; ++ for (i = 0; i < N; i++) ++ p[i].a = 5; ++ ++ for (i = 0; i < N; i++) ++ if (p[i].a != 5) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* Two more fields structure is not splitted. */ ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_global.c b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_global.c +new file mode 100644 +index 000000000..37a6a43a8 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_single_str_global.c +@@ -0,0 +1,34 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++typedef struct ++{ ++ int a; ++ int b; ++}str_t; ++ ++#define N 3 ++ ++str_t str; ++ ++int ++main () ++{ ++ int i; ++ int res = 1<<(1< ++typedef struct ++{ ++ int a; ++ int b; ++}str_t; ++ ++#define N 3 ++ ++int ++main () ++{ ++ int i; ++ int res = 1<<(1< ++typedef struct ++{ ++ int a; ++ int *b; ++}str_t; ++ ++#define N 3 ++ ++str_t *p; ++ ++int ++main () ++{ ++ str_t str; ++ int i; ++ int res = 1 << (1 << N); ++ p = &str; ++ str.a = 2; ++ ++ p->b = &(p->a); ++ ++ for (i=0; i < N; i++) ++ p->a = *(p->b)*(*(p->b)); ++ ++ if (p->a != res) ++ abort (); ++ ++ /* POSIX ignores all but the 8 low-order bits, but other ++ environments may not. */ ++ return (p->a & 255); ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "has escaped...Type escapes a cast to a different" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_two_strs.c b/gcc/testsuite/gcc.dg/struct/wo_prof_two_strs.c +new file mode 100644 +index 000000000..cba92e995 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_two_strs.c +@@ -0,0 +1,67 @@ ++/* { dg-do compile } */ ++/* { dg-do run } */ ++ ++#include ++ ++typedef struct ++{ ++ int a; ++ float b; ++}str_t1; ++ ++typedef struct ++{ ++ int c; ++ float d; ++}str_t2; ++ ++#ifdef STACK_SIZE ++#if STACK_SIZE > 16000 ++#define N 1000 ++#else ++#define N (STACK_SIZE/16) ++#endif ++#else ++#define N 1000 ++#endif ++ ++str_t1 *p1; ++str_t2 *p2; ++int num; ++ ++void ++foo (void) ++{ ++ int i; ++ ++ for (i=0; i < num; i++) ++ p2[i].c = 2; ++} ++ ++int ++main () ++{ ++ int i, r; ++ ++ r = rand (); ++ num = r > N ? N : r; ++ p1 = malloc (num * sizeof (str_t1)); ++ p2 = malloc (num * sizeof (str_t2)); ++ ++ if (p1 == NULL || p2 == NULL) ++ return 0; ++ ++ for (i = 0; i < num; i++) ++ p1[i].a = 1; ++ ++ foo (); ++ ++ for (i = 0; i < num; i++) ++ if (p1[i].a != 1 || p2[i].c != 2) ++ abort (); ++ ++ return 0; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +diff --git a/gcc/timevar.def b/gcc/timevar.def +index 2dae5e1c7..366118126 100644 +--- a/gcc/timevar.def ++++ b/gcc/timevar.def +@@ -80,6 +80,7 @@ DEFTIMEVAR (TV_IPA_CONSTANT_PROP , "ipa cp") + DEFTIMEVAR (TV_IPA_INLINING , "ipa inlining heuristics") + DEFTIMEVAR (TV_IPA_FNSPLIT , "ipa function splitting") + DEFTIMEVAR (TV_IPA_COMDATS , "ipa comdats") ++DEFTIMEVAR (TV_IPA_STRUCT_REORG , "ipa struct reorg optimization") + DEFTIMEVAR (TV_IPA_OPT , "ipa various optimizations") + DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS , "lto stream decompression") + DEFTIMEVAR (TV_IPA_LTO_COMPRESS , "lto stream compression") +diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h +index 606d1d60b..ec7be874c 100644 +--- a/gcc/tree-pass.h ++++ b/gcc/tree-pass.h +@@ -526,6 +526,7 @@ extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt); ++extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_target_clone (gcc::context *ctxt); +-- +2.33.0 + diff --git a/0016-CompleteStructRelayout-Complete-Structure-Relayout.patch b/0016-CompleteStructRelayout-Complete-Structure-Relayout.patch new file mode 100644 index 0000000..37657ef --- /dev/null +++ b/0016-CompleteStructRelayout-Complete-Structure-Relayout.patch @@ -0,0 +1,2056 @@ +From 699caeaa2d89966e4af1d36bc96b53eb4dac0a09 Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Fri, 25 Aug 2023 09:59:39 +0800 +Subject: [PATCH 16/22] [CompleteStructRelayout] Complete Structure Relayout + +Introduce complete structure reorganization based on original +structure reorganization optimization, which change array of +structure to structure of array in order to better utilize +spatial locality. +--- + gcc/ipa-struct-reorg/escapes.def | 2 + + gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 994 ++++++++++++++++-- + gcc/ipa-struct-reorg/ipa-struct-reorg.h | 33 + + .../g++.dg/struct/no-body-function.cpp | 18 + + .../g++.dg/struct/struct-reorg-1.cpp | 13 + + .../g++.dg/struct/struct-reorg-2.cpp | 17 + + .../g++.dg/struct/struct-reorg-3.cpp | 24 + + gcc/testsuite/g++.dg/struct/struct-reorg.exp | 26 + + gcc/testsuite/gcc.dg/struct/csr_1.c | 60 ++ + .../gcc.dg/struct/csr_allocation-1.c | 46 + + .../gcc.dg/struct/csr_allocation-2.c | 59 ++ + .../gcc.dg/struct/csr_allocation-3.c | 77 ++ + gcc/testsuite/gcc.dg/struct/csr_cast_int.c | 52 + + .../gcc.dg/struct/csr_separate_instance.c | 48 + + .../gcc.dg/struct/sr_address_of_field.c | 37 + + gcc/testsuite/gcc.dg/struct/sr_convert_mem.c | 23 + + gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c | 25 + + gcc/testsuite/gcc.dg/struct/sr_pointer_and.c | 17 + + .../gcc.dg/struct/sr_pointer_minus.c | 33 + + 19 files changed, 1539 insertions(+), 65 deletions(-) + create mode 100644 gcc/testsuite/g++.dg/struct/no-body-function.cpp + create mode 100644 gcc/testsuite/g++.dg/struct/struct-reorg-1.cpp + create mode 100644 gcc/testsuite/g++.dg/struct/struct-reorg-2.cpp + create mode 100644 gcc/testsuite/g++.dg/struct/struct-reorg-3.cpp + create mode 100644 gcc/testsuite/g++.dg/struct/struct-reorg.exp + create mode 100644 gcc/testsuite/gcc.dg/struct/csr_1.c + create mode 100644 gcc/testsuite/gcc.dg/struct/csr_allocation-1.c + create mode 100644 gcc/testsuite/gcc.dg/struct/csr_allocation-2.c + create mode 100644 gcc/testsuite/gcc.dg/struct/csr_allocation-3.c + create mode 100644 gcc/testsuite/gcc.dg/struct/csr_cast_int.c + create mode 100644 gcc/testsuite/gcc.dg/struct/csr_separate_instance.c + create mode 100644 gcc/testsuite/gcc.dg/struct/sr_address_of_field.c + create mode 100644 gcc/testsuite/gcc.dg/struct/sr_convert_mem.c + create mode 100644 gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/sr_pointer_and.c + create mode 100644 gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c + +diff --git a/gcc/ipa-struct-reorg/escapes.def b/gcc/ipa-struct-reorg/escapes.def +index c4c8e0739..d825eb3e6 100644 +--- a/gcc/ipa-struct-reorg/escapes.def ++++ b/gcc/ipa-struct-reorg/escapes.def +@@ -56,5 +56,7 @@ DEF_ESCAPE (escape_non_optimize, "Type used by a function which turns off struct + DEF_ESCAPE (escape_array, "Type is used in an array [not handled yet]") + DEF_ESCAPE (escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]") + DEF_ESCAPE (escape_return, "Type escapes via a return [not handled yet]") ++DEF_ESCAPE (escape_separate_instance, "Type escapes via a separate instance") ++DEF_ESCAPE (escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt") + + #undef DEF_ESCAPE +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +index 238530860..c8b975a92 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +@@ -104,10 +104,12 @@ along with GCC; see the file COPYING3. If not see + #include "tree-ssa-live.h" /* For remove_unused_locals. */ + #include "ipa-param-manipulation.h" + #include "gimplify-me.h" ++#include "cfgloop.h" + + namespace { + + using namespace struct_reorg; ++using namespace struct_relayout; + + #define VOID_POINTER_P(type) \ + (POINTER_TYPE_P (type) && VOID_TYPE_P (TREE_TYPE (type))) +@@ -194,6 +196,14 @@ gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type, + GSI_SAME_STMT); + } + ++enum srmode ++{ ++ NORMAL = 0, ++ COMPLETE_STRUCT_RELAYOUT ++}; ++ ++static bool is_result_of_mult (tree, tree *, tree); ++ + } // anon namespace + + +@@ -283,7 +293,8 @@ srtype::srtype (tree type) + : type (type), + chain_type (false), + escapes (does_not_escape), +- visited (false) ++ visited (false), ++ has_alloc_array (0) + { + for (int i = 0; i < max_split; i++) + newtype[i] = NULL_TREE; +@@ -483,13 +494,6 @@ srtype::dump (FILE *f) + fn->simple_dump (f); + } + fprintf (f, "\n }\n"); +- fprintf (f, "\n field_sites = {"); +- FOR_EACH_VEC_ELT (field_sites, i, field) +- { +- fprintf (f, " \n"); +- field->simple_dump (f); +- } +- fprintf (f, "\n }\n"); + fprintf (f, "}\n"); + } + +@@ -631,15 +635,7 @@ srtype::create_new_type (void) + + maxclusters++; + +- const char *tname = NULL; +- +- if (TYPE_NAME (type) != NULL) +- { +- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) +- tname = IDENTIFIER_POINTER (TYPE_NAME (type)); +- else if (DECL_NAME (TYPE_NAME (type)) != NULL) +- tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); +- } ++ const char *tname = get_type_name (type); + + for (unsigned i = 0; i < maxclusters; i++) + { +@@ -653,7 +649,10 @@ srtype::create_new_type (void) + if (tname) + { + name = concat (tname, ".reorg.", id, NULL); +- TYPE_NAME (newtype[i]) = get_identifier (name); ++ TYPE_NAME (newtype[i]) = build_decl (UNKNOWN_LOCATION, ++ TYPE_DECL, ++ get_identifier (name), ++ newtype[i]); + free (name); + } + } +@@ -673,6 +672,8 @@ srtype::create_new_type (void) + { + TYPE_FIELDS (newtype[i]) = newfields[i]; + layout_type (newtype[i]); ++ if (TYPE_NAME (newtype[i]) != NULL) ++ layout_decl (TYPE_NAME (newtype[i]), 0); + } + + warn_padded = save_warn_padded; +@@ -841,12 +842,6 @@ srfield::dump (FILE *f) + fprintf (f, ", offset = " HOST_WIDE_INT_PRINT_DEC, offset); + fprintf (f, ", type = "); + print_generic_expr (f, fieldtype); +- if (type) +- { +- fprintf (f, "( srtype = "); +- type->simple_dump (f); +- fprintf (f, ")"); +- } + fprintf (f, "\n}\n"); + } + +@@ -855,7 +850,8 @@ srfield::dump (FILE *f) + void + srfield::simple_dump (FILE *f) + { +- fprintf (f, "field (%d)", DECL_UID (fielddecl)); ++ if (fielddecl) ++ fprintf (f, "field (%d)", DECL_UID (fielddecl)); + } + + /* Dump out the access structure to FILE. */ +@@ -899,6 +895,92 @@ srdecl::dump (FILE *file) + } // namespace struct_reorg + + ++namespace struct_relayout { ++ ++/* Complete Structure Relayout Optimization. ++ It reorganizes all structure members, and puts same member together. ++ struct s { ++ long a; ++ int b; ++ struct s *c; ++ }; ++ Array looks like ++ abcabcabcabc... ++ will be transformed to ++ aaaa...bbbb...cccc... ++*/ ++ ++#define GPTR_SIZE(i) \ ++ TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (gptr[i]))) ++ ++unsigned transformed = 0; ++ ++unsigned ++csrtype::calculate_field_num (tree field_offset) ++{ ++ if (field_offset == NULL) ++ return 0; ++ ++ HOST_WIDE_INT off = int_byte_position (field_offset); ++ unsigned i = 1; ++ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ { ++ if (off == int_byte_position (field)) ++ return i; ++ i++; ++ } ++ return 0; ++} ++ ++void ++csrtype::init_type_info (void) ++{ ++ if (!type) ++ return; ++ new_size = old_size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); ++ ++ /* Close enough to pad to improve performance. ++ 33~63 should pad to 64 but 33~48 (first half) are too far away, and ++ 65~127 should pad to 128 but 65~96 (first half) are too far away. */ ++ if (old_size > 48 && old_size < 64) ++ new_size = 64; ++ if (old_size > 96 && old_size < 128) ++ new_size = 128; ++ ++ /* For performance reasons, only allow structure size ++ that is a power of 2 and not too big. */ ++ if (new_size != 1 && new_size != 2 ++ && new_size != 4 && new_size != 8 ++ && new_size != 16 && new_size != 32 ++ && new_size != 64 && new_size != 128) ++ { ++ new_size = 0; ++ field_count = 0; ++ return; ++ } ++ ++ unsigned i = 0; ++ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ if (TREE_CODE (field) == FIELD_DECL) ++ i++; ++ field_count = i; ++ ++ struct_size = build_int_cstu (TREE_TYPE (TYPE_SIZE_UNIT (type)), ++ new_size); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Type: "); ++ print_generic_expr (dump_file, type); ++ fprintf (dump_file, " has %d members.\n", field_count); ++ fprintf (dump_file, "Modify struct size from %ld to %ld.\n", ++ old_size, new_size); ++ } ++} ++ ++} // namespace struct_relayout ++ ++ + namespace { + + struct ipa_struct_reorg +@@ -907,13 +989,10 @@ public: + // Constructors + ipa_struct_reorg (void) + : current_function (NULL), +- done_recording (false) ++ done_recording (false), ++ current_mode (NORMAL) + {} + +- // Public methods +- unsigned execute (void); +- void mark_type_as_escape (tree type, escape_type, gimple *stmt = NULL); +-private: + // Fields + auto_vec_del types; + auto_vec_del functions; +@@ -921,8 +1000,13 @@ private: + srfunction *current_function; + + bool done_recording; ++ srmode current_mode; ++ ++ // Methods ++ unsigned execute (enum srmode mode); ++ void mark_type_as_escape (tree type, escape_type escapes, ++ gimple *stmt = NULL); + +- // Private methods + void dump_types (FILE *f); + void dump_types_escaped (FILE *f); + void dump_functions (FILE *f); +@@ -954,6 +1038,7 @@ private: + void maybe_record_allocation_site (cgraph_node *, gimple *); + void record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt); + void mark_expr_escape (tree, escape_type, gimple *stmt); ++ bool handled_allocation_stmt (gimple *stmt); + tree allocate_size (srtype *t, gimple *stmt); + + void mark_decls_in_as_not_needed (tree fn); +@@ -976,6 +1061,7 @@ private: + bool can_escape = false); + bool wholeaccess (tree expr, tree base, tree accesstype, srtype *t); + ++ void check_alloc_num (gimple *stmt, srtype *type); + void check_definition (srdecl *decl, vec &); + void check_uses (srdecl *decl, vec &); + void check_use (srdecl *decl, gimple *stmt, vec &); +@@ -990,8 +1076,591 @@ private: + + bool has_rewritten_type (srfunction *); + void maybe_mark_or_record_other_side (tree side, tree other, gimple *stmt); ++ ++ unsigned execute_struct_relayout (void); + }; + ++struct ipa_struct_relayout ++{ ++public: ++ // Fields ++ tree gptr[max_relayout_split + 1]; ++ csrtype ctype; ++ ipa_struct_reorg *sr; ++ cgraph_node *current_node; ++ ++ // Constructors ++ ipa_struct_relayout (tree type, ipa_struct_reorg *sr_) ++ { ++ ctype.type = type; ++ sr = sr_; ++ current_node = NULL; ++ for (int i = 0; i < max_relayout_split + 1; i++) ++ gptr[i] = NULL; ++ } ++ ++ // Methods ++ tree create_new_vars (tree type, const char *name); ++ void create_global_ptrs (void); ++ unsigned int rewrite (void); ++ void rewrite_stmt_in_function (void); ++ bool rewrite_debug (gimple *stmt, gimple_stmt_iterator *gsi); ++ bool rewrite_stmt (gimple *stmt, gimple_stmt_iterator *gsi); ++ bool handled_allocation_stmt (gcall *stmt); ++ void init_global_ptrs (gcall *stmt, gimple_stmt_iterator *gsi); ++ bool check_call_uses (gcall *stmt); ++ bool rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi); ++ tree create_ssa (tree node, gimple_stmt_iterator *gsi); ++ bool is_candidate (tree xhs); ++ tree rewrite_address (tree xhs, gimple_stmt_iterator *gsi); ++ tree rewrite_offset (tree offset, HOST_WIDE_INT num); ++ bool rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi); ++ bool maybe_rewrite_cst (tree cst, gimple_stmt_iterator *gsi, ++ HOST_WIDE_INT ×); ++ unsigned int execute (void); ++}; ++ ++} // anon namespace ++ ++namespace { ++ ++/* Methods for ipa_struct_relayout. */ ++ ++static void ++set_var_attributes (tree var) ++{ ++ if (!var) ++ return; ++ gcc_assert (TREE_CODE (var) == VAR_DECL); ++ ++ DECL_ARTIFICIAL (var) = 1; ++ DECL_EXTERNAL (var) = 0; ++ TREE_STATIC (var) = 1; ++ TREE_PUBLIC (var) = 0; ++ TREE_USED (var) = 1; ++ DECL_CONTEXT (var) = NULL; ++ TREE_THIS_VOLATILE (var) = 0; ++ TREE_ADDRESSABLE (var) = 0; ++ TREE_READONLY (var) = 0; ++ if (is_global_var (var)) ++ set_decl_tls_model (var, TLS_MODEL_NONE); ++} ++ ++tree ++ipa_struct_relayout::create_new_vars (tree type, const char *name) ++{ ++ gcc_assert (type); ++ tree new_type = build_pointer_type (type); ++ ++ tree new_name = NULL; ++ if (name) ++ new_name = get_identifier (name); ++ ++ tree new_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, new_name, new_type); ++ ++ /* Set new_var's attributes. */ ++ set_var_attributes (new_var); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Created new var: "); ++ print_generic_expr (dump_file, new_var); ++ fprintf (dump_file, "\n"); ++ } ++ return new_var; ++} ++ ++void ++ipa_struct_relayout::create_global_ptrs (void) ++{ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "Create global gptrs: {\n"); ++ ++ char *gptr0_name = NULL; ++ const char *type_name = get_type_name (ctype.type); ++ ++ if (type_name) ++ gptr0_name = concat (type_name, "_gptr0", NULL); ++ tree var_gptr0 = create_new_vars (ctype.type, gptr0_name); ++ gptr[0] = var_gptr0; ++ varpool_node::add (var_gptr0); ++ ++ unsigned i = 1; ++ for (tree field = TYPE_FIELDS (ctype.type); field; ++ field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL) ++ { ++ tree type = TREE_TYPE (field); ++ ++ char *name = NULL; ++ char id[10] = {0}; ++ sprintf (id, "%d", i); ++ const char *decl_name = IDENTIFIER_POINTER (DECL_NAME (field)); ++ ++ if (type_name && decl_name) ++ name = concat (type_name, "_", decl_name, "_gptr", id, NULL); ++ tree var = create_new_vars (type, name); ++ ++ gptr[i] = var; ++ varpool_node::add (var); ++ i++; ++ } ++ } ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "\nTotally create %d gptrs. }\n\n", i); ++ gcc_assert (ctype.field_count == i - 1); ++} ++ ++void ++ipa_struct_relayout::rewrite_stmt_in_function (void) ++{ ++ gcc_assert (cfun); ++ ++ basic_block bb = NULL; ++ gimple_stmt_iterator si; ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ for (si = gsi_start_bb (bb); !gsi_end_p (si);) ++ { ++ gimple *stmt = gsi_stmt (si); ++ if (rewrite_stmt (stmt, &si)) ++ gsi_remove (&si, true); ++ else ++ gsi_next (&si); ++ } ++ } ++ ++ /* Debug statements need to happen after all other statements ++ have changed. */ ++ FOR_EACH_BB_FN (bb, cfun) ++ { ++ for (si = gsi_start_bb (bb); !gsi_end_p (si);) ++ { ++ gimple *stmt = gsi_stmt (si); ++ if (gimple_code (stmt) == GIMPLE_DEBUG ++ && rewrite_debug (stmt, &si)) ++ gsi_remove (&si, true); ++ else ++ gsi_next (&si); ++ } ++ } ++} ++ ++unsigned int ++ipa_struct_relayout::rewrite (void) ++{ ++ cgraph_node *cnode = NULL; ++ function *fn = NULL; ++ FOR_EACH_FUNCTION (cnode) ++ { ++ if (!cnode->real_symbol_p () || !cnode->has_gimple_body_p ()) ++ continue; ++ if (cnode->definition) ++ { ++ fn = DECL_STRUCT_FUNCTION (cnode->decl); ++ if (fn == NULL) ++ continue; ++ ++ current_node = cnode; ++ push_cfun (fn); ++ ++ rewrite_stmt_in_function (); ++ ++ update_ssa (TODO_update_ssa_only_virtuals); ++ ++ if (flag_tree_pta) ++ compute_may_aliases (); ++ ++ remove_unused_locals (); ++ ++ cgraph_edge::rebuild_edges (); ++ ++ free_dominance_info (CDI_DOMINATORS); ++ ++ pop_cfun (); ++ current_node = NULL; ++ } ++ } ++ return TODO_verify_all; ++} ++ ++bool ++ipa_struct_relayout::rewrite_debug (gimple *stmt ATTRIBUTE_UNUSED, ++ gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED) ++{ ++ /* Delete debug gimple now. */ ++ return true; ++} ++ ++bool ++ipa_struct_relayout::rewrite_stmt (gimple *stmt, gimple_stmt_iterator *gsi) ++{ ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_ASSIGN: ++ return rewrite_assign (as_a (stmt), gsi); ++ case GIMPLE_CALL: ++ return rewrite_call (as_a (stmt), gsi); ++ default: ++ break; ++ } ++ return false; ++} ++ ++bool ++ipa_struct_relayout::handled_allocation_stmt (gcall *stmt) ++{ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) ++ return true; ++ return false; ++} ++ ++void ++ipa_struct_relayout::init_global_ptrs (gcall *stmt, gimple_stmt_iterator *gsi) ++{ ++ gcc_assert (handled_allocation_stmt (stmt)); ++ ++ tree lhs = gimple_call_lhs (stmt); ++ ++ /* Case that gimple is at the end of bb. */ ++ if (gsi_one_before_end_p (*gsi)) ++ { ++ gassign *gptr0 = gimple_build_assign (gptr[0], lhs); ++ gsi_insert_after (gsi, gptr0, GSI_SAME_STMT); ++ } ++ gsi_next (gsi); ++ ++ /* Emit gimple gptr0 = _X and gptr1 = _X. */ ++ gassign *gptr0 = gimple_build_assign (gptr[0], lhs); ++ gsi_insert_before (gsi, gptr0, GSI_SAME_STMT); ++ gassign *gptr1 = gimple_build_assign (gptr[1], lhs); ++ gsi_insert_before (gsi, gptr1, GSI_SAME_STMT); ++ ++ /* Emit gimple gptr_[i] = gptr_[i-1] + _Y[gap]. */ ++ for (unsigned i = 2; i <= ctype.field_count; i++) ++ { ++ gimple *new_stmt = NULL; ++ tree gptr_i_prev_ssa = create_ssa (gptr[i-1], gsi); ++ tree gptr_i_ssa = make_ssa_name (TREE_TYPE (gptr[i-1])); ++ ++ /* Emit gimple _Y[gap] = N * sizeof (member). */ ++ tree member_gap = gimplify_build2 (gsi, MULT_EXPR, ++ long_unsigned_type_node, ++ gimple_call_arg (stmt, 0), ++ GPTR_SIZE (i-1)); ++ ++ new_stmt = gimple_build_assign (gptr_i_ssa, POINTER_PLUS_EXPR, ++ gptr_i_prev_ssa, member_gap); ++ gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); ++ ++ gassign *gptr_i = gimple_build_assign (gptr[i], gptr_i_ssa); ++ gsi_insert_before (gsi, gptr_i, GSI_SAME_STMT); ++ } ++ gsi_prev (gsi); ++} ++ ++bool ++ipa_struct_relayout::check_call_uses (gcall *stmt) ++{ ++ gcc_assert (current_node); ++ srfunction *fn = sr->find_function (current_node); ++ tree lhs = gimple_call_lhs (stmt); ++ ++ if (fn == NULL) ++ return false; ++ ++ srdecl *d = fn->find_decl (lhs); ++ if (d == NULL) ++ return false; ++ if (types_compatible_p (d->type->type, ctype.type)) ++ return true; ++ ++ return false; ++} ++ ++bool ++ipa_struct_relayout::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) ++{ ++ if (handled_allocation_stmt (stmt)) ++ { ++ /* Rewrite stmt _X = calloc (N, sizeof (struct)). */ ++ tree size = gimple_call_arg (stmt, 1); ++ if (TREE_CODE (size) != INTEGER_CST) ++ return false; ++ if (tree_to_uhwi (size) != ctype.old_size) ++ return false; ++ if (!check_call_uses (stmt)) ++ return false; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Rewrite allocation call:\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "to\n"); ++ } ++ ++ /* Modify sizeof (struct). */ ++ gimple_call_set_arg (stmt, 1, ctype.struct_size); ++ update_stmt (stmt); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ ++ init_global_ptrs (stmt, gsi); ++ } ++ return false; ++} ++ ++tree ++ipa_struct_relayout::create_ssa (tree node, gimple_stmt_iterator *gsi) ++{ ++ gcc_assert (TREE_CODE (node) == VAR_DECL); ++ tree node_ssa = make_ssa_name (TREE_TYPE (node)); ++ gassign *stmt = gimple_build_assign (node_ssa, node); ++ gsi_insert_before (gsi, stmt, GSI_SAME_STMT); ++ return node_ssa; ++} ++ ++bool ++ipa_struct_relayout::is_candidate (tree xhs) ++{ ++ if (TREE_CODE (xhs) != COMPONENT_REF) ++ return false; ++ tree mem = TREE_OPERAND (xhs, 0); ++ if (TREE_CODE (mem) == MEM_REF) ++ { ++ tree type = TREE_TYPE (mem); ++ if (types_compatible_p (type, ctype.type)) ++ return true; ++ } ++ return false; ++} ++ ++tree ++ipa_struct_relayout::rewrite_address (tree xhs, gimple_stmt_iterator *gsi) ++{ ++ tree mem_ref = TREE_OPERAND (xhs, 0); ++ tree pointer = TREE_OPERAND (mem_ref, 0); ++ tree pointer_offset = TREE_OPERAND (mem_ref, 1); ++ tree field = TREE_OPERAND (xhs, 1); ++ ++ tree pointer_ssa = fold_convert (long_unsigned_type_node, pointer); ++ tree gptr0_ssa = fold_convert (long_unsigned_type_node, gptr[0]); ++ ++ /* Emit gimple _X1 = ptr - gptr0. */ ++ tree step1 = gimplify_build2 (gsi, MINUS_EXPR, long_unsigned_type_node, ++ pointer_ssa, gptr0_ssa); ++ ++ /* Emit gimple _X2 = _X1 / sizeof (struct). */ ++ tree step2 = gimplify_build2 (gsi, TRUNC_DIV_EXPR, long_unsigned_type_node, ++ step1, ctype.struct_size); ++ ++ unsigned field_num = ctype.calculate_field_num (field); ++ gcc_assert (field_num > 0 && field_num <= ctype.field_count); ++ ++ /* Emit gimple _X3 = _X2 * sizeof (member). */ ++ tree step3 = gimplify_build2 (gsi, MULT_EXPR, long_unsigned_type_node, ++ step2, GPTR_SIZE (field_num)); ++ ++ /* Emit gimple _X4 = gptr[I]. */ ++ tree gptr_field_ssa = create_ssa (gptr[field_num], gsi); ++ tree new_address = make_ssa_name (TREE_TYPE (gptr[field_num])); ++ gassign *new_stmt = gimple_build_assign (new_address, POINTER_PLUS_EXPR, ++ gptr_field_ssa, step3); ++ gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); ++ ++ /* MEM_REF with nonzero offset like ++ MEM[ptr + sizeof (struct)] = 0B ++ should be transformed to ++ MEM[gptr + sizeof (member)] = 0B ++ */ ++ HOST_WIDE_INT size ++ = tree_to_shwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_address)))); ++ tree new_size = rewrite_offset (pointer_offset, size); ++ if (new_size) ++ TREE_OPERAND (mem_ref, 1) = new_size; ++ ++ /* Update mem_ref pointer. */ ++ TREE_OPERAND (mem_ref, 0) = new_address; ++ ++ /* Update mem_ref TREE_TYPE. */ ++ TREE_TYPE (mem_ref) = TREE_TYPE (TREE_TYPE (new_address)); ++ ++ return mem_ref; ++} ++ ++tree ++ipa_struct_relayout::rewrite_offset (tree offset, HOST_WIDE_INT num) ++{ ++ if (TREE_CODE (offset) == INTEGER_CST) ++ { ++ bool sign = false; ++ HOST_WIDE_INT off = TREE_INT_CST_LOW (offset); ++ if (off == 0) ++ return NULL; ++ if (off < 0) ++ { ++ off = -off; ++ sign = true; ++ } ++ if (off % ctype.old_size == 0) ++ { ++ HOST_WIDE_INT times = off / ctype.old_size; ++ times = sign ? -times : times; ++ return build_int_cst (TREE_TYPE (offset), num * times); ++ } ++ } ++ return NULL; ++} ++ ++#define REWRITE_ASSIGN_TREE_IN_STMT(node) \ ++do \ ++{ \ ++ tree node = gimple_assign_##node (stmt); \ ++ if (node && is_candidate (node)) \ ++ { \ ++ tree mem_ref = rewrite_address (node, gsi); \ ++ gimple_assign_set_##node (stmt, mem_ref); \ ++ update_stmt (stmt); \ ++ } \ ++} while (0) ++ ++/* COMPONENT_REF = exp => MEM_REF = exp ++ / \ / \ ++ MEM_REF field gptr offset ++ / \ ++ pointer offset ++*/ ++bool ++ipa_struct_relayout::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) ++{ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Maybe rewrite assign:\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "to\n"); ++ } ++ ++ switch (gimple_num_ops (stmt)) ++ { ++ case 4: REWRITE_ASSIGN_TREE_IN_STMT (rhs3); // FALLTHRU ++ case 3: ++ { ++ REWRITE_ASSIGN_TREE_IN_STMT (rhs2); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ if (rhs2 && TREE_CODE (rhs2) == INTEGER_CST) ++ { ++ /* Handle pointer++ and pointer-- or ++ factor is euqal to struct size. */ ++ HOST_WIDE_INT times = 1; ++ if (maybe_rewrite_cst (rhs2, gsi, times)) ++ { ++ tree tmp = build_int_cst ( ++ TREE_TYPE (TYPE_SIZE_UNIT (ctype.type)), ++ ctype.new_size * times); ++ gimple_assign_set_rhs2 (stmt, tmp); ++ update_stmt (stmt); ++ } ++ } ++ } // FALLTHRU ++ case 2: REWRITE_ASSIGN_TREE_IN_STMT (rhs1); // FALLTHRU ++ case 1: REWRITE_ASSIGN_TREE_IN_STMT (lhs); // FALLTHRU ++ case 0: break; ++ default: gcc_unreachable (); ++ } ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } ++ return false; ++} ++ ++bool ++ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *gsi, ++ HOST_WIDE_INT ×) ++{ ++ bool ret = false; ++ gcc_assert (TREE_CODE (cst) == INTEGER_CST); ++ ++ gimple *stmt = gsi_stmt (*gsi); ++ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree lhs = gimple_assign_lhs (stmt); ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ if (types_compatible_p (inner_type (TREE_TYPE (rhs1)), ctype.type) ++ || types_compatible_p (inner_type (TREE_TYPE (lhs)), ctype.type)) ++ { ++ tree num = NULL; ++ if (is_result_of_mult (cst, &num, TYPE_SIZE_UNIT (ctype.type))) ++ { ++ times = TREE_INT_CST_LOW (num); ++ return true; ++ } ++ } ++ } ++ ++ if (gimple_assign_rhs_code (stmt) == MULT_EXPR) ++ { ++ if (gsi_one_before_end_p (*gsi)) ++ return false; ++ gsi_next (gsi); ++ gimple *stmt2 = gsi_stmt (*gsi); ++ ++ if (gimple_code (stmt2) == GIMPLE_ASSIGN ++ && gimple_assign_rhs_code (stmt2) == POINTER_PLUS_EXPR) ++ { ++ tree lhs = gimple_assign_lhs (stmt2); ++ tree rhs1 = gimple_assign_rhs1 (stmt2); ++ if (types_compatible_p (inner_type (TREE_TYPE (rhs1)), ctype.type) ++ || types_compatible_p (inner_type (TREE_TYPE (lhs)), ctype.type)) ++ { ++ tree num = NULL; ++ if (is_result_of_mult (cst, &num, TYPE_SIZE_UNIT (ctype.type))) ++ { ++ times = TREE_INT_CST_LOW (num); ++ ret = true; ++ } ++ } ++ } ++ gsi_prev (gsi); ++ return ret; ++ } ++ return false; ++} ++ ++unsigned int ++ipa_struct_relayout::execute (void) ++{ ++ ctype.init_type_info (); ++ if (ctype.field_count < min_relayout_split ++ || ctype.field_count > max_relayout_split) ++ return 0; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Complete Struct Relayout Type: "); ++ print_generic_expr (dump_file, ctype.type); ++ fprintf (dump_file, "\n"); ++ } ++ transformed++; ++ ++ create_global_ptrs (); ++ return rewrite (); ++} ++ ++} // anon namespace ++ ++ ++namespace { ++ ++/* Methods for ipa_struct_reorg. */ ++ + /* Dump all of the recorded types to file F. */ + + void +@@ -1189,7 +1858,7 @@ ipa_struct_reorg::record_type (tree type) + f->type = t1; + t1->add_field_site (f); + } +- if (t1 == type1) ++ if (t1 == type1 && current_mode != COMPLETE_STRUCT_RELAYOUT) + type1->mark_escape (escape_rescusive_type, NULL); + } + } +@@ -1331,6 +2000,12 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) + else + e = escape_type_volatile_array_or_ptrptr (TREE_TYPE (decl)); + ++ /* Separate instance is hard to trace in complete struct ++ relayout optimization. */ ++ if (current_mode == COMPLETE_STRUCT_RELAYOUT ++ && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) ++ e = escape_separate_instance; ++ + if (e != does_not_escape) + type->mark_escape (e, NULL); + } +@@ -1369,6 +2044,7 @@ ipa_struct_reorg::find_var (tree expr, gimple *stmt) + || TREE_CODE (expr) == VIEW_CONVERT_EXPR) + { + tree r = TREE_OPERAND (expr, 0); ++ tree orig_type = TREE_TYPE (expr); + if (handled_component_p (r) + || TREE_CODE (r) == MEM_REF) + { +@@ -1382,8 +2058,18 @@ ipa_struct_reorg::find_var (tree expr, gimple *stmt) + escape_vce, stmt); + } + if (TREE_CODE (r) == MEM_REF) +- mark_type_as_escape (TREE_TYPE (TREE_OPERAND (r, 1)), +- escape_addr, stmt); ++ { ++ mark_type_as_escape (TREE_TYPE (TREE_OPERAND (r, 1)), ++ escape_addr, stmt); ++ tree inner_type = TREE_TYPE (TREE_OPERAND (r, 0)); ++ if (orig_type != inner_type) ++ { ++ mark_type_as_escape (orig_type, ++ escape_cast_another_ptr, stmt); ++ mark_type_as_escape (inner_type, ++ escape_cast_another_ptr, stmt); ++ } ++ } + r = TREE_OPERAND (r, 0); + } + mark_expr_escape (r, escape_addr, stmt); +@@ -1407,7 +2093,8 @@ ipa_struct_reorg::find_vars (gimple *stmt) + { + case GIMPLE_ASSIGN: + if (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS +- || gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ || gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR ++ || gimple_assign_rhs_code (stmt) == NOP_EXPR) + { + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); +@@ -1432,6 +2119,32 @@ ipa_struct_reorg::find_vars (gimple *stmt) + current_function->record_decl (t, rhs, -1); + } + } ++ else ++ { ++ /* Because we won't handle these stmts in rewrite phase, ++ just mark these types as escaped. */ ++ switch (gimple_num_ops (stmt)) ++ { ++ case 4: mark_type_as_escape ( ++ TREE_TYPE (gimple_assign_rhs3 (stmt)), ++ escape_unhandled_rewrite, stmt); ++ // FALLTHRU ++ case 3: mark_type_as_escape ( ++ TREE_TYPE (gimple_assign_rhs2 (stmt)), ++ escape_unhandled_rewrite, stmt); ++ // FALLTHRU ++ case 2: mark_type_as_escape ( ++ TREE_TYPE (gimple_assign_rhs1 (stmt)), ++ escape_unhandled_rewrite, stmt); ++ // FALLTHRU ++ case 1: mark_type_as_escape ( ++ TREE_TYPE (gimple_assign_lhs (stmt)), ++ escape_unhandled_rewrite, stmt); ++ // FALLTHRU ++ case 0: break; ++ default: gcc_unreachable (); ++ } ++ } + break; + + case GIMPLE_CALL: +@@ -1514,9 +2227,21 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + /* If we have a integer, just check if it is a multiply of STRUCT_SIZE. */ + if (TREE_CODE (arg) == INTEGER_CST) + { +- if (integer_zerop (size_binop (FLOOR_MOD_EXPR, arg, struct_size))) ++ bool sign = false; ++ HOST_WIDE_INT size = TREE_INT_CST_LOW (arg); ++ if (size < 0) ++ { ++ size = -size; ++ sign = true; ++ } ++ tree arg2 = build_int_cst (TREE_TYPE (arg), size); ++ if (integer_zerop (size_binop (FLOOR_MOD_EXPR, arg2, struct_size))) + { +- *num = size_binop (FLOOR_DIV_EXPR, arg, struct_size); ++ tree number = size_binop (FLOOR_DIV_EXPR, arg2, struct_size); ++ if (sign) ++ number = build_int_cst (TREE_TYPE (number), ++ -tree_to_shwi (number)); ++ *num = number; + return true; + } + return false; +@@ -1586,16 +2311,21 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + + /* Return TRUE if STMT is an allocation statement that is handled. */ + +-static bool +-handled_allocation_stmt (gimple *stmt) ++bool ++ipa_struct_reorg::handled_allocation_stmt (gimple *stmt) + { +- if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_ALIGNED_ALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA) +- || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN)) ++ if (current_mode == COMPLETE_STRUCT_RELAYOUT ++ && gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) + return true; ++ ++ if (current_mode != COMPLETE_STRUCT_RELAYOUT) ++ if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALIGNED_ALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN)) ++ return true; + return false; + } + +@@ -1636,7 +2366,7 @@ ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt) + the size of structure. */ + if (operand_equal_p (arg1, struct_size, 0)) + return size; +- /* Check that first argument is a constant equal to ++ /* ??? Check that first argument is a constant equal to + the size of structure. */ + if (operand_equal_p (size, struct_size, 0)) + return arg1; +@@ -1751,6 +2481,25 @@ ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt) + } + } + ++static bool ++check_mem_ref_offset (tree expr) ++{ ++ tree num = NULL; ++ bool ret = false; ++ ++ if (TREE_CODE (expr) != MEM_REF) ++ return false; ++ ++ /* Try to find the structure size. */ ++ tree field_off = TREE_OPERAND (expr, 1); ++ tree tmp = TREE_OPERAND (expr, 0); ++ if (TREE_CODE (tmp) == ADDR_EXPR) ++ tmp = TREE_OPERAND (tmp, 0); ++ tree size = TYPE_SIZE_UNIT (inner_type (TREE_TYPE (tmp))); ++ ret = is_result_of_mult (field_off, &num, size); ++ return ret; ++} ++ + static tree + get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, + bool &realpart, bool &imagpart, +@@ -1792,7 +2541,8 @@ get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, + gcc_assert (TREE_CODE (field_off) == INTEGER_CST); + /* So we can mark the types as escaping if different. */ + accesstype = TREE_TYPE (field_off); +- offset += tree_to_uhwi (field_off); ++ if (!check_mem_ref_offset (expr)) ++ offset += tree_to_uhwi (field_off); + return TREE_OPERAND (expr, 0); + } + default: +@@ -2176,6 +2926,31 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, + type1->mark_escape (escape_cast_another_ptr, stmt); + } + ++void ++ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type) ++{ ++ if (current_mode == COMPLETE_STRUCT_RELAYOUT ++ && handled_allocation_stmt (stmt)) ++ { ++ tree arg0 = gimple_call_arg (stmt, 0); ++ basic_block bb = gimple_bb (stmt); ++ cgraph_node *node = current_function->node; ++ if (integer_onep (arg0)) ++ /* Actually NOT an array, but may ruin other array. */ ++ type->has_alloc_array = -1; ++ else if (bb->loop_father != NULL ++ && loop_outer (bb->loop_father) != NULL) ++ /* The allocation is in a loop. */ ++ type->has_alloc_array = -2; ++ else if (node->callers != NULL) ++ type->has_alloc_array = -3; ++ else ++ type->has_alloc_array = type->has_alloc_array < 0 ++ ? type->has_alloc_array ++ : type->has_alloc_array + 1; ++ } ++} ++ + /* + 2) Check SSA_NAMEs for non type usages (source or use) (worlist of srdecl) + a) if the SSA_NAME is sourced from a pointer plus, record the pointer and +@@ -2223,6 +2998,7 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) + if (!handled_allocation_stmt (stmt) + || !allocate_size (type, stmt)) + type->mark_escape (escape_return, stmt); ++ check_alloc_num (stmt, type); + return; + } + /* If the SSA_NAME is sourced from an inline-asm, +@@ -2264,6 +3040,20 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) + return; + } + ++ if (gimple_assign_rhs_code (stmt) == MAX_EXPR ++ || gimple_assign_rhs_code (stmt) == MIN_EXPR ++ || gimple_assign_rhs_code (stmt) == BIT_IOR_EXPR ++ || gimple_assign_rhs_code (stmt) == BIT_XOR_EXPR ++ || gimple_assign_rhs_code (stmt) == BIT_AND_EXPR) ++ { ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ if (TREE_CODE (rhs) == SSA_NAME) ++ check_type_and_push (rhs, type, worklist, stmt); ++ if (TREE_CODE (rhs2) == SSA_NAME) ++ check_type_and_push (rhs2, type, worklist, stmt); ++ return; ++ } ++ + /* Casts between pointers and integer are escaping. */ + if (gimple_assign_cast_p (stmt)) + { +@@ -2328,6 +3118,11 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, + srtype *t1 = find_type (inner_type (t)); + if (t1 == type) + { ++ /* In Complete Struct Relayout, if lhs type is the same ++ as rhs type, we could return without any harm. */ ++ if (current_mode == COMPLETE_STRUCT_RELAYOUT) ++ return; ++ + tree base; + bool indirect; + srtype *type1; +@@ -2376,8 +3171,11 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree rhs1 = gimple_cond_lhs (stmt); + tree rhs2 = gimple_cond_rhs (stmt); + tree orhs = rhs1; +- if (gimple_cond_code (stmt) != EQ_EXPR +- && gimple_cond_code (stmt) != NE_EXPR) ++ enum tree_code code = gimple_cond_code (stmt); ++ if (code != EQ_EXPR && code != NE_EXPR ++ && (current_mode != COMPLETE_STRUCT_RELAYOUT ++ || (code != LT_EXPR && code != LE_EXPR ++ && code != GT_EXPR && code != GE_EXPR))) + { + mark_expr_escape (rhs1, escape_non_eq, stmt); + mark_expr_escape (rhs2, escape_non_eq, stmt); +@@ -2406,8 +3204,11 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree rhs1 = gimple_assign_rhs1 (stmt); + tree rhs2 = gimple_assign_rhs2 (stmt); + tree orhs = rhs1; +- if (gimple_assign_rhs_code (stmt) != EQ_EXPR +- && gimple_assign_rhs_code (stmt) != NE_EXPR) ++ enum tree_code code = gimple_assign_rhs_code (stmt); ++ if (code != EQ_EXPR && code != NE_EXPR ++ && (current_mode != COMPLETE_STRUCT_RELAYOUT ++ || (code != LT_EXPR && code != LE_EXPR ++ && code != GT_EXPR && code != GE_EXPR))) + { + mark_expr_escape (rhs1, escape_non_eq, stmt); + mark_expr_escape (rhs2, escape_non_eq, stmt); +@@ -2692,6 +3493,12 @@ ipa_struct_reorg::record_accesses (void) + /* Record accesses inside a function. */ + if (cnode->definition) + record_function (cnode); ++ else ++ { ++ tree return_type = TREE_TYPE (TREE_TYPE (cnode->decl)); ++ mark_type_as_escape (return_type, escape_return, NULL); ++ } ++ + } + + if (dump_file && (dump_flags & TDF_DETAILS)) +@@ -2807,8 +3614,11 @@ ipa_struct_reorg::propagate_escape (void) + void + ipa_struct_reorg::prune_escaped_types (void) + { +- detect_cycles (); +- propagate_escape (); ++ if (current_mode != COMPLETE_STRUCT_RELAYOUT) ++ { ++ detect_cycles (); ++ propagate_escape (); ++ } + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +@@ -3954,17 +4764,66 @@ ipa_struct_reorg::rewrite_functions (void) + } + + unsigned int +-ipa_struct_reorg::execute (void) ++ipa_struct_reorg::execute_struct_relayout (void) + { +- /* FIXME: If there is a top-level inline-asm, +- the pass immediately returns. */ +- if (symtab->first_asm_symbol ()) +- return 0; +- record_accesses (); +- prune_escaped_types (); +- analyze_types (); ++ unsigned retval = 0; ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ tree type = types[i]->type; ++ if (TYPE_FIELDS (type) == NULL) ++ continue; ++ if (types[i]->has_alloc_array != 1) ++ continue; ++ if (types[i]->chain_type) ++ continue; ++ retval |= ipa_struct_relayout (type, this).execute (); ++ } ++ ++ if (dump_file) ++ { ++ if (transformed) ++ fprintf (dump_file, "\nNumber of structures to transform in " ++ "Complete Structure Relayout is %d\n", transformed); ++ else ++ fprintf (dump_file, "\nNo structures to transform in " ++ "Complete Structure Relayout.\n"); ++ } ++ ++ return retval; ++} ++ ++unsigned int ++ipa_struct_reorg::execute (enum srmode mode) ++{ ++ unsigned int ret = 0; ++ ++ if (mode == NORMAL) ++ { ++ current_mode = NORMAL; ++ /* FIXME: If there is a top-level inline-asm, ++ the pass immediately returns. */ ++ if (symtab->first_asm_symbol ()) ++ return 0; ++ record_accesses (); ++ prune_escaped_types (); ++ analyze_types (); ++ ++ ret = rewrite_functions (); ++ } ++ else if (mode == COMPLETE_STRUCT_RELAYOUT) ++ { ++ if (dump_file) ++ fprintf (dump_file, "\n\nTry Complete Struct Relayout:\n"); ++ current_mode = COMPLETE_STRUCT_RELAYOUT; ++ if (symtab->first_asm_symbol ()) ++ return 0; ++ record_accesses (); ++ prune_escaped_types (); ++ ++ ret = execute_struct_relayout (); ++ } + +- return rewrite_functions (); ++ return ret; + } + + const pass_data pass_data_ipa_struct_reorg = +@@ -3991,7 +4850,11 @@ public: + virtual bool gate (function *); + virtual unsigned int execute (function *) + { +- return ipa_struct_reorg ().execute (); ++ unsigned int ret = 0; ++ ret = ipa_struct_reorg ().execute (NORMAL); ++ if (!ret) ++ ret = ipa_struct_reorg ().execute (COMPLETE_STRUCT_RELAYOUT); ++ return ret; + } + + }; // class pass_ipa_struct_reorg +@@ -3999,10 +4862,11 @@ public: + bool + pass_ipa_struct_reorg::gate (function *) + { +- return (optimize ++ return (optimize >= 3 + && flag_ipa_struct_reorg + /* Don't bother doing anything if the program has errors. */ +- && !seen_error ()); ++ && !seen_error () ++ && flag_lto_partition == LTO_PARTITION_ONE); + } + + } // anon namespace +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +index a58794070..ef7f4c780 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +@@ -120,6 +120,9 @@ private: + public: + tree newtype[max_split]; + bool visited; ++ /* Negative number means it has illegal allocated arrays ++ that we do not optimize. */ ++ int has_alloc_array; + + // Constructors + srtype (tree type); +@@ -232,4 +235,34 @@ struct srdecl + + } // namespace struct_reorg + ++ ++namespace struct_relayout { ++ ++const int min_relayout_split = 8; ++const int max_relayout_split = 16; ++ ++struct csrtype ++{ ++ tree type; ++ unsigned HOST_WIDE_INT old_size; ++ unsigned HOST_WIDE_INT new_size; ++ unsigned field_count; ++ tree struct_size; ++ ++ // Constructors ++ csrtype () ++ : type (NULL), ++ old_size (0), ++ new_size (0), ++ field_count (0), ++ struct_size (NULL) ++ {} ++ ++ // Methods ++ unsigned calculate_field_num (tree field_offset); ++ void init_type_info (void); ++}; ++ ++} // namespace struct_relayout ++ + #endif +diff --git a/gcc/testsuite/g++.dg/struct/no-body-function.cpp b/gcc/testsuite/g++.dg/struct/no-body-function.cpp +new file mode 100644 +index 000000000..4e56e73fc +--- /dev/null ++++ b/gcc/testsuite/g++.dg/struct/no-body-function.cpp +@@ -0,0 +1,18 @@ ++/* { dg-do compile } */ ++/* { dg-options "-std=gnu++17 -Wno-builtin-declaration-mismatch -O3 -fwhole-program -flto-partition=one -fipa-struct-reorg -S" } */ ++ ++struct S { ++ int x; ++ double y; ++}; ++S f(); ++ ++const auto [x0, y0] = f(); ++const auto [x1, y1] = f(); ++ ++static union { ++int a; ++double b; ++}; ++ ++const auto [x2, y2] = f(); +diff --git a/gcc/testsuite/g++.dg/struct/struct-reorg-1.cpp b/gcc/testsuite/g++.dg/struct/struct-reorg-1.cpp +new file mode 100644 +index 000000000..6ab71abe1 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/struct/struct-reorg-1.cpp +@@ -0,0 +1,13 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O3 -fwhole-program -flto-partition=one -fipa-struct-reorg -fdump-ipa-struct_reorg-details -S" } */ ++ ++struct Foo { int foo; int a; }; ++Foo& ignoreSetMutex = *(new Foo); ++ ++struct Goo { int goo; int a; }; ++ ++int main () ++{ ++ Goo* a; ++ return a->goo = 90; ++} +diff --git a/gcc/testsuite/g++.dg/struct/struct-reorg-2.cpp b/gcc/testsuite/g++.dg/struct/struct-reorg-2.cpp +new file mode 100644 +index 000000000..72b7db8a9 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/struct/struct-reorg-2.cpp +@@ -0,0 +1,17 @@ ++/* { dg-do run } */ ++/* { dg-options "-O3 -fwhole-program -flto-partition=one -fipa-struct-reorg -fdump-ipa-struct_reorg-details" } */ ++ ++#include ++ ++struct testg { ++ int b; ++ float c; ++}; ++ ++testg *testgvar; ++int main () ++{ ++ testgvar = (testg*) calloc(10, sizeof(testg)); ++ int b = testgvar->b; ++ return b; ++} +diff --git a/gcc/testsuite/g++.dg/struct/struct-reorg-3.cpp b/gcc/testsuite/g++.dg/struct/struct-reorg-3.cpp +new file mode 100644 +index 000000000..771164a96 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/struct/struct-reorg-3.cpp +@@ -0,0 +1,24 @@ ++/* { dg-do run } */ ++/* { dg-options "-O3 -fwhole-program -flto-partition=one -fipa-struct-reorg -fdump-ipa-struct_reorg-details" } */ ++ ++#include ++ ++struct testg { ++ int b; ++ float c; ++ double d; ++ double e; ++ double f; ++ double h; ++ double i; ++ double j; ++ int k; ++}; ++ ++testg *testgvar; ++int main () ++{ ++ testgvar = (testg*) calloc(10, sizeof(testg)); ++ int b = testgvar->b; ++ return b; ++} +diff --git a/gcc/testsuite/g++.dg/struct/struct-reorg.exp b/gcc/testsuite/g++.dg/struct/struct-reorg.exp +new file mode 100644 +index 000000000..e3ffe1388 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/struct/struct-reorg.exp +@@ -0,0 +1,26 @@ ++# Copyright (C) 2021-2023 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 ++# . ++ ++load_lib g++-dg.exp ++ ++# Initialize `dg'. ++dg-init ++ ++g++-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cpp]] \ ++ "" "" ++ ++# All done. ++dg-finish +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/csr_1.c b/gcc/testsuite/gcc.dg/struct/csr_1.c +new file mode 100644 +index 000000000..811030bf1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/csr_1.c +@@ -0,0 +1,60 @@ ++// { dg-do run } ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++ node_p c; ++ node_p d; ++ long e; ++ long f; ++ long g; ++ long h; ++ long i; ++ long j; ++ long k; ++ long l; ++ int m; ++ int n; ++}; ++ ++const int MAX = 10000; ++node_p n; ++ ++int ++main () ++{ ++ n = (node_p) calloc (MAX, sizeof (node_t)); ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].a = 100; ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ if (n[i].a != 100) ++ { ++ abort (); ++ } ++ } ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].l = n[i].a; ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ if (n[i].l != 100) ++ { ++ abort (); ++ } ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform in Complete Structure Relayout is 1" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/csr_allocation-1.c b/gcc/testsuite/gcc.dg/struct/csr_allocation-1.c +new file mode 100644 +index 000000000..63bb695ae +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/csr_allocation-1.c +@@ -0,0 +1,46 @@ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++ node_p c; ++ node_p d; ++ long e; ++ long f; ++ long g; ++ long h; ++ long i; ++ long j; ++ long k; ++ long l; ++ int m; ++ int n; ++}; ++ ++const int MAX = 1; ++node_p n; ++ ++int ++main () ++{ ++ n = (node_p) calloc (MAX, sizeof (node_t)); ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].a = 100; ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ if (n[i].a != 100) ++ { ++ abort (); ++ } ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform in Complete Structure Relayout." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/csr_allocation-2.c b/gcc/testsuite/gcc.dg/struct/csr_allocation-2.c +new file mode 100644 +index 000000000..0f75d5d12 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/csr_allocation-2.c +@@ -0,0 +1,59 @@ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++ node_p c; ++ node_p d; ++ long e; ++ long f; ++ long g; ++ long h; ++ long i; ++ long j; ++ long k; ++ long l; ++ int m; ++ int n; ++}; ++ ++const int MAX = 10; ++node_p n; ++node_p m; ++ ++int main() ++{ ++ int i; ++ for (i = 0; i < MAX / 5; i++) ++ { ++ n = (node_p) calloc(MAX, sizeof(node_t)); ++ if (i == 0) ++ { ++ m = n; ++ } ++ } ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].a = 100; ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ m[i].a = 50; ++ } ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ if (n[i].a != 100) ++ { ++ abort (); ++ } ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform in Complete Structure Relayout." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/csr_allocation-3.c b/gcc/testsuite/gcc.dg/struct/csr_allocation-3.c +new file mode 100644 +index 000000000..3dcb674c6 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/csr_allocation-3.c +@@ -0,0 +1,77 @@ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++ node_p c; ++ node_p d; ++ long e; ++ long f; ++ long g; ++ long h; ++ long i; ++ long j; ++ long k; ++ long l; ++ int m; ++ int n; ++}; ++ ++const int MAX = 10; ++node_p n; ++node_p m; ++ ++void test (int, int) __attribute__((noinline)); ++ ++void ++test (int num, int flag) ++{ ++ if (num <= 0) ++ { ++ return; ++ } ++ n = (node_p) calloc (num, sizeof (node_t)); ++ if (flag) ++ { ++ m = n; ++ } ++ return; ++} ++ ++int ++main () ++{ ++ test (MAX, 1); ++ test (MAX, 0); ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].a = 100; ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ m[i].a = 50; ++ } ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ if (n[i].a != 100) ++ { ++ abort (); ++ } ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ if (m[i].a != 50) ++ { ++ abort (); ++ } ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform in Complete Structure Relayout." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/csr_cast_int.c b/gcc/testsuite/gcc.dg/struct/csr_cast_int.c +new file mode 100644 +index 000000000..6907158c9 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/csr_cast_int.c +@@ -0,0 +1,52 @@ ++// { dg-do run } ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++ node_p c; ++ node_p d; ++ long e; ++ long f; ++ long g; ++ long h; ++ long i; ++ long j; ++ long k; ++ long l; ++ int m; ++ int n; ++}; ++ ++const int MAX = 100; ++node_p n; ++unsigned long y; ++ ++int ++main () ++{ ++ n = (node_p) calloc (MAX, sizeof (node_t)); ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].b = 50; ++ } ++ ++ node_p x = &n[5]; ++ y = (unsigned long) x; ++ y += 8; ++ ++ if (*((unsigned long*) y) != 50) ++ { ++ abort (); ++ } ++ ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "struct node has escaped: \"Type escapes a cast from/to intergral type\"" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/csr_separate_instance.c b/gcc/testsuite/gcc.dg/struct/csr_separate_instance.c +new file mode 100644 +index 000000000..9e5e05838 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/csr_separate_instance.c +@@ -0,0 +1,48 @@ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++ node_p c; ++ node_p d; ++ long e; ++ long f; ++ long g; ++ long h; ++ long i; ++ long j; ++ long k; ++ long l; ++ int m; ++ int n; ++}; ++ ++const int MAX = 10000; ++node_p n; ++node_t t; ++ ++int ++main () ++{ ++ n = (node_p) calloc (MAX, sizeof (node_t)); ++ t.a = 100; ++ ++ for (int i = 0; i < MAX; i++) ++ { ++ n[i].a = t.a; ++ } ++ for (int i = 0; i < MAX; i++) ++ { ++ if (n[i].a != 100) ++ { ++ abort (); ++ } ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "struct node has escaped: \"Type escapes via a separate instance\"" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/sr_address_of_field.c b/gcc/testsuite/gcc.dg/struct/sr_address_of_field.c +new file mode 100644 +index 000000000..9d58edab8 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/sr_address_of_field.c +@@ -0,0 +1,37 @@ ++/* { dg-do run } */ ++ ++static struct S { ++ int *p1; ++ int *p2; ++} s; ++ ++typedef __UINTPTR_TYPE__ uintptr_t; ++ ++int ++foo () ++{ ++ int i = 1; ++ int j = 2; ++ struct S s; ++ int **p; ++ s.p1 = &i; ++ s.p2 = &j; ++ p = &s.p1; ++ uintptr_t pi = (uintptr_t) p; ++ pi = pi + sizeof (int *); ++ p = (int **)pi; ++ **p = 3; ++ return j; ++} ++ ++int ++main () ++{ ++ if (foo () != 3) ++ { ++ __builtin_abort (); ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "struct S has escaped: \"Type escapes via taking the address of field\"" "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/sr_convert_mem.c b/gcc/testsuite/gcc.dg/struct/sr_convert_mem.c +new file mode 100644 +index 000000000..a99ee0de4 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/sr_convert_mem.c +@@ -0,0 +1,23 @@ ++/* { dg-do compile } */ ++ ++struct T1 { ++ long var1; ++ int var2; ++}; ++ ++struct T2 { ++ long var1; ++ int var2; ++}; ++ ++void test (void*); ++ ++__attribute__((used)) void ++foo (struct T2 *t2) ++{ ++ struct T1* t1 = (void *)(&t2[1]); ++ void* data = (void *)(&t1[1]); ++ ++ test(data); ++ return; ++} +diff --git a/gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c b/gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c +new file mode 100644 +index 000000000..fb135ef0b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/sr_maxmin_expr.c +@@ -0,0 +1,25 @@ ++// { dg-do compile } ++ ++#include ++ ++struct S { ++ unsigned long a; ++ unsigned long b; ++}; ++ ++struct S* s; ++struct S* t = (struct S*) 1000; ++ ++int ++main () ++{ ++ s = (struct S*) calloc (1000, sizeof (struct S)); ++ s = s > t ? s : t; ++ if (s == 0) ++ { ++ abort (); ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/sr_pointer_and.c b/gcc/testsuite/gcc.dg/struct/sr_pointer_and.c +new file mode 100644 +index 000000000..9a4b10d9a +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/sr_pointer_and.c +@@ -0,0 +1,17 @@ ++/* { dg-do compile } */ ++ ++struct test {long val; struct test* next; }; ++ ++unsigned long P_DATA; ++ ++void func (struct test*); ++ ++__attribute__((used)) static void ++foo (struct test* pt) ++{ ++ struct test t; ++ ++ t.next = (void *)((unsigned long)pt->next & P_DATA); ++ func(&t); ++ return; ++} +diff --git a/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c b/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c +new file mode 100644 +index 000000000..9a82da0d6 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/sr_pointer_minus.c +@@ -0,0 +1,33 @@ ++// { dg-do compile } ++ ++#include ++ ++typedef struct node node_t; ++typedef struct node* node_p; ++ ++struct node { ++ unsigned long a; ++ unsigned long b; ++}; ++ ++int max; ++int x; ++ ++node_p n; ++node_p z; ++ ++int ++main () ++{ ++ n = (node_p) calloc (max, sizeof (node_t)); ++ ++ node_p xp = &n[x]; ++ ++ if (xp - z == 10) ++ { ++ abort (); ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "struct node has escaped: \"Type escapes via a unhandled rewrite stmt\"" "struct_reorg" } } */ +-- +2.33.0 + diff --git a/0017-StructReorg-Some-bugfix-for-structure-reorganization.patch b/0017-StructReorg-Some-bugfix-for-structure-reorganization.patch new file mode 100644 index 0000000..2e06afe --- /dev/null +++ b/0017-StructReorg-Some-bugfix-for-structure-reorganization.patch @@ -0,0 +1,489 @@ +From 2b4db34d3b21ff8597373e9e67858b3b60cc7dae Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Fri, 21 Jul 2023 11:20:51 +0800 +Subject: [PATCH 17/22] [StructReorg] Some bugfix for structure reorganization + +Some bugfix for structure reorganization, +1. disable type simplify in LTO within optimizations +2. only enable optimizations in C language +3. use new to initialize allocated memory in symbol-summary.h +4. cover escape scenarios not considered +--- + gcc/ipa-free-lang-data.cc | 11 ++ + gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 101 +++++++++++-------- + gcc/symbol-summary.h | 13 ++- + gcc/testsuite/gcc.dg/struct/struct_reorg-5.c | 31 ++++++ + gcc/testsuite/gcc.dg/struct/struct_reorg-6.c | 54 ++++++++++ + gcc/testsuite/gcc.dg/struct/struct_reorg-7.c | 38 +++++++ + gcc/testsuite/gcc.dg/struct/struct_reorg-8.c | 25 +++++ + gcc/testsuite/gcc.dg/struct/struct_reorg-9.c | 54 ++++++++++ + 8 files changed, 283 insertions(+), 44 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-5.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-6.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-7.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-8.c + create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-9.c + +diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc +index a74215685..5450be9fe 100644 +--- a/gcc/ipa-free-lang-data.cc ++++ b/gcc/ipa-free-lang-data.cc +@@ -102,6 +102,12 @@ fld_worklist_push (tree t, class free_lang_data_d *fld) + static tree + fld_simplified_type_name (tree type) + { ++ /* Simplify type will cause that struct A and struct A within ++ struct B are different type pointers, so skip it in structure ++ optimizations. */ ++ if (flag_ipa_struct_reorg) ++ return TYPE_NAME (type); ++ + if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL) + return TYPE_NAME (type); + /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the +@@ -340,6 +346,11 @@ fld_simplified_type (tree t, class free_lang_data_d *fld) + { + if (!t) + return t; ++ /* Simplify type will cause that struct A and struct A within ++ struct B are different type pointers, so skip it in structure ++ optimizations. */ ++ if (flag_ipa_struct_reorg) ++ return t; + if (POINTER_TYPE_P (t)) + return fld_incomplete_type_of (t, fld); + /* FIXME: This triggers verification error, see PR88140. */ +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +index c8b975a92..9f790b28b 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +@@ -105,6 +105,7 @@ along with GCC; see the file COPYING3. If not see + #include "ipa-param-manipulation.h" + #include "gimplify-me.h" + #include "cfgloop.h" ++#include "langhooks.h" + + namespace { + +@@ -196,6 +197,39 @@ gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type, + GSI_SAME_STMT); + } + ++/* Check whether in C language or LTO with only C language. */ ++ ++static bool ++lang_c_p (void) ++{ ++ const char *language_string = lang_hooks.name; ++ ++ if (!language_string) ++ return false; ++ ++ if (strcmp (language_string, "GNU GIMPLE") == 0) ++ { ++ unsigned i = 0; ++ tree t = NULL; ++ const char *unit_string = NULL; ++ ++ FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t) ++ { ++ unit_string = TRANSLATION_UNIT_LANGUAGE (t); ++ if (!unit_string ++ || (strncmp (unit_string, "GNU C", 5) != 0) ++ || (!ISDIGIT (unit_string[5]))) ++ return false; ++ } ++ return true; ++ } ++ else if (strncmp (language_string, "GNU C", 5) == 0 ++ && ISDIGIT (language_string[5])) ++ return true; ++ ++ return false; ++} ++ + enum srmode + { + NORMAL = 0, +@@ -1018,7 +1052,6 @@ public: + void analyze_types (void); + void clear_visited (void); + bool create_new_types (void); +- void restore_field_type (void); + void create_new_decls (void); + srdecl *find_decl (tree); + void create_new_functions (void); +@@ -2107,7 +2140,12 @@ ipa_struct_reorg::find_vars (gimple *stmt) + srtype *t = find_type (inner_type (TREE_TYPE (rhs))); + srdecl *d = find_decl (lhs); + if (!d && t) +- current_function->record_decl (t, lhs, -1); ++ { ++ current_function->record_decl (t, lhs, -1); ++ tree var = SSA_NAME_VAR (lhs); ++ if (var && VOID_POINTER_P (TREE_TYPE (var))) ++ current_function->record_decl (t, var, -1); ++ } + } + if (TREE_CODE (rhs) == SSA_NAME + && VOID_POINTER_P (TREE_TYPE (rhs)) +@@ -2116,7 +2154,12 @@ ipa_struct_reorg::find_vars (gimple *stmt) + srtype *t = find_type (inner_type (TREE_TYPE (lhs))); + srdecl *d = find_decl (rhs); + if (!d && t) +- current_function->record_decl (t, rhs, -1); ++ { ++ current_function->record_decl (t, rhs, -1); ++ tree var = SSA_NAME_VAR (rhs); ++ if (var && VOID_POINTER_P (TREE_TYPE (var))) ++ current_function->record_decl (t, var, -1); ++ } + } + } + else +@@ -2796,8 +2839,14 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt) + if (escapes != does_not_escape) + { + for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) +- mark_type_as_escape (TREE_TYPE (gimple_call_arg (stmt, i)), +- escapes); ++ { ++ mark_type_as_escape (TREE_TYPE (gimple_call_arg (stmt, i)), ++ escapes); ++ srdecl *d = current_function->find_decl ( ++ gimple_call_arg (stmt, i)); ++ if (d) ++ d->type->mark_escape (escapes, stmt); ++ } + return; + } + +@@ -3731,42 +3780,6 @@ ipa_struct_reorg::analyze_types (void) + } + } + +-/* When struct A has a struct B member, B's type info +- is not stored in +- TYPE_FIELDS (TREE_TYPE (TYPE_FIELDS (typeA))) +- Try to restore B's type information. */ +- +-void +-ipa_struct_reorg::restore_field_type (void) +-{ +- for (unsigned i = 0; i < types.length (); i++) +- { +- for (unsigned j = 0; j < types[i]->fields.length (); j++) +- { +- srfield *field = types[i]->fields[j]; +- if (TREE_CODE (inner_type (field->fieldtype)) == RECORD_TYPE) +- { +- /* If field type has TYPE_FIELDS information, +- we do not need to do this. */ +- if (TYPE_FIELDS (field->type->type) != NULL) +- continue; +- for (unsigned k = 0; k < types.length (); k++) +- { +- if (i == k) +- continue; +- const char *type1 = get_type_name (field->type->type); +- const char *type2 = get_type_name (types[k]->type); +- if (type1 == NULL || type2 == NULL) +- continue; +- if (type1 == type2 +- && TYPE_FIELDS (types[k]->type)) +- field->type = types[k]; +- } +- } +- } +- } +-} +- + /* Create all new types we want to create. */ + + bool +@@ -4647,7 +4660,6 @@ ipa_struct_reorg::rewrite_functions (void) + { + unsigned retval = 0; + +- restore_field_type (); + /* Create new types, if we did not create any new types, + then don't rewrite any accesses. */ + if (!create_new_types ()) +@@ -4866,7 +4878,10 @@ pass_ipa_struct_reorg::gate (function *) + && flag_ipa_struct_reorg + /* Don't bother doing anything if the program has errors. */ + && !seen_error () +- && flag_lto_partition == LTO_PARTITION_ONE); ++ && flag_lto_partition == LTO_PARTITION_ONE ++ /* Only enable struct optimizations in C since other ++ languages' grammar forbid. */ ++ && lang_c_p ()); + } + + } // anon namespace +diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h +index c54d3084c..3fe64047c 100644 +--- a/gcc/symbol-summary.h ++++ b/gcc/symbol-summary.h +@@ -103,6 +103,12 @@ protected: + /* Allocates new data that are stored within map. */ + T* allocate_new () + { ++ /* In structure optimizatons, we call new to ensure that ++ the allocated memory is initialized to 0. */ ++ if (flag_ipa_struct_reorg) ++ return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () ++ : new T (); ++ + /* Call gcc_internal_because we do not want to call finalizer for + a type T. We call dtor explicitly. */ + return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () +@@ -115,7 +121,12 @@ protected: + if (is_ggc ()) + ggc_delete (item); + else +- m_allocator.remove (item); ++ { ++ if (flag_ipa_struct_reorg) ++ delete item; ++ else ++ m_allocator.remove (item); ++ } + } + + /* Unregister all call-graph hooks. */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-5.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-5.c +new file mode 100644 +index 000000000..273baa9a3 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-5.c +@@ -0,0 +1,31 @@ ++/* { dg-do compile } */ ++/* { dg-additional-options "-flto -fno-use-linker-plugin" } */ ++ ++struct D ++{ ++ int n; ++ int c [8]; ++}; ++ ++struct A ++{ ++ int i; ++ char *p; ++}; ++ ++struct B ++{ ++ struct A *a; ++ struct D *d; ++}; ++ ++int dtInsert1 (struct B *b) ++{ ++ struct A a = { 0, 0 }; ++ struct D *d; ++ b->a = &a; ++ d = b->d; ++ &d->c [d->n]; ++ return 0; ++} ++ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-6.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-6.c +new file mode 100644 +index 000000000..455f9b501 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-6.c +@@ -0,0 +1,54 @@ ++/* { dg-do compile } */ ++/* { dg-additional-options "-flto -fno-use-linker-plugin" } */ ++ ++typedef struct basic_block_def *basic_block; ++typedef struct gimple_seq_node_d *gimple_seq_node; ++typedef struct gimple_seq_d *gimple_seq; ++typedef struct ++{ ++ gimple_seq_node ptr; ++ gimple_seq seq; ++ basic_block bb; ++} gimple_stmt_iterator; ++typedef void *gimple; ++extern void exit(int); ++struct gimple_seq_node_d ++{ ++ gimple stmt; ++ struct gimple_seq_node_d *next; ++}; ++struct gimple_seq_d ++{ ++}; ++static __inline__ gimple_stmt_iterator ++gsi_start (gimple_seq seq) ++{ ++ gimple_stmt_iterator i; ++ i.seq = seq; ++ return i; ++} ++static __inline__ unsigned char ++gsi_end_p (gimple_stmt_iterator i) ++{ ++ return i.ptr == ((void *)0); ++} ++static __inline__ void ++gsi_next (gimple_stmt_iterator *i) ++{ ++ i->ptr = i->ptr->next; ++} ++static __inline__ gimple ++gsi_stmt (gimple_stmt_iterator i) ++{ ++ return i.ptr->stmt; ++} ++void ++c_warn_unused_result (gimple_seq seq) ++{ ++ gimple_stmt_iterator i; ++ for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) ++ { ++ gimple g = gsi_stmt (i); ++ if (!g) exit(0); ++ } ++} +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-7.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-7.c +new file mode 100644 +index 000000000..afc0bd86c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-7.c +@@ -0,0 +1,38 @@ ++/* { dg-do run } */ ++ ++#include ++#include ++ ++struct gki_elem { ++ char *key; ++ int idx; ++}; ++ ++typedef struct { ++ struct gki_elem *table; ++ ++ int primelevel; ++ int nhash; ++ int nkeys; ++} GKI; ++ ++void * ++sre_malloc(size_t size) ++{ ++ void *ptr = malloc (size); ++ return ptr; ++} ++ ++__attribute__((noinline)) int ++GKIStoreKey(GKI *hash) ++{ ++ hash->table = sre_malloc(sizeof(struct gki_elem)); ++} ++ ++int ++main () ++{ ++ GKI *hash = malloc (sizeof(GKI)); ++ GKIStoreKey(hash); ++ return 0; ++} +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-8.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-8.c +new file mode 100644 +index 000000000..9bcfaf368 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-8.c +@@ -0,0 +1,25 @@ ++/* { dg-do run } */ ++ ++#include ++#include ++#include ++ ++typedef struct { ++ unsigned char blue; ++ unsigned char green; ++} Pixel; ++ ++typedef struct { ++ unsigned short colormaplength; ++ Pixel *colormapdata; ++} TargaImage; ++ ++TargaImage *img; ++ ++int main() { ++ img = (TargaImage *) malloc( sizeof(TargaImage) ); ++ if (img->colormaplength > 0) { ++ img->colormapdata = (Pixel *) malloc(sizeof(Pixel) * img->colormaplength); ++ memset(img->colormapdata, 0, (sizeof(Pixel) * img->colormaplength) ); ++ } ++} +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-9.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-9.c +new file mode 100644 +index 000000000..052f4e3bd +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-9.c +@@ -0,0 +1,54 @@ ++/* { dg-do run } */ ++ ++extern void abort(void); ++ ++struct packed_ushort { ++ unsigned short ucs; ++} __attribute__((packed)); ++ ++struct source { ++ int pos, length; ++}; ++ ++static int flag; ++ ++static void __attribute__((noinline)) fetch(struct source *p) ++{ ++ p->length = 128; ++} ++ ++static struct packed_ushort __attribute__((noinline)) next(struct source *p) ++{ ++ struct packed_ushort rv; ++ ++ if (p->pos >= p->length) { ++ if (flag) { ++ flag = 0; ++ fetch(p); ++ return next(p); ++ } ++ flag = 1; ++ rv.ucs = 0xffff; ++ return rv; ++ } ++ rv.ucs = 0; ++ return rv; ++} ++ ++int main(void) ++{ ++ struct source s; ++ int i; ++ ++ s.pos = 0; ++ s.length = 0; ++ flag = 0; ++ ++ for (i = 0; i < 16; i++) { ++ struct packed_ushort rv = next(&s); ++ if ((i == 0 && rv.ucs != 0xffff) ++ || (i > 0 && rv.ucs != 0)) ++ abort(); ++ } ++ return 0; ++} +-- +2.33.0 + diff --git a/0018-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch b/0018-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch new file mode 100644 index 0000000..6f99e5c --- /dev/null +++ b/0018-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch @@ -0,0 +1,342 @@ +From 19ded9dad06b22b9b7aa9e3902e3e7a38a2256ab Mon Sep 17 00:00:00 2001 +From: dingguangya +Date: Sat, 29 Jul 2023 18:27:10 +0800 +Subject: [PATCH 18/22] [ccmp] Add another optimization opportunity for ccmp + instruction + +Add flag -fccmp2. +Enables the use of the ccmp instruction by creating a new conflict +relationship for instances where temporary expressions replacement +cannot be effectively created. +--- + gcc/ccmp.cc | 33 ++++ + gcc/ccmp.h | 1 + + gcc/common.opt | 4 + + gcc/testsuite/gcc.target/aarch64/ccmp_3.c | 15 ++ + gcc/tree-ssa-coalesce.cc | 197 ++++++++++++++++++++++ + 5 files changed, 250 insertions(+) + create mode 100644 gcc/testsuite/gcc.target/aarch64/ccmp_3.c + +diff --git a/gcc/ccmp.cc b/gcc/ccmp.cc +index 3db0a264e..e34f3bcc6 100644 +--- a/gcc/ccmp.cc ++++ b/gcc/ccmp.cc +@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see + #include "cfgexpand.h" + #include "ccmp.h" + #include "predict.h" ++#include "gimple-iterator.h" + + /* Check whether T is a simple boolean variable or a SSA name + set by a comparison operator in the same basic block. */ +@@ -129,6 +130,38 @@ ccmp_candidate_p (gimple *g) + return false; + } + ++/* Check whether bb is a potential conditional compare candidate. */ ++bool ++check_ccmp_candidate (basic_block bb) ++{ ++ gimple_stmt_iterator gsi; ++ gimple *bb_last_stmt, *stmt; ++ tree op0, op1; ++ ++ gsi = gsi_last_bb (bb); ++ bb_last_stmt = gsi_stmt (gsi); ++ ++ if (bb_last_stmt && gimple_code (bb_last_stmt) == GIMPLE_COND) ++ { ++ op0 = gimple_cond_lhs (bb_last_stmt); ++ op1 = gimple_cond_rhs (bb_last_stmt); ++ ++ if (TREE_CODE (op0) == SSA_NAME ++ && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE ++ && TREE_CODE (op1) == INTEGER_CST ++ && ((gimple_cond_code (bb_last_stmt) == NE_EXPR) ++ || (gimple_cond_code (bb_last_stmt) == EQ_EXPR))) ++ { ++ stmt = SSA_NAME_DEF_STMT (op0); ++ if (stmt && gimple_code (stmt) == GIMPLE_ASSIGN) ++ { ++ return ccmp_candidate_p (stmt); ++ } ++ } ++ } ++ return false; ++} ++ + /* Extract the comparison we want to do from the tree. */ + void + get_compare_parts (tree t, int *up, rtx_code *rcode, +diff --git a/gcc/ccmp.h b/gcc/ccmp.h +index 1799d5fed..efe3a1c14 100644 +--- a/gcc/ccmp.h ++++ b/gcc/ccmp.h +@@ -21,5 +21,6 @@ along with GCC; see the file COPYING3. If not see + #define GCC_CCMP_H + + extern rtx expand_ccmp_expr (gimple *, machine_mode); ++extern bool check_ccmp_candidate (basic_block bb); + + #endif /* GCC_CCMP_H */ +diff --git a/gcc/common.opt b/gcc/common.opt +index 4d91ce8cf..0aa516719 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -2017,6 +2017,10 @@ fira-verbose= + Common RejectNegative Joined UInteger Var(flag_ira_verbose) Init(5) + -fira-verbose= Control IRA's level of diagnostic messages. + ++fccmp2 ++Common Var(flag_ccmp2) Init(0) Optimization ++Optimize potential ccmp instruction in complex scenarios. ++ + fivopts + Common Var(flag_ivopts) Init(1) Optimization + Optimize induction variables on trees. +diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_3.c b/gcc/testsuite/gcc.target/aarch64/ccmp_3.c +new file mode 100644 +index 000000000..b509ba810 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/aarch64/ccmp_3.c +@@ -0,0 +1,15 @@ ++/* { dg-do compile { target { aarch64*-*-linux* } } } */ ++/* { dg-options "-O -fdump-rtl-expand-details -fccmp2" } */ ++ ++int func (int a, int b, int c) ++{ ++ while(1) ++ { ++ if(a-- == 0 || b >= c) ++ { ++ return 1; ++ } ++ } ++} ++ ++/* { dg-final { scan-assembler-times "\tccmp\t" 1} } */ +diff --git a/gcc/tree-ssa-coalesce.cc b/gcc/tree-ssa-coalesce.cc +index dccf41ab8..195e06428 100644 +--- a/gcc/tree-ssa-coalesce.cc ++++ b/gcc/tree-ssa-coalesce.cc +@@ -38,6 +38,9 @@ along with GCC; see the file COPYING3. If not see + #include "explow.h" + #include "tree-dfa.h" + #include "stor-layout.h" ++#include "ccmp.h" ++#include "target.h" ++#include "tree-outof-ssa.h" + + /* This set of routines implements a coalesce_list. This is an object which + is used to track pairs of ssa_names which are desirable to coalesce +@@ -854,6 +857,198 @@ live_track_clear_base_vars (live_track *ptr) + bitmap_clear (&ptr->live_base_var); + } + ++/* Return true if gimple is a copy assignment. */ ++ ++static inline bool ++gimple_is_assign_copy_p (gimple *gs) ++{ ++ return (is_gimple_assign (gs) && gimple_assign_copy_p (gs) ++ && TREE_CODE (gimple_assign_lhs (gs)) == SSA_NAME ++ && TREE_CODE (gimple_assign_rhs1 (gs)) == SSA_NAME); ++} ++ ++#define MAX_CCMP_CONFLICT_NUM 5 ++ ++/* Clear high-cost conflict graphs. */ ++ ++static void ++remove_high_cost_graph_for_ccmp (ssa_conflicts *conflict_graph) ++{ ++ unsigned x = 0; ++ int add_conflict_num = 0; ++ bitmap b; ++ FOR_EACH_VEC_ELT (conflict_graph->conflicts, x, b) ++ { ++ if (b) ++ { ++ add_conflict_num++; ++ } ++ } ++ if (add_conflict_num >= MAX_CCMP_CONFLICT_NUM) ++ { ++ conflict_graph->conflicts.release (); ++ } ++} ++ ++/* Adding a new conflict graph to the original graph. */ ++ ++static void ++process_add_graph (live_track *live, basic_block bb, ++ ssa_conflicts *conflict_graph) ++{ ++ tree use, def; ++ ssa_op_iter iter; ++ gimple *first_visit_stmt = NULL; ++ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ++ gsi_next (&gsi)) ++ { ++ if (gimple_visited_p (gsi_stmt (gsi))) ++ { ++ first_visit_stmt = gsi_stmt (gsi); ++ break; ++ } ++ } ++ if (!first_visit_stmt) ++ return; ++ ++ for (gimple_stmt_iterator gsi = gsi_last_bb (bb); ++ gsi_stmt (gsi) != first_visit_stmt; gsi_prev (&gsi)) ++ { ++ gimple *stmt = gsi_stmt (gsi); ++ if (gimple_visited_p (gsi_stmt (gsi)) && is_gimple_debug (stmt)) ++ { ++ continue; ++ } ++ if (gimple_is_assign_copy_p (stmt)) ++ { ++ live_track_clear_var (live, gimple_assign_rhs1 (stmt)); ++ } ++ FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) ++ { ++ live_track_process_def (live, def, conflict_graph); ++ } ++ FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) ++ { ++ live_track_process_use (live, use); ++ } ++ } ++} ++ ++/* Build a conflict graph based on ccmp candidate. */ ++ ++static void ++add_ccmp_conflict_graph (ssa_conflicts *conflict_graph, ++ tree_live_info_p liveinfo, var_map map, basic_block bb) ++{ ++ live_track *live; ++ tree use, def; ++ ssa_op_iter iter; ++ live = new_live_track (map); ++ live_track_init (live, live_on_exit (liveinfo, bb)); ++ ++ gimple *last_stmt = gsi_stmt (gsi_last_bb (bb)); ++ gcc_assert (gimple_cond_lhs (last_stmt)); ++ ++ auto_vec stack; ++ stack.safe_push (gimple_cond_lhs (last_stmt)); ++ while (!stack.is_empty ()) ++ { ++ tree op = stack.pop (); ++ gimple *op_stmt = SSA_NAME_DEF_STMT (op); ++ if (!op_stmt || gimple_bb (op_stmt) != bb ++ || !is_gimple_assign (op_stmt) ++ || !ssa_is_replaceable_p (op_stmt)) ++ { ++ continue; ++ } ++ if (gimple_is_assign_copy_p (op_stmt)) ++ { ++ live_track_clear_var (live, gimple_assign_rhs1 (op_stmt)); ++ } ++ gimple_set_visited (op_stmt, true); ++ FOR_EACH_SSA_TREE_OPERAND (def, op_stmt, iter, SSA_OP_DEF) ++ { ++ live_track_process_def (live, def, conflict_graph); ++ } ++ FOR_EACH_SSA_TREE_OPERAND (use, op_stmt, iter, SSA_OP_USE) ++ { ++ stack.safe_push (use); ++ live_track_process_use (live, use); ++ } ++ } ++ ++ process_add_graph (live, bb, conflict_graph); ++ delete_live_track (live); ++ remove_high_cost_graph_for_ccmp (conflict_graph); ++} ++ ++/* Determine whether the ccmp conflict graph can be added. ++ i.e, ++ ++ ;; basic block 3, loop depth 1 ++ ;; pred: 2 ++ ;; 3 ++ # ivtmp.5_10 = PHI ++ _7 = b_4 (D) >= c_5 (D); ++ _8 = ivtmp.5_10 == 0; ++ _9 = _7 | _8; ++ ivtmp.5_11 = ivtmp.5_10 - 1; ++ if (_9 != 0) ++ goto ; [10.70%] ++ else ++ goto ; [89.30%] ++ ++ In the above loop, the expression will be replaced: ++ ++ _7 replaced by b_4 (D) >= c_5 (D) ++ _8 replaced by ivtmp.5_10 == 0 ++ ++ If the current case want use the ccmp instruction, then ++ ++ _9 can replaced by _7 | _8 ++ ++ So this requires that ivtmp.5_11 and ivtmp.5_10 be divided into different ++ partitions. ++ ++ Now this function can achieve this ability. */ ++ ++static void ++determine_add_ccmp_conflict_graph (basic_block bb, tree_live_info_p liveinfo, ++ var_map map, ssa_conflicts *graph) ++{ ++ if (!flag_ccmp2 || !targetm.gen_ccmp_first || !check_ccmp_candidate (bb)) ++ return; ++ for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); ++ gsi_next (&bsi)) ++ { ++ gimple_set_visited (gsi_stmt (bsi), false); ++ } ++ ssa_conflicts *ccmp_conflict_graph; ++ ccmp_conflict_graph = ssa_conflicts_new (num_var_partitions (map)); ++ add_ccmp_conflict_graph (ccmp_conflict_graph, liveinfo, map, bb); ++ unsigned x; ++ bitmap b; ++ if (ccmp_conflict_graph) ++ { ++ FOR_EACH_VEC_ELT (ccmp_conflict_graph->conflicts, x, b) ++ { ++ if (!b) ++ continue; ++ unsigned y = bitmap_first_set_bit (b); ++ if (!graph->conflicts[x] || !bitmap_bit_p (graph->conflicts[x], y)) ++ { ++ ssa_conflicts_add (graph, x, y); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "potential ccmp: add additional " ++ "conflict-ssa : bb[%d] %d:%d\n", ++ bb->index, x, y); ++ } ++ } ++ } ++ } ++ ssa_conflicts_delete (ccmp_conflict_graph); ++} + + /* Build a conflict graph based on LIVEINFO. Any partitions which are in the + partition view of the var_map liveinfo is based on get entries in the +@@ -938,6 +1133,8 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo) + live_track_process_use (live, var); + } + ++ determine_add_ccmp_conflict_graph (bb, liveinfo, map, graph); ++ + /* If result of a PHI is unused, looping over the statements will not + record any conflicts since the def was never live. Since the PHI node + is going to be translated out of SSA form, it will insert a copy. +-- +2.33.0 + diff --git a/0019-fp-model-Enable-fp-model-on-kunpeng.patch b/0019-fp-model-Enable-fp-model-on-kunpeng.patch new file mode 100644 index 0000000..46ea52c --- /dev/null +++ b/0019-fp-model-Enable-fp-model-on-kunpeng.patch @@ -0,0 +1,405 @@ +From 8cdb316a3fe205a3089b9c17aec0442f4d5f75be Mon Sep 17 00:00:00 2001 +From: bule +Date: Sun, 27 Aug 2023 16:49:04 +0800 +Subject: [PATCH 19/22] [fp-model] Enable fp-model on kunpeng + +Enable fp-model options on kunpeng for precision control. +--- + gcc/common.opt | 26 +++++ + gcc/config/aarch64/aarch64-linux.h | 3 +- + gcc/flag-types.h | 9 ++ + gcc/fortran/options.cc | 8 ++ + gcc/opts-common.cc | 146 ++++++++++++++++++++++++++++- + gcc/opts.cc | 68 ++++++++++++++ + 6 files changed, 256 insertions(+), 4 deletions(-) + +diff --git a/gcc/common.opt b/gcc/common.opt +index 8a0dafc52..f5eef8a45 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1642,6 +1642,32 @@ ffp-int-builtin-inexact + Common Var(flag_fp_int_builtin_inexact) Init(1) Optimization + Allow built-in functions ceil, floor, round, trunc to raise \"inexact\" exceptions. + ++fftz ++Common Var(flag_ftz) Optimization ++Control fpcr register for flush to zero. ++ ++fp-model= ++Common Joined RejectNegative Enum(fp_model) Var(flag_fp_model) Init(FP_MODEL_NORMAL) Optimization ++-fp-model=[normal|fast|precise|except|strict] Perform floating-point precision control. ++ ++Enum ++Name(fp_model) Type(enum fp_model) UnknownError(unknown floating point precision model %qs) ++ ++EnumValue ++Enum(fp_model) String(normal) Value(FP_MODEL_NORMAL) ++ ++EnumValue ++Enum(fp_model) String(fast) Value(FP_MODEL_FAST) ++ ++EnumValue ++Enum(fp_model) String(precise) Value(FP_MODEL_PRECISE) ++ ++EnumValue ++Enum(fp_model) String(except) Value(FP_MODEL_EXCEPT) ++ ++EnumValue ++Enum(fp_model) String(strict) Value(FP_MODEL_STRICT) ++ + ; Nonzero means don't put addresses of constant functions in registers. + ; Used for compiling the Unix kernel, where strange substitutions are + ; done on the assembly output. +diff --git a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h +index 5e4553d79..a5cba6391 100644 +--- a/gcc/config/aarch64/aarch64-linux.h ++++ b/gcc/config/aarch64/aarch64-linux.h +@@ -50,7 +50,8 @@ + #define LINK_SPEC LINUX_TARGET_LINK_SPEC AARCH64_ERRATA_LINK_SPEC + + #define GNU_USER_TARGET_MATHFILE_SPEC \ +- "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}" ++ "%{Ofast|ffast-math|funsafe-math-optimizations|fp-model=fast|fftz:\ ++ %{!fno-ftz:crtfastmath.o%s}}" + + #undef ENDFILE_SPEC + #define ENDFILE_SPEC \ +diff --git a/gcc/flag-types.h b/gcc/flag-types.h +index 2c8498169..64c64eb32 100644 +--- a/gcc/flag-types.h ++++ b/gcc/flag-types.h +@@ -260,6 +260,15 @@ enum fp_contract_mode { + FP_CONTRACT_FAST = 2 + }; + ++/* Floating-point precision mode. */ ++enum fp_model { ++ FP_MODEL_NORMAL = 0, ++ FP_MODEL_FAST = 1, ++ FP_MODEL_PRECISE = 2, ++ FP_MODEL_EXCEPT = 3, ++ FP_MODEL_STRICT = 4 ++}; ++ + /* Scalar storage order kind. */ + enum scalar_storage_order_kind { + SSO_NATIVE = 0, +diff --git a/gcc/fortran/options.cc b/gcc/fortran/options.cc +index d0fa634f1..3eb99a84a 100644 +--- a/gcc/fortran/options.cc ++++ b/gcc/fortran/options.cc +@@ -243,6 +243,7 @@ form_from_filename (const char *filename) + return f_form; + } + ++static void gfc_handle_fpe_option (const char *arg, bool trap); + + /* Finalize commandline options. */ + +@@ -286,6 +287,13 @@ gfc_post_options (const char **pfilename) + if (flag_protect_parens == -1) + flag_protect_parens = !optimize_fast; + ++ /* If fp-model=precise/strict, turn on all ffpe-trap and ffpe-summary. */ ++ if (flag_fp_model == FP_MODEL_EXCEPT || flag_fp_model == FP_MODEL_STRICT) ++ { ++ gfc_handle_fpe_option ("all", false); ++ gfc_handle_fpe_option ("invalid,zero,overflow,underflow", true); ++ } ++ + /* -Ofast sets implies -fstack-arrays unless an explicit size is set for + stack arrays. */ + if (flag_stack_arrays == -1 && flag_max_stack_var_size == -2) +diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc +index 7c07d5046..489a6e02a 100644 +--- a/gcc/opts-common.cc ++++ b/gcc/opts-common.cc +@@ -28,7 +28,8 @@ along with GCC; see the file COPYING3. If not see + #include "spellcheck.h" + #include "opts-jobserver.h" + +-static void prune_options (struct cl_decoded_option **, unsigned int *); ++static void prune_options (struct cl_decoded_option **, unsigned int *, ++ unsigned int); + + /* An option that is undocumented, that takes a joined argument, and + that doesn't fit any of the classes of uses (language/common, +@@ -1091,7 +1092,7 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv, + + *decoded_options = opt_array; + *decoded_options_count = num_decoded_options; +- prune_options (decoded_options, decoded_options_count); ++ prune_options (decoded_options, decoded_options_count, lang_mask); + } + + /* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the +@@ -1112,11 +1113,109 @@ cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx) + return false; + } + ++/* Check whether opt_idx exists in decoded_options array between index ++ start and end. If found, return its index in decoded_options, ++ else return end. */ ++static unsigned int ++find_opt_idx (const struct cl_decoded_option *decoded_options, ++ unsigned int decoded_options_count, ++ unsigned int start, unsigned int end, unsigned int opt_idx) ++{ ++ gcc_assert (end <= decoded_options_count); ++ gcc_assert (opt_idx < cl_options_count); ++ unsigned int k; ++ for (k = start; k < end; k++) ++ { ++ if (decoded_options[k].opt_index == opt_idx) ++ { ++ return k; ++ } ++ } ++ return k; ++} ++ ++/* remove the opt_index element from decoded_options array. */ ++static unsigned int ++remove_option (struct cl_decoded_option *decoded_options, ++ unsigned int decoded_options_count, ++ unsigned int opt_index) ++{ ++ gcc_assert (opt_index < decoded_options_count); ++ unsigned int i; ++ for (i = opt_index; i < decoded_options_count - 1; i++) ++ { ++ decoded_options[i] = decoded_options[i + 1]; ++ } ++ return decoded_options_count - 1; ++} ++ ++/* Handle the priority between fp-model, Ofast, and ++ ffast-math. */ ++static unsigned int ++handle_fp_model_driver (struct cl_decoded_option *decoded_options, ++ unsigned int decoded_options_count, ++ unsigned int fp_model_index, ++ unsigned int lang_mask) ++{ ++ struct cl_decoded_option fp_model_opt = decoded_options[fp_model_index]; ++ enum fp_model model = (enum fp_model) fp_model_opt.value; ++ if (model == FP_MODEL_PRECISE || model == FP_MODEL_STRICT) ++ { ++ /* If found Ofast, override Ofast with O3. */ ++ unsigned int Ofast_index; ++ Ofast_index = find_opt_idx (decoded_options, decoded_options_count, ++ 0, decoded_options_count, OPT_Ofast); ++ while (Ofast_index != decoded_options_count) ++ { ++ const char *tmp_argv = "-O3"; ++ decode_cmdline_option (&tmp_argv, lang_mask, ++ &decoded_options[Ofast_index]); ++ warning (0, "%<-Ofast%> is degraded to %<-O3%> due to %qs", ++ fp_model_opt.orig_option_with_args_text); ++ Ofast_index = find_opt_idx (decoded_options, decoded_options_count, ++ 0, decoded_options_count, OPT_Ofast); ++ } ++ /* If found ffast-math before fp-model=precise/strict ++ it, cancel it. */ ++ unsigned int ffast_math_index; ++ ffast_math_index ++ = find_opt_idx (decoded_options, decoded_options_count, 0, ++ fp_model_index, OPT_ffast_math); ++ if (ffast_math_index != fp_model_index) ++ { ++ decoded_options_count ++ = remove_option (decoded_options, decoded_options_count, ++ ffast_math_index); ++ warning (0, "%<-ffast-math%> before %qs is canceled", ++ fp_model_opt.orig_option_with_args_text); ++ } ++ } ++ if (model == FP_MODEL_FAST) ++ { ++ /* If found -fno-fast-math after fp-model=fast, cancel this one. */ ++ unsigned int fno_fast_math_index; ++ fno_fast_math_index ++ = find_opt_idx (decoded_options, decoded_options_count, fp_model_index, ++ decoded_options_count, OPT_ffast_math); ++ if (fno_fast_math_index != decoded_options_count ++ && decoded_options[fno_fast_math_index].value == 0) ++ { ++ decoded_options_count ++ = remove_option (decoded_options, decoded_options_count, ++ fp_model_index); ++ warning (0, ++ "%<-fp-model=fast%> before %<-fno-fast-math%> is canceled"); ++ } ++ } ++ return decoded_options_count; ++} ++ + /* Filter out options canceled by the ones after them. */ + + static void + prune_options (struct cl_decoded_option **decoded_options, +- unsigned int *decoded_options_count) ++ unsigned int *decoded_options_count, ++ unsigned int lang_mask) + { + unsigned int old_decoded_options_count = *decoded_options_count; + struct cl_decoded_option *old_decoded_options = *decoded_options; +@@ -1127,7 +1226,12 @@ prune_options (struct cl_decoded_option **decoded_options, + const struct cl_option *option; + unsigned int fdiagnostics_color_idx = 0; + ++ if (!diagnostic_ready_p ()) ++ diagnostic_initialize (global_dc, 0); ++ + /* Remove arguments which are negated by others after them. */ ++ ++ unsigned int fp_model_index = old_decoded_options_count; + new_decoded_options_count = 0; + for (i = 0; i < old_decoded_options_count; i++) + { +@@ -1151,6 +1255,34 @@ prune_options (struct cl_decoded_option **decoded_options, + fdiagnostics_color_idx = i; + continue; + ++ case OPT_fp_model_: ++ /* Only the last fp-model option will take effect. */ ++ unsigned int next_fp_model_idx; ++ next_fp_model_idx = find_opt_idx (old_decoded_options, ++ old_decoded_options_count, ++ i + 1, ++ old_decoded_options_count, ++ OPT_fp_model_); ++ if (next_fp_model_idx != old_decoded_options_count) ++ { ++ /* Found more than one fp-model, cancel this one. */ ++ if (old_decoded_options[i].value ++ != old_decoded_options[next_fp_model_idx].value) ++ { ++ warning (0, "%qs is overrided by %qs", ++ old_decoded_options[i]. ++ orig_option_with_args_text, ++ old_decoded_options[next_fp_model_idx]. ++ orig_option_with_args_text); ++ } ++ break; ++ } ++ else ++ { ++ /* Found the last fp-model option. */ ++ fp_model_index = new_decoded_options_count; ++ } ++ /* FALLTHRU. */ + default: + gcc_assert (opt_idx < cl_options_count); + option = &cl_options[opt_idx]; +@@ -1190,6 +1322,14 @@ keep: + break; + } + } ++ if (fp_model_index < new_decoded_options_count) ++ { ++ new_decoded_options_count ++ = handle_fp_model_driver (new_decoded_options, ++ new_decoded_options_count, ++ fp_model_index, ++ lang_mask); ++ } + + if (fdiagnostics_color_idx >= 1) + { +diff --git a/gcc/opts.cc b/gcc/opts.cc +index a97630d1c..b522ed7e2 100644 +--- a/gcc/opts.cc ++++ b/gcc/opts.cc +@@ -328,6 +328,7 @@ static void set_debug_level (uint32_t dinfo, int extended, + struct gcc_options *opts_set, + location_t loc); + static void set_fast_math_flags (struct gcc_options *opts, int set); ++static void set_fp_model_flags (struct gcc_options *opts, int set); + static void decode_d_option (const char *arg, struct gcc_options *opts, + location_t loc, diagnostic_context *dc); + static void set_unsafe_math_optimizations_flags (struct gcc_options *opts, +@@ -2857,6 +2858,10 @@ common_handle_option (struct gcc_options *opts, + set_fast_math_flags (opts, value); + break; + ++ case OPT_fp_model_: ++ set_fp_model_flags (opts, value); ++ break; ++ + case OPT_funsafe_math_optimizations: + set_unsafe_math_optimizations_flags (opts, value); + break; +@@ -3266,6 +3271,69 @@ set_fast_math_flags (struct gcc_options *opts, int set) + } + } + ++/* Handle fp-model options. */ ++static void ++set_fp_model_flags (struct gcc_options *opts, int set) ++{ ++ enum fp_model model = (enum fp_model) set; ++ switch (model) ++ { ++ case FP_MODEL_FAST: ++ /* Equivalent to open ffast-math. */ ++ set_fast_math_flags (opts, 1); ++ break; ++ ++ case FP_MODEL_PRECISE: ++ /* Equivalent to close ffast-math. */ ++ set_fast_math_flags (opts, 0); ++ /* Turn on -frounding-math -fsignaling-nans. */ ++ if (!opts->frontend_set_flag_signaling_nans) ++ opts->x_flag_signaling_nans = 1; ++ if (!opts->frontend_set_flag_rounding_math) ++ opts->x_flag_rounding_math = 1; ++ opts->x_flag_expensive_optimizations = 0; ++ opts->x_flag_code_hoisting = 0; ++ opts->x_flag_predictive_commoning = 0; ++ opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF; ++ break; ++ ++ case FP_MODEL_EXCEPT: ++ if (!opts->frontend_set_flag_signaling_nans) ++ opts->x_flag_signaling_nans = 1; ++ if (!opts->frontend_set_flag_errno_math) ++ opts->x_flag_errno_math = 1; ++ if (!opts->frontend_set_flag_trapping_math) ++ opts->x_flag_trapping_math = 1; ++ opts->x_flag_fp_int_builtin_inexact = 1; ++ /* Also turn on ffpe-trap in fortran. */ ++ break; ++ ++ case FP_MODEL_STRICT: ++ /* Turn on both precise and except. */ ++ if (!opts->frontend_set_flag_signaling_nans) ++ opts->x_flag_signaling_nans = 1; ++ if (!opts->frontend_set_flag_rounding_math) ++ opts->x_flag_rounding_math = 1; ++ opts->x_flag_expensive_optimizations = 0; ++ opts->x_flag_code_hoisting = 0; ++ opts->x_flag_predictive_commoning = 0; ++ if (!opts->frontend_set_flag_errno_math) ++ opts->x_flag_errno_math = 1; ++ if (!opts->frontend_set_flag_trapping_math) ++ opts->x_flag_trapping_math = 1; ++ opts->x_flag_fp_int_builtin_inexact = 1; ++ opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF; ++ break; ++ ++ case FP_MODEL_NORMAL: ++ /* Do nothing. */ ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++} ++ + /* When -funsafe-math-optimizations is set the following + flags are set as well. */ + static void +-- +2.33.0 + diff --git a/0020-simdmath-Enable-simdmath-on-kunpeng.patch b/0020-simdmath-Enable-simdmath-on-kunpeng.patch new file mode 100644 index 0000000..f6b7a48 --- /dev/null +++ b/0020-simdmath-Enable-simdmath-on-kunpeng.patch @@ -0,0 +1,317 @@ +From 49ad10199dbdda2c36850a2617f5c985977939c5 Mon Sep 17 00:00:00 2001 +From: bule +Date: Sun, 27 Aug 2023 16:49:42 +0800 +Subject: [PATCH 20/22] [simdmath] Enable simdmath on kunpeng + +This enable simd math function supported by libmathlib on fortran/c/c++. +Use -fsimdmath to turn on the generation of simdmath function. The +supported functions can be found in simdmath.h. Add more simd declaration +if you need more kinds of math functions. -msimdmath-64 is used to turn +on 64-bit simd math functions which is not supported by libmathlib. +Therefore, this option is default to off. +--- + gcc/c-family/c-opts.cc | 4 ++ + gcc/common.opt | 4 ++ + gcc/config/aarch64/aarch64.cc | 9 ++++- + gcc/config/aarch64/aarch64.opt | 6 +++ + gcc/fortran/scanner.cc | 3 ++ + gcc/opts.cc | 17 ++++++++ + .../gcc.target/aarch64/simd_pcs_attribute-3.c | 2 +- + libgomp/Makefile.am | 4 +- + libgomp/Makefile.in | 10 +++-- + libgomp/configure | 4 +- + libgomp/configure.ac | 2 +- + libgomp/simdmath.h.in | 40 +++++++++++++++++++ + libgomp/simdmath_f.h.in | 11 +++++ + 13 files changed, 106 insertions(+), 10 deletions(-) + create mode 100644 libgomp/simdmath.h.in + create mode 100644 libgomp/simdmath_f.h.in + +diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc +index a341a0617..5134f6128 100644 +--- a/gcc/c-family/c-opts.cc ++++ b/gcc/c-family/c-opts.cc +@@ -801,6 +801,10 @@ c_common_post_options (const char **pfilename) + if (cpp_opts->deps.style == DEPS_NONE) + check_deps_environment_vars (); + ++ if (flag_simdmath) ++ { ++ defer_opt (OPT_include, "simdmath.h"); ++ } + handle_deferred_opts (); + + sanitize_cpp_opts (); +diff --git a/gcc/common.opt b/gcc/common.opt +index f5eef8a45..e9d580957 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -2125,6 +2125,10 @@ fmath-errno + Common Var(flag_errno_math) Init(1) Optimization SetByCombined + Set errno after built-in math functions. + ++fsimdmath ++Common Var(flag_simdmath) Init(0) Optimization ++Enable auto-vectorize math functions for mathlib. This option will turn on -fno-math-errno and -fopenmp-simd. ++ + fmax-errors= + Common Joined RejectNegative UInteger Var(flag_max_errors) + -fmax-errors= Maximum number of errors to report. +diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc +index 226dc9dff..a3da4ca30 100644 +--- a/gcc/config/aarch64/aarch64.cc ++++ b/gcc/config/aarch64/aarch64.cc +@@ -26904,8 +26904,13 @@ aarch64_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node, + elt_bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type)); + if (known_eq (clonei->simdlen, 0U)) + { +- count = 2; +- vec_bits = (num == 0 ? 64 : 128); ++ /* Currently mathlib or sleef hasn't provide function for V2SF mode ++ simdclone of single precision functions. (e.g._ZCVnN2v_expf) ++ Therefore this mode is disabled by default to avoid link error. ++ Use -msimdmath-64 option to enable this mode. */ ++ count = flag_simdmath_64 ? 2 : 1; ++ vec_bits = ((num == 0 && flag_simdmath_64) ? 64 : 128); ++ + clonei->simdlen = exact_div (vec_bits, elt_bits); + } + else +diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt +index 92220b26e..a64b927e9 100644 +--- a/gcc/config/aarch64/aarch64.opt ++++ b/gcc/config/aarch64/aarch64.opt +@@ -190,6 +190,12 @@ precision of square root results to about 16 bits for + single precision and to 32 bits for double precision. + If enabled, it implies -mlow-precision-recip-sqrt. + ++msimdmath-64 ++Target Var(flag_simdmath_64) Optimization ++Allow compiler to generate V2SF 64 bits simdclone of math functions, ++which is not currently supported in mathlib or sleef. ++Therefore this option is disabled by default. ++ + mlow-precision-div + Target Var(flag_mlow_precision_div) Optimization + Enable the division approximation. Enabling this reduces +diff --git a/gcc/fortran/scanner.cc b/gcc/fortran/scanner.cc +index 2dff25147..63e262f51 100644 +--- a/gcc/fortran/scanner.cc ++++ b/gcc/fortran/scanner.cc +@@ -2769,6 +2769,9 @@ gfc_new_file (void) + if (flag_pre_include != NULL) + load_file (flag_pre_include, NULL, false); + ++ if (flag_simdmath) ++ load_file ("simdmath_f.h", NULL, false); ++ + if (gfc_cpp_enabled ()) + { + gfc_cpp_preprocess (gfc_source_file); +diff --git a/gcc/opts.cc b/gcc/opts.cc +index b522ed7e2..c3cc2c169 100644 +--- a/gcc/opts.cc ++++ b/gcc/opts.cc +@@ -322,6 +322,7 @@ static const char undocumented_msg[] = N_("This option lacks documentation."); + static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed."); + + typedef char *char_p; /* For DEF_VEC_P. */ ++static void set_simdmath_flags (struct gcc_options *opts, int set); + + static void set_debug_level (uint32_t dinfo, int extended, + const char *arg, struct gcc_options *opts, +@@ -2850,6 +2851,10 @@ common_handle_option (struct gcc_options *opts, + dc->min_margin_width = value; + break; + ++ case OPT_fsimdmath: ++ set_simdmath_flags (opts, value); ++ break; ++ + case OPT_fdump_: + /* Deferred. */ + break; +@@ -3227,6 +3232,18 @@ common_handle_option (struct gcc_options *opts, + return true; + } + ++/* The following routines are used to set -fno-math-errno and -fopenmp-simd ++ to enable vector mathlib. */ ++static void ++set_simdmath_flags (struct gcc_options *opts, int set) ++{ ++ if (set) ++ { ++ opts->x_flag_errno_math = 0; ++ opts->x_flag_openmp_simd = 1; ++ } ++} ++ + /* Used to set the level of strict aliasing warnings in OPTS, + when no level is specified (i.e., when -Wstrict-aliasing, and not + -Wstrict-aliasing=level was given). +diff --git a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c +index 95f6a6803..e0e0efa9d 100644 +--- a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c ++++ b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c +@@ -1,5 +1,5 @@ + /* { dg-do compile } */ +-/* { dg-options "-Ofast" } */ ++/* { dg-options "-Ofast -msimdmath-64" } */ + + __attribute__ ((__simd__)) + __attribute__ ((__nothrow__ , __leaf__ , __const__)) +diff --git a/libgomp/Makefile.am b/libgomp/Makefile.am +index f8b2a06d6..8dfa160d6 100644 +--- a/libgomp/Makefile.am ++++ b/libgomp/Makefile.am +@@ -75,10 +75,10 @@ libgomp_la_SOURCES += openacc.f90 + endif + + nodist_noinst_HEADERS = libgomp_f.h +-nodist_libsubinclude_HEADERS = omp.h openacc.h acc_prof.h ++nodist_libsubinclude_HEADERS = omp.h openacc.h acc_prof.h simdmath.h + if USE_FORTRAN + nodist_finclude_HEADERS = omp_lib.h omp_lib.f90 omp_lib.mod omp_lib_kinds.mod \ +- openacc_lib.h openacc.f90 openacc.mod openacc_kinds.mod ++ openacc_lib.h openacc.f90 openacc.mod openacc_kinds.mod simdmath_f.h + endif + + LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) +diff --git a/libgomp/Makefile.in b/libgomp/Makefile.in +index 6f0cb7161..90fc326f0 100644 +--- a/libgomp/Makefile.in ++++ b/libgomp/Makefile.in +@@ -147,7 +147,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno + mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs + CONFIG_HEADER = config.h +-CONFIG_CLEAN_FILES = omp.h omp_lib.h omp_lib.f90 libgomp_f.h \ ++CONFIG_CLEAN_FILES = omp.h omp_lib.h simdmath.h simdmath_f.h omp_lib.f90 libgomp_f.h \ + libgomp.spec + CONFIG_CLEAN_VPATH_FILES = + am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +@@ -583,9 +583,9 @@ libgomp_la_SOURCES = alloc.c atomic.c barrier.c critical.c env.c \ + @PLUGIN_GCN_TRUE@libgomp_plugin_gcn_la_LIBADD = libgomp.la $(PLUGIN_GCN_LIBS) + @PLUGIN_GCN_TRUE@libgomp_plugin_gcn_la_LIBTOOLFLAGS = --tag=disable-static + nodist_noinst_HEADERS = libgomp_f.h +-nodist_libsubinclude_HEADERS = omp.h openacc.h acc_prof.h ++nodist_libsubinclude_HEADERS = omp.h openacc.h acc_prof.h simdmath.h + @USE_FORTRAN_TRUE@nodist_finclude_HEADERS = omp_lib.h omp_lib.f90 omp_lib.mod omp_lib_kinds.mod \ +-@USE_FORTRAN_TRUE@ openacc_lib.h openacc.f90 openacc.mod openacc_kinds.mod ++@USE_FORTRAN_TRUE@ openacc_lib.h openacc.f90 openacc.mod openacc_kinds.mod simdmath_f.h + + LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) + LINK = $(LIBTOOL) --tag CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ +@@ -676,6 +676,10 @@ omp.h: $(top_builddir)/config.status $(srcdir)/omp.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + omp_lib.h: $(top_builddir)/config.status $(srcdir)/omp_lib.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ ++simdmath_f.h: $(top_builddir)/config.status $(srcdir)/simdmath_f.h.in ++ cd $(top_builddir) && $(SHELL) ./config.status $@ ++simdmath.h: $(top_builddir)/config.status $(srcdir)/simdmath.h.in ++ cd $(top_builddir) && $(SHELL) ./config.status $@ + omp_lib.f90: $(top_builddir)/config.status $(srcdir)/omp_lib.f90.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + libgomp_f.h: $(top_builddir)/config.status $(srcdir)/libgomp_f.h.in +diff --git a/libgomp/configure b/libgomp/configure +index 85fdb4d3f..471c957b7 100755 +--- a/libgomp/configure ++++ b/libgomp/configure +@@ -17064,7 +17064,7 @@ fi + + + +-ac_config_files="$ac_config_files omp.h omp_lib.h omp_lib.f90 libgomp_f.h" ++ac_config_files="$ac_config_files omp.h omp_lib.h simdmath.h simdmath_f.h omp_lib.f90 libgomp_f.h" + + ac_config_files="$ac_config_files Makefile testsuite/Makefile libgomp.spec" + +@@ -18215,6 +18215,8 @@ do + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "omp.h") CONFIG_FILES="$CONFIG_FILES omp.h" ;; + "omp_lib.h") CONFIG_FILES="$CONFIG_FILES omp_lib.h" ;; ++ "simdmath.h") CONFIG_FILES="$CONFIG_FILES simdmath.h" ;; ++ "simdmath_f.h") CONFIG_FILES="$CONFIG_FILES simdmath_f.h" ;; + "omp_lib.f90") CONFIG_FILES="$CONFIG_FILES omp_lib.f90" ;; + "libgomp_f.h") CONFIG_FILES="$CONFIG_FILES libgomp_f.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; +diff --git a/libgomp/configure.ac b/libgomp/configure.ac +index a9b1f3973..1f81a0d30 100644 +--- a/libgomp/configure.ac ++++ b/libgomp/configure.ac +@@ -472,7 +472,7 @@ CFLAGS="$save_CFLAGS" + # Determine what GCC version number to use in filesystem paths. + GCC_BASE_VER + +-AC_CONFIG_FILES(omp.h omp_lib.h omp_lib.f90 libgomp_f.h) ++AC_CONFIG_FILES(omp.h omp_lib.h simdmath.h simdmath_f.h omp_lib.f90 libgomp_f.h) + AC_CONFIG_FILES(Makefile testsuite/Makefile libgomp.spec) + AC_CONFIG_FILES([testsuite/libgomp-test-support.pt.exp:testsuite/libgomp-test-support.exp.in]) + AC_CONFIG_FILES([testsuite/libgomp-site-extra.exp]) +diff --git a/libgomp/simdmath.h.in b/libgomp/simdmath.h.in +new file mode 100644 +index 000000000..ab91a4ec3 +--- /dev/null ++++ b/libgomp/simdmath.h.in +@@ -0,0 +1,40 @@ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#pragma omp declare simd simdlen(2) notinbranch ++double cos (double x); ++ ++#pragma omp declare simd simdlen(4) notinbranch ++float cosf (float x); ++ ++#pragma omp declare simd simdlen(2) notinbranch ++double sin (double x); ++ ++#pragma omp declare simd simdlen(4) notinbranch ++float sinf (float x); ++ ++#pragma omp declare simd simdlen(2) notinbranch ++double exp (double x); ++ ++#pragma omp declare simd simdlen(4) notinbranch ++float expf (float x); ++ ++#pragma omp declare simd simdlen(2) notinbranch ++double log (double x); ++ ++#pragma omp declare simd simdlen(4) notinbranch ++float logf (float x); ++ ++#pragma omp declare simd simdlen(2) notinbranch ++double pow (double x, double y); ++ ++#pragma omp declare simd simdlen(4) notinbranch ++float powf (float x, float y); ++ ++#pragma omp declare simd simdlen(4) notinbranch ++float exp2f (float x); ++ ++#ifdef __cplusplus ++} // extern "C" ++#endif +diff --git a/libgomp/simdmath_f.h.in b/libgomp/simdmath_f.h.in +new file mode 100644 +index 000000000..550595015 +--- /dev/null ++++ b/libgomp/simdmath_f.h.in +@@ -0,0 +1,11 @@ ++!GCC$ builtin (cos) attributes simd (notinbranch) ++!GCC$ builtin (cosf) attributes simd (notinbranch) ++!GCC$ builtin (sin) attributes simd (notinbranch) ++!GCC$ builtin (sinf) attributes simd (notinbranch) ++!GCC$ builtin (exp) attributes simd (notinbranch) ++!GCC$ builtin (expf) attributes simd (notinbranch) ++!GCC$ builtin (exp2f) attributes simd (notinbranch) ++!GCC$ builtin (log) attributes simd (notinbranch) ++!GCC$ builtin (logf) attributes simd (notinbranch) ++!GCC$ builtin (pow) attributes simd (notinbranch) ++!GCC$ builtin (powf) attributes simd (notinbranch) +-- +2.33.0 + diff --git a/0021-StructReorderFields-Structure-reorder-fields.patch b/0021-StructReorderFields-Structure-reorder-fields.patch new file mode 100644 index 0000000..8324617 --- /dev/null +++ b/0021-StructReorderFields-Structure-reorder-fields.patch @@ -0,0 +1,5739 @@ +From 6997c9ad8985f6f0bfc16cdb46e7386af299a226 Mon Sep 17 00:00:00 2001 +From: h00564365 +Date: Mon, 31 Jul 2023 22:01:56 +0800 +Subject: [PATCH 21/22] [StructReorderFields] Structure reorder fields + +Introduce structure fields reordering optimization, that change +fields ordering of C-like structures in order to better utilize spatial +locality. +--- + gcc/common.opt | 4 + + gcc/doc/invoke.texi | 1 + + gcc/gimple-ssa-warn-access.cc | 2 +- + gcc/ipa-free-lang-data.cc | 4 +- + gcc/ipa-struct-reorg/escapes.def | 3 + + gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 2545 +++++++++++++---- + gcc/ipa-struct-reorg/ipa-struct-reorg.h | 14 +- + gcc/passes.def | 1 + + gcc/symbol-summary.h | 4 +- + .../struct/rf_DTE_struct_instance_field.c | 75 + + gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c | 94 + + .../gcc.dg/struct/rf_check_ptr_layers_bug.c | 24 + + .../gcc.dg/struct/rf_create_fields_bug.c | 82 + + .../gcc.dg/struct/rf_create_new_func_bug.c | 56 + + .../gcc.dg/struct/rf_ele_minus_verify.c | 60 + + .../gcc.dg/struct/rf_escape_by_base.c | 83 + + .../gcc.dg/struct/rf_external_func_types.c | 69 + + gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c | 72 + + .../gcc.dg/struct/rf_mem_ref_offset.c | 58 + + .../struct/rf_mul_layer_ptr_record_bug.c | 30 + + .../gcc.dg/struct/rf_pass_conflict.c | 109 + + gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c | 87 + + gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c | 71 + + .../gcc.dg/struct/rf_ptr_negate_expr.c | 55 + + gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c | 34 + + gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c | 55 + + gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c | 58 + + .../gcc.dg/struct/rf_rescusive_type.c | 57 + + .../struct/rf_rewrite_assign_more_cmp.c | 65 + + .../gcc.dg/struct/rf_rewrite_cond_bug.c | 72 + + .../gcc.dg/struct/rf_rewrite_cond_more_cmp.c | 58 + + .../gcc.dg/struct/rf_rewrite_phi_bug.c | 81 + + gcc/testsuite/gcc.dg/struct/rf_shwi.c | 23 + + gcc/testsuite/gcc.dg/struct/rf_visible_func.c | 92 + + .../gcc.dg/struct/rf_void_ptr_param_func.c | 54 + + gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 15 +- + gcc/testsuite/gcc.dg/struct/struct_reorg-1.c | 8 +- + gcc/testsuite/gcc.dg/struct/struct_reorg-3.c | 9 +- + gcc/timevar.def | 1 + + gcc/tree-pass.h | 1 + + 40 files changed, 3796 insertions(+), 490 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_external_func_types.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_shwi.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_visible_func.c + create mode 100644 gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c + +diff --git a/gcc/common.opt b/gcc/common.opt +index 0c7bd2f6c..98169de7c 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1954,6 +1954,10 @@ fipa-matrix-reorg + Common Ignore + Does nothing. Preserved for backward compatibility. + ++fipa-reorder-fields ++Common Var(flag_ipa_reorder_fields) Init(0) Optimization ++Perform structure fields reorder optimizations. ++ + fipa-struct-reorg + Common Var(flag_ipa_struct_reorg) Init(0) Optimization + Perform structure layout optimizations. +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index 3485cc8af..2b376e0e9 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -526,6 +526,7 @@ Objective-C and Objective-C++ Dialects}. + -finline-functions -finline-functions-called-once -finline-limit=@var{n} @gol + -finline-small-functions -fipa-modref -fipa-cp -fipa-cp-clone @gol + -fipa-bit-cp -fipa-vrp -fipa-pta -fipa-profile -fipa-pure-const @gol ++-fipa-reorder-fields @gol + -fipa-struct-reorg @gol + -fipa-reference -fipa-reference-addressable @gol + -fipa-stack-alignment -fipa-icf -fira-algorithm=@var{algorithm} @gol +diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc +index a24645783..7f5c92c96 100644 +--- a/gcc/gimple-ssa-warn-access.cc ++++ b/gcc/gimple-ssa-warn-access.cc +@@ -2198,7 +2198,7 @@ pass_waccess::gate (function *) + In pass waccess, it will traverse all SSA and cause ICE + when handling these unused SSA. So temporarily disable + pass waccess when enable structure optimizations. */ +- if (flag_ipa_struct_reorg) ++ if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) + return false; + + return (warn_free_nonheap_object +diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc +index 5450be9fe..a88381ddb 100644 +--- a/gcc/ipa-free-lang-data.cc ++++ b/gcc/ipa-free-lang-data.cc +@@ -105,7 +105,7 @@ fld_simplified_type_name (tree type) + /* Simplify type will cause that struct A and struct A within + struct B are different type pointers, so skip it in structure + optimizations. */ +- if (flag_ipa_struct_reorg) ++ if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) + return TYPE_NAME (type); + + if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL) +@@ -349,7 +349,7 @@ fld_simplified_type (tree t, class free_lang_data_d *fld) + /* Simplify type will cause that struct A and struct A within + struct B are different type pointers, so skip it in structure + optimizations. */ +- if (flag_ipa_struct_reorg) ++ if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) + return t; + if (POINTER_TYPE_P (t)) + return fld_incomplete_type_of (t, fld); +diff --git a/gcc/ipa-struct-reorg/escapes.def b/gcc/ipa-struct-reorg/escapes.def +index d825eb3e6..996a09bac 100644 +--- a/gcc/ipa-struct-reorg/escapes.def ++++ b/gcc/ipa-struct-reorg/escapes.def +@@ -58,5 +58,8 @@ DEF_ESCAPE (escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled + DEF_ESCAPE (escape_return, "Type escapes via a return [not handled yet]") + DEF_ESCAPE (escape_separate_instance, "Type escapes via a separate instance") + DEF_ESCAPE (escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt") ++DEF_ESCAPE (escape_via_orig_escape, "Type escapes via a original escape type") ++DEF_ESCAPE (escape_instance_field, "Type escapes via a field of instance") ++DEF_ESCAPE (escape_via_empty_no_orig, "Type escapes via empty and no original") + + #undef DEF_ESCAPE +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +index 9f790b28b..3e5f9538b 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +@@ -207,50 +207,88 @@ lang_c_p (void) + if (!language_string) + return false; + +- if (strcmp (language_string, "GNU GIMPLE") == 0) ++ if (lang_GNU_C ()) ++ return true; ++ else if (strcmp (language_string, "GNU GIMPLE") == 0) // For LTO check + { + unsigned i = 0; +- tree t = NULL; +- const char *unit_string = NULL; ++ tree t = NULL_TREE; + + FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t) + { +- unit_string = TRANSLATION_UNIT_LANGUAGE (t); +- if (!unit_string +- || (strncmp (unit_string, "GNU C", 5) != 0) +- || (!ISDIGIT (unit_string[5]))) ++ language_string = TRANSLATION_UNIT_LANGUAGE (t); ++ if (language_string == NULL ++ || strncmp (language_string, "GNU C", 5) ++ || (language_string[5] != '\0' ++ && !(ISDIGIT (language_string[5])))) + return false; + } + return true; + } +- else if (strncmp (language_string, "GNU C", 5) == 0 +- && ISDIGIT (language_string[5])) +- return true; +- + return false; + } + ++/* Get the number of pointer layers. */ ++ ++int ++get_ptr_layers (tree expr) ++{ ++ int layers = 0; ++ while (POINTER_TYPE_P (expr) || TREE_CODE (expr) == ARRAY_TYPE) ++ { ++ layers++; ++ expr = TREE_TYPE (expr); ++ } ++ return layers; ++} ++ ++/* Comparison pointer layers. */ ++ ++bool ++cmp_ptr_layers (tree a, tree b) ++{ ++ return get_ptr_layers (a) == get_ptr_layers (b); ++} ++ ++/* Return true if the ssa_name comes from the void* parameter. */ ++ ++bool ++is_from_void_ptr_parm (tree ssa_name) ++{ ++ gcc_assert (TREE_CODE (ssa_name) == SSA_NAME); ++ tree var = SSA_NAME_VAR (ssa_name); ++ return (var && TREE_CODE (var) == PARM_DECL ++ && VOID_POINTER_P (TREE_TYPE (ssa_name))); ++} ++ + enum srmode + { + NORMAL = 0, +- COMPLETE_STRUCT_RELAYOUT ++ COMPLETE_STRUCT_RELAYOUT, ++ STRUCT_REORDER_FIELDS + }; + +-static bool is_result_of_mult (tree, tree *, tree); ++static bool is_result_of_mult (tree arg, tree *num, tree struct_size); ++static bool isptrptr (tree type); + +-} // anon namespace ++srmode current_mode; + ++} // anon namespace + + namespace struct_reorg { + ++hash_map > fields_to_finish; ++ + /* Constructor of srfunction. */ + + srfunction::srfunction (cgraph_node *n) + : node (n), + old (NULL), + newnode (NULL), +- newf (NULL) +-{} ++ newf (NULL), ++ is_safe_func (false) ++{ ++} + + /* Add an ARG to the list of arguments for the function. */ + +@@ -400,12 +438,13 @@ srtype::add_field_site (srfield *field) + + /* Constructor of DECL. */ + +-srdecl::srdecl (srtype *tp, tree decl, int argnum) ++srdecl::srdecl (srtype *tp, tree decl, int argnum, tree orig_type) + : type (tp), + decl (decl), + func (NULL_TREE), + argumentnum (argnum), +- visited (false) ++ visited (false), ++ orig_type (orig_type) + { + if (TREE_CODE (decl) == SSA_NAME) + func = current_function_decl; +@@ -429,17 +468,23 @@ srfunction::find_decl (tree decl) + /* Record DECL of the TYPE with argument num ARG. */ + + srdecl * +-srfunction::record_decl (srtype *type, tree decl, int arg) ++srfunction::record_decl (srtype *type, tree decl, int arg, tree orig_type) + { + // Search for the decl to see if it is already there. + srdecl *decl1 = find_decl (decl); + + if (decl1) +- return decl1; ++ { ++ /* Added the orig_type information. */ ++ if (!decl1->orig_type && orig_type && isptrptr (orig_type)) ++ decl1->orig_type = orig_type; ++ return decl1; ++ } + + gcc_assert (type); + +- decl1 = new srdecl (type, decl, arg); ++ orig_type = isptrptr (TREE_TYPE (decl)) ? TREE_TYPE (decl) : orig_type; ++ decl1 = new srdecl (type, decl, arg, isptrptr (orig_type) ? orig_type : NULL); + decls.safe_push (decl1); + return decl1; + } +@@ -503,31 +548,21 @@ srtype::dump (FILE *f) + print_generic_expr (f, type); + fprintf (f, "(%d) { ", TYPE_UID (type)); + if (escapes != does_not_escape) +- fprintf (f, " escapes = \"%s\"\n", escape_reason ()); +- fprintf (f, " fields = { "); ++ fprintf (f, "escapes = \"%s\"", escape_reason ()); ++ fprintf (f, "\nfields = {\n"); + FOR_EACH_VEC_ELT (fields, i, field) +- { +- if (i == 0) +- fprintf (f, "\n "); +- else +- fprintf (f, "\n, "); +- field->dump (f); +- } +- fprintf (f, " }\n "); +- fprintf (f, "\n accesses = {"); ++ field->dump (f); ++ fprintf (f, "}\n "); ++ ++ fprintf (f, "\naccesses = {\n"); + FOR_EACH_VEC_ELT (accesses, i, access) +- { +- fprintf (f, "\n"); +- access->dump (f); +- } +- fprintf (f, " }\n "); +- fprintf (f, "\n functions = {"); ++ access->dump (f); ++ fprintf (f, "}\n "); ++ ++ fprintf (f, "\nfunctions = {\n"); + FOR_EACH_VEC_ELT (functions, i, fn) +- { +- fprintf (f, " \n"); +- fn->simple_dump (f); +- } +- fprintf (f, "\n }\n"); ++ fn->simple_dump (f); ++ fprintf (f, "}\n"); + fprintf (f, "}\n"); + } + +@@ -537,6 +572,8 @@ void + srtype::simple_dump (FILE *f) + { + print_generic_expr (f, type); ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ fprintf (f, "(%d)", TYPE_UID (type)); + } + + /* Analyze the type and decide what to be done with it. */ +@@ -572,6 +609,12 @@ srfield::create_new_fields (tree newtype[max_split], + tree newfields[max_split], + tree newlast[max_split]) + { ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ create_new_reorder_fields (newtype, newfields, newlast); ++ return; ++ } ++ + tree nt[max_split]; + + for (unsigned i = 0; i < max_split; i++) +@@ -620,6 +663,104 @@ srfield::create_new_fields (tree newtype[max_split], + } + } + ++/* Reorder fields. */ ++ ++void ++srfield::reorder_fields (tree newfields[max_split], tree newlast[max_split], ++ tree &field) ++{ ++ /* Reorder fields in descending. ++ newfields: always stores the first member of the chain ++ and with the largest size. ++ field: indicates the node to be inserted. */ ++ if (newfields[clusternum] == NULL) ++ { ++ newfields[clusternum] = field; ++ newlast[clusternum] = field; ++ } ++ else ++ { ++ tree tmp = newfields[clusternum]; ++ if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (field))) ++ > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (tmp)))) ++ { ++ DECL_CHAIN (field) = tmp; ++ newfields[clusternum] = field; ++ } ++ else ++ { ++ while (DECL_CHAIN (tmp) ++ && (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (field))) ++ <= tree_to_uhwi ( ++ TYPE_SIZE (TREE_TYPE (DECL_CHAIN (tmp)))))) ++ tmp = DECL_CHAIN (tmp); ++ ++ /* Now tmp size > field size ++ insert field: tmp -> xx ==> tmp -> field -> xx. */ ++ DECL_CHAIN (field) = DECL_CHAIN (tmp); // field -> xx ++ DECL_CHAIN (tmp) = field; // tmp -> field ++ } ++ } ++} ++ ++/* Create the new reorder fields for this field. ++ newtype[max_split]: srtype's member variable, ++ newfields[max_split]: created by create_new_type func, ++ newlast[max_split]: created by create_new_type func. */ ++ ++void ++srfield::create_new_reorder_fields (tree newtype[max_split], ++ tree newfields[max_split], ++ tree newlast[max_split]) ++{ ++ /* newtype, corresponding to newtype[max_split] in srtype. */ ++ tree nt = NULL_TREE; ++ if (type == NULL) ++ /* Common var. */ ++ nt = fieldtype; ++ else ++ { ++ /* RECORD_TYPE var. */ ++ if (type->has_escaped ()) ++ nt = type->type; ++ else ++ nt = type->newtype[0]; ++ } ++ tree field = make_node (FIELD_DECL); ++ ++ /* Used for recursive types. ++ fields_to_finish: hase_map in the format of "type: {fieldA, fieldB}", ++ key : indicates the original type, ++ vaule: filed that need to be updated to newtype. */ ++ if (nt == NULL) ++ { ++ nt = make_node (RECORD_TYPE); ++ auto_vec &fields ++ = fields_to_finish.get_or_insert (inner_type (type->type)); ++ fields.safe_push (field); ++ } ++ ++ DECL_NAME (field) = DECL_NAME (fielddecl); ++ if (type == NULL) ++ /* Common members do not need to reconstruct. ++ Otherwise, int* -> int** or void* -> void**. */ ++ TREE_TYPE (field) = nt; ++ else ++ TREE_TYPE (field) = reconstruct_complex_type (TREE_TYPE (fielddecl), nt); ++ DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (fielddecl); ++ SET_DECL_ALIGN (field, DECL_ALIGN (fielddecl)); ++ DECL_USER_ALIGN (field) = DECL_USER_ALIGN (fielddecl); ++ TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (fielddecl); ++ DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (fielddecl); ++ TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (fielddecl); ++ DECL_CONTEXT (field) = newtype[clusternum]; ++ ++ reorder_fields (newfields, newlast, field); ++ ++ /* srfield member variable, which stores the new field decl. */ ++ newfield[0] = field; ++} ++ + /* Create the new TYPE corresponding to THIS type. */ + + bool +@@ -655,7 +796,8 @@ srtype::create_new_type (void) + /* If the fields' types did have a change or + we are not splitting the struct into two clusters, + then just return false and don't change the type. */ +- if (!createnewtype && maxclusters == 0) ++ if (!createnewtype && maxclusters == 0 ++ && current_mode != STRUCT_REORDER_FIELDS) + { + newtype[0] = type; + return false; +@@ -664,6 +806,7 @@ srtype::create_new_type (void) + /* Should have at most max_split clusters. */ + gcc_assert (maxclusters < max_split); + ++ /* Record the first member of the field chain. */ + tree newfields[max_split]; + tree newlast[max_split]; + +@@ -682,7 +825,8 @@ srtype::create_new_type (void) + sprintf (id, "%d", i); + if (tname) + { +- name = concat (tname, ".reorg.", id, NULL); ++ name = concat (tname, current_mode == STRUCT_REORDER_FIELDS ++ ? ".reorder." : ".reorg.", id, NULL); + TYPE_NAME (newtype[i]) = build_decl (UNKNOWN_LOCATION, + TYPE_DECL, + get_identifier (name), +@@ -718,6 +862,7 @@ srtype::create_new_type (void) + for (unsigned i = 0; i < maxclusters; i++) + { + print_generic_expr (dump_file, newtype[i]); ++ fprintf (dump_file, "(%d)", TYPE_UID (newtype[i])); + fprintf (dump_file, "\n"); + } + } +@@ -776,8 +921,12 @@ srfunction::create_new_decls (void) + tree newinner[max_split]; + memset (newinner, 0, sizeof (newinner)); + for (unsigned j = 0; j < max_split && type->newtype[j]; j++) +- newtype1[j] = reconstruct_complex_type (TREE_TYPE (decls[i]->decl), +- type->newtype[j]); ++ { ++ newtype1[j] = reconstruct_complex_type ( ++ isptrptr (decls[i]->orig_type) ? decls[i]->orig_type ++ : TREE_TYPE (decls[i]->decl), ++ type->newtype[j]); ++ } + if (inner) + { + srdecl *in = find_decl (inner); +@@ -825,7 +974,8 @@ srfunction::create_new_decls (void) + sprintf (id, "%d", j); + if (tname) + { +- name = concat (tname, ".reorg.", id, NULL); ++ name = concat (tname, current_mode == STRUCT_REORDER_FIELDS ++ ? ".reorder." : ".reorg.", id, NULL); + new_name = get_identifier (name); + free (name); + } +@@ -850,7 +1000,6 @@ srfunction::create_new_decls (void) + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Created New decls for decl:\n"); +- fprintf (dump_file, "\n"); + decls[i]->dump (dump_file); + fprintf (dump_file, "\n"); + for (unsigned j = 0; j < max_split && decls[i]->newdecl[j]; j++) +@@ -876,7 +1025,7 @@ srfield::dump (FILE *f) + fprintf (f, ", offset = " HOST_WIDE_INT_PRINT_DEC, offset); + fprintf (f, ", type = "); + print_generic_expr (f, fieldtype); +- fprintf (f, "\n}\n"); ++ fprintf (f, "}\n"); + } + + /* A simplified dump out the field structure to FILE. */ +@@ -908,7 +1057,7 @@ sraccess::dump (FILE *f) + fprintf (f, " in function: %s/%d", node->name (), node->order); + fprintf (f, ", stmt:\n"); + print_gimple_stmt (f, stmt, 0); +- fprintf (f, "\n }\n"); ++ fprintf (f, "}\n"); + } + + /* Dump out the decl structure to FILE. */ +@@ -1023,8 +1172,7 @@ public: + // Constructors + ipa_struct_reorg (void) + : current_function (NULL), +- done_recording (false), +- current_mode (NORMAL) ++ done_recording (false) + {} + + // Fields +@@ -1032,9 +1180,10 @@ public: + auto_vec_del functions; + srglobal globals; + srfunction *current_function; ++ hash_set safe_functions; ++ auto_vec ext_func_types; + + bool done_recording; +- srmode current_mode; + + // Methods + unsigned execute (enum srmode mode); +@@ -1042,6 +1191,7 @@ public: + gimple *stmt = NULL); + + void dump_types (FILE *f); ++ void dump_newtypes (FILE *f); + void dump_types_escaped (FILE *f); + void dump_functions (FILE *f); + void record_accesses (void); +@@ -1049,6 +1199,9 @@ public: + bool walk_field_for_cycles (srtype *); + void prune_escaped_types (void); + void propagate_escape (void); ++ void propagate_escape_via_original (void); ++ void propagate_escape_via_empty_with_no_original (void); ++ void propagate_escape_via_ext_func_types (void); + void analyze_types (void); + void clear_visited (void); + bool create_new_types (void); +@@ -1060,8 +1213,11 @@ public: + srdecl *record_var (tree decl, + escape_type escapes = does_not_escape, + int arg = -1); ++ void record_safe_func_with_void_ptr_parm (void); + srfunction *record_function (cgraph_node *node); + srfunction *find_function (cgraph_node *node); ++ void record_field_type (tree field, srtype *base_srtype); ++ void record_struct_field_types (tree base_type, srtype *base_srtype); + srtype *record_type (tree type); + void process_union (tree type); + srtype *find_type (tree type); +@@ -1072,7 +1228,7 @@ public: + void record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt); + void mark_expr_escape (tree, escape_type, gimple *stmt); + bool handled_allocation_stmt (gimple *stmt); +- tree allocate_size (srtype *t, gimple *stmt); ++ tree allocate_size (srtype *t, srdecl *decl, gimple *stmt); + + void mark_decls_in_as_not_needed (tree fn); + +@@ -1087,21 +1243,23 @@ public: + bool ignore_missing_decl = false); + bool rewrite_lhs_rhs (tree lhs, tree rhs, tree newlhs[max_split], + tree newrhs[max_split]); +- bool get_type_field (tree expr, tree &base, bool &indirect, +- srtype *&type, srfield *&field, +- bool &realpart, bool &imagpart, +- bool &address, bool should_create = false, +- bool can_escape = false); ++ bool get_type_field (tree expr, tree &base, bool &indirect, srtype *&type, ++ srfield *&field, bool &realpart, bool &imagpart, ++ bool &address, bool &escape_from_base, ++ bool should_create = false, bool can_escape = false); + bool wholeaccess (tree expr, tree base, tree accesstype, srtype *t); + + void check_alloc_num (gimple *stmt, srtype *type); ++ void check_definition_assign (srdecl *decl, vec &worklist); ++ void check_definition_call (srdecl *decl, vec &worklist); + void check_definition (srdecl *decl, vec &); + void check_uses (srdecl *decl, vec &); + void check_use (srdecl *decl, gimple *stmt, vec &); +- void check_type_and_push (tree newdecl, srtype *type, ++ void check_type_and_push (tree newdecl, srdecl *decl, + vec &worklist, gimple *stmt); + void check_other_side (srdecl *decl, tree other, gimple *stmt, + vec &worklist); ++ void check_ptr_layers (tree a_expr, tree b_expr, gimple *stmt); + + void find_vars (gimple *stmt); + void find_var (tree expr, gimple *stmt); +@@ -1703,9 +1861,42 @@ ipa_struct_reorg::dump_types (FILE *f) + srtype *type; + FOR_EACH_VEC_ELT (types, i, type) + { ++ fprintf (f, "======= the %dth type: ======\n", i); + type->dump (f); ++ fprintf (f, "\n"); ++ } ++} ++ ++/* Dump all of the created newtypes to file F. */ ++ ++void ++ipa_struct_reorg::dump_newtypes (FILE *f) ++{ ++ unsigned i = 0; ++ srtype *type = NULL; ++ FOR_EACH_VEC_ELT (types, i, type) ++ { ++ if (type->has_escaped ()) ++ continue; ++ fprintf (f, "======= the %dth newtype: ======\n", i); ++ fprintf (f, "type : "); ++ print_generic_expr (f, type->newtype[0]); ++ fprintf (f, "(%d) ", TYPE_UID (type->newtype[0])); ++ fprintf (f, "{ "); ++ fprintf (f, "\nfields = {\n"); ++ ++ for (tree field = TYPE_FIELDS (TYPE_MAIN_VARIANT (type->newtype[0])); ++ field; field = DECL_CHAIN (field)) ++ { ++ fprintf (f, "field (%d) ", DECL_UID (field)); ++ fprintf (f, "{"); ++ fprintf (f, "type = "); ++ print_generic_expr (f, TREE_TYPE (field)); ++ fprintf (f, "}\n"); ++ } ++ fprintf (f, "}\n "); ++ fprintf (f, "\n"); + } +- fprintf (f, "\n"); + } + + /* Dump all of the recorded types to file F. */ +@@ -1803,6 +1994,8 @@ isarraytype (tree type) + static bool + isptrptr (tree type) + { ++ if (type == NULL) ++ return false; + bool firstptr = false; + while (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) + { +@@ -1817,154 +2010,740 @@ isptrptr (tree type) + return false; + } + +-/* Return the escape type which corresponds to if +- this is an volatile type, an array type or a pointer +- to a pointer type. */ ++/* Adding node to map and stack. */ + +-static escape_type +-escape_type_volatile_array_or_ptrptr (tree type) ++bool ++add_node (tree node, int layers, hash_map &map, ++ auto_vec &stack) + { +- if (isvolatile_type (type)) +- return escape_volatile; +- if (isarraytype (type)) +- return escape_array; +- if (isptrptr (type)) +- return escape_ptr_ptr; +- return does_not_escape; ++ if (TREE_CODE (node) != SSA_NAME) ++ return false; ++ if (map.get (node) == NULL) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, " "); ++ fprintf (dump_file, "add node: \t\t"); ++ print_generic_expr (dump_file, node); ++ fprintf (dump_file, ",\t\tptr layers: %d: \n", layers); ++ } ++ map.put (node, layers); ++ stack.safe_push (node); ++ } ++ else if (*map.get (node) != layers) ++ return false; ++ return true; + } + +-/* Record TYPE if not already recorded. */ ++/* Check the number of pointer layers of the gimple phi in definition. */ + +-srtype * +-ipa_struct_reorg::record_type (tree type) ++bool ++check_def_phi (tree def_node, hash_map &ptr_layers) + { +- unsigned typeuid; +- +- /* Get the main variant as we are going +- to record that type only. */ +- type = TYPE_MAIN_VARIANT (type); +- typeuid = TYPE_UID (type); ++ bool res = true; ++ gimple *def_stmt = SSA_NAME_DEF_STMT (def_node); ++ for (unsigned j = 0; j < gimple_phi_num_args (def_stmt); j++) ++ { ++ tree phi_node = gimple_phi_arg_def (def_stmt, j); ++ if (integer_zerop (phi_node)) ++ continue; ++ if (ptr_layers.get (phi_node) == NULL) ++ return false; ++ res &= *ptr_layers.get (def_node) == *ptr_layers.get (phi_node); ++ } ++ return res; ++} + +- srtype *type1; ++/* Check the number of pointer layers of the gimple assign in definition. */ + +- type1 = find_type (type); +- if (type1) +- return type1; ++bool ++check_def_assign (tree def_node, hash_map &ptr_layers) ++{ ++ bool res = true; ++ gimple *def_stmt = SSA_NAME_DEF_STMT (def_node); ++ gimple_rhs_class rhs_class = gimple_assign_rhs_class (def_stmt); ++ tree_code rhs_code = gimple_assign_rhs_code (def_stmt); ++ tree rhs1 = gimple_assign_rhs1 (def_stmt); ++ tree rhs1_base = TREE_CODE (rhs1) == MEM_REF ? TREE_OPERAND (rhs1, 0) : rhs1; ++ if (ptr_layers.get (rhs1_base) == NULL) ++ return false; ++ if (rhs_class == GIMPLE_SINGLE_RHS || rhs_class == GIMPLE_UNARY_RHS) ++ { ++ if (TREE_CODE (rhs1) == SSA_NAME) ++ res = *ptr_layers.get (def_node) == *ptr_layers.get (rhs1); ++ else if (TREE_CODE (rhs1) == MEM_REF) ++ res = *ptr_layers.get (def_node) ++ == *ptr_layers.get (TREE_OPERAND (rhs1, 0)); ++ else ++ { ++ return false; ++ } ++ } ++ else if (rhs_class == GIMPLE_BINARY_RHS) ++ { ++ if (rhs_code == POINTER_PLUS_EXPR) ++ res = *ptr_layers.get (def_node) == *ptr_layers.get (rhs1); ++ else if (rhs_code == BIT_AND_EXPR) ++ res = *ptr_layers.get (def_node) == *ptr_layers.get (rhs1); ++ else ++ return false; ++ } ++ else ++ return false; ++ return res; ++} + +- /* If already done recording just return NULL. */ +- if (done_recording) +- return NULL; ++/* Check node definition. */ + ++bool ++check_node_def (hash_map &ptr_layers) ++{ ++ bool res = true; + if (dump_file && (dump_flags & TDF_DETAILS)) +- fprintf (dump_file, "Recording new type: %u.\n", typeuid); +- +- type1 = new srtype (type); +- types.safe_push (type1); +- +- /* If the type has an user alignment set, +- that means the user most likely already setup the type. */ +- if (TYPE_USER_ALIGN (type)) +- type1->mark_escape (escape_user_alignment, NULL); +- +- for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ fprintf (dump_file, "\n======== check node definition ========\n"); ++ for (unsigned i = 1; i < num_ssa_names; ++i) + { +- if (TREE_CODE (field) == FIELD_DECL) ++ tree name = ssa_name (i); ++ if (name && ptr_layers.get (name) != NULL) + { +- tree t = TREE_TYPE (field); +- process_union (t); +- if (TREE_CODE (inner_type (t)) == UNION_TYPE +- || TREE_CODE (inner_type (t)) == QUAL_UNION_TYPE) +- type1->mark_escape (escape_union, NULL); +- if (isvolatile_type (t)) +- type1->mark_escape (escape_volatile, NULL); +- escape_type e = escape_type_volatile_array_or_ptrptr (t); +- if (e != does_not_escape) +- type1->mark_escape (e, NULL); +- if (handled_type (t)) +- { +- srtype *t1 = record_type (inner_type (t)); +- srfield *f = type1->find_field (int_byte_position (field)); +- /* We might have an variable sized type which +- we don't set the handle. */ +- if (f) +- { +- f->type = t1; +- t1->add_field_site (f); +- } +- if (t1 == type1 && current_mode != COMPLETE_STRUCT_RELAYOUT) +- type1->mark_escape (escape_rescusive_type, NULL); +- } ++ gimple *def_stmt = SSA_NAME_DEF_STMT (name); ++ if (dump_file && (dump_flags & TDF_DETAILS) ++ && gimple_code (def_stmt) != GIMPLE_DEBUG) ++ print_gimple_stmt (dump_file, def_stmt, 0); ++ ++ if (gimple_code (def_stmt) == GIMPLE_PHI) ++ res = check_def_phi (name, ptr_layers); ++ else if (gimple_code (def_stmt) == GIMPLE_ASSIGN) ++ res = check_def_assign (name, ptr_layers); ++ else if (gimple_code (def_stmt) == GIMPLE_NOP) ++ continue; ++ else ++ return false; + } + } ++ return res; ++} + +- return type1; ++/* Check pointer usage. */ ++ ++bool ++check_record_ptr_usage (gimple *use_stmt, tree ¤t_node, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack) ++{ ++ gimple_rhs_class rhs_class = gimple_assign_rhs_class (use_stmt); ++ tree rhs1 = gimple_assign_rhs1 (use_stmt); ++ tree lhs = gimple_assign_lhs (use_stmt); ++ if (rhs_class != GIMPLE_SINGLE_RHS ++ || (TREE_CODE (rhs1) != COMPONENT_REF && TREE_CODE (rhs1) != SSA_NAME) ++ || (TREE_CODE (lhs) != MEM_REF && TREE_CODE (lhs) != SSA_NAME)) ++ return false; ++ ++ bool res = true; ++ /* MEM[(long int *)a_1] = _1; (record). ++ If lhs is ssa_name, lhs cannot be the current node. ++ _2 = _1->flow; (No record). */ ++ if (TREE_CODE (rhs1) == SSA_NAME) ++ { ++ tree tmp = (rhs1 != current_node) ? rhs1 : lhs; ++ if (TREE_CODE (tmp) == MEM_REF) ++ res = add_node (TREE_OPERAND (tmp, 0), ++ *ptr_layers.get (current_node) + 1, ++ ptr_layers, ssa_name_stack); ++ else ++ res = add_node (tmp, *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); ++ } ++ else if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs1) == COMPONENT_REF) ++ res = !(POINTER_TYPE_P (TREE_TYPE (rhs1))); ++ else ++ res = false; ++ return res; + } + +-/* Mark TYPE as escaping with ESCAPES as the reason. */ ++/* Check and record a single node. */ + +-void +-ipa_struct_reorg::mark_type_as_escape (tree type, +- escape_type escapes, +- gimple *stmt) ++bool ++check_record_single_node (gimple *use_stmt, tree ¤t_node, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack) + { +- if (handled_type (type)) +- { +- srtype *stype = record_type (inner_type (type)); ++ gimple_rhs_class rhs_class = gimple_assign_rhs_class (use_stmt); ++ tree rhs1 = gimple_assign_rhs1 (use_stmt); ++ tree lhs = gimple_assign_lhs (use_stmt); ++ gcc_assert (rhs_class == GIMPLE_SINGLE_RHS || rhs_class == GIMPLE_UNARY_RHS); + +- if (!stype) +- return; ++ if ((TREE_CODE (rhs1) != SSA_NAME && TREE_CODE (rhs1) != MEM_REF) ++ || (TREE_CODE (lhs) != SSA_NAME && TREE_CODE (lhs) != MEM_REF)) ++ return false; + +- stype->mark_escape (escapes, stmt); ++ bool res = true; ++ if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs1) == MEM_REF) ++ /* Add such as: _2 = MEM[(struct arc_t * *)_1]. */ ++ res = add_node (lhs, *ptr_layers.get (current_node) - 1, ++ ptr_layers, ssa_name_stack); ++ else if (TREE_CODE (lhs) == MEM_REF && TREE_CODE (rhs1) == SSA_NAME) ++ { ++ /* Add such as: MEM[(long int *)a_1] = _1. */ ++ if (rhs1 == current_node) ++ res = add_node (TREE_OPERAND (lhs, 0), ++ *ptr_layers.get (current_node) + 1, ++ ptr_layers, ssa_name_stack); ++ else ++ res = add_node (rhs1, *ptr_layers.get (current_node) - 1, ++ ptr_layers, ssa_name_stack); + } ++ else if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs1) == SSA_NAME) ++ res = add_node (lhs, *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); ++ else ++ res = false; ++ ++ return res; + } + +-/* Maybe process the union of type TYPE, such that marking all of the fields' +- types as being escaping. */ ++/* Check and record multiple nodes. */ + +-void +-ipa_struct_reorg::process_union (tree type) ++bool ++check_record_mult_node (gimple *use_stmt, tree ¤t_node, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack) + { +- static hash_set unions_recorded; ++ gimple_rhs_class rhs_class = gimple_assign_rhs_class (use_stmt); ++ tree_code rhs_code = gimple_assign_rhs_code (use_stmt); ++ tree rhs1 = gimple_assign_rhs1 (use_stmt); ++ tree lhs = gimple_assign_lhs (use_stmt); ++ tree rhs2 = gimple_assign_rhs2 (use_stmt); ++ gcc_assert (rhs_class == GIMPLE_BINARY_RHS); ++ ++ if ((rhs_code != POINTER_PLUS_EXPR && rhs_code != POINTER_DIFF_EXPR ++ && rhs_code != BIT_AND_EXPR) ++ || (TREE_CODE (lhs) != SSA_NAME && TREE_CODE (rhs1) != SSA_NAME)) ++ return false; + +- type = inner_type (type); +- if (TREE_CODE (type) != UNION_TYPE +- && TREE_CODE (type) != QUAL_UNION_TYPE) +- return; ++ bool res = true; ++ if (rhs_code == POINTER_PLUS_EXPR) ++ res = add_node (lhs == current_node ? rhs1 : lhs, ++ *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); ++ else if (rhs_code == POINTER_DIFF_EXPR) ++ res = add_node (rhs1 != current_node ? rhs1 : rhs2, ++ *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); ++ else if (rhs_code == BIT_AND_EXPR) ++ { ++ if (TREE_CODE (rhs2) != INTEGER_CST) ++ return false; ++ res = add_node (lhs == current_node ? rhs1 : lhs, ++ *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); ++ } ++ return res; ++} + +- type = TYPE_MAIN_VARIANT (type); ++/* Check whether gimple assign is correctly used and record node. */ + +- /* We already processed this type. */ +- if (unions_recorded.add (type)) +- return; ++bool ++check_record_assign (tree ¤t_node, gimple *use_stmt, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack) ++{ ++ gimple_rhs_class rhs_class = gimple_assign_rhs_class (use_stmt); ++ if (*ptr_layers.get (current_node) == 1) ++ return check_record_ptr_usage (use_stmt, current_node, ++ ptr_layers, ssa_name_stack); ++ else if (*ptr_layers.get (current_node) > 1) ++ { ++ if (rhs_class != GIMPLE_BINARY_RHS ++ && rhs_class != GIMPLE_UNARY_RHS ++ && rhs_class != GIMPLE_SINGLE_RHS) ++ return false; + +- for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ if (rhs_class == GIMPLE_SINGLE_RHS || rhs_class == GIMPLE_UNARY_RHS) ++ return check_record_single_node (use_stmt, current_node, ++ ptr_layers, ssa_name_stack); ++ else if (rhs_class == GIMPLE_BINARY_RHS) ++ return check_record_mult_node (use_stmt, current_node, ++ ptr_layers, ssa_name_stack); ++ } ++ else ++ return false; ++ ++ return true; ++} ++ ++/* Check whether gimple phi is correctly used and record node. */ ++ ++bool ++check_record_phi (tree ¤t_node, gimple *use_stmt, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack) ++{ ++ bool res = true; ++ res &= add_node (gimple_phi_result (use_stmt), *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); ++ ++ for (unsigned i = 0; i < gimple_phi_num_args (use_stmt); i++) + { +- if (TREE_CODE (field) == FIELD_DECL) +- { +- mark_type_as_escape (TREE_TYPE (field), escape_union); +- process_union (TREE_TYPE (field)); +- } ++ if (integer_zerop (gimple_phi_arg_def (use_stmt, i))) ++ continue; ++ res &= add_node (gimple_phi_arg_def (use_stmt, i), ++ *ptr_layers.get (current_node), ++ ptr_layers, ssa_name_stack); + } ++ return res; + } + +-/* Used by record_var function as a callback to walk_tree. +- Mark the type as escaping if it has expressions which +- cannot be converted for global initializations. */ ++/* Check the use of callee. */ + +-static tree +-record_init_types (tree *tp, int *walk_subtrees, void *data) ++bool ++check_callee (cgraph_node *node, gimple *stmt, ++ hash_map &ptr_layers, int input_layers) + { +- ipa_struct_reorg *c = (ipa_struct_reorg *)data; +- switch (TREE_CODE (*tp)) ++ /* caller main () ++ { spec_qsort.constprop (_649, _651); } ++ def spec_qsort.constprop (void * a, size_t n) ++ { spec_qsort.constprop (a_1, _139); } */ ++ /* In safe functions, only call itself is allowed. */ ++ if (node->get_edge (stmt)->callee != node) ++ return false; ++ tree input_node = gimple_call_arg (stmt, 0); ++ if (ptr_layers.get (input_node) == NULL ++ || *ptr_layers.get (input_node) != input_layers) ++ return false; ++ if (SSA_NAME_VAR (input_node) != DECL_ARGUMENTS (node->decl)) ++ return false; ++ ++ for (unsigned i = 1; i < gimple_call_num_args (stmt); i++) + { +- CASE_CONVERT: +- case COMPONENT_REF: +- case VIEW_CONVERT_EXPR: +- case ARRAY_REF: +- { +- tree typeouter = TREE_TYPE (*tp); +- tree typeinner = TREE_TYPE (TREE_OPERAND (*tp, 0)); +- c->mark_type_as_escape (typeouter, escape_via_global_init); ++ if (ptr_layers.get (gimple_call_arg (stmt, i)) != NULL) ++ return false; ++ } ++ return true; ++} ++ ++/* Check the usage of input nodes and related nodes. */ ++ ++bool ++check_node_use (cgraph_node *node, tree current_node, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack, ++ int input_layers) ++{ ++ imm_use_iterator imm_iter; ++ gimple *use_stmt = NULL; ++ bool res = true; ++ /* Use FOR_EACH_IMM_USE_STMT as an indirect edge ++ to search for possible related nodes and push to stack. */ ++ FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, current_node) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS) ++ && gimple_code (use_stmt) != GIMPLE_DEBUG) ++ { ++ fprintf (dump_file, "%*s", 4, ""); ++ print_gimple_stmt (dump_file, use_stmt, 0); ++ } ++ /* For other types of gimple, do not record the node. */ ++ if (res) ++ { ++ if (gimple_code (use_stmt) == GIMPLE_PHI) ++ res = check_record_phi (current_node, use_stmt, ++ ptr_layers, ssa_name_stack); ++ else if (gimple_code (use_stmt) == GIMPLE_ASSIGN) ++ res = check_record_assign (current_node, use_stmt, ++ ptr_layers, ssa_name_stack); ++ else if (gimple_code (use_stmt) == GIMPLE_CALL) ++ res = check_callee (node, use_stmt, ptr_layers, input_layers); ++ else if (gimple_code (use_stmt) == GIMPLE_RETURN) ++ res = false; ++ } ++ } ++ return res; ++} ++ ++/* Trace the pointer layers of void node. */ ++ ++bool ++get_void_node_ptr_layers (tree input, int &input_layers) ++{ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "input type is void* node\n"); ++ imm_use_iterator imm_iter; ++ gimple *use_stmt = NULL; ++ FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, input) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ print_gimple_stmt (dump_file, use_stmt, 0); ++ if (gimple_code (use_stmt) == GIMPLE_ASSIGN ++ && gimple_assign_rhs_class (use_stmt) == GIMPLE_SINGLE_RHS) ++ { ++ tree rhs1 = gimple_assign_rhs1 (use_stmt); ++ tree lhs = gimple_assign_lhs (use_stmt); ++ if (TREE_CODE (lhs) == SSA_NAME && handled_type (TREE_TYPE (lhs))) ++ { ++ if (TREE_CODE (rhs1) == MEM_REF) ++ { ++ input_layers = get_ptr_layers (TREE_TYPE (lhs)) + 1; ++ return true; ++ } ++ } ++ } ++ } ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "end trace pointer layers of void* node\n"); ++ return false; ++} ++ ++/* Preparing the First Node for DFS. */ ++ ++bool ++set_init_node (cgraph_node *node, cgraph_edge *caller, ++ hash_map &ptr_layers, ++ auto_vec &ssa_name_stack, int &input_layers) ++{ ++ /* Set input_layer ++ caller spec_qsort.constprop (_649, _651) ++ |-- Obtains the actual ptr layer ++ from the input node. */ ++ caller->caller->get_untransformed_body (); ++ if (caller->call_stmt == NULL ++ || gimple_call_num_args (caller->call_stmt) == 0) ++ return false; ++ tree input = gimple_call_arg (caller->call_stmt, 0); ++ if (!(POINTER_TYPE_P (TREE_TYPE (input)) ++ || TREE_CODE (TREE_TYPE (input)) == ARRAY_TYPE)) ++ return false; ++ if (handled_type (TREE_TYPE (input))) ++ input_layers = get_ptr_layers (TREE_TYPE (input)); ++ else ++ { ++ if (VOID_POINTER_P (TREE_TYPE (input))) ++ { ++ if (!get_void_node_ptr_layers (input, input_layers)) ++ return false; ++ } ++ } ++ ++ /* Set initial node ++ def spec_qsort.constprop (void * a, size_t n) ++ |-- Find the initial ssa_name ++ from the parameter node. */ ++ tree parm = DECL_ARGUMENTS (node->decl); ++ for (unsigned j = 1; j < num_ssa_names; ++j) ++ { ++ tree name = ssa_name (j); ++ if (!name || has_zero_uses (name) || virtual_operand_p (name)) ++ continue; ++ if (SSA_NAME_VAR (name) == parm ++ && gimple_code (SSA_NAME_DEF_STMT (name)) == GIMPLE_NOP) ++ { ++ if (!add_node (name, input_layers, ptr_layers, ssa_name_stack)) ++ return false; ++ } ++ } ++ return !ssa_name_stack.is_empty (); ++} ++ ++/* Check the usage of each call. */ ++ ++bool ++check_each_call (cgraph_node *node, cgraph_edge *caller) ++{ ++ hash_map ptr_layers; ++ auto_vec ssa_name_stack; ++ int input_layers = 0; ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "======== check each call : %s/%u ========\n", ++ node->name (), node->order); ++ if (!set_init_node (node, caller, ptr_layers, ssa_name_stack, input_layers)) ++ return false; ++ int i = 0; ++ while (!ssa_name_stack.is_empty ()) ++ { ++ tree current_node = ssa_name_stack.pop (); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\ncur node %d: \t", i++); ++ print_generic_expr (dump_file, current_node); ++ fprintf (dump_file, ",\t\tptr layers: %d: \n", ++ *ptr_layers.get (current_node)); ++ } ++ if (get_ptr_layers (TREE_TYPE (current_node)) ++ > *ptr_layers.get (current_node)) ++ return false; ++ if (!check_node_use (node, current_node, ptr_layers, ssa_name_stack, ++ input_layers)) ++ return false; ++ } ++ ++ if (!check_node_def (ptr_layers)) ++ return false; ++ return true; ++} ++ ++/* Filter out function: void func (void*, int n), ++ and the function has no static variable, no structure-related variable, ++ and no global variable is used. */ ++ ++bool ++filter_func (cgraph_node *node) ++{ ++ tree parm = DECL_ARGUMENTS (node->decl); ++ if (!(parm && VOID_POINTER_P (TREE_TYPE (parm)) ++ && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (node->decl))))) ++ return false; ++ ++ for (parm = DECL_CHAIN (parm); parm; parm = DECL_CHAIN (parm)) ++ { ++ if (TREE_CODE (TREE_TYPE (parm)) != INTEGER_TYPE) ++ return false; ++ } ++ ++ if (DECL_STRUCT_FUNCTION (node->decl)->static_chain_decl) ++ return false; ++ ++ tree var = NULL_TREE; ++ unsigned int i = 0; ++ bool res = true; ++ FOR_EACH_LOCAL_DECL (cfun, i, var) ++ { ++ if (TREE_CODE (var) == VAR_DECL && handled_type (TREE_TYPE (var))) ++ res = false; ++ } ++ if (!res) ++ return false; ++ ++ for (unsigned j = 1; j < num_ssa_names; ++j) ++ { ++ tree name = ssa_name (j); ++ if (!name || has_zero_uses (name) || virtual_operand_p (name)) ++ continue; ++ tree var = SSA_NAME_VAR (name); ++ if (var && TREE_CODE (var) == VAR_DECL && is_global_var (var)) ++ return false; ++ } ++ return true; ++} ++ ++/* Check whether the function with the void* parameter and uses the input node ++ safely. ++ In these functions only component_ref can be used to dereference the last ++ layer of the input structure pointer. The hack operation pointer offset ++ after type cast cannot be used. ++*/ ++ ++bool ++is_safe_func_with_void_ptr_parm (cgraph_node *node) ++{ ++ if (!filter_func (node)) ++ return false; ++ ++ /* Distinguish Recursive Callers ++ normal_callers: main () ++ { spec_qsort.constprop (_649, _651); } ++ definition: spec_qsort.constprop (void * a, size_t n) ++ recursive_callers: { spec_qsort.constprop (a_1, _139); } */ ++ auto_vec callers = node->collect_callers (); ++ auto_vec normal_callers; ++ for (unsigned i = 0; i < callers.length (); i++) ++ { ++ if (callers[i]->caller != node) ++ normal_callers.safe_push (callers[i]); ++ } ++ if (normal_callers.length () == 0) ++ return false; ++ ++ for (unsigned i = 0; i < normal_callers.length (); i++) ++ { ++ if (!check_each_call (node, normal_callers[i])) ++ return false; ++ } ++ return true; ++} ++ ++/* Return the escape type which corresponds to if ++ this is an volatile type, an array type or a pointer ++ to a pointer type. */ ++ ++static escape_type ++escape_type_volatile_array_or_ptrptr (tree type) ++{ ++ if (isvolatile_type (type)) ++ return escape_volatile; ++ if (isarraytype (type)) ++ return escape_array; ++ if (isptrptr (type) && (current_mode != STRUCT_REORDER_FIELDS)) ++ return escape_ptr_ptr; ++ return does_not_escape; ++} ++ ++/* Record field type. */ ++ ++void ++ipa_struct_reorg::record_field_type (tree field, srtype *base_srtype) ++{ ++ tree field_type = TREE_TYPE (field); ++ /* The uid of the type in the structure is different ++ from that outside the structure. */ ++ srtype *field_srtype = record_type (inner_type (field_type)); ++ srfield *field_srfield = base_srtype->find_field (int_byte_position (field)); ++ /* We might have an variable sized type which we don't set the handle. */ ++ if (field_srfield) ++ { ++ field_srfield->type = field_srtype; ++ field_srtype->add_field_site (field_srfield); ++ } ++ if (field_srtype == base_srtype && current_mode != COMPLETE_STRUCT_RELAYOUT ++ && current_mode != STRUCT_REORDER_FIELDS) ++ base_srtype->mark_escape (escape_rescusive_type, NULL); ++ /* Types of non-pointer field are difficult to track the correctness ++ of the rewrite when it used by the escaped type. */ ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && TREE_CODE (field_type) == RECORD_TYPE) ++ field_srtype->mark_escape (escape_instance_field, NULL); ++} ++ ++/* Record structure all field types. */ ++ ++void ++ipa_struct_reorg::record_struct_field_types (tree base_type, ++ srtype *base_srtype) ++{ ++ for (tree field = TYPE_FIELDS (base_type); field; field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL) ++ { ++ tree field_type = TREE_TYPE (field); ++ process_union (field_type); ++ if (TREE_CODE (inner_type (field_type)) == UNION_TYPE ++ || TREE_CODE (inner_type (field_type)) == QUAL_UNION_TYPE) ++ base_srtype->mark_escape (escape_union, NULL); ++ if (isvolatile_type (field_type)) ++ base_srtype->mark_escape (escape_volatile, NULL); ++ escape_type e = escape_type_volatile_array_or_ptrptr (field_type); ++ if (e != does_not_escape) ++ base_srtype->mark_escape (e, NULL); ++ /* Types of non-pointer field are difficult to track the correctness ++ of the rewrite when it used by the escaped type. */ ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && TREE_CODE (field_type) == RECORD_TYPE) ++ base_srtype->mark_escape (escape_instance_field, NULL); ++ if (handled_type (field_type)) ++ record_field_type (field, base_srtype); ++ } ++ } ++} ++ ++/* Record TYPE if not already recorded. */ ++ ++srtype * ++ipa_struct_reorg::record_type (tree type) ++{ ++ unsigned typeuid; ++ ++ /* Get the main variant as we are going ++ to record that type only. */ ++ type = TYPE_MAIN_VARIANT (type); ++ typeuid = TYPE_UID (type); ++ ++ srtype *type1; ++ ++ type1 = find_type (type); ++ if (type1) ++ return type1; ++ ++ /* If already done recording just return NULL. */ ++ if (done_recording) ++ return NULL; ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "Recording new type: %u.\n", typeuid); ++ const char *type_name = get_type_name (type); ++ if (type_name == NULL) ++ fprintf (dump_file, "Recording new type NULL name\n"); ++ else ++ fprintf (dump_file, "Recording new type name: %s.\n", type_name); ++ } ++ ++ type1 = new srtype (type); ++ types.safe_push (type1); ++ ++ /* If the type has an user alignment set, ++ that means the user most likely already setup the type. */ ++ if (TYPE_USER_ALIGN (type)) ++ type1->mark_escape (escape_user_alignment, NULL); ++ ++ record_struct_field_types (type, type1); ++ ++ return type1; ++} ++ ++/* Mark TYPE as escaping with ESCAPES as the reason. */ ++ ++void ++ipa_struct_reorg::mark_type_as_escape (tree type, ++ escape_type escapes, ++ gimple *stmt) ++{ ++ if (handled_type (type)) ++ { ++ srtype *stype = record_type (inner_type (type)); ++ ++ if (!stype) ++ return; ++ ++ stype->mark_escape (escapes, stmt); ++ } ++} ++ ++/* Maybe process the union of type TYPE, such that marking all of the fields' ++ types as being escaping. */ ++ ++void ++ipa_struct_reorg::process_union (tree type) ++{ ++ static hash_set unions_recorded; ++ ++ type = inner_type (type); ++ if (TREE_CODE (type) != UNION_TYPE ++ && TREE_CODE (type) != QUAL_UNION_TYPE) ++ return; ++ ++ type = TYPE_MAIN_VARIANT (type); ++ ++ /* We already processed this type. */ ++ if (unions_recorded.add (type)) ++ return; ++ ++ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) ++ { ++ if (TREE_CODE (field) == FIELD_DECL) ++ { ++ mark_type_as_escape (TREE_TYPE (field), escape_union); ++ process_union (TREE_TYPE (field)); ++ } ++ } ++} ++ ++/* Used by record_var function as a callback to walk_tree. ++ Mark the type as escaping if it has expressions which ++ cannot be converted for global initializations. */ ++ ++static tree ++record_init_types (tree *tp, int *walk_subtrees, void *data) ++{ ++ ipa_struct_reorg *c = (ipa_struct_reorg *)data; ++ switch (TREE_CODE (*tp)) ++ { ++ CASE_CONVERT: ++ case COMPONENT_REF: ++ case VIEW_CONVERT_EXPR: ++ case ARRAY_REF: ++ { ++ tree typeouter = TREE_TYPE (*tp); ++ tree typeinner = TREE_TYPE (TREE_OPERAND (*tp, 0)); ++ c->mark_type_as_escape (typeouter, escape_via_global_init); + c->mark_type_as_escape (typeinner, escape_via_global_init); + break; + } +@@ -1996,6 +2775,8 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) + + process_union (TREE_TYPE (decl)); + ++ /* Only the structure type RECORD_TYPE is recorded. ++ Therefore, the void* type is filtered out. */ + if (handled_type (TREE_TYPE (decl))) + { + type = record_type (inner_type (TREE_TYPE (decl))); +@@ -2035,7 +2816,8 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) + + /* Separate instance is hard to trace in complete struct + relayout optimization. */ +- if (current_mode == COMPLETE_STRUCT_RELAYOUT ++ if ((current_mode == COMPLETE_STRUCT_RELAYOUT ++ || current_mode == STRUCT_REORDER_FIELDS) + && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) + e = escape_separate_instance; + +@@ -2078,11 +2860,9 @@ ipa_struct_reorg::find_var (tree expr, gimple *stmt) + { + tree r = TREE_OPERAND (expr, 0); + tree orig_type = TREE_TYPE (expr); +- if (handled_component_p (r) +- || TREE_CODE (r) == MEM_REF) ++ if (handled_component_p (r) || TREE_CODE (r) == MEM_REF) + { +- while (handled_component_p (r) +- || TREE_CODE (r) == MEM_REF) ++ while (handled_component_p (r) || TREE_CODE (r) == MEM_REF) + { + if (TREE_CODE (r) == VIEW_CONVERT_EXPR) + { +@@ -2114,8 +2894,10 @@ ipa_struct_reorg::find_var (tree expr, gimple *stmt) + srtype *type; + srfield *field; + bool realpart, imagpart, address; ++ bool escape_from_base = false; ++ /* The should_create flag is true, the declaration can be recorded. */ + get_type_field (expr, base, indirect, type, field, +- realpart, imagpart, address, true, true); ++ realpart, imagpart, address, escape_from_base, true, true); + } + + void +@@ -2132,36 +2914,79 @@ ipa_struct_reorg::find_vars (gimple *stmt) + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + find_var (gimple_assign_lhs (stmt), stmt); ++ /* _2 = MEM[(struct arc_t * *)_1]; ++ records the right value _1 declaration. */ + find_var (gimple_assign_rhs1 (stmt), stmt); +- if (TREE_CODE (lhs) == SSA_NAME ++ ++ /* Add a safe func mechanism. */ ++ bool l_find = true; ++ bool r_find = true; ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ l_find = !(current_function->is_safe_func ++ && TREE_CODE (lhs) == SSA_NAME ++ && is_from_void_ptr_parm (lhs)); ++ r_find = !(current_function->is_safe_func ++ && TREE_CODE (rhs) == SSA_NAME ++ && is_from_void_ptr_parm (rhs)); ++ } ++ ++ if ((TREE_CODE (lhs) == SSA_NAME) + && VOID_POINTER_P (TREE_TYPE (lhs)) +- && handled_type (TREE_TYPE (rhs))) ++ && handled_type (TREE_TYPE (rhs)) && l_find) + { + srtype *t = find_type (inner_type (TREE_TYPE (rhs))); + srdecl *d = find_decl (lhs); + if (!d && t) + { +- current_function->record_decl (t, lhs, -1); ++ current_function->record_decl (t, lhs, -1, ++ isptrptr (TREE_TYPE (rhs)) ? TREE_TYPE (rhs) : NULL); + tree var = SSA_NAME_VAR (lhs); + if (var && VOID_POINTER_P (TREE_TYPE (var))) +- current_function->record_decl (t, var, -1); ++ current_function->record_decl (t, var, -1, ++ isptrptr (TREE_TYPE (rhs)) ? TREE_TYPE (rhs) : NULL); + } + } ++ /* Find void ssa_name such as: ++ void * _1; struct arc * _2; ++ _2 = _1 + _3; _1 = calloc (100, 40). */ + if (TREE_CODE (rhs) == SSA_NAME + && VOID_POINTER_P (TREE_TYPE (rhs)) +- && handled_type (TREE_TYPE (lhs))) ++ && handled_type (TREE_TYPE (lhs)) && r_find) + { + srtype *t = find_type (inner_type (TREE_TYPE (lhs))); + srdecl *d = find_decl (rhs); + if (!d && t) + { +- current_function->record_decl (t, rhs, -1); ++ current_function->record_decl (t, rhs, -1, ++ isptrptr (TREE_TYPE (lhs)) ? TREE_TYPE (lhs) : NULL); + tree var = SSA_NAME_VAR (rhs); + if (var && VOID_POINTER_P (TREE_TYPE (var))) +- current_function->record_decl (t, var, -1); ++ current_function->record_decl (t, var, -1, ++ isptrptr (TREE_TYPE (lhs)) ? TREE_TYPE (lhs) : NULL); + } + } + } ++ else if ((current_mode == STRUCT_REORDER_FIELDS) ++ && (gimple_assign_rhs_code (stmt) == LE_EXPR ++ || gimple_assign_rhs_code (stmt) == LT_EXPR ++ || gimple_assign_rhs_code (stmt) == GE_EXPR ++ || gimple_assign_rhs_code (stmt) == GT_EXPR)) ++ { ++ find_var (gimple_assign_lhs (stmt), stmt); ++ find_var (gimple_assign_rhs1 (stmt), stmt); ++ find_var (gimple_assign_rhs2 (stmt), stmt); ++ } ++ /* Find void ssa_name from stmt such as: _2 = _1 - old_arcs_1. */ ++ else if ((current_mode == STRUCT_REORDER_FIELDS) ++ && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR ++ && types_compatible_p ( ++ TYPE_MAIN_VARIANT (TREE_TYPE (gimple_assign_rhs1 (stmt))), ++ TYPE_MAIN_VARIANT (TREE_TYPE (gimple_assign_rhs2 (stmt))))) ++ { ++ find_var (gimple_assign_rhs1 (stmt), stmt); ++ find_var (gimple_assign_rhs2 (stmt), stmt); ++ } + else + { + /* Because we won't handle these stmts in rewrite phase, +@@ -2232,27 +3057,134 @@ ipa_struct_reorg::find_vars (gimple *stmt) + } + } + +-/* Maybe record access of statement for further analaysis. */ ++/* Maybe record access of statement for further analaysis. */ ++ ++void ++ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt) ++{ ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_ASSIGN: ++ maybe_record_assign (node, as_a (stmt)); ++ break; ++ case GIMPLE_CALL: ++ maybe_record_call (node, as_a (stmt)); ++ break; ++ case GIMPLE_DEBUG: ++ break; ++ case GIMPLE_GOTO: ++ case GIMPLE_SWITCH: ++ break; ++ default: ++ break; ++ } ++} ++ ++/* Calculate the multiplier. */ ++ ++static bool ++calculate_mult_num (tree arg, tree *num, tree struct_size) ++{ ++ gcc_assert (TREE_CODE (arg) == INTEGER_CST); ++ bool sign = false; ++ HOST_WIDE_INT size = TREE_INT_CST_LOW (arg); ++ if (size < 0) ++ { ++ size = -size; ++ sign = true; ++ } ++ tree arg2 = build_int_cst (TREE_TYPE (arg), size); ++ if (integer_zerop (size_binop (FLOOR_MOD_EXPR, arg2, struct_size))) ++ { ++ tree number = size_binop (FLOOR_DIV_EXPR, arg2, struct_size); ++ if (sign) ++ number = build_int_cst (TREE_TYPE (number), -tree_to_shwi (number)); ++ *num = number; ++ return true; ++ } ++ return false; ++} ++ ++/* Trace and calculate the multiplier of PLUS_EXPR. */ ++ ++static bool ++trace_calculate_plus (gimple *size_def_stmt, tree *num, tree struct_size) ++{ ++ gcc_assert (gimple_assign_rhs_code (size_def_stmt) == PLUS_EXPR); ++ ++ tree num1 = NULL_TREE; ++ tree num2 = NULL_TREE; ++ tree arg0 = gimple_assign_rhs1 (size_def_stmt); ++ tree arg1 = gimple_assign_rhs2 (size_def_stmt); ++ if (!is_result_of_mult (arg0, &num1, struct_size) || num1 == NULL_TREE) ++ return false; ++ if (!is_result_of_mult (arg1, &num2, struct_size) || num2 == NULL_TREE) ++ return false; ++ *num = size_binop (PLUS_EXPR, num1, num2); ++ return true; ++} ++ ++/* Trace and calculate the multiplier of MULT_EXPR. */ ++ ++static bool ++trace_calculate_mult (gimple *size_def_stmt, tree *num, tree struct_size) ++{ ++ gcc_assert (gimple_assign_rhs_code (size_def_stmt) == MULT_EXPR); ++ ++ tree arg0 = gimple_assign_rhs1 (size_def_stmt); ++ tree arg1 = gimple_assign_rhs2 (size_def_stmt); ++ tree num1 = NULL_TREE; ++ ++ if (is_result_of_mult (arg0, &num1, struct_size) && num1 != NULL_TREE) ++ { ++ *num = size_binop (MULT_EXPR, arg1, num1); ++ return true; ++ } ++ if (is_result_of_mult (arg1, &num1, struct_size) && num1 != NULL_TREE) ++ { ++ *num = size_binop (MULT_EXPR, arg0, num1); ++ return true; ++ } ++ *num = NULL_TREE; ++ return false; ++} ++ ++/* Trace and calculate the multiplier of NEGATE_EXPR. */ ++ ++static bool ++trace_calculate_negate (gimple *size_def_stmt, tree *num, tree struct_size) ++{ ++ gcc_assert (gimple_assign_rhs_code (size_def_stmt) == NEGATE_EXPR); ++ ++ /* Support NEGATE_EXPR trace: _3 = -_2; _2 = _1 * 72. */ ++ tree num1 = NULL_TREE; ++ tree arg0 = gimple_assign_rhs1 (size_def_stmt); ++ if (!is_result_of_mult (arg0, &num1, struct_size) || num1 == NULL_TREE) ++ return false; ++ tree num0 = build_int_cst (TREE_TYPE (num1), -1); ++ *num = size_binop (MULT_EXPR, num0, num1); ++ return true; ++} ++ ++/* Trace and calculate the multiplier of POINTER_DIFF_EXPR. */ + +-void +-ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt) ++static bool ++trace_calculate_diff (gimple *size_def_stmt, tree *num) + { +- switch (gimple_code (stmt)) ++ gcc_assert (gimple_assign_rhs_code (size_def_stmt) == NOP_EXPR); ++ ++ /* Support POINTER_DIFF_EXPR trace: ++ _3 = (long unsigned int) _2; _2 = _1 - old_arcs_1. */ ++ tree arg = gimple_assign_rhs1 (size_def_stmt); ++ size_def_stmt = SSA_NAME_DEF_STMT (arg); ++ if (size_def_stmt && is_gimple_assign (size_def_stmt) ++ && gimple_assign_rhs_code (size_def_stmt) == POINTER_DIFF_EXPR) + { +- case GIMPLE_ASSIGN: +- maybe_record_assign (node, as_a (stmt)); +- break; +- case GIMPLE_CALL: +- maybe_record_call (node, as_a (stmt)); +- break; +- case GIMPLE_DEBUG: +- break; +- case GIMPLE_GOTO: +- case GIMPLE_SWITCH: +- break; +- default: +- break; ++ *num = NULL_TREE; ++ return true; + } ++ *num = NULL_TREE; ++ return false; + } + + /* This function checks whether ARG is a result of multiplication +@@ -2269,26 +3201,8 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + + /* If we have a integer, just check if it is a multiply of STRUCT_SIZE. */ + if (TREE_CODE (arg) == INTEGER_CST) +- { +- bool sign = false; +- HOST_WIDE_INT size = TREE_INT_CST_LOW (arg); +- if (size < 0) +- { +- size = -size; +- sign = true; +- } +- tree arg2 = build_int_cst (TREE_TYPE (arg), size); +- if (integer_zerop (size_binop (FLOOR_MOD_EXPR, arg2, struct_size))) +- { +- tree number = size_binop (FLOOR_DIV_EXPR, arg2, struct_size); +- if (sign) +- number = build_int_cst (TREE_TYPE (number), +- -tree_to_shwi (number)); +- *num = number; +- return true; +- } +- return false; +- } ++ return calculate_mult_num (arg, num, struct_size); ++ + gimple *size_def_stmt = SSA_NAME_DEF_STMT (arg); + + /* If the allocation statement was of the form +@@ -2304,43 +3218,20 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + return false; + + // FIXME: this should handle SHIFT also. +- if (gimple_assign_rhs_code (size_def_stmt) == PLUS_EXPR) +- { +- tree num1, num2; +- tree arg0 = gimple_assign_rhs1 (size_def_stmt); +- tree arg1 = gimple_assign_rhs2 (size_def_stmt); +- if (!is_result_of_mult (arg0, &num1, struct_size)) +- return false; +- if (!is_result_of_mult (arg1, &num2, struct_size)) +- return false; +- *num = size_binop (PLUS_EXPR, num1, num2); +- return true; +- } +- else if (gimple_assign_rhs_code (size_def_stmt) == MULT_EXPR) +- { +- tree arg0 = gimple_assign_rhs1 (size_def_stmt); +- tree arg1 = gimple_assign_rhs2 (size_def_stmt); +- tree num1; +- +- if (is_result_of_mult (arg0, &num1, struct_size)) +- { +- *num = size_binop (MULT_EXPR, arg1, num1); +- return true; +- } +- if (is_result_of_mult (arg1, &num1, struct_size)) +- { +- *num = size_binop (MULT_EXPR, arg0, num1); +- return true; +- } +- +- *num = NULL_TREE; +- return false; +- } +- else if (gimple_assign_rhs_code (size_def_stmt) == SSA_NAME) ++ tree_code rhs_code = gimple_assign_rhs_code (size_def_stmt); ++ if (rhs_code == PLUS_EXPR) ++ return trace_calculate_plus (size_def_stmt, num, struct_size); ++ else if (rhs_code == MULT_EXPR) ++ return trace_calculate_mult (size_def_stmt, num, struct_size); ++ else if (rhs_code == SSA_NAME) + { + arg = gimple_assign_rhs1 (size_def_stmt); + size_def_stmt = SSA_NAME_DEF_STMT (arg); + } ++ else if (rhs_code == NEGATE_EXPR && current_mode == STRUCT_REORDER_FIELDS) ++ return trace_calculate_negate (size_def_stmt, num, struct_size); ++ else if (rhs_code == NOP_EXPR && current_mode == STRUCT_REORDER_FIELDS) ++ return trace_calculate_diff (size_def_stmt, num); + else + { + *num = NULL_TREE; +@@ -2357,18 +3248,22 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + bool + ipa_struct_reorg::handled_allocation_stmt (gimple *stmt) + { +- if (current_mode == COMPLETE_STRUCT_RELAYOUT ++ if ((current_mode == STRUCT_REORDER_FIELDS) ++ && (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))) ++ return true; ++ if ((current_mode == COMPLETE_STRUCT_RELAYOUT) + && gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) + return true; +- +- if (current_mode != COMPLETE_STRUCT_RELAYOUT) +- if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_ALIGNED_ALLOC) +- || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA) +- || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN)) +- return true; ++ if ((current_mode == NORMAL) ++ && (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALIGNED_ALLOC) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA) ++ || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))) ++ return true; + return false; + } + +@@ -2376,7 +3271,7 @@ ipa_struct_reorg::handled_allocation_stmt (gimple *stmt) + elements in the array allocated. */ + + tree +-ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt) ++ipa_struct_reorg::allocate_size (srtype *type, srdecl *decl, gimple *stmt) + { + if (!stmt + || gimple_code (stmt) != GIMPLE_CALL +@@ -2396,6 +3291,10 @@ ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt) + + tree struct_size = TYPE_SIZE_UNIT (type->type); + ++ /* Specify the correct size to relax multi-layer pointer. */ ++ if (TREE_CODE (decl->decl) == SSA_NAME && isptrptr (decl->orig_type)) ++ struct_size = TYPE_SIZE_UNIT (decl->orig_type); ++ + tree size = gimple_call_arg (stmt, 0); + + if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) +@@ -2409,8 +3308,10 @@ ipa_struct_reorg::allocate_size (srtype *type, gimple *stmt) + the size of structure. */ + if (operand_equal_p (arg1, struct_size, 0)) + return size; +- /* ??? Check that first argument is a constant equal to +- the size of structure. */ ++ /* ??? Check that first argument is a constant ++ equal to the size of structure. */ ++ /* If the allocated number is equal to the value of struct_size, ++ the value of arg1 is changed to the allocated number. */ + if (operand_equal_p (size, struct_size, 0)) + return arg1; + if (dump_file && (dump_flags & TDF_DETAILS)) +@@ -2453,10 +3354,16 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, + + if (!d) + { ++ /* MEM[(struct arc *)_1].head = _2; _2 = calloc (100, 104). */ + if (VOID_POINTER_P (TREE_TYPE (side)) + && TREE_CODE (side) == SSA_NAME) +- current_function->record_decl (type, side, -1); ++ { ++ /* The type is other, the declaration is side. */ ++ current_function->record_decl (type, side, -1, ++ isptrptr (TREE_TYPE (other)) ? TREE_TYPE (other) : NULL); ++ } + else ++ /* *_1 = &MEM[(void *)&x + 8B]. */ + type->mark_escape (escape_cast_another_ptr, stmt); + } + else if (type != d->type) +@@ -2464,6 +3371,17 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, + type->mark_escape (escape_cast_another_ptr, stmt); + d->type->mark_escape (escape_cast_another_ptr, stmt); + } ++ /* x_1 = y.x_nodes; void *x; ++ Directly mark the structure pointer type assigned ++ to the void* variable as escape. */ ++ else if (current_mode == STRUCT_REORDER_FIELDS ++ && TREE_CODE (side) == SSA_NAME ++ && VOID_POINTER_P (TREE_TYPE (side)) ++ && SSA_NAME_VAR (side) ++ && VOID_POINTER_P (TREE_TYPE (SSA_NAME_VAR (side)))) ++ mark_type_as_escape (TREE_TYPE (other), escape_cast_void, stmt); ++ ++ check_ptr_layers (side, other, stmt); + } + + /* Record accesses in an assignment statement STMT. */ +@@ -2486,8 +3404,12 @@ ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt) + if (!handled_type (TREE_TYPE (lhs))) + return; + /* Check if rhs2 is a multiplication of the size of the type. */ ++ /* The size adjustment and judgment of multi-layer pointers ++ are added. */ + if (is_result_of_mult (rhs2, &num, +- TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs))))) ++ isptrptr (TREE_TYPE (lhs)) ++ ? TYPE_SIZE_UNIT (TREE_TYPE (lhs)) ++ : TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs))))) + { + record_stmt_expr (lhs, node, stmt); + record_stmt_expr (rhs1, node, stmt); +@@ -2525,9 +3447,8 @@ ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt) + } + + static bool +-check_mem_ref_offset (tree expr) ++check_mem_ref_offset (tree expr, tree *num) + { +- tree num = NULL; + bool ret = false; + + if (TREE_CODE (expr) != MEM_REF) +@@ -2538,15 +3459,18 @@ check_mem_ref_offset (tree expr) + tree tmp = TREE_OPERAND (expr, 0); + if (TREE_CODE (tmp) == ADDR_EXPR) + tmp = TREE_OPERAND (tmp, 0); +- tree size = TYPE_SIZE_UNIT (inner_type (TREE_TYPE (tmp))); +- ret = is_result_of_mult (field_off, &num, size); ++ /* Specify the correct size for the multi-layer pointer. */ ++ tree size = isptrptr (TREE_TYPE (tmp)) ++ ? TYPE_SIZE_UNIT (TREE_TYPE (tmp)) ++ : TYPE_SIZE_UNIT (inner_type (TREE_TYPE (tmp))); ++ ret = is_result_of_mult (field_off, num, size); + return ret; + } + + static tree + get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, + bool &realpart, bool &imagpart, +- tree &accesstype) ++ tree &accesstype, tree *num) + { + offset = 0; + realpart = false; +@@ -2569,22 +3493,29 @@ get_ref_base_and_offset (tree &e, HOST_WIDE_INT &offset, + { + case COMPONENT_REF: + { ++ /* x.a = _1; If expr is the lvalue of stmt, ++ then field type is FIELD_DECL - POINTER_TYPE - RECORD_TYPE. */ + tree field = TREE_OPERAND (expr, 1); + tree field_off = byte_position (field); + if (TREE_CODE (field_off) != INTEGER_CST) + return NULL; + offset += tree_to_shwi (field_off); ++ /* x.a = _1; If expr is the lvalue of stmt, ++ then expr type is VAR_DECL - RECORD_TYPE (fetch x) */ + expr = TREE_OPERAND (expr, 0); + accesstype = NULL; + break; + } + case MEM_REF: + { ++ /* _2 = MEM[(struct s * *)_1]; ++ If expr is the right value of stmt, then field_off type is ++ INTEGER_CST - POINTER_TYPE - POINTER_TYPE - RECORD_TYPE. */ + tree field_off = TREE_OPERAND (expr, 1); + gcc_assert (TREE_CODE (field_off) == INTEGER_CST); + /* So we can mark the types as escaping if different. */ + accesstype = TREE_TYPE (field_off); +- if (!check_mem_ref_offset (expr)) ++ if (!check_mem_ref_offset (expr, num)) + offset += tree_to_uhwi (field_off); + return TREE_OPERAND (expr, 0); + } +@@ -2626,10 +3557,11 @@ ipa_struct_reorg::wholeaccess (tree expr, tree base, + bool + ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + srtype *&type, srfield *&field, +- bool &realpart, bool &imagpart, +- bool &address, bool should_create, ++ bool &realpart, bool &imagpart, bool &address, ++ bool &escape_from_base, bool should_create, + bool can_escape) + { ++ tree num = NULL_TREE; + HOST_WIDE_INT offset; + tree accesstype; + address = false; +@@ -2641,8 +3573,9 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + mark_as_bit_field = true; + } + ++ /* Ref is classified into two types: COMPONENT_REF or MER_REF. */ + base = get_ref_base_and_offset (expr, offset, realpart, imagpart, +- accesstype); ++ accesstype, &num); + + /* Variable access, unkown type. */ + if (base == NULL) +@@ -2680,6 +3613,8 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + if (!t) + return false; + } ++ /* If no such decl is finded ++ or orig_type is not added to this decl, then add it. */ + else if (!d && accesstype) + { + if (!should_create) +@@ -2691,15 +3626,52 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + t = record_type (inner_type (accesstype)); + if (!t || t->has_escaped ()) + return false; +- /* If base is not void* mark the type as escaping. */ +- if (!VOID_POINTER_P (TREE_TYPE (base))) ++ /* If base is not void* mark the type as escaping. ++ release INTEGER_TYPE cast to struct pointer. ++ (If t has escpaed above, then directly returns ++ and doesn't mark escape follow.). */ ++ /* _1 = MEM[(struct arc_t * *)a_1]. ++ then base a_1: ssa_name - pointer_type - integer_type. */ ++ if (current_mode == STRUCT_REORDER_FIELDS) + { +- gcc_assert (can_escape); +- t->mark_escape (escape_cast_another_ptr, NULL); +- return false; ++ bool is_int_ptr = POINTER_TYPE_P (TREE_TYPE (base)) ++ && (TREE_CODE (inner_type (TREE_TYPE (base))) ++ == INTEGER_TYPE); ++ if (!(VOID_POINTER_P (TREE_TYPE (base)) ++ || (current_function->is_safe_func && is_int_ptr))) ++ { ++ gcc_assert (can_escape); ++ t->mark_escape (escape_cast_another_ptr, NULL); ++ return false; ++ } ++ if (TREE_CODE (base) == SSA_NAME ++ && !(current_function->is_safe_func && is_int_ptr)) ++ { ++ /* Add a safe func mechanism. */ ++ if (!(current_function->is_safe_func ++ && is_from_void_ptr_parm (base))) ++ /* Add auxiliary information of the multi-layer pointer ++ type. */ ++ current_function->record_decl (t, base, -1, ++ isptrptr (accesstype) ? accesstype : NULL); ++ } ++ } ++ else ++ { ++ if (!(VOID_POINTER_P (TREE_TYPE (base)))) ++ { ++ gcc_assert (can_escape); ++ t->mark_escape (escape_cast_another_ptr, NULL); ++ return false; ++ } ++ if (TREE_CODE (base) == SSA_NAME) ++ { ++ /* Add auxiliary information of the multi-layer pointer ++ type. */ ++ current_function->record_decl (t, base, -1, ++ isptrptr (accesstype) ? accesstype : NULL); ++ } + } +- if (TREE_CODE (base) == SSA_NAME) +- current_function->record_decl (t, base, -1); + } + else if (!d) + return false; +@@ -2707,7 +3679,10 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + t = d->type; + + if (t->has_escaped ()) ++ { ++ escape_from_base = true; + return false; ++ } + + if (mark_as_bit_field) + { +@@ -2716,6 +3691,17 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + return false; + } + ++ /* Escape the operation of fetching field with pointer offset such as: ++ *(&(t->right)) = malloc (0); -> MEM[(struct node * *)_1 + 8B] = malloc (0); ++ */ ++ if (current_mode != NORMAL ++ && (TREE_CODE (expr) == MEM_REF) && (offset != 0)) ++ { ++ gcc_assert (can_escape); ++ t->mark_escape (escape_non_multiply_size, NULL); ++ return false; ++ } ++ + if (wholeaccess (expr, base, accesstype, t)) + { + field = NULL; +@@ -2733,7 +3719,6 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + print_generic_expr (dump_file, expr); + fprintf (dump_file, "\n"); + print_generic_expr (dump_file, base); +- fprintf (dump_file, "\n"); + } + gcc_assert (can_escape); + t->mark_escape (escape_unkown_field, NULL); +@@ -2747,9 +3732,8 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + print_generic_expr (dump_file, f->fieldtype); + fprintf (dump_file, "\naccess type = "); + print_generic_expr (dump_file, TREE_TYPE (expr)); +- fprintf (dump_file, "original expr = "); ++ fprintf (dump_file, "\noriginal expr = "); + print_generic_expr (dump_file, expr); +- fprintf (dump_file, "\n"); + } + gcc_assert (can_escape); + t->mark_escape (escape_unkown_field, NULL); +@@ -2772,8 +3756,9 @@ ipa_struct_reorg::mark_expr_escape (tree expr, escape_type escapes, + srtype *type; + srfield *field; + bool realpart, imagpart, address; ++ bool escape_from_base = false; + if (!get_type_field (expr, base, indirect, type, field, +- realpart, imagpart, address)) ++ realpart, imagpart, address, escape_from_base)) + return; + + type->mark_escape (escapes, stmt); +@@ -2846,10 +3831,23 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt) + gimple_call_arg (stmt, i)); + if (d) + d->type->mark_escape (escapes, stmt); ++ ++ if (escapes == escape_external_function ++ && !gimple_call_builtin_p (stmt, BUILT_IN_MEMSET)) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "escape_external_function: "); ++ print_gimple_stmt (dump_file, stmt, 0); ++ } ++ if (d) ++ ext_func_types.safe_push (d->type); ++ } + } + return; + } + ++ /* Get func param it's tree_list. */ + argtype = TYPE_ARG_TYPES (gimple_call_fntype (stmt)); + for (unsigned i = 0; i < gimple_call_num_args (stmt); i++) + { +@@ -2857,9 +3855,14 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt) + if (argtype) + { + tree argtypet = TREE_VALUE (argtype); +- if (!free_or_realloc ++ /* callee_func (_1, _2); ++ Check the callee func, instead of current func. */ ++ if (!(free_or_realloc ++ || (current_mode == STRUCT_REORDER_FIELDS ++ && safe_functions.contains ( ++ node->get_edge (stmt)->callee))) + && VOID_POINTER_P (argtypet)) +- mark_type_as_escape (TREE_TYPE (arg), escape_cast_void); ++ mark_type_as_escape (TREE_TYPE (arg), escape_cast_void, stmt); + else + record_stmt_expr (arg, node, stmt); + } +@@ -2878,12 +3881,22 @@ ipa_struct_reorg::record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt) + srtype *type; + srfield *field; + bool realpart, imagpart, address; ++ bool escape_from_base = false; + if (!get_type_field (expr, base, indirect, type, field, +- realpart, imagpart, address)) ++ realpart, imagpart, address, escape_from_base)) + return; + +- if (!opt_for_fn (current_function_decl, flag_ipa_struct_reorg)) +- type->mark_escape (escape_non_optimize, stmt); ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ if (!opt_for_fn (current_function_decl, flag_ipa_reorder_fields)) ++ type->mark_escape (escape_non_optimize, stmt); ++ } ++ else ++ { ++ if (!opt_for_fn (current_function_decl, flag_ipa_struct_reorg)) ++ type->mark_escape (escape_non_optimize, stmt); ++ } ++ + + /* Record it. */ + type->add_access (new sraccess (stmt, node, type, field)); +@@ -2901,10 +3914,10 @@ ipa_struct_reorg::find_function (cgraph_node *node) + } + + void +-ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, +- vec &worklist, +- gimple *stmt) ++ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl, ++ vec &worklist, gimple *stmt) + { ++ srtype *type = decl->type; + if (integer_zerop (newdecl)) + return; + +@@ -2916,7 +3929,8 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, + type->mark_escape (escape_cast_another_ptr, stmt); + return; + } +- if (d->type == type) ++ if (d->type == type ++ && cmp_ptr_layers (TREE_TYPE (newdecl), TREE_TYPE (decl->decl))) + return; + + srtype *type1 = d->type; +@@ -2967,7 +3981,9 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srtype *type, + /* Only add to the worklist if the decl is a SSA_NAME. */ + if (TREE_CODE (newdecl) == SSA_NAME) + worklist.safe_push (d); +- if (d->type == type) ++ tree a_decl = d->orig_type ? d->orig_type : TREE_TYPE (newdecl); ++ tree b_decl = decl->orig_type ? decl->orig_type : TREE_TYPE (decl->decl); ++ if (d->type == type && cmp_ptr_layers (a_decl, b_decl)) + return; + + srtype *type1 = d->type; +@@ -3000,6 +4016,96 @@ ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type) + } + } + ++/* Check the definition of gimple assign. */ ++ ++void ++ipa_struct_reorg::check_definition_assign (srdecl *decl, ++ vec &worklist) ++{ ++ tree ssa_name = decl->decl; ++ srtype *type = decl->type; ++ gimple *stmt = SSA_NAME_DEF_STMT (ssa_name); ++ gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN); ++ /* a) if the SSA_NAME is sourced from a pointer plus, record the pointer and ++ check to make sure the addition was a multiple of the size. ++ check the pointer type too. */ ++ tree rhs = gimple_assign_rhs1 (stmt); ++ if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) ++ { ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree num = NULL_TREE; ++ /* Specify the correct size for the multi-layer pointer. */ ++ if (!is_result_of_mult (rhs2, &num, isptrptr (decl->orig_type) ++ ? TYPE_SIZE_UNIT (decl->orig_type) ++ : TYPE_SIZE_UNIT (type->type))) ++ type->mark_escape (escape_non_multiply_size, stmt); ++ ++ if (TREE_CODE (rhs) == SSA_NAME) ++ check_type_and_push (rhs, decl, worklist, stmt); ++ return; ++ } ++ ++ if (gimple_assign_rhs_code (stmt) == MAX_EXPR ++ || gimple_assign_rhs_code (stmt) == MIN_EXPR ++ || gimple_assign_rhs_code (stmt) == BIT_IOR_EXPR ++ || gimple_assign_rhs_code (stmt) == BIT_XOR_EXPR ++ || gimple_assign_rhs_code (stmt) == BIT_AND_EXPR) ++ { ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ if (TREE_CODE (rhs) == SSA_NAME) ++ check_type_and_push (rhs, decl, worklist, stmt); ++ if (TREE_CODE (rhs2) == SSA_NAME) ++ check_type_and_push (rhs2, decl, worklist, stmt); ++ return; ++ } ++ ++ /* Casts between pointers and integer are escaping. */ ++ if (gimple_assign_cast_p (stmt)) ++ { ++ type->mark_escape (escape_cast_int, stmt); ++ return; ++ } ++ ++ /* d) if the name is from a cast/assignment, make sure it is used as ++ that type or void* ++ i) If void* then push the ssa_name into worklist. */ ++ gcc_assert (gimple_assign_single_p (stmt)); ++ check_other_side (decl, rhs, stmt, worklist); ++ check_ptr_layers (decl->decl, rhs, stmt); ++} ++ ++/* Check the definition of gimple call. */ ++ ++void ++ipa_struct_reorg::check_definition_call (srdecl *decl, vec &worklist) ++{ ++ tree ssa_name = decl->decl; ++ srtype *type = decl->type; ++ gimple *stmt = SSA_NAME_DEF_STMT (ssa_name); ++ gcc_assert (gimple_code (stmt) == GIMPLE_CALL); ++ ++ /* For realloc, check the type of the argument. */ ++ if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)) ++ check_type_and_push (gimple_call_arg (stmt, 0), decl, worklist, stmt); ++ ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ if (!handled_allocation_stmt (stmt)) ++ type->mark_escape (escape_return, stmt); ++ if (!allocate_size (type, decl, stmt)) ++ type->mark_escape (escape_non_multiply_size, stmt); ++ } ++ else ++ { ++ if (!handled_allocation_stmt (stmt) ++ || !allocate_size (type, decl, stmt)) ++ type->mark_escape (escape_return, stmt); ++ } ++ ++ check_alloc_num (stmt, type); ++ return; ++} ++ + /* + 2) Check SSA_NAMEs for non type usages (source or use) (worlist of srdecl) + a) if the SSA_NAME is sourced from a pointer plus, record the pointer and +@@ -3029,9 +4135,12 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) + if (var + && TREE_CODE (var) == PARM_DECL + && VOID_POINTER_P (TREE_TYPE (ssa_name))) +- type->mark_escape (escape_cast_void, NULL); ++ type->mark_escape (escape_cast_void, SSA_NAME_DEF_STMT (ssa_name)); + return; + } ++ if (current_mode == STRUCT_REORDER_FIELDS && SSA_NAME_VAR (ssa_name) ++ && VOID_POINTER_P (TREE_TYPE (SSA_NAME_VAR (ssa_name)))) ++ type->mark_escape (escape_cast_void, SSA_NAME_DEF_STMT (ssa_name)); + gimple *stmt = SSA_NAME_DEF_STMT (ssa_name); + + /* +@@ -3039,17 +4148,7 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) + i) Add SSA_NAME (void*) to the worklist if allocated from realloc + */ + if (gimple_code (stmt) == GIMPLE_CALL) +- { +- /* For realloc, check the type of the argument. */ +- if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)) +- check_type_and_push (gimple_call_arg (stmt, 0), type, worklist, stmt); +- +- if (!handled_allocation_stmt (stmt) +- || !allocate_size (type, stmt)) +- type->mark_escape (escape_return, stmt); +- check_alloc_num (stmt, type); +- return; +- } ++ check_definition_call (decl, worklist); + /* If the SSA_NAME is sourced from an inline-asm, + just mark the type as escaping. */ + if (gimple_code (stmt) == GIMPLE_ASM) +@@ -3065,58 +4164,11 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) + { + for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++) + check_type_and_push (gimple_phi_arg_def (stmt, i), +- type, worklist, stmt); +- return; +- } +- +- gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN); +- /* +- a) if the SSA_NAME is sourced from a pointer plus, record the pointer and +- check to make sure the addition was a multiple of the size. +- check the pointer type too. +- */ +- +- tree rhs = gimple_assign_rhs1 (stmt); +- if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) +- { +- tree rhs2 = gimple_assign_rhs2 (stmt); +- tree num; +- if (!is_result_of_mult (rhs2, &num, TYPE_SIZE_UNIT (type->type))) +- type->mark_escape (escape_non_multiply_size, stmt); +- +- if (TREE_CODE (rhs) == SSA_NAME) +- check_type_and_push (rhs, type, worklist, stmt); +- return; +- } +- +- if (gimple_assign_rhs_code (stmt) == MAX_EXPR +- || gimple_assign_rhs_code (stmt) == MIN_EXPR +- || gimple_assign_rhs_code (stmt) == BIT_IOR_EXPR +- || gimple_assign_rhs_code (stmt) == BIT_XOR_EXPR +- || gimple_assign_rhs_code (stmt) == BIT_AND_EXPR) +- { +- tree rhs2 = gimple_assign_rhs2 (stmt); +- if (TREE_CODE (rhs) == SSA_NAME) +- check_type_and_push (rhs, type, worklist, stmt); +- if (TREE_CODE (rhs2) == SSA_NAME) +- check_type_and_push (rhs2, type, worklist, stmt); +- return; +- } +- +- /* Casts between pointers and integer are escaping. */ +- if (gimple_assign_cast_p (stmt)) +- { +- type->mark_escape (escape_cast_int, stmt); ++ decl, worklist, stmt); + return; + } +- +- /* +- d) if the name is from a cast/assignment, make sure it is used as that +- type or void* +- i) If void* then push the ssa_name into worklist +- */ +- gcc_assert (gimple_assign_single_p (stmt)); +- check_other_side (decl, rhs, stmt, worklist); ++ if (gimple_code (stmt) == GIMPLE_ASSIGN) ++ check_definition_assign (decl, worklist); + } + + /* Mark the types used by the inline-asm as escaping. +@@ -3149,45 +4201,121 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, + { + srtype *type = decl->type; + +- if (TREE_CODE (other) == SSA_NAME +- || DECL_P (other) ++ if (TREE_CODE (other) == SSA_NAME || DECL_P (other) + || TREE_CODE (other) == INTEGER_CST) + { +- check_type_and_push (other, type, worklist, stmt); ++ check_type_and_push (other, decl, worklist, stmt); ++ return; ++ } ++ ++ tree t = TREE_TYPE (other); ++ if (!handled_type (t)) ++ { ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ return; ++ } ++ ++ srtype *t1 = find_type (inner_type (t)); ++ if (t1 == type) ++ { ++ /* In Complete Struct Relayout, if lhs type is the same ++ as rhs type, we could return without any harm. */ ++ if (current_mode == COMPLETE_STRUCT_RELAYOUT) ++ return; ++ ++ tree base; ++ bool indirect; ++ srtype *type1; ++ srfield *field; ++ bool realpart, imagpart, address; ++ bool escape_from_base = false; ++ if (!get_type_field (other, base, indirect, type1, field, ++ realpart, imagpart, address, escape_from_base)) ++ { ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ /* Release INTEGER_TYPE cast to struct pointer. */ ++ bool cast_from_int_ptr = current_function->is_safe_func && base ++ && find_decl (base) == NULL && POINTER_TYPE_P (TREE_TYPE (base)) ++ && (TREE_CODE (inner_type (TREE_TYPE (base))) == INTEGER_TYPE); ++ ++ /* Add a safe func mechanism. */ ++ bool from_void_ptr_parm = current_function->is_safe_func ++ && TREE_CODE (base) == SSA_NAME && is_from_void_ptr_parm (base); ++ ++ /* Release type is used by a type which escapes. */ ++ if (escape_from_base || cast_from_int_ptr || from_void_ptr_parm) ++ return; ++ } ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ } ++ + return; + } + +- tree t = TREE_TYPE (other); +- if (!handled_type (t)) ++ if (t1) ++ t1->mark_escape (escape_cast_another_ptr, stmt); ++ ++ type->mark_escape (escape_cast_another_ptr, stmt); ++} ++ ++ ++/* Get the expr base. */ ++ ++void ++get_base (tree &base, tree expr) ++{ ++ if (TREE_CODE (expr) == MEM_REF) ++ base = TREE_OPERAND (expr, 0); ++ else if (TREE_CODE (expr) == COMPONENT_REF) ++ { ++ base = TREE_OPERAND (expr, 0); ++ base = (TREE_CODE (base) == MEM_REF) ? TREE_OPERAND (base, 0) : base; ++ } ++ else if (TREE_CODE (expr) == ADDR_EXPR) ++ base = TREE_OPERAND (expr, 0); ++} ++ ++/* Check whether the number of pointer layers of exprs is equal, ++ marking unequals as escape. */ ++ ++void ++ipa_struct_reorg::check_ptr_layers (tree a_expr, tree b_expr, gimple *stmt) ++{ ++ if (current_mode != STRUCT_REORDER_FIELDS || current_function->is_safe_func ++ || !(POINTER_TYPE_P (TREE_TYPE (a_expr))) ++ || !(POINTER_TYPE_P (TREE_TYPE (b_expr))) ++ || !handled_type (TREE_TYPE (a_expr)) ++ || !handled_type (TREE_TYPE (b_expr))) ++ return; ++ ++ tree a_base = a_expr; ++ tree b_base = b_expr; ++ get_base (a_base, a_expr); ++ get_base (b_base, b_expr); ++ ++ srdecl *a = find_decl (a_base); ++ srdecl *b = find_decl (b_base); ++ if (a && b == NULL && TREE_CODE (b_expr) != INTEGER_CST) + { +- type->mark_escape (escape_cast_another_ptr, stmt); ++ a->type->mark_escape (escape_cast_another_ptr, stmt); + return; + } +- +- srtype *t1 = find_type (inner_type (t)); +- if (t1 == type) ++ else if (b && a == NULL && TREE_CODE (a_expr) != INTEGER_CST) + { +- /* In Complete Struct Relayout, if lhs type is the same +- as rhs type, we could return without any harm. */ +- if (current_mode == COMPLETE_STRUCT_RELAYOUT) +- return; +- +- tree base; +- bool indirect; +- srtype *type1; +- srfield *field; +- bool realpart, imagpart, address; +- if (!get_type_field (other, base, indirect, type1, field, +- realpart, imagpart, address)) +- type->mark_escape (escape_cast_another_ptr, stmt); +- ++ b->type->mark_escape (escape_cast_another_ptr, stmt); + return; + } ++ else if (a == NULL && b == NULL) ++ return; + +- if (t1) +- t1->mark_escape (escape_cast_another_ptr, stmt); ++ if (cmp_ptr_layers (TREE_TYPE (a_expr), TREE_TYPE (b_expr))) ++ return; + +- type->mark_escape (escape_cast_another_ptr, stmt); ++ if (a) ++ a->type->mark_escape (escape_cast_another_ptr, stmt); ++ if (b) ++ b->type->mark_escape (escape_cast_another_ptr, stmt); + } + + void +@@ -3205,7 +4333,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + check to make sure they are used correctly. */ + if (gimple_code (stmt) == GIMPLE_PHI) + { +- check_type_and_push (gimple_phi_result (stmt), type, worklist, stmt); ++ check_type_and_push (gimple_phi_result (stmt), decl, worklist, stmt); + return; + } + +@@ -3221,10 +4349,15 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree rhs2 = gimple_cond_rhs (stmt); + tree orhs = rhs1; + enum tree_code code = gimple_cond_code (stmt); +- if (code != EQ_EXPR && code != NE_EXPR +- && (current_mode != COMPLETE_STRUCT_RELAYOUT +- || (code != LT_EXPR && code != LE_EXPR +- && code != GT_EXPR && code != GE_EXPR))) ++ if ((current_mode == NORMAL && (code != EQ_EXPR && code != NE_EXPR)) ++ || (current_mode == COMPLETE_STRUCT_RELAYOUT ++ && (code != EQ_EXPR && code != NE_EXPR ++ && code != LT_EXPR && code != LE_EXPR ++ && code != GT_EXPR && code != GE_EXPR)) ++ || (current_mode == STRUCT_REORDER_FIELDS ++ && (code != EQ_EXPR && code != NE_EXPR ++ && code != LT_EXPR && code != LE_EXPR ++ && code != GT_EXPR && code != GE_EXPR))) + { + mark_expr_escape (rhs1, escape_non_eq, stmt); + mark_expr_escape (rhs2, escape_non_eq, stmt); +@@ -3235,7 +4368,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + return; + if (TREE_CODE (orhs) != SSA_NAME) + mark_expr_escape (rhs1, escape_non_eq, stmt); +- check_type_and_push (orhs, type, worklist, stmt); ++ check_type_and_push (orhs, decl, worklist, stmt); + return; + } + +@@ -3254,9 +4387,14 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree rhs2 = gimple_assign_rhs2 (stmt); + tree orhs = rhs1; + enum tree_code code = gimple_assign_rhs_code (stmt); +- if (code != EQ_EXPR && code != NE_EXPR +- && (current_mode != COMPLETE_STRUCT_RELAYOUT +- || (code != LT_EXPR && code != LE_EXPR ++ if ((current_mode == NORMAL && (code != EQ_EXPR && code != NE_EXPR)) ++ || (current_mode == COMPLETE_STRUCT_RELAYOUT ++ && (code != EQ_EXPR && code != NE_EXPR ++ && code != LT_EXPR && code != LE_EXPR ++ && code != GT_EXPR && code != GE_EXPR)) ++ || (current_mode == STRUCT_REORDER_FIELDS ++ && (code != EQ_EXPR && code != NE_EXPR ++ && code != LT_EXPR && code != LE_EXPR + && code != GT_EXPR && code != GE_EXPR))) + { + mark_expr_escape (rhs1, escape_non_eq, stmt); +@@ -3268,7 +4406,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + return; + if (TREE_CODE (orhs) != SSA_NAME) + mark_expr_escape (rhs1, escape_non_eq, stmt); +- check_type_and_push (orhs, type, worklist, stmt); ++ check_type_and_push (orhs, decl, worklist, stmt); + return; + } + +@@ -3282,6 +4420,7 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + check_other_side (decl, lhs, stmt, worklist); + return; + } ++ check_ptr_layers (lhs, rhs, stmt); + } + + if (is_gimple_assign (stmt) +@@ -3291,9 +4430,26 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree lhs = gimple_assign_lhs (stmt); + tree num; + check_other_side (decl, lhs, stmt, worklist); +- if (!is_result_of_mult (rhs2, &num, TYPE_SIZE_UNIT (type->type))) ++ check_ptr_layers (lhs, decl->decl, stmt); ++ /* Specify the correct size for the multi-layer pointer. */ ++ if (!is_result_of_mult (rhs2, &num, isptrptr (decl->orig_type) ++ ? TYPE_SIZE_UNIT (decl->orig_type) ++ : TYPE_SIZE_UNIT (type->type))) + type->mark_escape (escape_non_multiply_size, stmt); + } ++ ++ if (is_gimple_assign (stmt) ++ && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR) ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree other = rhs1 == decl->decl ? rhs2 : rhs1; ++ ++ check_other_side (decl, other, stmt, worklist); ++ check_ptr_layers (decl->decl, other, stmt); ++ return; ++ } ++ + } + + /* +@@ -3360,17 +4516,43 @@ ipa_struct_reorg::record_function (cgraph_node *node) + if (DECL_PRESERVE_P (node->decl)) + escapes = escape_marked_as_used; + else if (!node->local) +- escapes = escape_visible_function; ++ { ++ if (current_mode != STRUCT_REORDER_FIELDS) ++ escapes = escape_visible_function; ++ if (current_mode == STRUCT_REORDER_FIELDS && node->externally_visible) ++ escapes = escape_visible_function; ++ } + else if (!node->can_change_signature) + escapes = escape_cannot_change_signature; + else if (!tree_versionable_function_p (node->decl)) + escapes = escape_noclonable_function; +- else if (!opt_for_fn (node->decl, flag_ipa_struct_reorg)) +- escapes = escape_non_optimize; ++ ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ if (!opt_for_fn (node->decl, flag_ipa_reorder_fields)) ++ escapes = escape_non_optimize; ++ } ++ else if (current_mode == NORMAL || current_mode == COMPLETE_STRUCT_RELAYOUT) ++ { ++ if (!opt_for_fn (node->decl, flag_ipa_struct_reorg)) ++ escapes = escape_non_optimize; ++ } + + basic_block bb; + gimple_stmt_iterator si; + ++ /* Add a safe func mechanism. */ ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ current_function->is_safe_func = safe_functions.contains (node); ++ if (dump_file) ++ { ++ fprintf (dump_file, "\nfunction %s/%u: is_safe_func = %d\n", ++ node->name (), node->order, ++ current_function->is_safe_func); ++ } ++ } ++ + /* Record the static chain decl. */ + if (fn->static_chain_decl) + { +@@ -3503,6 +4685,42 @@ ipa_struct_reorg::record_function (cgraph_node *node) + return sfn; + } + ++ ++/* For a function that contains the void* parameter and passes the structure ++ pointer, check whether the function uses the input node safely. ++ For these functions, the void* parameter and related ssa_name are not ++ recorded in record_function (), and the input structure type is not escaped. ++*/ ++ ++void ++ipa_struct_reorg::record_safe_func_with_void_ptr_parm () ++{ ++ cgraph_node *node = NULL; ++ FOR_EACH_FUNCTION (node) ++ { ++ if (!node->real_symbol_p ()) ++ continue; ++ if (node->definition) ++ { ++ if (!node->has_gimple_body_p () || node->inlined_to) ++ continue; ++ node->get_body (); ++ function *fn = DECL_STRUCT_FUNCTION (node->decl); ++ if (!fn) ++ continue; ++ push_cfun (fn); ++ if (is_safe_func_with_void_ptr_parm (node)) ++ { ++ safe_functions.add (node); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "\nfunction %s/%u is safe function.\n", ++ node->name (), node->order); ++ } ++ pop_cfun (); ++ } ++ } ++} ++ + /* Record all accesses for all types including global variables. */ + + void +@@ -3534,6 +4752,10 @@ ipa_struct_reorg::record_accesses (void) + record_var (var->decl, escapes); + } + ++ /* Add a safe func mechanism. */ ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ record_safe_func_with_void_ptr_parm (); ++ + FOR_EACH_FUNCTION (cnode) + { + if (!cnode->real_symbol_p ()) +@@ -3552,11 +4774,14 @@ ipa_struct_reorg::record_accesses (void) + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "all types (before pruning):\n"); ++ fprintf (dump_file, "\n"); ++ fprintf (dump_file, "==============================================\n\n"); ++ fprintf (dump_file, "======== all types (before pruning): ========\n\n"); + dump_types (dump_file); +- fprintf (dump_file, "all functions (before pruning):\n"); ++ fprintf (dump_file, "======= all functions (before pruning): =======\n"); + dump_functions (dump_file); + } ++ /* If record_var () is called later, new types will not be recorded. */ + done_recording = true; + } + +@@ -3580,6 +4805,7 @@ ipa_struct_reorg::walk_field_for_cycles (srtype *type) + { + if (!field->type) + ; ++ /* If there are two members of the same structure pointer type? */ + else if (field->type->visited + || walk_field_for_cycles (field->type)) + { +@@ -3658,22 +4884,113 @@ ipa_struct_reorg::propagate_escape (void) + } while (changed); + } + ++/* If the original type (with members) has escaped, corresponding to the ++ struct pointer type (empty member) in the structure fields ++ should also marked as escape. */ ++ ++void ++ipa_struct_reorg::propagate_escape_via_original (void) ++{ ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ for (unsigned j = 0; j < types.length (); j++) ++ { ++ const char *type1 = get_type_name (types[i]->type); ++ const char *type2 = get_type_name (types[j]->type); ++ if (type1 == NULL || type2 == NULL) ++ continue; ++ if (type1 == type2 && types[j]->has_escaped ()) ++ { ++ if (!types[i]->has_escaped ()) ++ types[i]->mark_escape (escape_via_orig_escape, NULL); ++ break; ++ } ++ } ++ } ++} ++ ++/* Marks the fileds as empty and does not have the original structure type ++ is escape. */ ++ ++void ++ipa_struct_reorg::propagate_escape_via_empty_with_no_original (void) ++{ ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ if (types[i]->fields.length () == 0) ++ { ++ for (unsigned j = 0; j < types.length (); j++) ++ { ++ if (i != j && types[j]->fields.length ()) ++ { ++ const char *type1 = get_type_name (types[i]->type); ++ const char *type2 = get_type_name (types[j]->type); ++ if (type1 != NULL && type2 != NULL && type1 == type2) ++ break; ++ } ++ if (j == types.length () - 1) ++ types[i]->mark_escape (escape_via_empty_no_orig, NULL); ++ } ++ } ++ } ++} ++ ++/* Escape propagation is performed on types that escape through external ++ functions. */ ++ ++void ++ipa_struct_reorg::propagate_escape_via_ext_func_types (void) ++{ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ fprintf (dump_file, "\n propagate_escape_via_ext_func_types: \n\n"); ++ unsigned i = 0; ++ hash_set visited_types; ++ while (i < ext_func_types.length ()) ++ { ++ visited_types.add (ext_func_types[i]); ++ unsigned j = 0; ++ srfield * field; ++ FOR_EACH_VEC_ELT (ext_func_types[i]->fields, j, field) ++ { ++ if (field->type) ++ { ++ if (!field->type->has_escaped ()) ++ field->type->mark_escape (escape_dependent_type_escapes, NULL); ++ if (!visited_types.contains (field->type)) ++ ext_func_types.safe_push (field->type); ++ } ++ } ++ i++; ++ } ++} ++ + /* Prune the escaped types and their decls from what was recorded. */ + + void + ipa_struct_reorg::prune_escaped_types (void) + { +- if (current_mode != COMPLETE_STRUCT_RELAYOUT) ++ if (current_mode != COMPLETE_STRUCT_RELAYOUT ++ && current_mode != STRUCT_REORDER_FIELDS) + { ++ /* Detect recusive types and mark them as escaping. */ + detect_cycles (); ++ /* If contains or is contained by the escape type, ++ mark them as escaping. */ + propagate_escape (); + } ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ propagate_escape_via_original (); ++ propagate_escape_via_empty_with_no_original (); ++ propagate_escape_via_ext_func_types (); ++ } + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "all types (after prop but before pruning):\n"); ++ fprintf (dump_file, "==============================================\n\n"); ++ fprintf (dump_file, "all types (after prop but before pruning): \n\n"); + dump_types (dump_file); +- fprintf (dump_file, "all functions (after prop but before pruning):\n"); ++ fprintf (dump_file, "all functions (after prop but before pruning): \n"); + dump_functions (dump_file); + } + +@@ -3721,7 +5038,8 @@ ipa_struct_reorg::prune_escaped_types (void) + /* Prune functions which don't refer to any variables any more. */ + if (function->args.is_empty () + && function->decls.is_empty () +- && function->globals.is_empty ()) ++ && function->globals.is_empty () ++ && current_mode != STRUCT_REORDER_FIELDS) + { + delete function; + functions.ordered_remove (i); +@@ -3746,24 +5064,31 @@ ipa_struct_reorg::prune_escaped_types (void) + + /* Prune types that escape, all references to those types + will have been removed in the above loops. */ +- for (unsigned i = 0; i < types.length ();) ++ /* The escape type is not deleted in STRUCT_REORDER_FIELDS, ++ Then the type that contains the escaped type fields ++ can find complete information. */ ++ if (current_mode != STRUCT_REORDER_FIELDS) + { +- srtype *type = types[i]; +- if (type->has_escaped ()) ++ for (unsigned i = 0; i < types.length ();) + { +- /* All references to this type should have been removed now. */ +- delete type; +- types.ordered_remove (i); ++ srtype *type = types[i]; ++ if (type->has_escaped ()) ++ { ++ /* All references to this type should have been removed now. */ ++ delete type; ++ types.ordered_remove (i); ++ } ++ else ++ i++; + } +- else +- i++; + } + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "all types (after pruning):\n"); ++ fprintf (dump_file, "==============================================\n\n"); ++ fprintf (dump_file, "========= all types (after pruning): =========\n\n"); + dump_types (dump_file); +- fprintf (dump_file, "all functions (after pruning):\n"); ++ fprintf (dump_file, "======== all functions (after pruning): ========\n"); + dump_functions (dump_file); + } + } +@@ -3790,6 +5115,26 @@ ipa_struct_reorg::create_new_types (void) + for (unsigned i = 0; i < types.length (); i++) + newtypes += types[i]->create_new_type (); + ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ for (unsigned i = 0; i < types.length (); i++) ++ { ++ auto_vec *fields = fields_to_finish.get (types[i]->type); ++ if (fields) ++ { ++ for (unsigned j = 0; j < fields->length (); j++) ++ { ++ tree field = (*fields)[j]; ++ TREE_TYPE (field) ++ = reconstruct_complex_type (TREE_TYPE (field), ++ types[i]->newtype[0]); ++ } ++ } ++ } ++ for (unsigned i = 0; i < types.length (); i++) ++ layout_type (types[i]->newtype[0]); ++ } ++ + if (dump_file) + { + if (newtypes) +@@ -3894,7 +5239,8 @@ ipa_struct_reorg::create_new_args (cgraph_node *new_node) + char *name = NULL; + if (tname) + { +- name = concat (tname, ".reorg.0", NULL); ++ name = concat (tname, current_mode == STRUCT_REORDER_FIELDS ++ ? ".reorder.0" : ".reorg.0", NULL); + new_name = get_identifier (name); + free (name); + } +@@ -3980,9 +5326,10 @@ ipa_struct_reorg::create_new_functions (void) + fprintf (dump_file, "\n"); + } + statistics_counter_event (NULL, "Create new function", 1); +- new_node = node->create_version_clone_with_body (vNULL, NULL, +- NULL, NULL, NULL, +- "struct_reorg"); ++ new_node = node->create_version_clone_with_body ( ++ vNULL, NULL, NULL, NULL, NULL, ++ current_mode == STRUCT_REORDER_FIELDS ++ ? "struct_reorder" : "struct_reorg"); + new_node->can_change_signature = node->can_change_signature; + new_node->make_local (); + f->newnode = new_node; +@@ -4026,6 +5373,7 @@ ipa_struct_reorg::rewrite_expr (tree expr, + srfield *f; + bool realpart, imagpart; + bool address; ++ bool escape_from_base = false; + + tree newbase[max_split]; + memset (newexpr, 0, sizeof (tree[max_split])); +@@ -4043,8 +5391,8 @@ ipa_struct_reorg::rewrite_expr (tree expr, + return true; + } + +- if (!get_type_field (expr, base, indirect, t, f, +- realpart, imagpart, address)) ++ if (!get_type_field (expr, base, indirect, t, f, realpart, imagpart, ++ address, escape_from_base)) + return false; + + /* If the type is not changed, then just return false. */ +@@ -4107,7 +5455,38 @@ ipa_struct_reorg::rewrite_expr (tree expr, + if (address) + newbase1 = build_fold_addr_expr (newbase1); + if (indirect) +- newbase1 = build_simple_mem_ref (newbase1); ++ { ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ /* Supports the MEM_REF offset. ++ _1 = MEM[(struct arc *)ap_1 + 72B].flow; ++ Old rewrite: _1 = ap.reorder.0_8->flow; ++ New rewrite: _1 ++ = MEM[(struct arc.reorder.0 *)ap.reorder.0_8 + 64B].flow; ++ */ ++ HOST_WIDE_INT offset_tmp = 0; ++ HOST_WIDE_INT mem_offset = 0; ++ bool realpart_tmp = false; ++ bool imagpart_tmp = false; ++ tree accesstype_tmp = NULL_TREE; ++ tree num = NULL_TREE; ++ get_ref_base_and_offset (expr, offset_tmp, ++ realpart_tmp, imagpart_tmp, ++ accesstype_tmp, &num); ++ ++ tree ptype = TREE_TYPE (newbase1); ++ /* Specify the correct size for the multi-layer pointer. */ ++ tree size = isptrptr (ptype) ? TYPE_SIZE_UNIT (ptype) : ++ TYPE_SIZE_UNIT (inner_type (ptype)); ++ mem_offset = (num != NULL) ++ ? TREE_INT_CST_LOW (num) * tree_to_shwi (size) ++ : 0; ++ newbase1 = build2 (MEM_REF, TREE_TYPE (ptype), newbase1, ++ build_int_cst (ptype, mem_offset)); ++ } ++ else ++ newbase1 = build_simple_mem_ref (newbase1); ++ } + newexpr[i] = build3 (COMPONENT_REF, TREE_TYPE (f->newfield[i]), + newbase1, f->newfield[i], NULL_TREE); + if (imagpart) +@@ -4151,8 +5530,12 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + return remove; + } + +- if (gimple_assign_rhs_code (stmt) == EQ_EXPR +- || gimple_assign_rhs_code (stmt) == NE_EXPR) ++ if ((current_mode != STRUCT_REORDER_FIELDS ++ && (gimple_assign_rhs_code (stmt) == EQ_EXPR ++ || gimple_assign_rhs_code (stmt) == NE_EXPR)) ++ || (current_mode == STRUCT_REORDER_FIELDS ++ && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) ++ == tcc_comparison))) + { + tree rhs1 = gimple_assign_rhs1 (stmt); + tree rhs2 = gimple_assign_rhs2 (stmt); +@@ -4160,6 +5543,10 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + tree newrhs2[max_split]; + tree_code rhs_code = gimple_assign_rhs_code (stmt); + tree_code code = rhs_code == EQ_EXPR ? BIT_AND_EXPR : BIT_IOR_EXPR; ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && rhs_code != EQ_EXPR && rhs_code != NE_EXPR) ++ code = rhs_code; ++ + if (!rewrite_lhs_rhs (rhs1, rhs2, newrhs1, newrhs2)) + return false; + tree newexpr = NULL_TREE; +@@ -4201,20 +5588,78 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + internal_error ( + "The rhs of pointer is not a multiplicate and it slips through"); + +- num = gimplify_build1 (gsi, NOP_EXPR, sizetype, num); ++ /* Add the judgment of num, support for POINTER_DIFF_EXPR. ++ _6 = _4 + _5; ++ _5 = (long unsigned int) _3; ++ _3 = _1 - old_2. */ ++ if (current_mode != STRUCT_REORDER_FIELDS ++ || (current_mode == STRUCT_REORDER_FIELDS && (num != NULL))) ++ num = gimplify_build1 (gsi, NOP_EXPR, sizetype, num); + for (unsigned i = 0; i < max_split && newlhs[i]; i++) + { + gimple *new_stmt; + +- tree newsize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (newlhs[i]))); +- newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype, num, newsize); +- new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR, +- newrhs[i], newsize); ++ if (num != NULL) ++ { ++ tree newsize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (newlhs[i]))); ++ newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype, num, ++ newsize); ++ new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR, ++ newrhs[i], newsize); ++ } ++ else ++ new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR, ++ newrhs[i], rhs2); + gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); + remove = true; + } + return remove; + } ++ ++ /* Support POINTER_DIFF_EXPR rewriting. */ ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR) ++ { ++ tree rhs1 = gimple_assign_rhs1 (stmt); ++ tree rhs2 = gimple_assign_rhs2 (stmt); ++ tree newrhs1[max_split]; ++ tree newrhs2[max_split]; ++ ++ bool r1 = rewrite_expr (rhs1, newrhs1); ++ bool r2 = rewrite_expr (rhs2, newrhs2); ++ ++ if (r1 != r2) ++ { ++ /* Handle NULL pointer specially. */ ++ if (r1 && !r2 && integer_zerop (rhs2)) ++ { ++ r2 = true; ++ for (unsigned i = 0; i < max_split && newrhs1[i]; i++) ++ newrhs2[i] = fold_convert (TREE_TYPE (newrhs1[i]), rhs2); ++ } ++ else if (r2 && !r1 && integer_zerop (rhs1)) ++ { ++ r1 = true; ++ for (unsigned i = 0; i < max_split && newrhs2[i]; i++) ++ newrhs1[i] = fold_convert (TREE_TYPE (newrhs2[i]), rhs1); ++ } ++ else ++ return false; ++ } ++ else if (!r1 && !r2) ++ return false; ++ ++ /* The two operands always have pointer/reference type. */ ++ for (unsigned i = 0; i < max_split && newrhs1[i] && newrhs2[i]; i++) ++ { ++ gimple_assign_set_rhs1 (stmt, newrhs1[i]); ++ gimple_assign_set_rhs2 (stmt, newrhs2[i]); ++ update_stmt (stmt); ++ } ++ remove = false; ++ return remove; ++ } ++ + if (gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS) + { + tree lhs = gimple_assign_lhs (stmt); +@@ -4222,9 +5667,8 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "rewriting statement:\n"); ++ fprintf (dump_file, "\nrewriting stamtenet:\n"); + print_gimple_stmt (dump_file, stmt, 0); +- fprintf (dump_file, "\n"); + } + tree newlhs[max_split]; + tree newrhs[max_split]; +@@ -4271,7 +5715,7 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) + if (!decl || !decl->type) + return false; + srtype *type = decl->type; +- tree num = allocate_size (type, stmt); ++ tree num = allocate_size (type, decl, stmt); + gcc_assert (num); + memset (newrhs1, 0, sizeof (newrhs1)); + +@@ -4291,7 +5735,10 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) + /* Go through each new lhs. */ + for (unsigned i = 0; i < max_split && decl->newdecl[i]; i++) + { +- tree newsize = TYPE_SIZE_UNIT (type->type); ++ /* Specify the correct size for the multi-layer pointer. */ ++ tree newsize = isptrptr (decl->orig_type) ++ ? TYPE_SIZE_UNIT (decl->orig_type) ++ : TYPE_SIZE_UNIT (type->newtype[i]); + gimple *g; + /* Every allocation except for calloc needs + the size multiplied out. */ +@@ -4352,6 +5799,23 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) + gcc_assert (node); + srfunction *f = find_function (node); + ++ /* Add a safe func mechanism. */ ++ if (current_mode == STRUCT_REORDER_FIELDS && f && f->is_safe_func) ++ { ++ tree expr = gimple_call_arg (stmt, 0); ++ tree newexpr[max_split]; ++ if (!rewrite_expr (expr, newexpr)) ++ return false; ++ ++ if (newexpr[1] == NULL) ++ { ++ gimple_call_set_arg (stmt, 0, newexpr[0]); ++ update_stmt (stmt); ++ return false; ++ } ++ return false; ++ } ++ + /* Did not find the function or had not cloned it return saying don't + change the function call. */ + if (!f || !f->newf) +@@ -4437,7 +5901,7 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) + && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME) + SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; + +- gsi_replace (gsi, new_stmt, false); ++ gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); + + /* We need to defer cleaning EH info on the new statement to + fixup-cfg. We may not have dominator information at this point +@@ -4450,7 +5914,7 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) + add_stmt_to_eh_lp (new_stmt, lp_nr); + } + +- return false; ++ return true; + } + + /* Rewrite the conditional statement STMT. Return TRUE if the +@@ -4462,50 +5926,52 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi) + tree_code rhs_code = gimple_cond_code (stmt); + + /* Handle only equals or not equals conditionals. */ +- if (rhs_code != EQ_EXPR +- && rhs_code != NE_EXPR) ++ if ((current_mode != STRUCT_REORDER_FIELDS ++ && (rhs_code != EQ_EXPR && rhs_code != NE_EXPR)) ++ || (current_mode == STRUCT_REORDER_FIELDS ++ && TREE_CODE_CLASS (rhs_code) != tcc_comparison)) + return false; +- tree rhs1 = gimple_cond_lhs (stmt); +- tree rhs2 = gimple_cond_rhs (stmt); ++ tree lhs = gimple_cond_lhs (stmt); ++ tree rhs = gimple_cond_rhs (stmt); + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "COND: Rewriting\n"); ++ fprintf (dump_file, "\nCOND: Rewriting\n"); + print_gimple_stmt (dump_file, stmt, 0); ++ print_generic_expr (dump_file, lhs); + fprintf (dump_file, "\n"); +- print_generic_expr (dump_file, rhs1); +- fprintf (dump_file, "\n"); +- print_generic_expr (dump_file, rhs2); ++ print_generic_expr (dump_file, rhs); + fprintf (dump_file, "\n"); + } + +- tree newrhs1[max_split]; +- tree newrhs2[max_split]; +- tree_code code = rhs_code == EQ_EXPR ? BIT_AND_EXPR : BIT_IOR_EXPR; +- if (!rewrite_lhs_rhs (rhs1, rhs2, newrhs1, newrhs2)) ++ tree newlhs[max_split] = {}; ++ tree newrhs[max_split] = {}; ++ if (!rewrite_lhs_rhs (lhs, rhs, newlhs, newrhs)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) +- fprintf (dump_file, "\nDid nothing to statement.\n"); ++ fprintf (dump_file, "Did nothing to statement.\n"); + return false; + } + +- tree newexpr = NULL_TREE; +- for (unsigned i = 0; i < max_split && newrhs1[i]; i++) ++ /* Old rewrite: if (x_1 != 0B) ++ -> _1 = x.reorder.0_1 != 0B; if (_1 != 1) ++ The logic is incorrect. ++ New rewrite: if (x_1 != 0B) ++ -> if (x.reorder.0_1 != 0B); */ ++ for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++) + { +- tree expr = gimplify_build2 (gsi, rhs_code, boolean_type_node, +- newrhs1[i], newrhs2[i]); +- if (!newexpr) +- newexpr = expr; +- else +- newexpr = gimplify_build2 (gsi, code, boolean_type_node, +- newexpr, expr); +- } +- +- if (newexpr) +- { +- gimple_cond_set_lhs (stmt, newexpr); +- gimple_cond_set_rhs (stmt, boolean_true_node); ++ if (newlhs[i]) ++ gimple_cond_set_lhs (stmt, newlhs[i]); ++ if (newrhs[i]) ++ gimple_cond_set_rhs (stmt, newrhs[i]); + update_stmt (stmt); ++ ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "replaced with:\n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ fprintf (dump_file, "\n"); ++ } + } + return false; + } +@@ -4516,6 +5982,9 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi) + bool + ipa_struct_reorg::rewrite_debug (gimple *stmt, gimple_stmt_iterator *) + { ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ /* Delete debug gimple now. */ ++ return true; + bool remove = false; + if (gimple_debug_bind_p (stmt)) + { +@@ -4568,7 +6037,7 @@ ipa_struct_reorg::rewrite_phi (gphi *phi) + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "\nrewriting PHI:"); ++ fprintf (dump_file, "\nrewriting PHI:\n"); + print_gimple_stmt (dump_file, phi, 0); + } + +@@ -4579,7 +6048,15 @@ ipa_struct_reorg::rewrite_phi (gphi *phi) + { + tree newrhs[max_split]; + phi_arg_d rhs = *gimple_phi_arg (phi, i); +- rewrite_expr (rhs.def, newrhs); ++ ++ /* Handling the NULL phi Node. */ ++ bool r = rewrite_expr (rhs.def, newrhs); ++ if (!r && integer_zerop (rhs.def)) ++ { ++ for (unsigned i = 0; i < max_split && newlhs[i]; i++) ++ newrhs[i] = fold_convert (TREE_TYPE (newlhs[i]), rhs.def); ++ } ++ + for (unsigned j = 0; j < max_split && newlhs[j]; j++) + { + SET_PHI_ARG_DEF (newphi[j], i, newrhs[j]); +@@ -4590,7 +6067,7 @@ ipa_struct_reorg::rewrite_phi (gphi *phi) + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "\ninto\n:"); ++ fprintf (dump_file, "into:\n"); + for (unsigned i = 0; i < max_split && newlhs[i]; i++) + { + print_gimple_stmt (dump_file, newphi[i], 0); +@@ -4663,12 +6140,59 @@ ipa_struct_reorg::rewrite_functions (void) + /* Create new types, if we did not create any new types, + then don't rewrite any accesses. */ + if (!create_new_types ()) +- return 0; ++ { ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ for (unsigned i = 0; i < functions.length (); i++) ++ { ++ srfunction *f = functions[i]; ++ cgraph_node *node = f->node; ++ push_cfun (DECL_STRUCT_FUNCTION (node->decl)); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\nNo rewrite:\n"); ++ dump_function_to_file (current_function_decl, dump_file, ++ dump_flags | TDF_VOPS); ++ } ++ pop_cfun (); ++ } ++ } ++ return 0; ++ } ++ ++ if (current_mode == STRUCT_REORDER_FIELDS && dump_file) ++ { ++ fprintf (dump_file, "=========== all created newtypes: ===========\n\n"); ++ dump_newtypes (dump_file); ++ } + + if (functions.length ()) + { + retval = TODO_remove_functions; + create_new_functions (); ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ prune_escaped_types (); ++ } ++ } ++ ++ if (current_mode == STRUCT_REORDER_FIELDS) ++ { ++ for (unsigned i = 0; i < functions.length (); i++) ++ { ++ srfunction *f = functions[i]; ++ cgraph_node *node = f->node; ++ push_cfun (DECL_STRUCT_FUNCTION (node->decl)); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "==== Before create decls: %dth_%s ====\n\n", ++ i, f->node->name ()); ++ if (current_function_decl) ++ dump_function_to_file (current_function_decl, dump_file, ++ dump_flags | TDF_VOPS); ++ } ++ pop_cfun (); ++ } + } + + create_new_decls (); +@@ -4691,9 +6215,12 @@ ipa_struct_reorg::rewrite_functions (void) + + if (dump_file && (dump_flags & TDF_DETAILS)) + { +- fprintf (dump_file, "\nBefore rewrite:\n"); ++ fprintf (dump_file, "\nBefore rewrite: %dth_%s\n", ++ i, f->node->name ()); + dump_function_to_file (current_function_decl, dump_file, + dump_flags | TDF_VOPS); ++ fprintf (dump_file, "\n======== Start to rewrite: %dth_%s ========\n", ++ i, f->node->name ()); + } + FOR_EACH_BB_FN (bb, cfun) + { +@@ -4761,9 +6288,10 @@ ipa_struct_reorg::rewrite_functions (void) + + free_dominance_info (CDI_DOMINATORS); + +- if (dump_file && (dump_flags & TDF_DETAILS)) ++ if (dump_file) + { +- fprintf (dump_file, "\nAfter rewrite:\n"); ++ fprintf (dump_file, "\nAfter rewrite: %dth_%s\n", ++ i, f->node->name ()); + dump_function_to_file (current_function_decl, dump_file, + dump_flags | TDF_VOPS); + } +@@ -4809,16 +6337,21 @@ ipa_struct_reorg::execute (enum srmode mode) + { + unsigned int ret = 0; + +- if (mode == NORMAL) ++ if (dump_file) ++ fprintf (dump_file, "\n\n====== ipa_struct_reorg level %d ======\n\n", ++ mode); ++ ++ if (mode == NORMAL || mode == STRUCT_REORDER_FIELDS) + { +- current_mode = NORMAL; +- /* FIXME: If there is a top-level inline-asm, ++ current_mode = mode; ++ /* If there is a top-level inline-asm, + the pass immediately returns. */ + if (symtab->first_asm_symbol ()) + return 0; + record_accesses (); + prune_escaped_types (); +- analyze_types (); ++ if (current_mode == NORMAL) ++ analyze_types (); + + ret = rewrite_functions (); + } +@@ -4881,7 +6414,55 @@ pass_ipa_struct_reorg::gate (function *) + && flag_lto_partition == LTO_PARTITION_ONE + /* Only enable struct optimizations in C since other + languages' grammar forbid. */ +- && lang_c_p ()); ++ && lang_c_p () ++ /* Only enable struct optimizations in lto or whole_program. */ ++ && (in_lto_p || flag_whole_program)); ++} ++ ++const pass_data pass_data_ipa_reorder_fields = ++{ ++ SIMPLE_IPA_PASS, // type ++ "reorder_fields", // name ++ OPTGROUP_NONE, // optinfo_flags ++ TV_IPA_REORDER_FIELDS, // tv_id ++ 0, // properties_required ++ 0, // properties_provided ++ 0, // properties_destroyed ++ 0, // todo_flags_start ++ 0, // todo_flags_finish ++}; ++ ++class pass_ipa_reorder_fields : public simple_ipa_opt_pass ++{ ++public: ++ pass_ipa_reorder_fields (gcc::context *ctxt) ++ : simple_ipa_opt_pass (pass_data_ipa_reorder_fields, ctxt) ++ {} ++ ++ /* opt_pass methods: */ ++ virtual bool gate (function *); ++ virtual unsigned int execute (function *) ++ { ++ unsigned int ret = 0; ++ ret = ipa_struct_reorg ().execute (STRUCT_REORDER_FIELDS); ++ return ret; ++ } ++ ++}; // class pass_ipa_reorder_fields ++ ++bool ++pass_ipa_reorder_fields::gate (function *) ++{ ++ return (optimize >= 3 ++ && flag_ipa_reorder_fields ++ /* Don't bother doing anything if the program has errors. */ ++ && !seen_error () ++ && flag_lto_partition == LTO_PARTITION_ONE ++ /* Only enable struct optimizations in C since other ++ languages' grammar forbid. */ ++ && lang_c_p () ++ /* Only enable struct optimizations in lto or whole_program. */ ++ && (in_lto_p || flag_whole_program)); + } + + } // anon namespace +@@ -4891,4 +6472,10 @@ simple_ipa_opt_pass * + make_pass_ipa_struct_reorg (gcc::context *ctxt) + { + return new pass_ipa_struct_reorg (ctxt); +-} +\ No newline at end of file ++} ++ ++simple_ipa_opt_pass * ++make_pass_ipa_reorder_fields (gcc::context *ctxt) ++{ ++ return new pass_ipa_reorder_fields (ctxt); ++} +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +index ef7f4c780..6f85adeb4 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +@@ -68,12 +68,14 @@ struct srfunction + auto_vec args; + auto_vec globals; + auto_vec_del decls; +- srdecl *record_decl (srtype *, tree, int arg); ++ srdecl *record_decl (srtype *, tree, int arg, tree orig_type = NULL); + + srfunction *old; + cgraph_node *newnode; + srfunction *newf; + ++ bool is_safe_func; ++ + // Constructors + srfunction (cgraph_node *n); + +@@ -184,6 +186,11 @@ struct srfield + void create_new_fields (tree newtype[max_split], + tree newfields[max_split], + tree newlast[max_split]); ++ void reorder_fields (tree newfields[max_split], tree newlast[max_split], ++ tree &field); ++ void create_new_reorder_fields (tree newtype[max_split], ++ tree newfields[max_split], ++ tree newlast[max_split]); + }; + + struct sraccess +@@ -221,8 +228,11 @@ struct srdecl + + tree newdecl[max_split]; + ++ /* Auxiliary record complete original type information of the void* type. */ ++ tree orig_type; ++ + // Constructors +- srdecl (srtype *type, tree decl, int argumentnum = -1); ++ srdecl (srtype *type, tree decl, int argumentnum = -1, tree orgtype = NULL); + + // Methods + void dump (FILE *file); +diff --git a/gcc/passes.def b/gcc/passes.def +index 9692066e4..bdc835b87 100644 +--- a/gcc/passes.def ++++ b/gcc/passes.def +@@ -178,6 +178,7 @@ along with GCC; see the file COPYING3. If not see + compiled unit. */ + INSERT_PASSES_AFTER (all_late_ipa_passes) + NEXT_PASS (pass_ipa_pta); ++ NEXT_PASS (pass_ipa_reorder_fields); + /* FIXME: this should be a normal IP pass. */ + NEXT_PASS (pass_ipa_struct_reorg); + NEXT_PASS (pass_omp_simd_clone); +diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h +index 3fe64047c..6fa529eee 100644 +--- a/gcc/symbol-summary.h ++++ b/gcc/symbol-summary.h +@@ -105,7 +105,7 @@ protected: + { + /* In structure optimizatons, we call new to ensure that + the allocated memory is initialized to 0. */ +- if (flag_ipa_struct_reorg) ++ if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) + return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () + : new T (); + +@@ -122,7 +122,7 @@ protected: + ggc_delete (item); + else + { +- if (flag_ipa_struct_reorg) ++ if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) + delete item; + else + m_allocator.remove (item); +diff --git a/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c b/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c +new file mode 100644 +index 000000000..b95be2dab +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c +@@ -0,0 +1,75 @@ ++// escape_instance_field, "Type escapes via a field of instance". ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++ node_t node; ++} network_t; ++ ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++ network_t* net_add; ++ node_t node; ++}; ++ ++ ++const int MAX = 100; ++ ++/* let it escape_array, "Type is used in an array [not handled yet]". */ ++network_t* net[2]; ++ ++int ++main () ++{ ++ net[0] = (network_t*) calloc (1, sizeof(network_t)); ++ net[0]->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ ++ /* Contains an escape type and has structure instance field. */ ++ net[0]->arcs->node = net[0]->node; ++ ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c +new file mode 100644 +index 000000000..3d243313b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c +@@ -0,0 +1,94 @@ ++// Verify in escape_dependent_type_escapes, ++// the multi-layer dereference is rewriting correctly,and the memory access ++// is correct. ++ ++// release ++// escape_dependent_type_escapes, ++// "Type uses a type which escapes or is used by a type which escapes" ++// avoid escape_cast_another_ptr, "Type escapes a cast to a different pointer" ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++ network_t* net_add; ++}; ++ ++ ++const int MAX = 100; ++ ++/* let it escape_array, "Type is used in an array [not handled yet]". */ ++network_t* net[2]; ++arc_p stop_arcs = NULL; ++ ++int ++main () ++{ ++ net[0] = (network_t*) calloc (1, sizeof(network_t)); ++ net[0]->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ stop_arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ ++ net[0]->arcs->id = 100; ++ ++ for (unsigned i = 0; i < 3; i++) ++ { ++ net[0]->arcs->id = net[0]->arcs->id + 2; ++ stop_arcs->cost = net[0]->arcs->id / 2; ++ stop_arcs->net_add = net[0]; ++ printf("stop_arcs->cost = %ld\n", stop_arcs->cost); ++ net[0]->arcs++; ++ stop_arcs++; ++ } ++ ++ if( net[1] != 0 && stop_arcs != 0) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c b/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c +new file mode 100644 +index 000000000..faaf1e3a5 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c +@@ -0,0 +1,24 @@ ++/* check_ptr_layers bugfix.*/ ++/* { dg-do compile } */ ++struct { ++ char a; ++} **b = 0, *e = 0; ++long c; ++char d = 9; ++int f; ++ ++void g() ++{ ++ for (; f;) ++ if (c) ++ (*e).a++; ++ if (!d) ++ for (;;) ++ b &&c; ++} ++int ++main() ++{ ++ g(); ++} ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c b/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c +new file mode 100644 +index 000000000..886706ae9 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c +@@ -0,0 +1,82 @@ ++// bugfix: ++// Common members do not need to reconstruct. ++// Otherwise, eg:int* -> int** and void* -> void**. ++/* { dg-do compile } */ ++ ++#include ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t* cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t** org_cost; ++}; ++ ++struct a ++{ ++ int t; ++ int t1; ++}; ++ ++__attribute__((noinline)) int ++f(int i, int j) ++{ ++ struct a *t = NULL; ++ struct a t1 = {i, j}; ++ t = &t1; ++ auto int g(void) __attribute__((noinline)); ++ int g(void) ++ { ++ return t->t + t->t1; ++ } ++ return g(); ++} ++ ++arc_t **ap = NULL; ++const int MAX = 100; ++ ++int ++main() ++{ ++ if (f(1, 2) != 3) ++ { ++ abort (); ++ } ++ ap = (arc_t**) malloc(MAX * sizeof(arc_t*)); ++ (*ap)[0].id = 300; ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c b/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c +new file mode 100644 +index 000000000..f3785f392 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c +@@ -0,0 +1,56 @@ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++#define MallocOrDie(x) sre_malloc((x)) ++ ++struct gki_elem { ++ char *key; ++ int idx; ++ struct gki_elem *nxt; ++}; ++ ++typedef struct { ++ struct gki_elem **table; ++ ++ int primelevel; ++ int nhash; ++ int nkeys; ++} GKI; ++ ++void ++Die(char *format, ...) ++{ ++ exit(1); ++} ++ ++void * ++sre_malloc(size_t size) ++{ ++ void *ptr; ++ ++ if ((ptr = malloc (size)) == NULL) ++ { ++ Die("malloc of %ld bytes failed", size); ++ } ++ return ptr; ++} ++ ++ ++__attribute__((noinline)) int ++GKIStoreKey(GKI *hash, char *key) ++{ ++ hash->table[0] = MallocOrDie(sizeof(struct gki_elem)); ++} ++ ++int ++main () ++{ ++ GKI *hash; ++ char *key; ++ GKIStoreKey(hash, key); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c b/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c +new file mode 100644 +index 000000000..1415d759a +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c +@@ -0,0 +1,60 @@ ++// verify newarc[cmp-1].flow ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++arc_p ap = NULL; ++ ++int ++main () ++{ ++ ap = (arc_p) calloc(MAX, sizeof(arc_t)); ++ printf("%d\n", ap[0].id); ++ for (int i = 1; i < MAX; i++) ++ { ++ ap[i-1].id = 500; ++ } ++ printf("%d\n", ap[0].id); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c b/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c +new file mode 100644 +index 000000000..003da0b57 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c +@@ -0,0 +1,83 @@ ++// release type is used by a type which escapes. ++// avoid escape_cast_another_ptr, "Type escapes a cast to a different pointer" ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++network_t* net = NULL; ++arc_p stop_arcs = NULL; ++int cnt = 0; ++ ++int ++main () ++{ ++ net = (network_t*) calloc (1, 20); ++ net->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ stop_arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ if(!(net->arcs)) ++ { ++ return -1; ++ } ++ ++ for( int i = 0; i < MAX; i++, net->arcs = stop_arcs) ++ { ++ cnt++; ++ } ++ ++ net = (network_t*) calloc (1, 20); ++ if( !(net->arcs) ) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c b/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c +new file mode 100644 +index 000000000..84a34f241 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c +@@ -0,0 +1,69 @@ ++/* { dg-do compile } */ ++/* { dg-additional-options "-shared" } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ int x; ++ arc_p arcs, sorted_arcs; ++ node_p nodes, stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++extern int bcf_sr_add_reader (network_t *); ++extern int bcf_hdr_dup (arc_p); ++ ++int ++test () ++{ ++ network_t *net = (network_t *) calloc (1, 20); ++ ++ if (!bcf_sr_add_reader(net)) ++ printf("error"); ++ arc_p arc = net->nodes->basic_arc; ++ if(!bcf_hdr_dup(arc)) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c +new file mode 100644 +index 000000000..10dcf098c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c +@@ -0,0 +1,72 @@ ++// release escape_cast_another_ptr, "Type escapes a cast to a different pointer" ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++typedef int cmp_t(const void *, const void *); ++ ++__attribute__((noinline)) void ++spec_qsort(void *a, cmp_t *cmp) ++{ ++ char *pb = NULL; ++ while (cmp(pb, a)) ++ { ++ pb += 1; ++ } ++} ++ ++static int arc_compare( arc_t **a1, int a2 ) ++{ ++ if( (*a1)->id < a2 ) ++ { ++ return -1; ++ } ++ return 1; ++} ++ ++int ++main() ++{ ++ spec_qsort(NULL, (int (*)(const void *, const void *))arc_compare); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c b/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c +new file mode 100644 +index 000000000..8d1a9a114 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c +@@ -0,0 +1,58 @@ ++/* Supports the MEM_REF offset. ++ _1 = MEM[(struct arc *)ap_4 + 72B].flow; ++ Old rewrite:_1 = ap.reorder.0_8->flow; ++ New rewrite:_1 = MEM[(struct arc.reorder.0 *)ap.reorder.0_8 + 64B].flow. */ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main () ++{ ++ const int MAX = 100; ++ /* A similar scenario can be reproduced only by using local variables. */ ++ arc_p ap = NULL; ++ ap = (arc_p) calloc(MAX, sizeof(arc_t)); ++ printf("%d\n", ap[1].flow); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c b/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c +new file mode 100644 +index 000000000..23765fc56 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c +@@ -0,0 +1,30 @@ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct T_HASH_ENTRY ++{ ++ unsigned int hash; ++ unsigned int klen; ++ char *key; ++} iHashEntry; ++ ++typedef struct T_HASH ++{ ++ unsigned int size; ++ unsigned int fill; ++ unsigned int keys; ++ ++ iHashEntry **array; ++} uHash; ++ ++uHash *retval; ++ ++int ++main() { ++ retval->array = (iHashEntry **)calloc(sizeof(iHashEntry *), retval->size); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c +new file mode 100644 +index 000000000..54e737ee8 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c +@@ -0,0 +1,109 @@ ++// For testing: ++/* ++Compile options: gcc -O3 -g ++-flto -flto-partition=one -fipa-reorder-fields -fipa-struct-reorg ++-v -save-temps -fdump-ipa-all-details test.c -o test ++ ++in COMPLETE_STRUCT_RELAYOUT pass: ++N type: struct node.reorder.0 new = "Type escapes a cast to a different pointer" ++copy$head_26 = test_arc.reorder.0_49->head; ++ ++type : struct arc.reorder.0(1599) { ++fields = { ++field (5382) {type = cost_t} ++field (5383) {type = struct node.reorder.0 *} // but node has escaped. ++field (5384) {type = struct node.reorder.0 *} ++field (5386) {type = struct arc.reorder.0 *} ++field (5387) {type = struct arc.reorder.0 *} ++field (5388) {type = flow_t} ++field (5389) {type = cost_t} ++field (5381) {type = int} ++field (5385) {type = short int} ++} ++ ++// The types of the two types are inconsistent after the rewriting. ++newarc_2(D)->tail = tail_1(D); ++vs ++struct_reorder.0_61(D)->tail = tail_1(D); ++*/ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++__attribute__((noinline)) void ++replace_weaker_arc( arc_t *newarc, node_t *tail, node_t *head) ++{ ++ printf("test"); ++} ++ ++__attribute__((noinline)) int64_t ++switch_arcs(arc_t** deleted_arcs, arc_t* arcnew) ++{ ++ int64_t count = 0; ++ arc_t *test_arc, copy; ++ ++ if (!test_arc->ident) ++ { ++ copy = *test_arc; ++ count++; ++ *test_arc = arcnew[0]; ++ replace_weaker_arc(arcnew, NULL, NULL); ++ } ++ return count; ++} ++ ++int ++main () ++{ ++ switch_arcs(NULL, NULL); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c b/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c +new file mode 100644 +index 000000000..2ae46fb31 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c +@@ -0,0 +1,87 @@ ++// escape_cast_void, "Type escapes a cast to/from void*" ++// stop_393 = net.stop_nodes; void *stop; ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs, sorted_arcs; ++ int x; ++ node_p nodes, stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++network_t* net = NULL; ++int cnt = 0; ++ ++__attribute__((noinline)) int ++primal_feasible (network_t *net) ++{ ++ void* stop; ++ node_t *node; ++ ++ node = net->nodes; ++ stop = (void *)net->stop_nodes; ++ for( node++; node < (node_t *)stop; node++ ) ++ { ++ printf( "PRIMAL NETWORK SIMPLEX: " ); ++ } ++ return 0; ++} ++ ++int ++main () ++{ ++ net = (network_t*) calloc (1, 20); ++ net->nodes = calloc (MAX, sizeof (node_t)); ++ net->stop_nodes = calloc (MAX, sizeof (node_t)); ++ cnt = primal_feasible( net ); ++ ++ net = (network_t*) calloc (1, 20); ++ if( !(net->arcs) ) ++ { ++ return -1; ++ } ++ return cnt; ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c +new file mode 100644 +index 000000000..3a3c10b70 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c +@@ -0,0 +1,71 @@ ++// support POINTER_DIFF_EXPR & NOP_EXPR to avoid ++// escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt" ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main () ++{ ++ arc_t *old_arcs; ++ node_t *node; ++ node_t *stop; ++ size_t off; ++ network_t* net; ++ ++ for( ; node->number < stop->number; node++ ) ++ { ++ off = node->basic_arc - old_arcs; ++ node->basic_arc = (arc_t *)(net->arcs + off); ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c +new file mode 100644 +index 000000000..7b7d110df +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c +@@ -0,0 +1,55 @@ ++// support NEGATE_EXPR rewriting ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main () ++{ ++ int64_t susp = 0; ++ const int MAX = 100; ++ arc_p ap = (arc_p) calloc(MAX, sizeof(arc_t)); ++ ap -= susp; ++ printf("%d\n", ap[1].flow); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c +new file mode 100644 +index 000000000..317aafa5f +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c +@@ -0,0 +1,34 @@ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++struct node ++{ ++ struct node *left, *right; ++ double a, b, c, d, e, f; ++} ++*a; ++int b, c; ++void ++CreateNode (struct node **p1) ++{ ++ *p1 = calloc (10, sizeof (struct node)); ++} ++ ++int ++main () ++{ ++ a->left = 0; ++ struct node *t = a; ++ CreateNode (&t->right); ++ ++ struct node p = *a; ++ b = 1; ++ if (p.left) ++ b = 0; ++ if (b) ++ printf (" Tree.\n"); ++} ++ ++/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c +new file mode 100644 +index 000000000..01a33f669 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c +@@ -0,0 +1,55 @@ ++// release escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]"; ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++arc_t **ap = NULL; ++ ++int ++main () ++{ ++ ap = (arc_t**) malloc(MAX * sizeof(arc_t*)); ++ (*ap)[0].id = 300; ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c +new file mode 100644 +index 000000000..a38556533 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c +@@ -0,0 +1,58 @@ ++// release escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]" ++ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++arc_p **ap; ++ ++ ++int ++main () ++{ ++ ap = (arc_p**) calloc(MAX, sizeof(arc_p*)); ++ (**ap)[0].id = 500; ++ ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c b/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c +new file mode 100644 +index 000000000..5c17ee528 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c +@@ -0,0 +1,57 @@ ++// release escape_rescusive_type, "Recusive type" ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++arc_p ap = NULL; ++ ++int ++main () ++{ ++ ap = (arc_p) calloc (MAX, sizeof (arc_t)); ++ ap[0].id = 100; ++ ap[0].head = (node_p) calloc (MAX, sizeof (node_t)); ++ ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c +new file mode 100644 +index 000000000..710517ee9 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c +@@ -0,0 +1,65 @@ ++// support more gimple assign rhs code ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++__attribute__((noinline)) int ++compare(arc_p p1, arc_p p2) ++{ ++ return p1 < p2; ++} ++ ++int n = 0; ++int m = 0; ++ ++int ++main () ++{ ++ scanf ("%d %d", &n, &m); ++ arc_p p = calloc (10, sizeof (struct arc)); ++ if (compare (&p[n], &p[m])) ++ { ++ printf ("ss!"); ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c +new file mode 100644 +index 000000000..6ed0a5d2d +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c +@@ -0,0 +1,72 @@ ++// rewrite_cond bugfix; ++/* ++if (iterator_600 != 0B) ++old rewrite: _1369 = iterator.reorder.0_1249 != 0B; if (_1369 != 1) ++new rewrite: if (iterator.reorder.0_1249 != 0B) ++*/ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct list_elem ++{ ++ arc_t* arc; ++ struct list_elem* next; ++}list_elem; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int i = 0; ++ ++int ++main () ++{ ++ register list_elem *first_list_elem; ++ register list_elem* iterator; ++ iterator = first_list_elem->next; ++ while (iterator) ++ { ++ iterator = iterator->next; ++ i++; ++ } ++ ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c +new file mode 100644 +index 000000000..5a2dd964f +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c +@@ -0,0 +1,58 @@ ++// support if (_150 >= _154) ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main() ++{ ++ arc_p **ap = (arc_p**) malloc(1 * sizeof(arc_p*)); ++ arc_p **arcs_pointer_sorted = (arc_p**) malloc(1 * sizeof(arc_p*)); ++ arcs_pointer_sorted[0] = (arc_p*) calloc (1, sizeof(arc_p)); ++ ++ if (arcs_pointer_sorted >= ap) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c +new file mode 100644 +index 000000000..faa90b42d +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c +@@ -0,0 +1,81 @@ ++/* ++Exclude the rewriting error caused by ++first_list_elem = (list_elem *)NULL; ++rewriting PHI:first_list_elem_700 = PHI <0B(144), 0B(146)> ++into: ++first_list_elem.reorder.0_55 = PHI <(144), (146)> ++*/ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct list_elem ++{ ++ arc_t* arc; ++ struct list_elem* next; ++}list_elem; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout, firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail, head; ++ short ident; ++ arc_p nextout, nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++ ++list_elem* new_list_elem; ++list_elem* first_list_elem; ++ ++int ++main () ++{ ++ int i = 0; ++ list_elem *first_list_elem; ++ list_elem *new_list_elem; ++ arc_t *arcout; ++ for( ; i < MAX && arcout->ident == -1; i++); ++ ++ first_list_elem = (list_elem *)NULL; ++ for( ; i < MAX; i++) ++ { ++ new_list_elem = (list_elem*) calloc(1, sizeof(list_elem)); ++ new_list_elem->next = first_list_elem; ++ first_list_elem = new_list_elem; ++ } ++ if (first_list_elem != 0) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_shwi.c b/gcc/testsuite/gcc.dg/struct/rf_shwi.c +new file mode 100644 +index 000000000..2bb326ff2 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_shwi.c +@@ -0,0 +1,23 @@ ++/* { dg-do compile } */ ++ ++struct foo {int dx; long dy; int dz; }; ++struct goo {long offset; struct foo* pfoo; }; ++ ++void* func (long); ++ ++__attribute__((used)) static void ++test(struct goo* g) ++{ ++ void* pvoid; ++ struct foo* f; ++ ++ for (f = g->pfoo; f->dx; f++) ++ { ++ if (f->dy) ++ break; ++ } ++ f--; ++ ++ pvoid = func(f->dz + g->offset); ++ return; ++} +diff --git a/gcc/testsuite/gcc.dg/struct/rf_visible_func.c b/gcc/testsuite/gcc.dg/struct/rf_visible_func.c +new file mode 100644 +index 000000000..8f2da99cc +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_visible_func.c +@@ -0,0 +1,92 @@ ++// release escape_visible_function, "Type escapes via expternally visible function call" ++// compile options: gcc -O3 -fno-inline -fwhole-program ++// -flto-partition=one -fipa-struct-reorg arc_compare.c -fdump-ipa-all -S -v ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++__attribute__((noinline)) static int ++arc_compare( arc_t **a1, arc_t **a2 ) ++{ ++ if( (*a1)->flow > (*a2)->flow ) ++ { ++ return 1; ++ } ++ if( (*a1)->flow < (*a2)->flow ) ++ { ++ return -1; ++ } ++ if( (*a1)->id < (*a2)->id ) ++ { ++ return -1; ++ } ++ ++ return 1; ++} ++ ++__attribute__((noinline)) void ++spec_qsort(void *array, int nitems, int size, ++ int (*cmp)(const void*,const void*)) ++{ ++ for (int i = 0; i < nitems - 1; i++) ++ { ++ if (cmp (array , array)) ++ { ++ printf ("CMP 1\n"); ++ } ++ else ++ { ++ printf ("CMP 2\n"); ++ } ++ } ++} ++ ++typedef int cmp_t(const void *, const void *); ++ ++int ++main () ++{ ++ void *p = calloc (100, sizeof (arc_t **)); ++ spec_qsort (p, 100, 0, (int (*)(const void *, const void *))arc_compare); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c b/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c +new file mode 100644 +index 000000000..723142c59 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c +@@ -0,0 +1,54 @@ ++// Add a safe func mechanism. ++// avoid escape_unkown_field, "Type escapes via an unkown field accessed" ++// avoid escape_cast_void, "Type escapes a cast to/from void*" eg: GIMPLE_NOP ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++void ++__attribute__((noinline)) spec_qsort (void *a, size_t es) ++{ ++ char *pa; ++ char *pb; ++ int cmp_result; ++ ++ while ((*(arc_t **)a)->id < *((int *)a)) ++ { ++ if (cmp_result == 0) ++ { ++ spec_qsort (a, es); ++ pa = (char *)a - es; ++ a += es; ++ *(long *)pb = *(long *)pa; ++ } ++ else ++ { ++ a -= pa - pb; ++ } ++ } ++} ++ ++int ++main() ++{ ++ arc_p **arcs_pointer_sorted; ++ spec_qsort (arcs_pointer_sorted[0], sizeof (arc_p)); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +index 43913104e..5a476e8f9 100644 +--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp ++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +@@ -27,8 +27,21 @@ set STRUCT_REORG_TORTURE_OPTIONS [list \ + + set-torture-options $STRUCT_REORG_TORTURE_OPTIONS {{}} + +-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \ ++# -fipa-struct-reorg ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/wo_*.c]] \ ++ "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/w_*.c]] \ + "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/struct_reorg*.cpp]] \ ++ "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sr_*.c]] \ ++ "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \ ++ "" "-fipa-struct-reorg -fdump-ipa-all -flto-partition=one -fwhole-program" ++ ++# -fipa-reorder-fields ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \ ++ "" "-fipa-reorder-fields -fdump-ipa-all -flto-partition=one -fwhole-program" + + # All done. + torture-finish +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c +index 6565fe8dd..23444fe8b 100644 +--- a/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-1.c +@@ -1,5 +1,5 @@ + // { dg-do compile } +-// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all" } ++// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all -fwhole-program" } + + struct a + { +@@ -21,4 +21,10 @@ int g(void) + return b->t; + } + ++int main() ++{ ++ f (); ++ return g (); ++} ++ + /* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c +index 5864ad46f..2d1f95c99 100644 +--- a/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c ++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-3.c +@@ -1,5 +1,5 @@ + // { dg-do compile } +-// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all" } ++// { dg-options "-O3 -flto-partition=one -fipa-struct-reorg -fdump-ipa-all -fwhole-program" } + + #include + typedef struct { +@@ -10,7 +10,7 @@ typedef struct { + compile_stack_elt_t *stack; + unsigned size; + } compile_stack_type; +-void f (const char *p, const char *pend, int c) ++__attribute__((noinline)) void f (const char *p, const char *pend, int c) + { + compile_stack_type compile_stack; + while (p != pend) +@@ -20,4 +20,9 @@ void f (const char *p, const char *pend, int c) + * sizeof (compile_stack_elt_t)); + } + ++int main() ++{ ++ f (NULL, NULL, 1); ++} ++ + /* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +diff --git a/gcc/timevar.def b/gcc/timevar.def +index 98a5a490f..2b27c858a 100644 +--- a/gcc/timevar.def ++++ b/gcc/timevar.def +@@ -80,6 +80,7 @@ DEFTIMEVAR (TV_IPA_CONSTANT_PROP , "ipa cp") + DEFTIMEVAR (TV_IPA_INLINING , "ipa inlining heuristics") + DEFTIMEVAR (TV_IPA_FNSPLIT , "ipa function splitting") + DEFTIMEVAR (TV_IPA_COMDATS , "ipa comdats") ++DEFTIMEVAR (TV_IPA_REORDER_FIELDS , "ipa struct reorder fields optimization") + DEFTIMEVAR (TV_IPA_STRUCT_REORG , "ipa struct reorg optimization") + DEFTIMEVAR (TV_IPA_OPT , "ipa various optimizations") + DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS , "lto stream decompression") +diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h +index 56898e019..a9ec8ed21 100644 +--- a/gcc/tree-pass.h ++++ b/gcc/tree-pass.h +@@ -527,6 +527,7 @@ extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt); ++extern simple_ipa_opt_pass *make_pass_ipa_reorder_fields (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt); +-- +2.33.0 + diff --git a/0022-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch b/0022-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch new file mode 100644 index 0000000..2822078 --- /dev/null +++ b/0022-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch @@ -0,0 +1,1753 @@ +From 9d03b0a7741915e3a0172d60b9c21bf5abbda89e Mon Sep 17 00:00:00 2001 +From: Mingchuan Wu +Date: Mon, 28 Aug 2023 18:11:02 +0800 +Subject: [PATCH 22/22] [DFE] Add Dead Field Elimination in Struct-Reorg. + +We can transform gimple to eliminate fields that are never read +and replace the dead fields in stmt by creating a new ssa. +--- + gcc/common.opt | 4 + + gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 240 +++++++++++++++++- + gcc/ipa-struct-reorg/ipa-struct-reorg.h | 8 + + gcc/opts.cc | 17 ++ + gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c | 86 +++++++ + .../gcc.dg/struct/dfe_ele_minus_verify.c | 60 +++++ + .../gcc.dg/struct/dfe_extr_board_init.c | 77 ++++++ + gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c | 84 ++++++ + gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c | 56 ++++ + gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c | 162 ++++++++++++ + gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c | 126 +++++++++ + .../gcc.dg/struct/dfe_extr_mv_udc_core.c | 82 ++++++ + .../gcc.dg/struct/dfe_extr_tcp_usrreq.c | 58 +++++ + .../gcc.dg/struct/dfe_extr_ui_main.c | 61 +++++ + .../gcc.dg/struct/dfe_mem_ref_offset.c | 58 +++++ + .../struct/dfe_mul_layer_ptr_record_bug.c | 30 +++ + gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c | 71 ++++++ + .../gcc.dg/struct/dfe_ptr_negate_expr.c | 55 ++++ + gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c | 55 ++++ + gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 4 + + .../struct/wo_prof_escape_replace_type.c | 49 ++++ + 21 files changed, 1436 insertions(+), 7 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c + create mode 100644 gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c + +diff --git a/gcc/common.opt b/gcc/common.opt +index 14633c821..8bb735551 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1988,6 +1988,10 @@ fipa-struct-reorg + Common Var(flag_ipa_struct_reorg) Init(0) Optimization + Perform structure layout optimizations. + ++fipa-struct-reorg= ++Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 3) ++-fipa-struct-reorg=[0,1,2,3] adding none, struct-reorg, reorder-fields, dfe optimizations. ++ + fipa-vrp + Common Var(flag_ipa_vrp) Optimization + Perform IPA Value Range Propagation. +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +index 3e5f9538b..eac5fac7e 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +@@ -87,6 +87,7 @@ along with GCC; see the file COPYING3. If not see + #include "tree-pretty-print.h" + #include "gimple-pretty-print.h" + #include "gimple-iterator.h" ++#include "gimple-walk.h" + #include "cfg.h" + #include "ssa.h" + #include "tree-dfa.h" +@@ -268,10 +269,43 @@ enum srmode + STRUCT_REORDER_FIELDS + }; + ++/* Enum the struct layout optimize level, ++ which should be the same as the option -fstruct-reorg=. */ ++ ++enum struct_layout_opt_level ++{ ++ NONE = 0, ++ STRUCT_REORG, ++ STRUCT_REORDER_FIELDS_SLO, ++ DEAD_FIELD_ELIMINATION ++}; ++ + static bool is_result_of_mult (tree arg, tree *num, tree struct_size); + static bool isptrptr (tree type); ++void get_base (tree &base, tree expr); + + srmode current_mode; ++hash_map replace_type_map; ++ ++/* Return true if one of these types is created by struct-reorg. */ ++ ++static bool ++is_replace_type (tree type1, tree type2) ++{ ++ if (replace_type_map.is_empty ()) ++ return false; ++ if (type1 == NULL_TREE || type2 == NULL_TREE) ++ return false; ++ tree *type_value = replace_type_map.get (type1); ++ if (type_value) ++ if (types_compatible_p (*type_value, type2)) ++ return true; ++ type_value = replace_type_map.get (type2); ++ if (type_value) ++ if (types_compatible_p (*type_value, type1)) ++ return true; ++ return false; ++} + + } // anon namespace + +@@ -353,7 +387,8 @@ srfield::srfield (tree field, srtype *base) + fielddecl (field), + base (base), + type (NULL), +- clusternum (0) ++ clusternum (0), ++ field_access (EMPTY_FIELD) + { + for (int i = 0; i < max_split; i++) + newfield[i] = NULL_TREE; +@@ -392,6 +427,25 @@ srtype::srtype (tree type) + } + } + ++/* Check it if all fields in the RECORD_TYPE are referenced. */ ++ ++bool ++srtype::has_dead_field (void) ++{ ++ bool may_dfe = false; ++ srfield *this_field; ++ unsigned i; ++ FOR_EACH_VEC_ELT (fields, i, this_field) ++ { ++ if (!(this_field->field_access & READ_FIELD)) ++ { ++ may_dfe = true; ++ break; ++ } ++ } ++ return may_dfe; ++} ++ + /* Mark the type as escaping type E at statement STMT. */ + + void +@@ -595,7 +649,17 @@ srtype::analyze (void) + into 2 different structures. In future we intend to add profile + info and/or static heuristics to differentiate splitting process. */ + if (fields.length () == 2) +- fields[1]->clusternum = 1; ++ { ++ /* Currently, when the replacement structure type exists, ++ we only split the replacement structure. */ ++ for (hash_map::iterator it = replace_type_map.begin (); ++ it != replace_type_map.end (); ++it) ++ { ++ if (types_compatible_p ((*it).second, this->type)) ++ return; ++ } ++ fields[1]->clusternum = 1; ++ } + + /* Otherwise we do nothing. */ + if (fields.length () >= 3) +@@ -838,6 +902,10 @@ srtype::create_new_type (void) + for (unsigned i = 0; i < fields.length (); i++) + { + srfield *f = fields[i]; ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION ++ && !(f->field_access & READ_FIELD)) ++ continue; + f->create_new_fields (newtype, newfields, newlast); + } + +@@ -856,6 +924,16 @@ srtype::create_new_type (void) + + warn_padded = save_warn_padded; + ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && replace_type_map.get (this->newtype[0]) == NULL) ++ replace_type_map.put (this->newtype[0], this->type); ++ if (dump_file) ++ { ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION ++ && has_dead_field ()) ++ fprintf (dump_file, "Dead field elimination.\n"); ++ } + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Created %d types:\n", maxclusters); +@@ -1269,6 +1347,7 @@ public: + void maybe_mark_or_record_other_side (tree side, tree other, gimple *stmt); + + unsigned execute_struct_relayout (void); ++ bool remove_dead_field_stmt (tree lhs); + }; + + struct ipa_struct_relayout +@@ -3057,6 +3136,119 @@ ipa_struct_reorg::find_vars (gimple *stmt) + } + } + ++static HOST_WIDE_INT ++get_offset (tree op, HOST_WIDE_INT offset) ++{ ++ switch (TREE_CODE (op)) ++ { ++ case COMPONENT_REF: ++ { ++ return int_byte_position (TREE_OPERAND (op, 1)); ++ } ++ case MEM_REF: ++ { ++ return tree_to_uhwi (TREE_OPERAND (op, 1)); ++ } ++ default: ++ return offset; ++ } ++ return offset; ++} ++ ++/* Record field access. */ ++static void ++record_field_access (tree type, HOST_WIDE_INT offset, ++ unsigned access, void *data) ++{ ++ srtype *this_srtype = ((ipa_struct_reorg *)data)->find_type (type); ++ if (this_srtype == NULL) ++ return; ++ srfield *this_srfield = this_srtype->find_field (offset); ++ if (this_srfield == NULL) ++ return; ++ ++ this_srfield->field_access |= access; ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "record field access %d:", access); ++ print_generic_expr (dump_file, type); ++ fprintf (dump_file, " field:"); ++ print_generic_expr (dump_file, this_srfield->fielddecl); ++ fprintf (dump_file, "\n"); ++ } ++ return; ++ ++} ++ ++/* Update field_access in srfield. */ ++ ++static void ++update_field_access (tree node, tree op, unsigned access, void *data) ++{ ++ HOST_WIDE_INT offset = 0; ++ offset = get_offset (op, offset); ++ tree node_type = inner_type (TREE_TYPE (node)); ++ record_field_access (node_type, offset, access, data); ++ tree base = node; ++ get_base (base, node); ++ tree base_type = inner_type (TREE_TYPE (base)); ++ if (!types_compatible_p (base_type, node_type)) ++ { ++ record_field_access (base_type, get_offset (node, offset), ++ access, data); ++ } ++ return; ++} ++ ++/* A callback for walk_stmt_load_store_ops to visit store. */ ++ ++static bool ++find_field_p_store (gimple *stmt ATTRIBUTE_UNUSED, ++ tree node, tree op, void *data) ++{ ++ update_field_access (node, op, WRITE_FIELD, data); ++ ++ return false; ++} ++ ++/* A callback for walk_stmt_load_store_ops to visit load. */ ++ ++static bool ++find_field_p_load (gimple *stmt ATTRIBUTE_UNUSED, ++ tree node, tree op, void *data) ++{ ++ update_field_access (node, op, READ_FIELD, data); ++ ++ return false; ++} ++ ++/* Determine whether the stmt should be deleted. */ ++ ++bool ++ipa_struct_reorg::remove_dead_field_stmt (tree lhs) ++{ ++ tree base = NULL_TREE; ++ bool indirect = false; ++ srtype *t = NULL; ++ srfield *f = NULL; ++ bool realpart = false; ++ bool imagpart = false; ++ bool address = false; ++ bool escape_from_base = false; ++ if (!get_type_field (lhs, base, indirect, t, f, realpart, imagpart, ++ address, escape_from_base)) ++ return false; ++ if (t ==NULL) ++ return false; ++ if (t->newtype[0] == t->type) ++ return false; ++ if (f == NULL) ++ return false; ++ if (f->newfield[0] == NULL) ++ return true; ++ return false; ++} ++ + /* Maybe record access of statement for further analaysis. */ + + void +@@ -3078,6 +3270,13 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt) + default: + break; + } ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION) ++ { ++ /* Look for loads and stores. */ ++ walk_stmt_load_store_ops (stmt, this, find_field_p_load, ++ find_field_p_store); ++ } + } + + /* Calculate the multiplier. */ +@@ -3368,8 +3567,11 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, + } + else if (type != d->type) + { +- type->mark_escape (escape_cast_another_ptr, stmt); +- d->type->mark_escape (escape_cast_another_ptr, stmt); ++ if (!is_replace_type (d->type->type, type->type)) ++ { ++ type->mark_escape (escape_cast_another_ptr, stmt); ++ d->type->mark_escape (escape_cast_another_ptr, stmt); ++ } + } + /* x_1 = y.x_nodes; void *x; + Directly mark the structure pointer type assigned +@@ -3949,8 +4151,9 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl, + } + /* If we have a non void* or a decl (which is hard to track), + then mark the type as escaping. */ +- if (!VOID_POINTER_P (TREE_TYPE (newdecl)) +- || DECL_P (newdecl)) ++ if (replace_type_map.get (type->type) == NULL ++ && (!VOID_POINTER_P (TREE_TYPE (newdecl)) ++ || DECL_P (newdecl))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { +@@ -4216,7 +4419,9 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, + } + + srtype *t1 = find_type (inner_type (t)); +- if (t1 == type) ++ /* In the other side check, escape mark is added ++ when the replacement struct type exists. */ ++ if (t1 == type || is_replace_type (inner_type (t), type->type)) + { + /* In Complete Struct Relayout, if lhs type is the same + as rhs type, we could return without any harm. */ +@@ -5513,6 +5718,27 @@ bool + ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + { + bool remove = false; ++ ++ if (current_mode == STRUCT_REORDER_FIELDS ++ && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION ++ && remove_dead_field_stmt (gimple_assign_lhs (stmt))) ++ { ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "\n rewriting statement (remove): \n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ } ++ /* Replace the dead field in stmt by creating a dummy ssa. */ ++ tree dummy_ssa = make_ssa_name (TREE_TYPE (gimple_assign_lhs (stmt))); ++ gimple_assign_set_lhs (stmt, dummy_ssa); ++ update_stmt (stmt); ++ if (dump_file && (dump_flags & TDF_DETAILS)) ++ { ++ fprintf (dump_file, "To: \n"); ++ print_gimple_stmt (dump_file, stmt, 0); ++ } ++ } ++ + if (gimple_clobber_p (stmt)) + { + tree lhs = gimple_assign_lhs (stmt); +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +index 6f85adeb4..719f7b308 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h +@@ -143,6 +143,7 @@ public: + + bool create_new_type (void); + void analyze (void); ++ bool has_dead_field (void); + void mark_escape (escape_type, gimple *stmt); + bool has_escaped (void) + { +@@ -164,6 +165,12 @@ public: + } + }; + ++/* Bitflags used for determining if a field ++ is never accessed, read or written. */ ++const unsigned EMPTY_FIELD = 0x0u; ++const unsigned READ_FIELD = 0x01u; ++const unsigned WRITE_FIELD = 0x02u; ++ + struct srfield + { + unsigned HOST_WIDE_INT offset; +@@ -175,6 +182,7 @@ struct srfield + unsigned clusternum; + + tree newfield[max_split]; ++ unsigned field_access; /* FIELD_DECL -> bitflag (use for dfe). */ + + // Constructors + srfield (tree field, srtype *base); +diff --git a/gcc/opts.cc b/gcc/opts.cc +index c3cc2c169..b868d189e 100644 +--- a/gcc/opts.cc ++++ b/gcc/opts.cc +@@ -2957,6 +2957,23 @@ common_handle_option (struct gcc_options *opts, + SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value); + break; + ++ case OPT_fipa_struct_reorg_: ++ /* No break here - do -fipa-struct-reorg processing. */ ++ /* FALLTHRU. */ ++ case OPT_fipa_struct_reorg: ++ opts->x_flag_ipa_struct_reorg = value; ++ if (value && !opts->x_struct_layout_optimize_level) ++ { ++ /* Using the -fipa-struct-reorg option is equivalent to using ++ -fipa-struct-reorg=1. */ ++ opts->x_struct_layout_optimize_level = 1; ++ } ++ break; ++ ++ case OPT_fipa_reorder_fields: ++ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_struct_reorg, value); ++ break; ++ + case OPT_fprofile_generate_: + opts->x_profile_data_prefix = xstrdup (arg); + value = true; +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c +new file mode 100644 +index 000000000..0c9e384c4 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c +@@ -0,0 +1,86 @@ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++ network_t* net_add; ++}; ++ ++ ++const int MAX = 100; ++ ++/* let it escape_array, "Type is used in an array [not handled yet]". */ ++network_t* net[2]; ++arc_p stop_arcs = NULL; ++ ++int ++main () ++{ ++ net[0] = (network_t*) calloc (1, sizeof(network_t)); ++ net[0]->arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ stop_arcs = (arc_p) calloc (MAX, sizeof (arc_t)); ++ ++ net[0]->arcs->id = 100; ++ ++ for (unsigned i = 0; i < 3; i++) ++ { ++ net[0]->arcs->id = net[0]->arcs->id + 2; ++ stop_arcs->cost = net[0]->arcs->id / 2; ++ stop_arcs->net_add = net[0]; ++ printf("stop_arcs->cost = %ld\n", stop_arcs->cost); ++ net[0]->arcs++; ++ stop_arcs++; ++ } ++ ++ if( net[1] != 0 && stop_arcs != 0) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c +new file mode 100644 +index 000000000..717fcc386 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c +@@ -0,0 +1,60 @@ ++// verify newarc[cmp-1].flow ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++arc_p ap = NULL; ++ ++int ++main () ++{ ++ ap = (arc_p) calloc(MAX, sizeof(arc_t)); ++ printf("%d\n", ap[0].id); ++ for (int i = 1; i < MAX; i++) ++ { ++ ap[i-1].id = 500; ++ } ++ printf("%d\n", ap[0].id); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c +new file mode 100644 +index 000000000..7723c240b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c +@@ -0,0 +1,77 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++typedef struct TYPE_5__ TYPE_2__; ++typedef struct TYPE_4__ TYPE_1__; ++ ++struct TYPE_4__ ++{ ++ int Pin; ++ int Pull; ++ int Mode; ++ int Speed; ++}; ++ ++struct TYPE_5__ ++{ ++ int MEMRMP; ++}; ++typedef TYPE_1__ GPIO_InitTypeDef; ++ ++int BT_RST_PIN; ++int BT_RST_PORT; ++int CONN_POS10_PIN; ++int CONN_POS10_PORT; ++int GPIO_HIGH (int, int); ++int GPIO_MODE_INPUT; ++int GPIO_MODE_OUTPUT_PP; ++int GPIO_NOPULL; ++int GPIO_PULLUP; ++int GPIO_SPEED_FREQ_LOW; ++int HAL_GPIO_Init (int, TYPE_1__ *); ++scalar_t__ IS_GPIO_RESET (int, int); ++TYPE_2__ *SYSCFG; ++int __HAL_RCC_GPIOB_CLK_ENABLE (); ++int __HAL_RCC_GPIOC_CLK_ENABLE (); ++ ++__attribute__((used)) static void ++LBF_DFU_If_Needed (void) ++{ ++ GPIO_InitTypeDef GPIO_InitStruct; ++ __HAL_RCC_GPIOC_CLK_ENABLE (); ++ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; ++ GPIO_InitStruct.Pull = GPIO_NOPULL; ++ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; ++ GPIO_InitStruct.Pin = BT_RST_PIN; ++ HAL_GPIO_Init (BT_RST_PORT, &GPIO_InitStruct); ++ ++ GPIO_HIGH (BT_RST_PORT, BT_RST_PIN); ++ __HAL_RCC_GPIOB_CLK_ENABLE (); ++ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; ++ GPIO_InitStruct.Pull = GPIO_PULLUP; ++ GPIO_InitStruct.Pin = CONN_POS10_PIN; ++ HAL_GPIO_Init (CONN_POS10_PORT, &GPIO_InitStruct); ++ ++ if (IS_GPIO_RESET (CONN_POS10_PORT, CONN_POS10_PIN)) ++ { ++ SYSCFG->MEMRMP = 0x00000001; ++ asm ( ++ "LDR R0, =0x000000\n\t" ++ "LDR SP, [R0, #0]\n\t" ++ ); ++ asm ( ++ "LDR R0, [R0, #0]\n\t" ++ "BX R0\n\t" ++ ); ++ } ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c +new file mode 100644 +index 000000000..a1feac966 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c +@@ -0,0 +1,84 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++typedef struct TYPE_2__ TYPE_1__; ++ ++struct net_device ++{ ++ struct claw_privbk* ml_priv; ++}; ++struct clawctl ++{ ++ int linkid; ++}; ++struct claw_privbk ++{ ++ int system_validate_comp; ++ TYPE_1__* p_env; ++ int ctl_bk; ++}; ++typedef int __u8; ++struct TYPE_2__ ++{ ++ scalar_t__ packing; ++ int api_type; ++}; ++ ++int CLAW_DBF_TEXT (int, int, char*); ++int CONNECTION_REQUEST; ++int HOST_APPL_NAME; ++scalar_t__ PACKING_ASK; ++scalar_t__ PACK_SEND; ++int WS_APPL_NAME_IP_NAME; ++int WS_APPL_NAME_PACKED; ++int claw_send_control (struct net_device*, int, int, int, int, int, int); ++int setup; ++ ++__attribute__((noinline)) int ++claw_send_control (struct net_device* net, int a, int b, int c, int d, int e, ++ int f) ++{ ++ return net->ml_priv->system_validate_comp + a + b + c + d + f; ++} ++ ++__attribute__((used)) static int ++claw_snd_conn_req (struct net_device *dev, __u8 link) ++{ ++ int rc; ++ struct claw_privbk *privptr = dev->ml_priv; ++ struct clawctl *p_ctl; ++ CLAW_DBF_TEXT (2, setup, "snd_conn"); ++ rc = 1; ++ p_ctl = (struct clawctl *)&privptr->ctl_bk; ++ p_ctl->linkid = link; ++ if (privptr->system_validate_comp == 0x00) ++ { ++ return rc; ++ } ++ if (privptr->p_env->packing == PACKING_ASK) ++ { ++ rc = claw_send_control (dev, CONNECTION_REQUEST, 0, 0, 0, ++ WS_APPL_NAME_PACKED, WS_APPL_NAME_PACKED); ++ } ++ if (privptr->p_env->packing == PACK_SEND) ++ { ++ rc = claw_send_control (dev, CONNECTION_REQUEST, 0, 0, 0, ++ WS_APPL_NAME_IP_NAME, WS_APPL_NAME_IP_NAME); ++ } ++ if (privptr->p_env->packing == 0) ++ { ++ rc = claw_send_control (dev, CONNECTION_REQUEST, 0, 0, 0, ++ HOST_APPL_NAME, privptr->p_env->api_type); ++ } ++ return rc; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c +new file mode 100644 +index 000000000..fd1e936ca +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c +@@ -0,0 +1,56 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++typedef struct TYPE_4__ TYPE_2__; ++typedef struct TYPE_3__ TYPE_1__; ++ ++typedef int uint8_t; ++typedef int uint16_t; ++ ++struct TYPE_4__ ++{ ++ size_t cpu_id; ++}; ++ ++struct TYPE_3__ ++{ ++ int cpuc_dtrace_flags; ++}; ++ ++TYPE_2__ *CPU; ++volatile int CPU_DTRACE_FAULT; ++TYPE_1__ *cpu_core; ++scalar_t__ dtrace_load8 (uintptr_t); ++ ++__attribute__((used)) static int ++dtrace_bcmp (const void *s1, const void *s2, size_t len) ++{ ++ volatile uint16_t *flags; ++ flags = (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; ++ if (s1 == s2) ++ return (0); ++ if (s1 == NULL || s2 == NULL) ++ return (1); ++ if (s1 != s2 && len != 0) ++ { ++ const uint8_t *ps1 = s1; ++ const uint8_t *ps2 = s2; ++ do ++ { ++ if (dtrace_load8 ((uintptr_t)ps1++) != *ps2++) ++ return (1); ++ } ++ while (--len != 0 && !(*flags & CPU_DTRACE_FAULT)); ++ } ++ return (0); ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c +new file mode 100644 +index 000000000..b13d785a9 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c +@@ -0,0 +1,162 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++struct mrb_context ++{ ++ size_t stack; ++ size_t stbase; ++ size_t stend; ++ size_t eidx; ++ int *ci; ++ int *cibase; ++ int status; ++}; ++ ++struct RObject ++{ ++ int dummy; ++}; ++ ++struct RHash ++{ ++ int dummy; ++}; ++ ++struct RFiber ++{ ++ struct mrb_context *cxt; ++}; ++ ++struct RClass ++{ ++ int dummy; ++}; ++ ++struct RBasic ++{ ++ int tt; ++}; ++ ++struct RArray ++{ ++ int dummy; ++}; ++ ++typedef int mrb_state; ++typedef int mrb_gc; ++typedef int mrb_callinfo; ++size_t ARY_LEN (struct RArray *); ++size_t MRB_ENV_STACK_LEN (struct RBasic *); ++int MRB_FIBER_TERMINATED; ++ ++#define MRB_TT_ARRAY 140 ++#define MRB_TT_CLASS 139 ++#define MRB_TT_DATA 138 ++#define MRB_TT_ENV 137 ++#define MRB_TT_EXCEPTION 136 ++#define MRB_TT_FIBER 135 ++#define MRB_TT_HASH 134 ++#define MRB_TT_ICLASS 133 ++#define MRB_TT_MODULE 132 ++#define MRB_TT_OBJECT 131 ++#define MRB_TT_PROC 130 ++#define MRB_TT_RANGE 129 ++#define MRB_TT_SCLASS 128 ++ ++size_t ci_nregs (int *); ++int gc_mark_children (int *, int *, struct RBasic *); ++size_t mrb_gc_mark_hash_size (int *, struct RHash *); ++size_t mrb_gc_mark_iv_size (int *, struct RObject *); ++size_t mrb_gc_mark_mt_size (int *, struct RClass *); ++ ++__attribute__((used)) static size_t ++gc_gray_mark (mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) ++{ ++ size_t children = 0; ++ gc_mark_children (mrb, gc, obj); ++ switch (obj->tt) ++ { ++ case MRB_TT_ICLASS: ++ children++; ++ break; ++ ++ case MRB_TT_CLASS: ++ case MRB_TT_SCLASS: ++ case MRB_TT_MODULE: ++ { ++ struct RClass *c = (struct RClass *)obj; ++ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj); ++ children += mrb_gc_mark_mt_size (mrb, c); ++ children ++; ++ } ++ break; ++ ++ case MRB_TT_OBJECT: ++ case MRB_TT_DATA: ++ case MRB_TT_EXCEPTION: ++ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj); ++ break; ++ ++ case MRB_TT_ENV: ++ children += MRB_ENV_STACK_LEN (obj); ++ break; ++ ++ case MRB_TT_FIBER: ++ { ++ struct mrb_context *c = ((struct RFiber *)obj)->cxt; ++ size_t i; ++ mrb_callinfo *ci; ++ if (!c || c->status == MRB_FIBER_TERMINATED) ++ break; ++ ++ i = c->stack - c->stbase; ++ if (c->ci) ++ { ++ i += ci_nregs (c->ci); ++ } ++ if (c->stbase + i > c->stend) ++ i = c->stend - c->stbase; ++ ++ children += i; ++ children += c->eidx; ++ if (c->cibase) ++ { ++ for (i = 0, ci = c->cibase; ci <= c->ci; i++, ci++) ++ ; ++ } ++ children += i; ++ } ++ break; ++ ++ case MRB_TT_ARRAY: ++ { ++ struct RArray *a = (struct RArray *)obj; ++ children += ARY_LEN (a); ++ } ++ break; ++ ++ case MRB_TT_HASH: ++ children += mrb_gc_mark_iv_size (mrb, (struct RObject *)obj); ++ children += mrb_gc_mark_hash_size (mrb, (struct RHash *)obj); ++ break; ++ ++ case MRB_TT_PROC: ++ case MRB_TT_RANGE: ++ children += 2; ++ break; ++ default: ++ break; ++ } ++ ++ return children; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c +new file mode 100644 +index 000000000..bc28a658a +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c +@@ -0,0 +1,126 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++typedef struct TYPE_6__ TYPE_3__; ++typedef struct TYPE_5__ TYPE_2__; ++typedef struct TYPE_4__ TYPE_1__; ++ ++struct io_accel2_cmd ++{ ++ int dummy; ++}; ++ ++struct hpsa_tmf_struct ++{ ++ int it_nexus; ++}; ++ ++struct hpsa_scsi_dev_t ++{ ++ int nphysical_disks; ++ int ioaccel_handle; ++ struct hpsa_scsi_dev_t **phys_disk; ++}; ++ ++struct ctlr_info ++{ ++ TYPE_3__ *pdev; ++ struct io_accel2_cmd *ioaccel2_cmd_pool; ++}; ++struct TYPE_4__ ++{ ++ int LunAddrBytes; ++}; ++ ++struct TYPE_5__ ++{ ++ TYPE_1__ LUN; ++}; ++ ++struct CommandList ++{ ++ size_t cmdindex; ++ int cmd_type; ++ struct hpsa_scsi_dev_t *phys_disk; ++ TYPE_2__ Header; ++}; ++ ++struct TYPE_6__ ++{ ++ int dev; ++}; ++ ++int BUG (); ++#define CMD_IOACCEL1 132 ++#define CMD_IOACCEL2 131 ++#define CMD_IOCTL_PEND 130 ++#define CMD_SCSI 129 ++#define IOACCEL2_TMF 128 ++int dev_err (int *, char *, int); ++scalar_t__ hpsa_is_cmd_idle (struct CommandList *); ++int le32_to_cpu (int); ++int test_memcmp (unsigned char *, int *, int); ++ ++__attribute__((used)) static bool ++hpsa_cmd_dev_match (struct ctlr_info *h, struct CommandList *c, ++ struct hpsa_scsi_dev_t *dev, unsigned char *scsi3addr) ++{ ++ int i; ++ bool match = false; ++ struct io_accel2_cmd * c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; ++ struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *)c2; ++ ++ if (hpsa_is_cmd_idle (c)) ++ return false; ++ ++ switch (c->cmd_type) ++ { ++ case CMD_SCSI: ++ case CMD_IOCTL_PEND: ++ match = !test_memcmp (scsi3addr, &c->Header.LUN.LunAddrBytes, ++ sizeof (c->Header.LUN.LunAddrBytes)); ++ break; ++ ++ case CMD_IOACCEL1: ++ case CMD_IOACCEL2: ++ if (c->phys_disk == dev) ++ { ++ match = true; ++ } ++ else ++ { ++ for (i = 0; i < dev->nphysical_disks && !match; i++) ++ { ++ match = dev->phys_disk[i] == c->phys_disk; ++ } ++ } ++ break; ++ ++ case IOACCEL2_TMF: ++ for (i = 0; i < dev->nphysical_disks && !match; i++) ++ { ++ match = dev->phys_disk[i]->ioaccel_handle == ++ le32_to_cpu (ac->it_nexus); ++ } ++ break; ++ ++ case 0: ++ match = false; ++ break; ++ default: ++ dev_err (&h->pdev->dev, "unexpected cmd_type: %d\n", c->cmd_type); ++ BUG (); ++ } ++ ++ return match; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c +new file mode 100644 +index 000000000..0a585ac3d +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c +@@ -0,0 +1,82 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++typedef struct TYPE_4__ TYPE_2__; ++typedef struct TYPE_3__ TYPE_1__; ++typedef int u32; ++ ++struct mv_udc ++{ ++ TYPE_2__ *op_regs; ++ TYPE_1__ *ep_dqh; ++ struct mv_ep *eps; ++}; ++ ++struct mv_ep ++{ ++ TYPE_1__ *dqh; ++ struct mv_udc *udc; ++}; ++ ++struct TYPE_4__ ++{ ++ int *epctrlx; ++}; ++ ++struct TYPE_3__ ++{ ++ int max_packet_length; ++ int next_dtd_ptr; ++}; ++ ++int EP0_MAX_PKT_SIZE; ++int EPCTRL_RX_ENABLE; ++int EPCTRL_RX_EP_TYPE_SHIFT; ++int EPCTRL_TX_ENABLE; ++int EPCTRL_TX_EP_TYPE_SHIFT; ++int EP_QUEUE_HEAD_IOS; ++int EP_QUEUE_HEAD_MAX_PKT_LEN_POS; ++int EP_QUEUE_HEAD_NEXT_TERMINATE; ++int USB_ENDPOINT_XFER_CONTROL; ++int readl (int *); ++int writel (int, int *); ++ ++__attribute__((used)) static void ++ep0_reset (struct mv_udc *udc) ++{ ++ struct mv_ep *ep; ++ u32 epctrlx; ++ int i = 0; ++ for (i = 0; i < 2; i++) ++ { ++ ep = &udc->eps[i]; ++ ep->udc = udc; ++ ep->dqh = &udc->ep_dqh[i]; ++ ep->dqh->max_packet_length = ++ (EP0_MAX_PKT_SIZE << EP_QUEUE_HEAD_MAX_PKT_LEN_POS) ++ | EP_QUEUE_HEAD_IOS; ++ ep->dqh->next_dtd_ptr = EP_QUEUE_HEAD_NEXT_TERMINATE; ++ epctrlx = readl (&udc->op_regs->epctrlx[0]); ++ if (i) ++ { ++ epctrlx |= EPCTRL_TX_ENABLE ++ | (USB_ENDPOINT_XFER_CONTROL << EPCTRL_TX_EP_TYPE_SHIFT); ++ } ++ else ++ { ++ epctrlx |= EPCTRL_RX_ENABLE ++ | (USB_ENDPOINT_XFER_CONTROL << EPCTRL_RX_EP_TYPE_SHIFT); ++ } ++ writel (epctrlx, &udc->op_regs->epctrlx[0]); ++ } ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c +new file mode 100644 +index 000000000..bddd862fe +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c +@@ -0,0 +1,58 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++struct tcpcb ++{ ++ int t_state; ++}; ++ ++struct socket ++{ ++ int dummy; ++}; ++ ++struct proc ++{ ++ int dummy; ++}; ++ ++struct inpcb ++{ ++ scalar_t__ inp_lport; ++}; ++ ++int COMMON_END (int); ++int COMMON_START (); ++int PRU_LISTEN; ++int TCPS_LISTEN; ++int in_pcbbind (struct inpcb *, int *, struct proc *); ++struct inpcb* sotoinpcb (struct socket *); ++ ++__attribute__((used)) static void ++tcp_usr_listen (struct socket *so, struct proc *p) ++{ ++ int error = 0; ++ struct inpcb *inp = sotoinpcb (so); ++ struct tcpcb *tp; ++ ++ COMMON_START (); ++ if (inp->inp_lport == 0) ++ { ++ error = in_pcbbind (inp, NULL, p); ++ } ++ if (error == 0) ++ { ++ tp->t_state = TCPS_LISTEN; ++ } ++ COMMON_END (PRU_LISTEN); ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c +new file mode 100644 +index 000000000..1a06f5eec +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c +@@ -0,0 +1,61 @@ ++/* { dg-do compile} */ ++ ++#define NULL ((void*)0) ++typedef unsigned long size_t; ++typedef long intptr_t; ++typedef unsigned long uintptr_t; ++typedef long scalar_t__; ++typedef int bool; ++#define false 0 ++#define true 1 ++ ++typedef struct TYPE_4__ TYPE_2__; ++typedef struct TYPE_3__ TYPE_1__; ++ ++struct TYPE_4__ ++{ ++ size_t modCount; ++ TYPE_1__ *modList; ++}; ++ ++struct TYPE_3__ ++{ ++ void *modDescr; ++ void *modName; ++}; ++ ++size_t MAX_MODS; ++void *String_Alloc (char *); ++int test_strlen (char *); ++int trap_FD_GetFileList (char *, char *, char *, int); ++TYPE_2__ uiInfo; ++ ++__attribute__((used)) static void ++UI_LoadMods () ++{ ++ int numdirs; ++ char dirlist[2048]; ++ char *dirptr; ++ char *descptr; ++ int i; ++ int dirlen; ++ ++ uiInfo.modCount = 0; ++ numdirs = trap_FD_GetFileList ("$modelist", "", dirlist, sizeof (dirlist)); ++ dirptr = dirlist; ++ for (i = 0; i < numdirs; i++) ++ { ++ dirlen = test_strlen (dirptr) + 1; ++ descptr = dirptr + dirlen; ++ uiInfo.modList[uiInfo.modCount].modName = String_Alloc (dirptr); ++ uiInfo.modList[uiInfo.modCount].modDescr = String_Alloc (descptr); ++ dirptr += dirlen + test_strlen (descptr) + 1; ++ uiInfo.modCount++; ++ if (uiInfo.modCount >= MAX_MODS) ++ { ++ break; ++ } ++ } ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c +new file mode 100644 +index 000000000..94eb88d5c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c +@@ -0,0 +1,58 @@ ++/* Supports the MEM_REF offset. ++ _1 = MEM[(struct arc *)ap_4 + 72B].flow; ++ Old rewrite:_1 = ap.reorder.0_8->flow; ++ New rewrite:_1 = MEM[(struct arc.reorder.0 *)ap.reorder.0_8 + 64B].flow. */ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main () ++{ ++ const int MAX = 100; ++ /* A similar scenario can be reproduced only by using local variables. */ ++ arc_p ap = NULL; ++ ap = (arc_p) calloc(MAX, sizeof(arc_t)); ++ printf("%d\n", ap[1].flow); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c +new file mode 100644 +index 000000000..bbf9420d0 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c +@@ -0,0 +1,30 @@ ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct T_HASH_ENTRY ++{ ++ unsigned int hash; ++ unsigned int klen; ++ char *key; ++} iHashEntry; ++ ++typedef struct T_HASH ++{ ++ unsigned int size; ++ unsigned int fill; ++ unsigned int keys; ++ ++ iHashEntry **array; ++} uHash; ++ ++uHash *retval; ++ ++int ++main() { ++ retval->array = (iHashEntry **)calloc(sizeof(iHashEntry *), retval->size); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c +new file mode 100644 +index 000000000..f706db968 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c +@@ -0,0 +1,71 @@ ++// support POINTER_DIFF_EXPR & NOP_EXPR to avoid ++// escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt" ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++typedef struct network ++{ ++ arc_p arcs; ++ arc_p sorted_arcs; ++ int x; ++ node_p nodes; ++ node_p stop_nodes; ++} network_t; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main () ++{ ++ arc_t *old_arcs; ++ node_t *node; ++ node_t *stop; ++ size_t off; ++ network_t* net; ++ ++ for( ; node->number < stop->number; node++ ) ++ { ++ off = node->basic_arc - old_arcs; ++ node->basic_arc = (arc_t *)(net->arcs + off); ++ } ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 3 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c +new file mode 100644 +index 000000000..963295cb4 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c +@@ -0,0 +1,55 @@ ++// support NEGATE_EXPR rewriting ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++int ++main () ++{ ++ int64_t susp = 0; ++ const int MAX = 100; ++ arc_p ap = (arc_p) calloc(MAX, sizeof(arc_t)); ++ ap -= susp; ++ printf("%d\n", ap[1].flow); ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c +new file mode 100644 +index 000000000..aa10506a1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c +@@ -0,0 +1,55 @@ ++// release escape_ptr_ptr, "Type is used in a pointer to a pointer [not handled yet]"; ++/* { dg-do compile } */ ++ ++#include ++#include ++ ++typedef struct node node_t; ++typedef struct node *node_p; ++ ++typedef struct arc arc_t; ++typedef struct arc *arc_p; ++ ++struct node ++{ ++ int64_t potential; ++ int orientation; ++ node_p child; ++ node_p pred; ++ node_p sibling; ++ node_p sibling_prev; ++ arc_p basic_arc; ++ arc_p firstout; ++ arc_p firstin; ++ arc_p arc_tmp; ++ int64_t flow; ++ int64_t depth; ++ int number; ++ int time; ++}; ++ ++struct arc ++{ ++ int id; ++ int64_t cost; ++ node_p tail; ++ node_p head; ++ short ident; ++ arc_p nextout; ++ arc_p nextin; ++ int64_t flow; ++ int64_t org_cost; ++}; ++ ++const int MAX = 100; ++arc_t **ap = NULL; ++ ++int ++main () ++{ ++ ap = (arc_t**) malloc(MAX * sizeof(arc_t*)); ++ (*ap)[0].id = 300; ++ return 0; ++} ++ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +index 5a476e8f9..6ccb753b5 100644 +--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp ++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +@@ -43,6 +43,10 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \ + gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \ + "" "-fipa-reorder-fields -fdump-ipa-all -flto-partition=one -fwhole-program" + ++# -fipa-struct-reorg=3 ++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \ ++ "" "-fipa-reorder-fields -fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program" ++ + # All done. + torture-finish + dg-finish +diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c +new file mode 100644 +index 000000000..fa8c66b9e +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_replace_type.c +@@ -0,0 +1,49 @@ ++/* { dg-do compile } */ ++ ++#include ++ ++struct AngleDef ++{ ++ double K; ++ double th0; ++}; ++typedef struct AngleDef angldef; ++ ++struct bndangdihe ++{ ++ int nbond; ++ int nangl; ++ int ndihe; ++}; ++typedef struct bndangdihe bah; ++ ++struct ambprmtop ++{ ++ double *AnglK; ++ double *AnglEq; ++ bah nBAH; ++ angldef *AParam; ++ char source[512]; ++ char eprulesource[512]; ++}; ++typedef struct ambprmtop prmtop; ++ ++static void OrderBondParameters (prmtop *tp) ++{ ++ int i; ++ tp->AParam = (angldef *)malloc (tp->nBAH.nangl * sizeof (angldef)); ++ for (i = 0; i < tp->nBAH.nangl; i++) ++ { ++ tp->AParam[i].K = tp->AnglK[i]; ++ tp->AParam[i].th0 = tp->AnglEq[i]; ++ } ++} ++ ++void main () ++{ ++ prmtop *tp = (prmtop *)malloc (100 * sizeof (prmtop)); ++ OrderBondParameters (tp); ++} ++ ++/*---------------------------------------------------------------------------------------------*/ ++/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */ +-- +2.33.0 + diff --git a/0023-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch b/0023-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch new file mode 100644 index 0000000..7577a01 --- /dev/null +++ b/0023-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch @@ -0,0 +1,44 @@ +From 9dc6d315ba350c9113f486ec897217a82838fb73 Mon Sep 17 00:00:00 2001 +From: Xiong Zhou +Date: Mon, 7 Aug 2023 14:44:56 +0800 +Subject: [PATCH 1/2] [PGO kernel] Add fkernel-pgo option to support PGO kernel + compilation. + +--- + gcc/common.opt | 4 ++++ + gcc/tree-profile.cc | 4 +++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/gcc/common.opt b/gcc/common.opt +index e365a48bc..bd3b7dcb1 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -2363,6 +2363,10 @@ fprofile-generate= + Common Joined RejectNegative + Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=. + ++fkernel-pgo ++Common Var(flag_kernel_pgo) Optimization Init(0) ++Disable TLS setting of instrumentation variables to support PGO kernel compilation in -fprofile-generate, as kernel does not support TLS. ++ + fprofile-info-section + Common RejectNegative + Register the profile information in the .gcov_info section instead of using a constructor/destructor. +diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc +index 6d40401f8..e7646f1a1 100644 +--- a/gcc/tree-profile.cc ++++ b/gcc/tree-profile.cc +@@ -108,7 +108,9 @@ init_ic_make_global_vars (void) + DECL_ARTIFICIAL (ic_tuple_var) = 1; + DECL_INITIAL (ic_tuple_var) = NULL; + DECL_EXTERNAL (ic_tuple_var) = 1; +- if (targetm.have_tls) ++ /* Disable TLS setting when compiling kernel in -fprofile-generate, ++ as kernel does not support TLS. */ ++ if (targetm.have_tls && !flag_kernel_pgo) + set_decl_tls_model (ic_tuple_var, decl_default_tls_model (ic_tuple_var)); + } + +-- +2.33.0 + diff --git a/0024-Struct-Reorg-Refactoring-and-merge-reorder-fields-in.patch b/0024-Struct-Reorg-Refactoring-and-merge-reorder-fields-in.patch new file mode 100644 index 0000000..ddea235 --- /dev/null +++ b/0024-Struct-Reorg-Refactoring-and-merge-reorder-fields-in.patch @@ -0,0 +1,1470 @@ +From 535d00d764c38e70c563ac59e702a20e3b744a95 Mon Sep 17 00:00:00 2001 +From: liyancheng <412998149@qq.com> +Date: Tue, 29 Aug 2023 19:18:21 +0800 +Subject: [PATCH] [Struct Reorg] Refactoring and merge reorder fields into + struct reorg optimization + +Merge reorder_fields pass into struct_reorg pass. Using flag -fipa-struct-reorg=[0,1,2,3] +to enable none, strcut reorg, reorder fields and dfe optimizations. +--- + gcc/gimple-ssa-warn-access.cc | 2 +- + gcc/ipa-free-lang-data.cc | 9 +- + gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 353 ++++++++---------- + gcc/passes.def | 1 - + gcc/symbol-summary.h | 4 +- + gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c | 2 +- + .../gcc.dg/struct/dfe_ele_minus_verify.c | 2 +- + .../gcc.dg/struct/dfe_extr_board_init.c | 2 +- + gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c | 2 +- + gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c | 2 +- + gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c | 2 +- + gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c | 2 +- + .../gcc.dg/struct/dfe_extr_mv_udc_core.c | 2 +- + .../gcc.dg/struct/dfe_extr_tcp_usrreq.c | 2 +- + .../gcc.dg/struct/dfe_extr_ui_main.c | 2 +- + .../gcc.dg/struct/dfe_mem_ref_offset.c | 2 +- + .../struct/dfe_mul_layer_ptr_record_bug.c | 2 +- + gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c | 2 +- + .../gcc.dg/struct/dfe_ptr_negate_expr.c | 2 +- + gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c | 2 +- + .../struct/rf_DTE_struct_instance_field.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c | 2 +- + .../gcc.dg/struct/rf_check_ptr_layers_bug.c | 2 +- + .../gcc.dg/struct/rf_create_fields_bug.c | 2 +- + .../gcc.dg/struct/rf_create_new_func_bug.c | 2 +- + .../gcc.dg/struct/rf_ele_minus_verify.c | 2 +- + .../gcc.dg/struct/rf_escape_by_base.c | 2 +- + .../gcc.dg/struct/rf_external_func_types.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c | 2 +- + .../gcc.dg/struct/rf_mem_ref_offset.c | 2 +- + .../struct/rf_mul_layer_ptr_record_bug.c | 2 +- + .../gcc.dg/struct/rf_pass_conflict.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c | 2 +- + .../gcc.dg/struct/rf_ptr_negate_expr.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c | 2 +- + .../gcc.dg/struct/rf_rescusive_type.c | 2 +- + .../struct/rf_rewrite_assign_more_cmp.c | 2 +- + .../gcc.dg/struct/rf_rewrite_cond_bug.c | 2 +- + .../gcc.dg/struct/rf_rewrite_cond_more_cmp.c | 2 +- + .../gcc.dg/struct/rf_rewrite_phi_bug.c | 2 +- + gcc/testsuite/gcc.dg/struct/rf_visible_func.c | 2 +- + .../gcc.dg/struct/rf_void_ptr_param_func.c | 2 +- + gcc/testsuite/gcc.dg/struct/struct-reorg.exp | 2 +- + gcc/timevar.def | 1 - + gcc/tree-pass.h | 1 - + 48 files changed, 201 insertions(+), 252 deletions(-) + +diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc +index 7f5c92c96..a24645783 100644 +--- a/gcc/gimple-ssa-warn-access.cc ++++ b/gcc/gimple-ssa-warn-access.cc +@@ -2198,7 +2198,7 @@ pass_waccess::gate (function *) + In pass waccess, it will traverse all SSA and cause ICE + when handling these unused SSA. So temporarily disable + pass waccess when enable structure optimizations. */ +- if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) ++ if (flag_ipa_struct_reorg) + return false; + + return (warn_free_nonheap_object +diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc +index a88381ddb..801e95cea 100644 +--- a/gcc/ipa-free-lang-data.cc ++++ b/gcc/ipa-free-lang-data.cc +@@ -49,6 +49,9 @@ + #include "except.h" + #include "ipa-utils.h" + ++/* Check whether in C language or LTO with only C language. */ ++extern bool lang_c_p (void); ++ + namespace { + + /* Data used when collecting DECLs and TYPEs for language data removal. */ +@@ -105,7 +108,8 @@ fld_simplified_type_name (tree type) + /* Simplify type will cause that struct A and struct A within + struct B are different type pointers, so skip it in structure + optimizations. */ +- if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) ++ if (flag_ipa_struct_reorg && lang_c_p () ++ && flag_lto_partition == LTO_PARTITION_ONE) + return TYPE_NAME (type); + + if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL) +@@ -349,7 +353,8 @@ fld_simplified_type (tree t, class free_lang_data_d *fld) + /* Simplify type will cause that struct A and struct A within + struct B are different type pointers, so skip it in structure + optimizations. */ +- if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) ++ if (flag_ipa_struct_reorg && lang_c_p () ++ && flag_lto_partition == LTO_PARTITION_ONE) + return t; + if (POINTER_TYPE_P (t)) + return fld_incomplete_type_of (t, fld); +diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +index eac5fac7e..dcc6df496 100644 +--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc ++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc +@@ -108,6 +108,37 @@ along with GCC; see the file COPYING3. If not see + #include "cfgloop.h" + #include "langhooks.h" + ++/* Check whether in C language or LTO with only C language. */ ++ ++bool ++lang_c_p (void) ++{ ++ const char *language_string = lang_hooks.name; ++ ++ if (!language_string) ++ return false; ++ ++ if (lang_GNU_C ()) ++ return true; ++ else if (strcmp (language_string, "GNU GIMPLE") == 0) // for LTO check ++ { ++ unsigned i = 0; ++ tree t = NULL_TREE; ++ ++ FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t) ++ { ++ language_string = TRANSLATION_UNIT_LANGUAGE (t); ++ if (language_string == NULL ++ || strncmp (language_string, "GNU C", 5) ++ || (language_string[5] != '\0' ++ && !(ISDIGIT (language_string[5])))) ++ return false; ++ } ++ return true; ++ } ++ return false; ++} ++ + namespace { + + using namespace struct_reorg; +@@ -198,37 +229,6 @@ gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type, + GSI_SAME_STMT); + } + +-/* Check whether in C language or LTO with only C language. */ +- +-static bool +-lang_c_p (void) +-{ +- const char *language_string = lang_hooks.name; +- +- if (!language_string) +- return false; +- +- if (lang_GNU_C ()) +- return true; +- else if (strcmp (language_string, "GNU GIMPLE") == 0) // For LTO check +- { +- unsigned i = 0; +- tree t = NULL_TREE; +- +- FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t) +- { +- language_string = TRANSLATION_UNIT_LANGUAGE (t); +- if (language_string == NULL +- || strncmp (language_string, "GNU C", 5) +- || (language_string[5] != '\0' +- && !(ISDIGIT (language_string[5])))) +- return false; +- } +- return true; +- } +- return false; +-} +- + /* Get the number of pointer layers. */ + + int +@@ -262,29 +262,23 @@ is_from_void_ptr_parm (tree ssa_name) + && VOID_POINTER_P (TREE_TYPE (ssa_name))); + } + +-enum srmode +-{ +- NORMAL = 0, +- COMPLETE_STRUCT_RELAYOUT, +- STRUCT_REORDER_FIELDS +-}; +- + /* Enum the struct layout optimize level, + which should be the same as the option -fstruct-reorg=. */ + + enum struct_layout_opt_level + { + NONE = 0, +- STRUCT_REORG, +- STRUCT_REORDER_FIELDS_SLO, +- DEAD_FIELD_ELIMINATION ++ STRUCT_SPLIT = 1 << 0, ++ COMPLETE_STRUCT_RELAYOUT = 1 << 1, ++ STRUCT_REORDER_FIELDS = 1 << 2, ++ DEAD_FIELD_ELIMINATION = 1 << 3 + }; + + static bool is_result_of_mult (tree arg, tree *num, tree struct_size); + static bool isptrptr (tree type); + void get_base (tree &base, tree expr); + +-srmode current_mode; ++static unsigned int current_layout_opt_level; + hash_map replace_type_map; + + /* Return true if one of these types is created by struct-reorg. */ +@@ -626,7 +620,7 @@ void + srtype::simple_dump (FILE *f) + { + print_generic_expr (f, type); +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + fprintf (f, "(%d)", TYPE_UID (type)); + } + +@@ -673,7 +667,7 @@ srfield::create_new_fields (tree newtype[max_split], + tree newfields[max_split], + tree newlast[max_split]) + { +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + create_new_reorder_fields (newtype, newfields, newlast); + return; +@@ -861,7 +855,7 @@ srtype::create_new_type (void) + we are not splitting the struct into two clusters, + then just return false and don't change the type. */ + if (!createnewtype && maxclusters == 0 +- && current_mode != STRUCT_REORDER_FIELDS) ++ && current_layout_opt_level < STRUCT_REORDER_FIELDS) + { + newtype[0] = type; + return false; +@@ -889,8 +883,7 @@ srtype::create_new_type (void) + sprintf (id, "%d", i); + if (tname) + { +- name = concat (tname, current_mode == STRUCT_REORDER_FIELDS +- ? ".reorder." : ".reorg.", id, NULL); ++ name = concat (tname, ".reorg.", id, NULL); + TYPE_NAME (newtype[i]) = build_decl (UNKNOWN_LOCATION, + TYPE_DECL, + get_identifier (name), +@@ -902,8 +895,7 @@ srtype::create_new_type (void) + for (unsigned i = 0; i < fields.length (); i++) + { + srfield *f = fields[i]; +- if (current_mode == STRUCT_REORDER_FIELDS +- && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION ++ if (current_layout_opt_level & DEAD_FIELD_ELIMINATION + && !(f->field_access & READ_FIELD)) + continue; + f->create_new_fields (newtype, newfields, newlast); +@@ -924,13 +916,12 @@ srtype::create_new_type (void) + + warn_padded = save_warn_padded; + +- if (current_mode == STRUCT_REORDER_FIELDS ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && replace_type_map.get (this->newtype[0]) == NULL) + replace_type_map.put (this->newtype[0], this->type); + if (dump_file) + { +- if (current_mode == STRUCT_REORDER_FIELDS +- && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION ++ if (current_layout_opt_level & DEAD_FIELD_ELIMINATION + && has_dead_field ()) + fprintf (dump_file, "Dead field elimination.\n"); + } +@@ -1052,8 +1043,7 @@ srfunction::create_new_decls (void) + sprintf (id, "%d", j); + if (tname) + { +- name = concat (tname, current_mode == STRUCT_REORDER_FIELDS +- ? ".reorder." : ".reorg.", id, NULL); ++ name = concat (tname, ".reorg.", id, NULL); + new_name = get_identifier (name); + free (name); + } +@@ -1264,7 +1254,7 @@ public: + bool done_recording; + + // Methods +- unsigned execute (enum srmode mode); ++ unsigned execute (unsigned int opt); + void mark_type_as_escape (tree type, escape_type escapes, + gimple *stmt = NULL); + +@@ -2651,7 +2641,7 @@ escape_type_volatile_array_or_ptrptr (tree type) + return escape_volatile; + if (isarraytype (type)) + return escape_array; +- if (isptrptr (type) && (current_mode != STRUCT_REORDER_FIELDS)) ++ if (isptrptr (type) && (current_layout_opt_level < STRUCT_REORDER_FIELDS)) + return escape_ptr_ptr; + return does_not_escape; + } +@@ -2672,12 +2662,11 @@ ipa_struct_reorg::record_field_type (tree field, srtype *base_srtype) + field_srfield->type = field_srtype; + field_srtype->add_field_site (field_srfield); + } +- if (field_srtype == base_srtype && current_mode != COMPLETE_STRUCT_RELAYOUT +- && current_mode != STRUCT_REORDER_FIELDS) ++ if (field_srtype == base_srtype && current_layout_opt_level == STRUCT_SPLIT) + base_srtype->mark_escape (escape_rescusive_type, NULL); + /* Types of non-pointer field are difficult to track the correctness + of the rewrite when it used by the escaped type. */ +- if (current_mode == STRUCT_REORDER_FIELDS ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && TREE_CODE (field_type) == RECORD_TYPE) + field_srtype->mark_escape (escape_instance_field, NULL); + } +@@ -2704,7 +2693,7 @@ ipa_struct_reorg::record_struct_field_types (tree base_type, + base_srtype->mark_escape (e, NULL); + /* Types of non-pointer field are difficult to track the correctness + of the rewrite when it used by the escaped type. */ +- if (current_mode == STRUCT_REORDER_FIELDS ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && TREE_CODE (field_type) == RECORD_TYPE) + base_srtype->mark_escape (escape_instance_field, NULL); + if (handled_type (field_type)) +@@ -2895,8 +2884,7 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg) + + /* Separate instance is hard to trace in complete struct + relayout optimization. */ +- if ((current_mode == COMPLETE_STRUCT_RELAYOUT +- || current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT + && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE) + e = escape_separate_instance; + +@@ -3000,7 +2988,7 @@ ipa_struct_reorg::find_vars (gimple *stmt) + /* Add a safe func mechanism. */ + bool l_find = true; + bool r_find = true; +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + l_find = !(current_function->is_safe_func + && TREE_CODE (lhs) == SSA_NAME +@@ -3046,7 +3034,7 @@ ipa_struct_reorg::find_vars (gimple *stmt) + } + } + } +- else if ((current_mode == STRUCT_REORDER_FIELDS) ++ else if ((current_layout_opt_level >= STRUCT_REORDER_FIELDS) + && (gimple_assign_rhs_code (stmt) == LE_EXPR + || gimple_assign_rhs_code (stmt) == LT_EXPR + || gimple_assign_rhs_code (stmt) == GE_EXPR +@@ -3057,7 +3045,7 @@ ipa_struct_reorg::find_vars (gimple *stmt) + find_var (gimple_assign_rhs2 (stmt), stmt); + } + /* Find void ssa_name from stmt such as: _2 = _1 - old_arcs_1. */ +- else if ((current_mode == STRUCT_REORDER_FIELDS) ++ else if ((current_layout_opt_level >= STRUCT_REORDER_FIELDS) + && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR + && types_compatible_p ( + TYPE_MAIN_VARIANT (TREE_TYPE (gimple_assign_rhs1 (stmt))), +@@ -3270,8 +3258,7 @@ ipa_struct_reorg::maybe_record_stmt (cgraph_node *node, gimple *stmt) + default: + break; + } +- if (current_mode == STRUCT_REORDER_FIELDS +- && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION) ++ if (current_layout_opt_level & DEAD_FIELD_ELIMINATION) + { + /* Look for loads and stores. */ + walk_stmt_load_store_ops (stmt, this, find_field_p_load, +@@ -3427,9 +3414,11 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + arg = gimple_assign_rhs1 (size_def_stmt); + size_def_stmt = SSA_NAME_DEF_STMT (arg); + } +- else if (rhs_code == NEGATE_EXPR && current_mode == STRUCT_REORDER_FIELDS) ++ else if (rhs_code == NEGATE_EXPR ++ && current_layout_opt_level >= STRUCT_REORDER_FIELDS) + return trace_calculate_negate (size_def_stmt, num, struct_size); +- else if (rhs_code == NOP_EXPR && current_mode == STRUCT_REORDER_FIELDS) ++ else if (rhs_code == NOP_EXPR ++ && current_layout_opt_level >= STRUCT_REORDER_FIELDS) + return trace_calculate_diff (size_def_stmt, num); + else + { +@@ -3447,15 +3436,15 @@ is_result_of_mult (tree arg, tree *num, tree struct_size) + bool + ipa_struct_reorg::handled_allocation_stmt (gimple *stmt) + { +- if ((current_mode == STRUCT_REORDER_FIELDS) ++ if ((current_layout_opt_level >= STRUCT_REORDER_FIELDS) + && (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) + || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) + || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))) + return true; +- if ((current_mode == COMPLETE_STRUCT_RELAYOUT) ++ if ((current_layout_opt_level == COMPLETE_STRUCT_RELAYOUT) + && gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)) + return true; +- if ((current_mode == NORMAL) ++ if ((current_layout_opt_level == STRUCT_SPLIT) + && (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC) + || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC) + || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC) +@@ -3576,7 +3565,7 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other, + /* x_1 = y.x_nodes; void *x; + Directly mark the structure pointer type assigned + to the void* variable as escape. */ +- else if (current_mode == STRUCT_REORDER_FIELDS ++ else if (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && TREE_CODE (side) == SSA_NAME + && VOID_POINTER_P (TREE_TYPE (side)) + && SSA_NAME_VAR (side) +@@ -3834,7 +3823,7 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + and doesn't mark escape follow.). */ + /* _1 = MEM[(struct arc_t * *)a_1]. + then base a_1: ssa_name - pointer_type - integer_type. */ +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + bool is_int_ptr = POINTER_TYPE_P (TREE_TYPE (base)) + && (TREE_CODE (inner_type (TREE_TYPE (base))) +@@ -3896,7 +3885,7 @@ ipa_struct_reorg::get_type_field (tree expr, tree &base, bool &indirect, + /* Escape the operation of fetching field with pointer offset such as: + *(&(t->right)) = malloc (0); -> MEM[(struct node * *)_1 + 8B] = malloc (0); + */ +- if (current_mode != NORMAL ++ if (current_layout_opt_level > STRUCT_SPLIT + && (TREE_CODE (expr) == MEM_REF) && (offset != 0)) + { + gcc_assert (can_escape); +@@ -4060,7 +4049,7 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt) + /* callee_func (_1, _2); + Check the callee func, instead of current func. */ + if (!(free_or_realloc +- || (current_mode == STRUCT_REORDER_FIELDS ++ || (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && safe_functions.contains ( + node->get_edge (stmt)->callee))) + && VOID_POINTER_P (argtypet)) +@@ -4088,12 +4077,7 @@ ipa_struct_reorg::record_stmt_expr (tree expr, cgraph_node *node, gimple *stmt) + realpart, imagpart, address, escape_from_base)) + return; + +- if (current_mode == STRUCT_REORDER_FIELDS) +- { +- if (!opt_for_fn (current_function_decl, flag_ipa_reorder_fields)) +- type->mark_escape (escape_non_optimize, stmt); +- } +- else ++ if (current_layout_opt_level > NONE) + { + if (!opt_for_fn (current_function_decl, flag_ipa_struct_reorg)) + type->mark_escape (escape_non_optimize, stmt); +@@ -4197,7 +4181,7 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl, + void + ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type) + { +- if (current_mode == COMPLETE_STRUCT_RELAYOUT ++ if (current_layout_opt_level == COMPLETE_STRUCT_RELAYOUT + && handled_allocation_stmt (stmt)) + { + tree arg0 = gimple_call_arg (stmt, 0); +@@ -4291,7 +4275,7 @@ ipa_struct_reorg::check_definition_call (srdecl *decl, vec &worklist) + if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)) + check_type_and_push (gimple_call_arg (stmt, 0), decl, worklist, stmt); + +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + if (!handled_allocation_stmt (stmt)) + type->mark_escape (escape_return, stmt); +@@ -4341,7 +4325,8 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist) + type->mark_escape (escape_cast_void, SSA_NAME_DEF_STMT (ssa_name)); + return; + } +- if (current_mode == STRUCT_REORDER_FIELDS && SSA_NAME_VAR (ssa_name) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS ++ && SSA_NAME_VAR (ssa_name) + && VOID_POINTER_P (TREE_TYPE (SSA_NAME_VAR (ssa_name)))) + type->mark_escape (escape_cast_void, SSA_NAME_DEF_STMT (ssa_name)); + gimple *stmt = SSA_NAME_DEF_STMT (ssa_name); +@@ -4425,7 +4410,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, + { + /* In Complete Struct Relayout, if lhs type is the same + as rhs type, we could return without any harm. */ +- if (current_mode == COMPLETE_STRUCT_RELAYOUT) ++ if (current_layout_opt_level == COMPLETE_STRUCT_RELAYOUT) + return; + + tree base; +@@ -4437,7 +4422,7 @@ ipa_struct_reorg::check_other_side (srdecl *decl, tree other, gimple *stmt, + if (!get_type_field (other, base, indirect, type1, field, + realpart, imagpart, address, escape_from_base)) + { +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + /* Release INTEGER_TYPE cast to struct pointer. */ + bool cast_from_int_ptr = current_function->is_safe_func && base +@@ -4487,7 +4472,8 @@ get_base (tree &base, tree expr) + void + ipa_struct_reorg::check_ptr_layers (tree a_expr, tree b_expr, gimple *stmt) + { +- if (current_mode != STRUCT_REORDER_FIELDS || current_function->is_safe_func ++ if (current_layout_opt_level < STRUCT_REORDER_FIELDS ++ || current_function->is_safe_func + || !(POINTER_TYPE_P (TREE_TYPE (a_expr))) + || !(POINTER_TYPE_P (TREE_TYPE (b_expr))) + || !handled_type (TREE_TYPE (a_expr)) +@@ -4554,12 +4540,9 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree rhs2 = gimple_cond_rhs (stmt); + tree orhs = rhs1; + enum tree_code code = gimple_cond_code (stmt); +- if ((current_mode == NORMAL && (code != EQ_EXPR && code != NE_EXPR)) +- || (current_mode == COMPLETE_STRUCT_RELAYOUT +- && (code != EQ_EXPR && code != NE_EXPR +- && code != LT_EXPR && code != LE_EXPR +- && code != GT_EXPR && code != GE_EXPR)) +- || (current_mode == STRUCT_REORDER_FIELDS ++ if ((current_layout_opt_level == STRUCT_SPLIT ++ && (code != EQ_EXPR && code != NE_EXPR)) ++ || (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT + && (code != EQ_EXPR && code != NE_EXPR + && code != LT_EXPR && code != LE_EXPR + && code != GT_EXPR && code != GE_EXPR))) +@@ -4592,15 +4575,12 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt, + tree rhs2 = gimple_assign_rhs2 (stmt); + tree orhs = rhs1; + enum tree_code code = gimple_assign_rhs_code (stmt); +- if ((current_mode == NORMAL && (code != EQ_EXPR && code != NE_EXPR)) +- || (current_mode == COMPLETE_STRUCT_RELAYOUT +- && (code != EQ_EXPR && code != NE_EXPR +- && code != LT_EXPR && code != LE_EXPR +- && code != GT_EXPR && code != GE_EXPR)) +- || (current_mode == STRUCT_REORDER_FIELDS ++ if ((current_layout_opt_level == STRUCT_SPLIT ++ && (code != EQ_EXPR && code != NE_EXPR)) ++ || (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT + && (code != EQ_EXPR && code != NE_EXPR + && code != LT_EXPR && code != LE_EXPR +- && code != GT_EXPR && code != GE_EXPR))) ++ && code != GT_EXPR && code != GE_EXPR))) + { + mark_expr_escape (rhs1, escape_non_eq, stmt); + mark_expr_escape (rhs2, escape_non_eq, stmt); +@@ -4722,9 +4702,9 @@ ipa_struct_reorg::record_function (cgraph_node *node) + escapes = escape_marked_as_used; + else if (!node->local) + { +- if (current_mode != STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level < STRUCT_REORDER_FIELDS) + escapes = escape_visible_function; +- if (current_mode == STRUCT_REORDER_FIELDS && node->externally_visible) ++ else if (node->externally_visible) + escapes = escape_visible_function; + } + else if (!node->can_change_signature) +@@ -4732,12 +4712,7 @@ ipa_struct_reorg::record_function (cgraph_node *node) + else if (!tree_versionable_function_p (node->decl)) + escapes = escape_noclonable_function; + +- if (current_mode == STRUCT_REORDER_FIELDS) +- { +- if (!opt_for_fn (node->decl, flag_ipa_reorder_fields)) +- escapes = escape_non_optimize; +- } +- else if (current_mode == NORMAL || current_mode == COMPLETE_STRUCT_RELAYOUT) ++ if (current_layout_opt_level > NONE) + { + if (!opt_for_fn (node->decl, flag_ipa_struct_reorg)) + escapes = escape_non_optimize; +@@ -4747,10 +4722,10 @@ ipa_struct_reorg::record_function (cgraph_node *node) + gimple_stmt_iterator si; + + /* Add a safe func mechanism. */ +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + current_function->is_safe_func = safe_functions.contains (node); +- if (dump_file) ++ if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "\nfunction %s/%u: is_safe_func = %d\n", + node->name (), node->order, +@@ -4958,7 +4933,7 @@ ipa_struct_reorg::record_accesses (void) + } + + /* Add a safe func mechanism. */ +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + record_safe_func_with_void_ptr_parm (); + + FOR_EACH_FUNCTION (cnode) +@@ -5174,8 +5149,7 @@ ipa_struct_reorg::propagate_escape_via_ext_func_types (void) + void + ipa_struct_reorg::prune_escaped_types (void) + { +- if (current_mode != COMPLETE_STRUCT_RELAYOUT +- && current_mode != STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level == STRUCT_SPLIT) + { + /* Detect recusive types and mark them as escaping. */ + detect_cycles (); +@@ -5183,7 +5157,7 @@ ipa_struct_reorg::prune_escaped_types (void) + mark them as escaping. */ + propagate_escape (); + } +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + propagate_escape_via_original (); + propagate_escape_via_empty_with_no_original (); +@@ -5244,7 +5218,7 @@ ipa_struct_reorg::prune_escaped_types (void) + if (function->args.is_empty () + && function->decls.is_empty () + && function->globals.is_empty () +- && current_mode != STRUCT_REORDER_FIELDS) ++ && current_layout_opt_level < STRUCT_REORDER_FIELDS) + { + delete function; + functions.ordered_remove (i); +@@ -5272,7 +5246,7 @@ ipa_struct_reorg::prune_escaped_types (void) + /* The escape type is not deleted in STRUCT_REORDER_FIELDS, + Then the type that contains the escaped type fields + can find complete information. */ +- if (current_mode != STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level < STRUCT_REORDER_FIELDS) + { + for (unsigned i = 0; i < types.length ();) + { +@@ -5320,7 +5294,7 @@ ipa_struct_reorg::create_new_types (void) + for (unsigned i = 0; i < types.length (); i++) + newtypes += types[i]->create_new_type (); + +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + for (unsigned i = 0; i < types.length (); i++) + { +@@ -5444,8 +5418,7 @@ ipa_struct_reorg::create_new_args (cgraph_node *new_node) + char *name = NULL; + if (tname) + { +- name = concat (tname, current_mode == STRUCT_REORDER_FIELDS +- ? ".reorder.0" : ".reorg.0", NULL); ++ name = concat (tname, ".reorg.0", NULL); + new_name = get_identifier (name); + free (name); + } +@@ -5532,9 +5505,7 @@ ipa_struct_reorg::create_new_functions (void) + } + statistics_counter_event (NULL, "Create new function", 1); + new_node = node->create_version_clone_with_body ( +- vNULL, NULL, NULL, NULL, NULL, +- current_mode == STRUCT_REORDER_FIELDS +- ? "struct_reorder" : "struct_reorg"); ++ vNULL, NULL, NULL, NULL, NULL, "struct_reorg"); + new_node->can_change_signature = node->can_change_signature; + new_node->make_local (); + f->newnode = new_node; +@@ -5661,7 +5632,7 @@ ipa_struct_reorg::rewrite_expr (tree expr, + newbase1 = build_fold_addr_expr (newbase1); + if (indirect) + { +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + /* Supports the MEM_REF offset. + _1 = MEM[(struct arc *)ap_1 + 72B].flow; +@@ -5719,8 +5690,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + { + bool remove = false; + +- if (current_mode == STRUCT_REORDER_FIELDS +- && struct_layout_optimize_level >= DEAD_FIELD_ELIMINATION ++ if (current_layout_opt_level & DEAD_FIELD_ELIMINATION + && remove_dead_field_stmt (gimple_assign_lhs (stmt))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) +@@ -5756,10 +5726,10 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + return remove; + } + +- if ((current_mode != STRUCT_REORDER_FIELDS ++ if ((current_layout_opt_level < STRUCT_REORDER_FIELDS + && (gimple_assign_rhs_code (stmt) == EQ_EXPR + || gimple_assign_rhs_code (stmt) == NE_EXPR)) +- || (current_mode == STRUCT_REORDER_FIELDS ++ || (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) + == tcc_comparison))) + { +@@ -5769,7 +5739,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + tree newrhs2[max_split]; + tree_code rhs_code = gimple_assign_rhs_code (stmt); + tree_code code = rhs_code == EQ_EXPR ? BIT_AND_EXPR : BIT_IOR_EXPR; +- if (current_mode == STRUCT_REORDER_FIELDS ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && rhs_code != EQ_EXPR && rhs_code != NE_EXPR) + code = rhs_code; + +@@ -5818,8 +5788,9 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + _6 = _4 + _5; + _5 = (long unsigned int) _3; + _3 = _1 - old_2. */ +- if (current_mode != STRUCT_REORDER_FIELDS +- || (current_mode == STRUCT_REORDER_FIELDS && (num != NULL))) ++ if (current_layout_opt_level < STRUCT_REORDER_FIELDS ++ || (current_layout_opt_level >= STRUCT_REORDER_FIELDS ++ && (num != NULL))) + num = gimplify_build1 (gsi, NOP_EXPR, sizetype, num); + for (unsigned i = 0; i < max_split && newlhs[i]; i++) + { +@@ -5843,7 +5814,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi) + } + + /* Support POINTER_DIFF_EXPR rewriting. */ +- if (current_mode == STRUCT_REORDER_FIELDS ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && gimple_assign_rhs_code (stmt) == POINTER_DIFF_EXPR) + { + tree rhs1 = gimple_assign_rhs1 (stmt); +@@ -6026,7 +5997,8 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi) + srfunction *f = find_function (node); + + /* Add a safe func mechanism. */ +- if (current_mode == STRUCT_REORDER_FIELDS && f && f->is_safe_func) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS ++ && f && f->is_safe_func) + { + tree expr = gimple_call_arg (stmt, 0); + tree newexpr[max_split]; +@@ -6152,9 +6124,9 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi) + tree_code rhs_code = gimple_cond_code (stmt); + + /* Handle only equals or not equals conditionals. */ +- if ((current_mode != STRUCT_REORDER_FIELDS ++ if ((current_layout_opt_level < STRUCT_REORDER_FIELDS + && (rhs_code != EQ_EXPR && rhs_code != NE_EXPR)) +- || (current_mode == STRUCT_REORDER_FIELDS ++ || (current_layout_opt_level >= STRUCT_REORDER_FIELDS + && TREE_CODE_CLASS (rhs_code) != tcc_comparison)) + return false; + tree lhs = gimple_cond_lhs (stmt); +@@ -6208,7 +6180,7 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi) + bool + ipa_struct_reorg::rewrite_debug (gimple *stmt, gimple_stmt_iterator *) + { +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + /* Delete debug gimple now. */ + return true; + bool remove = false; +@@ -6367,7 +6339,7 @@ ipa_struct_reorg::rewrite_functions (void) + then don't rewrite any accesses. */ + if (!create_new_types ()) + { +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + for (unsigned i = 0; i < functions.length (); i++) + { +@@ -6386,7 +6358,7 @@ ipa_struct_reorg::rewrite_functions (void) + return 0; + } + +- if (current_mode == STRUCT_REORDER_FIELDS && dump_file) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS && dump_file) + { + fprintf (dump_file, "=========== all created newtypes: ===========\n\n"); + dump_newtypes (dump_file); +@@ -6396,13 +6368,13 @@ ipa_struct_reorg::rewrite_functions (void) + { + retval = TODO_remove_functions; + create_new_functions (); +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + prune_escaped_types (); + } + } + +- if (current_mode == STRUCT_REORDER_FIELDS) ++ if (current_layout_opt_level >= STRUCT_REORDER_FIELDS) + { + for (unsigned i = 0; i < functions.length (); i++) + { +@@ -6559,33 +6531,33 @@ ipa_struct_reorg::execute_struct_relayout (void) + } + + unsigned int +-ipa_struct_reorg::execute (enum srmode mode) ++ipa_struct_reorg::execute (unsigned int opt) + { + unsigned int ret = 0; + + if (dump_file) + fprintf (dump_file, "\n\n====== ipa_struct_reorg level %d ======\n\n", +- mode); ++ opt); + +- if (mode == NORMAL || mode == STRUCT_REORDER_FIELDS) ++ if (opt != COMPLETE_STRUCT_RELAYOUT) + { +- current_mode = mode; ++ current_layout_opt_level = opt; + /* If there is a top-level inline-asm, + the pass immediately returns. */ + if (symtab->first_asm_symbol ()) + return 0; + record_accesses (); + prune_escaped_types (); +- if (current_mode == NORMAL) ++ if (current_layout_opt_level == STRUCT_SPLIT) + analyze_types (); + + ret = rewrite_functions (); + } +- else if (mode == COMPLETE_STRUCT_RELAYOUT) ++ else + { + if (dump_file) + fprintf (dump_file, "\n\nTry Complete Struct Relayout:\n"); +- current_mode = COMPLETE_STRUCT_RELAYOUT; ++ current_layout_opt_level = COMPLETE_STRUCT_RELAYOUT; + if (symtab->first_asm_symbol ()) + return 0; + record_accesses (); +@@ -6622,10 +6594,37 @@ public: + virtual unsigned int execute (function *) + { + unsigned int ret = 0; +- ret = ipa_struct_reorg ().execute (NORMAL); +- if (!ret) +- ret = ipa_struct_reorg ().execute (COMPLETE_STRUCT_RELAYOUT); +- return ret; ++ unsigned int ret_reorg = 0; ++ unsigned int level = 0; ++ switch (struct_layout_optimize_level) ++ { ++ case 3: level |= DEAD_FIELD_ELIMINATION; ++ // FALLTHRU ++ case 2: level |= STRUCT_REORDER_FIELDS; ++ // FALLTHRU ++ case 1: ++ level |= COMPLETE_STRUCT_RELAYOUT; ++ level |= STRUCT_SPLIT; ++ break; ++ case 0: break; ++ default: gcc_unreachable (); ++ } ++ /* Preserved for backward compatibility, reorder fields needs run before ++ struct split and complete struct relayout. */ ++ if (flag_ipa_reorder_fields && level < STRUCT_REORDER_FIELDS) ++ ret = ipa_struct_reorg ().execute (STRUCT_REORDER_FIELDS); ++ ++ if (level >= STRUCT_REORDER_FIELDS) ++ ret = ipa_struct_reorg ().execute (level); ++ ++ if (level >= COMPLETE_STRUCT_RELAYOUT) ++ { ++ /* Preserved for backward compatibility. */ ++ ret_reorg = ipa_struct_reorg ().execute (STRUCT_SPLIT); ++ if (!ret_reorg) ++ ret_reorg = ipa_struct_reorg ().execute (COMPLETE_STRUCT_RELAYOUT); ++ } ++ return ret | ret_reorg; + } + + }; // class pass_ipa_struct_reorg +@@ -6645,52 +6644,6 @@ pass_ipa_struct_reorg::gate (function *) + && (in_lto_p || flag_whole_program)); + } + +-const pass_data pass_data_ipa_reorder_fields = +-{ +- SIMPLE_IPA_PASS, // type +- "reorder_fields", // name +- OPTGROUP_NONE, // optinfo_flags +- TV_IPA_REORDER_FIELDS, // tv_id +- 0, // properties_required +- 0, // properties_provided +- 0, // properties_destroyed +- 0, // todo_flags_start +- 0, // todo_flags_finish +-}; +- +-class pass_ipa_reorder_fields : public simple_ipa_opt_pass +-{ +-public: +- pass_ipa_reorder_fields (gcc::context *ctxt) +- : simple_ipa_opt_pass (pass_data_ipa_reorder_fields, ctxt) +- {} +- +- /* opt_pass methods: */ +- virtual bool gate (function *); +- virtual unsigned int execute (function *) +- { +- unsigned int ret = 0; +- ret = ipa_struct_reorg ().execute (STRUCT_REORDER_FIELDS); +- return ret; +- } +- +-}; // class pass_ipa_reorder_fields +- +-bool +-pass_ipa_reorder_fields::gate (function *) +-{ +- return (optimize >= 3 +- && flag_ipa_reorder_fields +- /* Don't bother doing anything if the program has errors. */ +- && !seen_error () +- && flag_lto_partition == LTO_PARTITION_ONE +- /* Only enable struct optimizations in C since other +- languages' grammar forbid. */ +- && lang_c_p () +- /* Only enable struct optimizations in lto or whole_program. */ +- && (in_lto_p || flag_whole_program)); +-} +- + } // anon namespace + + +@@ -6699,9 +6652,3 @@ make_pass_ipa_struct_reorg (gcc::context *ctxt) + { + return new pass_ipa_struct_reorg (ctxt); + } +- +-simple_ipa_opt_pass * +-make_pass_ipa_reorder_fields (gcc::context *ctxt) +-{ +- return new pass_ipa_reorder_fields (ctxt); +-} +diff --git a/gcc/passes.def b/gcc/passes.def +index bdc835b87..9692066e4 100644 +--- a/gcc/passes.def ++++ b/gcc/passes.def +@@ -178,7 +178,6 @@ along with GCC; see the file COPYING3. If not see + compiled unit. */ + INSERT_PASSES_AFTER (all_late_ipa_passes) + NEXT_PASS (pass_ipa_pta); +- NEXT_PASS (pass_ipa_reorder_fields); + /* FIXME: this should be a normal IP pass. */ + NEXT_PASS (pass_ipa_struct_reorg); + NEXT_PASS (pass_omp_simd_clone); +diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h +index 6fa529eee..3fe64047c 100644 +--- a/gcc/symbol-summary.h ++++ b/gcc/symbol-summary.h +@@ -105,7 +105,7 @@ protected: + { + /* In structure optimizatons, we call new to ensure that + the allocated memory is initialized to 0. */ +- if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) ++ if (flag_ipa_struct_reorg) + return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () + : new T (); + +@@ -122,7 +122,7 @@ protected: + ggc_delete (item); + else + { +- if (flag_ipa_struct_reorg || flag_ipa_reorder_fields) ++ if (flag_ipa_struct_reorg) + delete item; + else + m_allocator.remove (item); +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c +index 0c9e384c4..afa181e07 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_DTE_verify.c +@@ -83,4 +83,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c +index 717fcc386..c87db2aba 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ele_minus_verify.c +@@ -57,4 +57,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c +index 7723c240b..d217f7bd8 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_board_init.c +@@ -74,4 +74,4 @@ LBF_DFU_If_Needed (void) + } + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c +index a1feac966..f9e2cf471 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_claw.c +@@ -81,4 +81,4 @@ claw_snd_conn_req (struct net_device *dev, __u8 link) + return rc; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c +index fd1e936ca..c86c4bb3c 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_dtrace.c +@@ -53,4 +53,4 @@ dtrace_bcmp (const void *s1, const void *s2, size_t len) + return (0); + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c +index b13d785a9..8484d29d2 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_gc.c +@@ -159,4 +159,4 @@ gc_gray_mark (mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) + return children; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c +index bc28a658a..300b2dac4 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_hpsa.c +@@ -123,4 +123,4 @@ hpsa_cmd_dev_match (struct ctlr_info *h, struct CommandList *c, + return match; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c +index 0a585ac3d..9397b98ea 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_mv_udc_core.c +@@ -79,4 +79,4 @@ ep0_reset (struct mv_udc *udc) + } + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c +index bddd862fe..0ae75e13e 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_tcp_usrreq.c +@@ -55,4 +55,4 @@ tcp_usr_listen (struct socket *so, struct proc *p) + COMMON_END (PRU_LISTEN); + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c +index 1a06f5eec..512fb37a7 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_extr_ui_main.c +@@ -58,4 +58,4 @@ UI_LoadMods () + } + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 1 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c +index 94eb88d5c..0dea5517c 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_mem_ref_offset.c +@@ -55,4 +55,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c +index bbf9420d0..00bd911c1 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_mul_layer_ptr_record_bug.c +@@ -27,4 +27,4 @@ main() { + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c +index f706db968..0cfa6554e 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_diff.c +@@ -68,4 +68,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 3 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 3 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c +index 963295cb4..4a7069244 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_negate_expr.c +@@ -52,4 +52,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c +index aa10506a1..b91efe10f 100644 +--- a/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c ++++ b/gcc/testsuite/gcc.dg/struct/dfe_ptr_ptr.c +@@ -52,4 +52,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "reorder_fields" } } */ ++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 2 "struct_reorg" } } */ +diff --git a/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c b/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c +index b95be2dab..1b6a462e2 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_DTE_struct_instance_field.c +@@ -72,4 +72,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c b/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c +index 3d243313b..346c71264 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_DTE_verify.c +@@ -91,4 +91,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c b/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c +index faaf1e3a5..b876fef86 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_check_ptr_layers_bug.c +@@ -21,4 +21,4 @@ main() + { + g(); + } +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c b/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c +index 886706ae9..7d7641f01 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_create_fields_bug.c +@@ -79,4 +79,4 @@ main() + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c b/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c +index f3785f392..63fb3f828 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_create_new_func_bug.c +@@ -53,4 +53,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c b/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c +index 1415d759a..8c431e15f 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ele_minus_verify.c +@@ -57,4 +57,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c b/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c +index 003da0b57..efc95a4cd 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_escape_by_base.c +@@ -80,4 +80,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c b/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c +index 84a34f241..2a9bea783 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_external_func_types.c +@@ -66,4 +66,4 @@ test () + return 0; + } + +-/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c +index 10dcf098c..75fc10575 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_int_cast_ptr.c +@@ -69,4 +69,4 @@ main() + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c b/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c +index 8d1a9a114..9fb06877b 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_mem_ref_offset.c +@@ -55,4 +55,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c b/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c +index 23765fc56..e8eb0eaa0 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_mul_layer_ptr_record_bug.c +@@ -27,4 +27,4 @@ main() { + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c +index 54e737ee8..bd535afd0 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_pass_conflict.c +@@ -106,4 +106,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c b/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c +index 2ae46fb31..11393a197 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr2void_lto.c +@@ -84,4 +84,4 @@ main () + return cnt; + } + +-/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c +index 3a3c10b70..d601fae64 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_diff.c +@@ -68,4 +68,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c +index 7b7d110df..4d5f25aa1 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_negate_expr.c +@@ -52,4 +52,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c +index 317aafa5f..b3891fde9 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_offset.c +@@ -31,4 +31,4 @@ main () + printf (" Tree.\n"); + } + +-/* { dg-final { scan-ipa-dump "No structures to transform." "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "No structures to transform." "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c +index 01a33f669..4df79e4f0 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr.c +@@ -52,4 +52,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c +index a38556533..49d2106d1 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_ptr_ptr_ptr.c +@@ -55,4 +55,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c b/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c +index 5c17ee528..f71c7894f 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_rescusive_type.c +@@ -54,4 +54,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c +index 710517ee9..721cee2c6 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_assign_more_cmp.c +@@ -62,4 +62,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c +index 6ed0a5d2d..3871d3d99 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_bug.c +@@ -69,4 +69,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c +index 5a2dd964f..5ad206433 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_cond_more_cmp.c +@@ -55,4 +55,4 @@ main() + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c +index faa90b42d..a002f9889 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_phi_bug.c +@@ -78,4 +78,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 3" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_visible_func.c b/gcc/testsuite/gcc.dg/struct/rf_visible_func.c +index 8f2da99cc..f77a062bd 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_visible_func.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_visible_func.c +@@ -89,4 +89,4 @@ main () + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 2" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c b/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c +index 723142c59..cba6225a5 100644 +--- a/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c ++++ b/gcc/testsuite/gcc.dg/struct/rf_void_ptr_param_func.c +@@ -51,4 +51,4 @@ main() + return 0; + } + +-/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "reorder_fields" } } */ +\ No newline at end of file ++/* { dg-final { scan-ipa-dump "Number of structures to transform is 1" "struct_reorg" } } */ +\ No newline at end of file +diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +index 6ccb753b5..278c4e4f5 100644 +--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp ++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +@@ -45,7 +45,7 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \ + + # -fipa-struct-reorg=3 + gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \ +- "" "-fipa-reorder-fields -fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program" ++ "" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program" + + # All done. + torture-finish +diff --git a/gcc/timevar.def b/gcc/timevar.def +index 2b27c858a..98a5a490f 100644 +--- a/gcc/timevar.def ++++ b/gcc/timevar.def +@@ -80,7 +80,6 @@ DEFTIMEVAR (TV_IPA_CONSTANT_PROP , "ipa cp") + DEFTIMEVAR (TV_IPA_INLINING , "ipa inlining heuristics") + DEFTIMEVAR (TV_IPA_FNSPLIT , "ipa function splitting") + DEFTIMEVAR (TV_IPA_COMDATS , "ipa comdats") +-DEFTIMEVAR (TV_IPA_REORDER_FIELDS , "ipa struct reorder fields optimization") + DEFTIMEVAR (TV_IPA_STRUCT_REORG , "ipa struct reorg optimization") + DEFTIMEVAR (TV_IPA_OPT , "ipa various optimizations") + DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS , "lto stream decompression") +diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h +index a9ec8ed21..56898e019 100644 +--- a/gcc/tree-pass.h ++++ b/gcc/tree-pass.h +@@ -527,7 +527,6 @@ extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt); + extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt); +-extern simple_ipa_opt_pass *make_pass_ipa_reorder_fields (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt); + extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt); +-- +2.33.0 + diff --git a/0025-AArch64-Rewrite-the-tsv110-option.patch b/0025-AArch64-Rewrite-the-tsv110-option.patch new file mode 100644 index 0000000..d2e0dcd --- /dev/null +++ b/0025-AArch64-Rewrite-the-tsv110-option.patch @@ -0,0 +1,114 @@ +From 2f0d0b1298fb9c3266bb102796b027a5570ad833 Mon Sep 17 00:00:00 2001 +From: dingguangya +Date: Mon, 4 Sep 2023 16:27:38 +0800 +Subject: [PATCH 1/2] [AArch64] Rewrite the tsv110 option + +Reset the more appropriate options for tsv110. +--- + gcc/common/config/aarch64/aarch64-common.cc | 76 +++++++++++++++++++++ + 1 file changed, 76 insertions(+) + +diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc +index dfda5b837..85ce8133b 100644 +--- a/gcc/common/config/aarch64/aarch64-common.cc ++++ b/gcc/common/config/aarch64/aarch64-common.cc +@@ -44,6 +44,8 @@ + #undef TARGET_OPTION_INIT_STRUCT + #define TARGET_OPTION_INIT_STRUCT aarch64_option_init_struct + ++#define INVALID_IMP ((unsigned) -1) ++ + /* Set default optimization options. */ + static const struct default_options aarch_option_optimization_table[] = + { +@@ -65,6 +67,77 @@ static const struct default_options aarch_option_optimization_table[] = + { OPT_LEVELS_NONE, 0, NULL, 0 } + }; + ++/* CPU vendor id. */ ++static unsigned vendor_id = INVALID_IMP; ++ ++/* The part number of the CPU. */ ++static unsigned part_id = INVALID_IMP; ++ ++/* Return the hex integer that is after ':' for the FIELD. ++ Return -1 if there was problem parsing the integer. */ ++static unsigned ++parse_cpuinfo (char *field) ++{ ++ if (field == NULL) ++ return INVALID_IMP; ++ const char *rest = strchr (field, ':'); ++ ++ if (rest == NULL) ++ return INVALID_IMP; ++ ++ char *after; ++ unsigned fint = strtol (rest + 1, &after, 16); ++ if (after == rest + 1) ++ return INVALID_IMP; ++ return fint; ++} ++ ++/* Read CPU vendor_id and part_id. */ ++ ++static void ++read_cpuinfo () ++{ ++ FILE *fp = fopen ("/proc/cpuinfo", "r"); ++ if (fp == NULL) ++ return; ++ ++ /* Read 1024-byte data from /proc/cpuinfo. */ ++ char cpuinfo[1024]; ++ fread(cpuinfo, sizeof(char), sizeof(cpuinfo) - 1, fp); ++ ++ char *vendor = strstr(cpuinfo, "CPU implementer"); ++ vendor_id = parse_cpuinfo(vendor); ++ ++ char *part = strstr(cpuinfo, "CPU part"); ++ part_id = parse_cpuinfo(part); ++ ++ fclose(fp); ++} ++ ++/* Reset the tsv110 option. After checking the platform information, ++ this function can reset the more appropriate options. ++ TODO: Currently, this function is not applicable to the cross ++ compilation scenario. */ ++ ++static void ++reset_tsv110_option () ++{ ++ /* Read CPU Information. */ ++ if (vendor_id == INVALID_IMP) ++ read_cpuinfo (); ++ ++ if (vendor_id == 0x48 && part_id == 0xd01) ++ { ++ /* Outline-atomics is enabled by default and ++ aarch64_flag_outline_atomics defaults to 2. Therefore, the current ++ modification affects only the default scenario. When the option ++ moutline-atomics is added, the value of aarch64_flag_outline_atomics is 1, ++ that is, aarch64_flag_outline_atomics is not reset to 0. */ ++ if (aarch64_flag_outline_atomics == 2) ++ aarch64_flag_outline_atomics = 0; ++ } ++} ++ + /* Implement TARGET_HANDLE_OPTION. + This function handles the target specific options for CPU/target selection. + +@@ -83,6 +156,9 @@ aarch64_handle_option (struct gcc_options *opts, + const char *arg = decoded->arg; + int val = decoded->value; + ++ /* Reset the tsv110 options. */ ++ reset_tsv110_option (); ++ + switch (code) + { + case OPT_march_: +-- +2.33.0 + diff --git a/0026-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch b/0026-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch new file mode 100644 index 0000000..b57a5a6 --- /dev/null +++ b/0026-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch @@ -0,0 +1,37 @@ +From 7efae59159577657f22511aa3b2cebe85ca60d9d Mon Sep 17 00:00:00 2001 +From: dingguangya +Date: Mon, 4 Sep 2023 16:30:58 +0800 +Subject: [PATCH 2/2] [GOMP] Enabling moutline-atomics improves libgomp + performance in multi-thread scenarios + +Libgomp is used in multi-thread scenarios, +Enabling moutline-atomics improves performance. +--- + libgomp/configure.tgt | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/libgomp/configure.tgt b/libgomp/configure.tgt +index 2cd7272fc..f924e9f98 100644 +--- a/libgomp/configure.tgt ++++ b/libgomp/configure.tgt +@@ -32,6 +32,17 @@ if test $gcc_cv_have_tls = yes ; then + esac + fi + ++# Enabling moutline-atomics improves libgomp performance in multi-thread scenarios. ++case "${target_cpu}" in ++ aarch64*) ++ case "${target}" in ++ aarch64*-*-linux*) ++ XCFLAGS="${XCFLAGS} -moutline-atomics" ++ ;; ++ esac ++ ;; ++esac ++ + tmake_file= + # Since we require POSIX threads, assume a POSIX system by default. + config_path="posix" +-- +2.33.0 + diff --git a/0027-LoopElim-Redundant-loop-elimination-optimization.patch b/0027-LoopElim-Redundant-loop-elimination-optimization.patch new file mode 100644 index 0000000..91b45cd --- /dev/null +++ b/0027-LoopElim-Redundant-loop-elimination-optimization.patch @@ -0,0 +1,503 @@ +From 14d9ee793571c6b6f16fa098cde137ebac7aa58f Mon Sep 17 00:00:00 2001 +From: eastb233 +Date: Mon, 4 Sep 2023 14:58:42 +0800 +Subject: [PATCH] [LoopElim] Redundant loop elimination optimization + +Introduce redundant loop elimination optimization controlled +by -floop-elim. And it's often used with -ffinite-loops. +--- + gcc/common.opt | 4 + + gcc/tree-ssa-phiopt.cc | 448 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 452 insertions(+) + +diff --git a/gcc/common.opt b/gcc/common.opt +index cae7b380f..b01df919e 100644 +--- a/gcc/common.opt ++++ b/gcc/common.opt +@@ -1230,6 +1230,10 @@ fcompare-elim + Common Var(flag_compare_elim_after_reload) Optimization + Perform comparison elimination after register allocation has finished. + ++floop-elim ++Common Var(flag_loop_elim) Init(0) Optimization ++Perform redundant loop elimination. ++ + fconserve-stack + Common Var(flag_conserve_stack) Optimization + Do not perform optimizations increasing noticeably stack usage. +diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc +index c56d0b9ff..cf300d141 100644 +--- a/gcc/tree-ssa-phiopt.cc ++++ b/gcc/tree-ssa-phiopt.cc +@@ -77,6 +77,7 @@ static hash_set * get_non_trapping (); + static void replace_phi_edge_with_variable (basic_block, edge, gphi *, tree); + static void hoist_adjacent_loads (basic_block, basic_block, + basic_block, basic_block); ++static bool do_phiopt_pattern (basic_block, basic_block, basic_block); + static bool gate_hoist_loads (void); + + /* This pass tries to transform conditional stores into unconditional +@@ -266,6 +267,10 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) + hoist_adjacent_loads (bb, bb1, bb2, bb3); + continue; + } ++ else if (flag_loop_elim && do_phiopt_pattern (bb, bb1, bb2)) ++ { ++ continue; ++ } + else + continue; + +@@ -3767,6 +3772,449 @@ hoist_adjacent_loads (basic_block bb0, basic_block bb1, + } + } + ++static bool check_uses (tree, hash_set *); ++ ++/* Check SSA_NAME is used in ++ if (SSA_NAME == 0) ++ ... ++ or ++ if (SSA_NAME != 0) ++ ... ++*/ ++static bool ++check_uses_cond (const_tree ssa_name, gimple *stmt, ++ hash_set *hset ATTRIBUTE_UNUSED) ++{ ++ tree_code code = gimple_cond_code (stmt); ++ if (code != EQ_EXPR && code != NE_EXPR) ++ { ++ return false; ++ } ++ ++ tree lhs = gimple_cond_lhs (stmt); ++ tree rhs = gimple_cond_rhs (stmt); ++ if ((lhs == ssa_name && integer_zerop (rhs)) ++ || (rhs == ssa_name && integer_zerop (lhs))) ++ { ++ return true; ++ } ++ ++ return false; ++} ++ ++/* Check SSA_NAME is used in ++ _tmp = SSA_NAME == 0; ++ or ++ _tmp = SSA_NAME != 0; ++ or ++ _tmp = SSA_NAME | _tmp2; ++*/ ++static bool ++check_uses_assign (const_tree ssa_name, gimple *stmt, hash_set *hset) ++{ ++ tree_code code = gimple_assign_rhs_code (stmt); ++ tree lhs, rhs1, rhs2; ++ ++ switch (code) ++ { ++ case EQ_EXPR: ++ case NE_EXPR: ++ rhs1 = gimple_assign_rhs1 (stmt); ++ rhs2 = gimple_assign_rhs2 (stmt); ++ if ((rhs1 == ssa_name && integer_zerop (rhs2)) ++ || (rhs2 == ssa_name && integer_zerop (rhs1))) ++ { ++ return true; ++ } ++ break; ++ ++ case BIT_IOR_EXPR: ++ lhs = gimple_assign_lhs (stmt); ++ if (hset->contains (lhs)) ++ { ++ return false; ++ } ++ /* We should check the use of _tmp further. */ ++ return check_uses (lhs, hset); ++ ++ default: ++ break; ++ } ++ return false; ++} ++ ++/* Check SSA_NAME is used in ++ # result = PHI ++*/ ++static bool ++check_uses_phi (const_tree ssa_name, gimple *stmt, hash_set *hset) ++{ ++ for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++) ++ { ++ tree arg = gimple_phi_arg_def (stmt, i); ++ if (!integer_zerop (arg) && arg != ssa_name) ++ { ++ return false; ++ } ++ } ++ ++ tree result = gimple_phi_result (stmt); ++ ++ /* It is used to avoid infinite recursion, ++ ++ if (cond) ++ goto ++ else ++ goto ++ ++ ++ # _tmp2 = PHI <0 (bb 1), _tmp3 (bb 3)> ++ {BODY} ++ if (cond) ++ goto ++ else ++ goto ++ ++ ++ # _tmp3 = PHI <0 (bb 1), _tmp2 (bb 2)> ++ {BODY} ++ if (cond) ++ goto ++ else ++ goto ++ ++ ++ ... ++ */ ++ if (hset->contains (result)) ++ { ++ return false; ++ } ++ ++ return check_uses (result, hset); ++} ++ ++/* Check the use of SSA_NAME, it should only be used in comparison ++ operation and PHI node. HSET is used to record the ssa_names ++ that have been already checked. */ ++static bool ++check_uses (tree ssa_name, hash_set *hset) ++{ ++ imm_use_iterator imm_iter; ++ use_operand_p use_p; ++ ++ if (TREE_CODE (ssa_name) != SSA_NAME) ++ { ++ return false; ++ } ++ ++ if (SSA_NAME_VAR (ssa_name) ++ && is_global_var (SSA_NAME_VAR (ssa_name))) ++ { ++ return false; ++ } ++ ++ hset->add (ssa_name); ++ ++ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ssa_name) ++ { ++ gimple *stmt = USE_STMT (use_p); ++ ++ /* Ignore debug gimple statements. */ ++ if (is_gimple_debug (stmt)) ++ { ++ continue; ++ } ++ ++ switch (gimple_code (stmt)) ++ { ++ case GIMPLE_COND: ++ if (!check_uses_cond (ssa_name, stmt, hset)) ++ { ++ return false; ++ } ++ break; ++ ++ case GIMPLE_ASSIGN: ++ if (!check_uses_assign (ssa_name, stmt, hset)) ++ { ++ return false; ++ } ++ break; ++ ++ case GIMPLE_PHI: ++ if (!check_uses_phi (ssa_name, stmt, hset)) ++ { ++ return false; ++ } ++ break; ++ ++ default: ++ return false; ++ } ++ } ++ return true; ++} ++ ++static bool ++check_def_gimple (gimple *def1, gimple *def2, const_tree result) ++{ ++ /* def1 and def2 should be POINTER_PLUS_EXPR. */ ++ if (!is_gimple_assign (def1) || !is_gimple_assign (def2) ++ || gimple_assign_rhs_code (def1) != POINTER_PLUS_EXPR ++ || gimple_assign_rhs_code (def2) != POINTER_PLUS_EXPR) ++ { ++ return false; ++ } ++ ++ tree rhs12 = gimple_assign_rhs2 (def1); ++ ++ tree rhs21 = gimple_assign_rhs1 (def2); ++ tree rhs22 = gimple_assign_rhs2 (def2); ++ ++ if (rhs21 != result) ++ { ++ return false; ++ } ++ ++ /* We should have a positive pointer-plus constant to ensure ++ that the pointer value is continuously increasing. */ ++ if (TREE_CODE (rhs12) != INTEGER_CST || TREE_CODE (rhs22) != INTEGER_CST ++ || compare_tree_int (rhs12, 0) <= 0 || compare_tree_int (rhs22, 0) <= 0) ++ { ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool ++check_loop_body (basic_block bb0, basic_block bb2, const_tree result) ++{ ++ gimple *g01 = first_stmt (bb0); ++ if (!g01 || !is_gimple_assign (g01) ++ || gimple_assign_rhs_code (g01) != MEM_REF ++ || TREE_OPERAND (gimple_assign_rhs1 (g01), 0) != result) ++ { ++ return false; ++ } ++ ++ gimple *g02 = g01->next; ++ /* GIMPLE_COND would be the last gimple in a basic block, ++ and have no other side effects on RESULT. */ ++ if (!g02 || gimple_code (g02) != GIMPLE_COND) ++ { ++ return false; ++ } ++ ++ if (first_stmt (bb2) != last_stmt (bb2)) ++ { ++ return false; ++ } ++ ++ return true; ++} ++ ++/* Pattern is like ++
++   arg1 = base (rhs11) + cst (rhs12); [def1]
++   goto 
++
++   
++   arg2 = result (rhs21) + cst (rhs22); [def2]
++
++   
++   # result = PHI 
++   _v = *result;  [g01]
++   if (_v == 0)   [g02]
++     goto 
++   else
++     goto 
++
++   
++   _1 = result - base;     [g1]
++   _2 = _1 /[ex] cst;      [g2]
++   _3 = (unsigned int) _2; [g3]
++   if (_3 == 0)
++   ...
++*/
++static bool
++check_bb_order (basic_block bb0, basic_block &bb1, basic_block &bb2,
++		gphi *phi_stmt, gimple *&output)
++{
++  /* Start check from PHI node in BB0.  */
++  if (gimple_phi_num_args (phi_stmt) != 2
++      || virtual_operand_p (gimple_phi_result (phi_stmt)))
++    {
++      return false;
++    }
++
++  tree result = gimple_phi_result (phi_stmt);
++  tree arg1 = gimple_phi_arg_def (phi_stmt, 0);
++  tree arg2 = gimple_phi_arg_def (phi_stmt, 1);
++
++  if (TREE_CODE (arg1) != SSA_NAME
++      || TREE_CODE (arg2) != SSA_NAME
++      || SSA_NAME_IS_DEFAULT_DEF (arg1)
++      || SSA_NAME_IS_DEFAULT_DEF (arg2))
++    {
++      return false;
++    }
++
++  gimple *def1 = SSA_NAME_DEF_STMT (arg1);
++  gimple *def2 = SSA_NAME_DEF_STMT (arg2);
++
++  /* Swap bb1 and bb2 if pattern is like
++     if (_v != 0)
++       goto 
++     else
++       goto 
++  */
++  if (gimple_bb (def2) == bb1 && EDGE_SUCC (bb1, 0)->dest == bb0)
++    {
++      std::swap (bb1, bb2);
++    }
++
++  /* prebb[def1] --> bb0 <-- bb2[def2] */
++  if (!gimple_bb (def1)
++      || EDGE_SUCC (gimple_bb (def1), 0)->dest != bb0
++      || gimple_bb (def2) != bb2 || EDGE_SUCC (bb2, 0)->dest != bb0)
++    {
++      return false;
++    }
++
++  /* Check whether define gimple meets the pattern requirements.  */
++  if (!check_def_gimple (def1, def2, result))
++    {
++      return false;
++    }
++
++  if (!check_loop_body (bb0, bb2, result))
++    {
++      return false;
++    }
++
++  output = def1;
++  return true;
++}
++
++/* Check pattern
++   
++   _1 = result - base;     [g1]
++   _2 = _1 /[ex] cst;      [g2]
++   _3 = (unsigned int) _2; [g3]
++   if (_3 == 0)
++   ...
++*/
++static bool
++check_gimple_order (basic_block bb1, const_tree base, const_tree cst,
++		    const_tree result, gimple *&output)
++{
++  gimple *g1 = first_stmt (bb1);
++  if (!g1 || !is_gimple_assign (g1)
++      || gimple_assign_rhs_code (g1) != POINTER_DIFF_EXPR
++      || gimple_assign_rhs1 (g1) != result
++      || gimple_assign_rhs2 (g1) != base)
++    {
++      return false;
++    }
++
++  gimple *g2 = g1->next;
++  if (!g2 || !is_gimple_assign (g2)
++      || gimple_assign_rhs_code (g2) != EXACT_DIV_EXPR
++      || gimple_assign_lhs (g1) != gimple_assign_rhs1 (g2)
++      || TREE_CODE (gimple_assign_rhs2 (g2)) != INTEGER_CST)
++    {
++      return false;
++    }
++
++  /* INTEGER_CST cst in gimple def1.  */
++  HOST_WIDE_INT num1 = TREE_INT_CST_LOW (cst);
++  /* INTEGER_CST cst in gimple g2.  */
++  HOST_WIDE_INT num2 = TREE_INT_CST_LOW (gimple_assign_rhs2 (g2));
++  /* _2 must be at least a positive number.  */
++  if (num2 == 0 || num1 / num2 <= 0)
++    {
++      return false;
++    }
++
++  gimple *g3 = g2->next;
++  if (!g3 || !is_gimple_assign (g3)
++      || gimple_assign_rhs_code (g3) != NOP_EXPR
++      || gimple_assign_lhs (g2) != gimple_assign_rhs1 (g3)
++      || TREE_CODE (gimple_assign_lhs (g3)) != SSA_NAME)
++    {
++      return false;
++    }
++
++  /* _3 should only be used in comparison operation or PHI node.  */
++  hash_set *hset = new hash_set;
++  if (!check_uses (gimple_assign_lhs (g3), hset))
++    {
++      delete hset;
++      return false;
++    }
++  delete hset;
++
++  output = g3;
++  return true;
++}
++
++static bool
++do_phiopt_pattern (basic_block bb0, basic_block bb1, basic_block bb2)
++{
++  gphi_iterator gsi;
++
++  for (gsi = gsi_start_phis (bb0); !gsi_end_p (gsi); gsi_next (&gsi))
++    {
++      gphi *phi_stmt = gsi.phi ();
++      gimple *def1 = NULL;
++      tree base, cst, result;
++
++      if (!check_bb_order (bb0, bb1, bb2, phi_stmt, def1))
++	{
++	  continue;
++	}
++
++      base = gimple_assign_rhs1 (def1);
++      cst = gimple_assign_rhs2 (def1);
++      result = gimple_phi_result (phi_stmt);
++
++      gimple *stmt = NULL;
++      if (!check_gimple_order (bb1, base, cst, result, stmt))
++	{
++	  continue;
++	}
++
++      gcc_assert (stmt);
++
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  fprintf (dump_file, "PHIOPT pattern optimization (1) - Rewrite:\n");
++	  print_gimple_stmt (dump_file, stmt, 0);
++	  fprintf (dump_file, "to\n");
++	}
++
++      /* Rewrite statement
++	   _3 = (unsigned int) _2;
++	 to
++	   _3 = (unsigned int) 1;
++      */
++      tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
++      gimple_assign_set_rhs1 (stmt, build_int_cst (type, 1));
++      update_stmt (stmt);
++
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  print_gimple_stmt (dump_file, stmt, 0);
++	  fprintf (dump_file, "\n");
++	}
++
++      return true;
++    }
++  return false;
++}
++
+ /* Determine whether we should attempt to hoist adjacent loads out of
+    diamond patterns in pass_phiopt.  Always hoist loads if
+    -fhoist-adjacent-loads is specified and the target machine has
+-- 
+2.28.0.windows.1
+
diff --git a/0028-Array-widen-compare-Fix-the-return-value-match-after.patch b/0028-Array-widen-compare-Fix-the-return-value-match-after.patch
new file mode 100644
index 0000000..c5622b8
--- /dev/null
+++ b/0028-Array-widen-compare-Fix-the-return-value-match-after.patch
@@ -0,0 +1,40 @@
+From a89b84cd038e02f0cdafecea1cf337d5f8480683 Mon Sep 17 00:00:00 2001
+From: dingguangya 
+Date: Fri, 8 Sep 2023 11:55:04 +0800
+Subject: [PATCH] [Array-widen-compare] Fix the return value match after update
+ the get_loop_exit_edges interface
+
+The get_loop_exit_edges interface returns a value type
+from vec -> auto_vec
+
+diff --git a/gcc/tree-ssa-loop-array-widen-compare.cc b/gcc/tree-ssa-loop-array-widen-compare.cc
+index ba6170fa0..d27f91f11 100644
+--- a/gcc/tree-ssa-loop-array-widen-compare.cc
++++ b/gcc/tree-ssa-loop-array-widen-compare.cc
+@@ -272,12 +272,12 @@ record_origin_loop_exit_info (class loop *loop)
+       || origin_loop.cond_stmt1 != NULL || origin_loop.cond_stmt2 != NULL)
+     return false;
+ 
+-  vec exit_edges = get_loop_exit_edges (loop);
++  auto_vec exit_edges = get_loop_exit_edges (loop);
+   if (exit_edges == vNULL)
+     return false;
+ 
+   if (exit_edges.length () != 2)
+-    goto fail;
++    return false;
+ 
+   FOR_EACH_VEC_ELT (exit_edges, i, e)
+     {
+@@ -304,8 +304,6 @@ record_origin_loop_exit_info (class loop *loop)
+       && origin_loop.cond_stmt1 != NULL && origin_loop.cond_stmt2 != NULL)
+     found = true;
+ 
+-fail:
+-  exit_edges.release ();
+   return found;
+ }
+ 
+-- 
+2.33.0
+
diff --git a/0029-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch b/0029-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch
new file mode 100644
index 0000000..7b09747
--- /dev/null
+++ b/0029-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch
@@ -0,0 +1,1191 @@
+From 7930d75c9fd3f36cc2dce934569f00c71248bb31 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Sat, 25 Nov 2023 10:28:48 +0800
+Subject: [PATCH] [Struct Reorg] Add Safe Structure Pointer Compression
+
+Safe structure pointer compression allows safely transfer pointers
+stored in structure into the index of structure array with smaller
+type to reduce the size of structure.
+Add flag -fipa-struct-reorg=4 to enable safe structure pointer
+compression.
+Add param compressed-pointer-size=[8,16,32] to control the compressed
+pointer size.
+---
+ gcc/common.opt                           |   5 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 908 ++++++++++++++++++++++-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.h  |   4 +
+ gcc/params.opt                           |   4 +
+ 4 files changed, 882 insertions(+), 39 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index b01df919e..f6e20c1e8 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1993,8 +1993,9 @@ Common Var(flag_ipa_struct_reorg) Init(0) Optimization
+ Perform structure layout optimizations.
+ 
+ fipa-struct-reorg=
+-Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 3)
+--fipa-struct-reorg=[0,1,2,3] adding none, struct-reorg, reorder-fields, dfe optimizations.
++Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 4)
++-fipa-struct-reorg=[0,1,2,3,4] adding none, struct-reorg, reorder-fields,
++dfe, safe-pointer-compression optimizations.
+ 
+ fipa-vrp
+ Common Var(flag_ipa_vrp) Optimization
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index dcc6df496..5d451c4c8 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -89,6 +89,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "gimple-iterator.h"
+ #include "gimple-walk.h"
+ #include "cfg.h"
++#include "cfghooks.h" /* For split_block.  */
+ #include "ssa.h"
+ #include "tree-dfa.h"
+ #include "fold-const.h"
+@@ -147,7 +148,27 @@ using namespace struct_relayout;
+ #define VOID_POINTER_P(type) \
+   (POINTER_TYPE_P (type) && VOID_TYPE_P (TREE_TYPE (type)))
+ 
+-/* Return true iff TYPE is stdarg va_list type.  */
++static void
++set_var_attributes (tree var)
++{
++  if (!var)
++    return;
++  gcc_assert (TREE_CODE (var) == VAR_DECL);
++
++  DECL_ARTIFICIAL (var) = 1;
++  DECL_EXTERNAL (var) = 0;
++  TREE_STATIC (var) = 1;
++  TREE_PUBLIC (var) = 0;
++  TREE_USED (var) = 1;
++  DECL_CONTEXT (var) = NULL;
++  TREE_THIS_VOLATILE (var) = 0;
++  TREE_ADDRESSABLE (var) = 0;
++  TREE_READONLY (var) = 0;
++  if (is_global_var (var))
++    set_decl_tls_model (var, TLS_MODEL_NONE);
++}
++
++/* Return true if TYPE is stdarg va_list type.  */
+ 
+ static inline bool
+ is_va_list_type (tree type)
+@@ -271,9 +292,15 @@ enum struct_layout_opt_level
+   STRUCT_SPLIT = 1 << 0,
+   COMPLETE_STRUCT_RELAYOUT = 1 << 1,
+   STRUCT_REORDER_FIELDS = 1 << 2,
+-  DEAD_FIELD_ELIMINATION = 1 << 3
++  DEAD_FIELD_ELIMINATION = 1 << 3,
++  POINTER_COMPRESSION_SAFE = 1 << 4
+ };
+ 
++/* Defines the target pointer size of compressed pointer, which should be 8,
++   16, 32.  */
++
++static int compressed_size = 32;
++
+ static bool is_result_of_mult (tree arg, tree *num, tree struct_size);
+ static bool isptrptr (tree type);
+ void get_base (tree &base, tree expr);
+@@ -394,7 +421,10 @@ srtype::srtype (tree type)
+   : type (type),
+     chain_type (false),
+     escapes (does_not_escape),
++    pc_gptr (NULL_TREE),
+     visited (false),
++    pc_candidate (false),
++    has_legal_alloc_num (false),
+     has_alloc_array (0)
+ {
+   for (int i = 0; i < max_split; i++)
+@@ -476,6 +506,31 @@ srtype::mark_escape (escape_type e, gimple *stmt)
+     }
+ }
+ 
++/* Create a global header for compressed struct.  */
++
++void
++srtype::create_global_ptr_for_pc ()
++{
++  if (!pc_candidate || pc_gptr != NULL_TREE)
++    return;
++
++  const char *type_name = get_type_name (type);
++  gcc_assert (type_name != NULL);
++
++  char *gptr_name = concat (type_name, "_pc", NULL);
++  tree new_name = get_identifier (gptr_name);
++  tree new_type = build_pointer_type (newtype[0]);
++  tree new_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, new_name, new_type);
++  set_var_attributes (new_var);
++  pc_gptr = new_var;
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\nType: %s has create global header for pointer"
++	       " compression: %s\n", type_name, gptr_name);
++
++  free (gptr_name);
++}
++
+ /* Add FIELD to the list of fields that use this type.  */
+ 
+ void
+@@ -798,15 +853,31 @@ srfield::create_new_reorder_fields (tree newtype[max_split],
+       fields.safe_push (field);
+     }
+ 
+-  DECL_NAME (field) = DECL_NAME (fielddecl);
+   if (type == NULL)
+-    /* Common members do not need to reconstruct.
++    {
++      DECL_NAME (field) = DECL_NAME (fielddecl);
++      /* Common members do not need to reconstruct.
+        Otherwise, int* -> int** or void* -> void**.  */
+-    TREE_TYPE (field) = nt;
++      TREE_TYPE (field) = nt;
++      SET_DECL_ALIGN (field, DECL_ALIGN (fielddecl));
++    }
++  else if (type->pc_candidate)
++    {
++      const char *old_name = IDENTIFIER_POINTER (DECL_NAME (fielddecl));
++      char *new_name = concat (old_name, "_pc", NULL);
++      DECL_NAME (field) = get_identifier (new_name);
++      free (new_name);
++      TREE_TYPE (field) = make_unsigned_type (compressed_size);
++      SET_DECL_ALIGN (field, compressed_size);
++    }
+   else
+-    TREE_TYPE (field) = reconstruct_complex_type (TREE_TYPE (fielddecl), nt);
++    {
++      TREE_TYPE (field) = reconstruct_complex_type (TREE_TYPE (fielddecl), nt);
++      DECL_NAME (field) = DECL_NAME (fielddecl);
++      SET_DECL_ALIGN (field, DECL_ALIGN (fielddecl));
++    }
++
+   DECL_SOURCE_LOCATION (field) = DECL_SOURCE_LOCATION (fielddecl);
+-  SET_DECL_ALIGN (field, DECL_ALIGN (fielddecl));
+   DECL_USER_ALIGN (field) = DECL_USER_ALIGN (fielddecl);
+   TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (fielddecl);
+   DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (fielddecl);
+@@ -925,6 +996,10 @@ srtype::create_new_type (void)
+ 	  && has_dead_field ())
+ 	fprintf (dump_file, "Dead field elimination.\n");
+     }
++
++  if (pc_candidate && pc_gptr == NULL_TREE)
++    create_global_ptr_for_pc ();
++
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "Created %d types:\n", maxclusters);
+@@ -1338,6 +1413,30 @@ public:
+ 
+   unsigned execute_struct_relayout (void);
+   bool remove_dead_field_stmt (tree lhs);
++
++  // Pointer compression methods:
++  void check_and_prune_struct_for_pointer_compression (void);
++  void try_rewrite_with_pointer_compression (gassign *, gimple_stmt_iterator *,
++					     tree, tree, tree &, tree &);
++  bool safe_void_cmp_p (tree, srtype *);
++  bool pc_candidate_st_type_p (tree);
++  bool pc_candidate_tree_p (tree);
++  bool pc_type_conversion_candidate_p (tree);
++  bool pc_direct_rewrite_chance_p (tree, tree &);
++  bool compress_candidate_with_check (gimple_stmt_iterator *, tree, tree &);
++  bool compress_candidate (gassign *, gimple_stmt_iterator *, tree, tree &);
++  bool decompress_candidate_with_check (gimple_stmt_iterator *, tree, tree &);
++  bool decompress_candidate (gimple_stmt_iterator *, tree, tree, tree &,
++			     tree &);
++  srtype *get_compression_candidate_type (tree);
++  tree compress_ptr_to_offset (tree, srtype *, gimple_stmt_iterator *);
++  tree decompress_offset_to_ptr (tree, srtype *, gimple_stmt_iterator *);
++  basic_block create_bb_for_compress_candidate (basic_block, tree, srtype *,
++						tree &);
++  basic_block create_bb_for_decompress_candidate (basic_block, tree, srtype *,
++						  tree &);
++  basic_block create_bb_for_compress_nullptr (basic_block, tree &);
++  basic_block create_bb_for_decompress_nullptr (basic_block, tree, tree &);
+ };
+ 
+ struct ipa_struct_relayout
+@@ -1386,26 +1485,6 @@ namespace {
+ 
+ /* Methods for ipa_struct_relayout.  */
+ 
+-static void
+-set_var_attributes (tree var)
+-{
+-  if (!var)
+-    return;
+-  gcc_assert (TREE_CODE (var) == VAR_DECL);
+-
+-  DECL_ARTIFICIAL (var) = 1;
+-  DECL_EXTERNAL (var) = 0;
+-  TREE_STATIC (var) = 1;
+-  TREE_PUBLIC (var) = 0;
+-  TREE_USED (var) = 1;
+-  DECL_CONTEXT (var) = NULL;
+-  TREE_THIS_VOLATILE (var) = 0;
+-  TREE_ADDRESSABLE (var) = 0;
+-  TREE_READONLY (var) = 0;
+-  if (is_global_var (var))
+-    set_decl_tls_model (var, TLS_MODEL_NONE);
+-}
+-
+ tree
+ ipa_struct_relayout::create_new_vars (tree type, const char *name)
+ {
+@@ -2985,6 +3064,19 @@ ipa_struct_reorg::find_vars (gimple *stmt)
+ 	     records the right value _1 declaration.  */
+ 	  find_var (gimple_assign_rhs1 (stmt), stmt);
+ 
++	  /* Pointer types from non-zero pointer need to be escaped in pointer
++	     compression and complete relayout.
++	     e.g _1->t = (struct *) 0x400000.  */
++	  if (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT
++	      && TREE_CODE (lhs) == COMPONENT_REF
++	      && TREE_CODE (TREE_TYPE (lhs)) == POINTER_TYPE
++	      && TREE_CODE (rhs) == INTEGER_CST
++	      && !integer_zerop (rhs))
++	    {
++	      mark_type_as_escape (inner_type (TREE_TYPE (lhs)),
++				   escape_cast_int, stmt);
++	    }
++
+ 	  /* Add a safe func mechanism.  */
+ 	  bool l_find = true;
+ 	  bool r_find = true;
+@@ -3436,12 +3528,13 @@ is_result_of_mult (tree arg, tree *num, tree struct_size)
+ bool
+ ipa_struct_reorg::handled_allocation_stmt (gimple *stmt)
+ {
+-  if ((current_layout_opt_level >= STRUCT_REORDER_FIELDS)
++  if ((current_layout_opt_level & STRUCT_REORDER_FIELDS)
+       && (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC)
+ 	  || gimple_call_builtin_p (stmt, BUILT_IN_MALLOC)
+ 	  || gimple_call_builtin_p (stmt, BUILT_IN_CALLOC)))
+     return true;
+-  if ((current_layout_opt_level == COMPLETE_STRUCT_RELAYOUT)
++  if ((current_layout_opt_level == COMPLETE_STRUCT_RELAYOUT
++       || current_layout_opt_level & POINTER_COMPRESSION_SAFE)
+       && gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
+     return true;
+   if ((current_layout_opt_level == STRUCT_SPLIT)
+@@ -3563,14 +3656,19 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other,
+ 	}
+     }
+   /* x_1 = y.x_nodes; void *x;
+-     Directly mark the structure pointer type assigned
+-     to the void* variable as escape.  */
++     Mark the structure pointer type assigned
++     to the void* variable as escape.  Unless the void* is only used to compare
++     with variables of the same type.  */
+   else if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+ 	   && TREE_CODE (side) == SSA_NAME
+ 	   && VOID_POINTER_P (TREE_TYPE (side))
+ 	   && SSA_NAME_VAR (side)
+ 	   && VOID_POINTER_P (TREE_TYPE (SSA_NAME_VAR (side))))
+-    mark_type_as_escape (TREE_TYPE (other), escape_cast_void, stmt);
++      if (current_layout_opt_level < POINTER_COMPRESSION_SAFE
++	  || !safe_void_cmp_p (side, type))
++	{
++	  mark_type_as_escape (TREE_TYPE (other), escape_cast_void, stmt);
++	}
+ 
+   check_ptr_layers (side, other, stmt);
+ }
+@@ -4181,7 +4279,7 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
+ void
+ ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type)
+ {
+-  if (current_layout_opt_level == COMPLETE_STRUCT_RELAYOUT
++  if (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT
+       && handled_allocation_stmt (stmt))
+     {
+       tree arg0 = gimple_call_arg (stmt, 0);
+@@ -4200,6 +4298,23 @@ ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type)
+ 	type->has_alloc_array = type->has_alloc_array < 0
+ 				  ? type->has_alloc_array
+ 				  : type->has_alloc_array + 1;
++
++      if (current_layout_opt_level & POINTER_COMPRESSION_SAFE
++	  && TREE_CODE (arg0) == INTEGER_CST)
++	{
++	  /* Only known size during compilation can be optimized
++	     at this level.  */
++	  unsigned HOST_WIDE_INT max_alloc_size = 0;
++	  switch (compressed_size)
++	    {
++	      case 8: max_alloc_size = 0xff; break; // max of uint8
++	      case 16: max_alloc_size = 0xffff; break; // max of uint16
++	      case 32: max_alloc_size = 0xffffffff; break; // max of uint32
++	      default: gcc_unreachable (); break;
++	    }
++	  if (tree_to_uhwi (arg0) < max_alloc_size)
++	    type->has_legal_alloc_num = true;
++	}
+     }
+ }
+ 
+@@ -4328,7 +4443,13 @@ ipa_struct_reorg::check_definition (srdecl *decl, vec &worklist)
+   if (current_layout_opt_level >= STRUCT_REORDER_FIELDS
+       && SSA_NAME_VAR (ssa_name)
+       && VOID_POINTER_P (TREE_TYPE (SSA_NAME_VAR (ssa_name))))
+-    type->mark_escape (escape_cast_void, SSA_NAME_DEF_STMT (ssa_name));
++      {
++	if (current_layout_opt_level < POINTER_COMPRESSION_SAFE
++	  || !safe_void_cmp_p (ssa_name, type))
++	  {
++	    type->mark_escape (escape_cast_void, SSA_NAME_DEF_STMT (ssa_name));
++	  }
++      }
+   gimple *stmt = SSA_NAME_DEF_STMT (ssa_name);
+ 
+   /*
+@@ -5294,6 +5415,8 @@ ipa_struct_reorg::create_new_types (void)
+   for (unsigned i = 0; i < types.length (); i++)
+     newtypes += types[i]->create_new_type ();
+ 
++  /* Some new types may not have been created at create_new_type (), so
++     recreate new type for all struct fields.  */
+   if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+     {
+       for (unsigned i = 0; i < types.length (); i++)
+@@ -5304,9 +5427,18 @@ ipa_struct_reorg::create_new_types (void)
+ 	      for (unsigned j = 0; j < fields->length (); j++)
+ 		{
+ 		  tree field = (*fields)[j];
+-		  TREE_TYPE (field)
+-		  = reconstruct_complex_type (TREE_TYPE (field),
+-					      types[i]->newtype[0]);
++		  if (types[i]->pc_candidate)
++		    {
++		      TREE_TYPE (field)
++			= make_unsigned_type (compressed_size);
++		      SET_DECL_ALIGN (field, compressed_size);
++		    }
++		  else
++		    {
++		      TREE_TYPE (field)
++			= reconstruct_complex_type (TREE_TYPE (field),
++						    types[i]->newtype[0]);
++		    }
+ 		}
+ 	    }
+ 	}
+@@ -5685,6 +5817,554 @@ ipa_struct_reorg::rewrite_expr (tree expr,
+   return true;
+ }
+ 
++/* Emit a series of gimples to compress the pointer to the index relative to
++   the global header.  The basic blocks where gsi is located must have at least
++   one stmt.  */
++
++tree
++ipa_struct_reorg::compress_ptr_to_offset (tree xhs, srtype *type,
++					  gimple_stmt_iterator *gsi)
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nCompress candidate pointer:\n");
++      print_generic_expr (dump_file, xhs);
++      fprintf (dump_file, "\nto offset:\n");
++    }
++
++  /* Emit gimple _X1 = ptr - gptr.  */
++  tree pointer_addr = fold_convert (long_unsigned_type_node, xhs);
++  tree gptr_addr = fold_convert (long_unsigned_type_node, type->pc_gptr);
++  tree step1 = gimplify_build2 (gsi, MINUS_EXPR, long_unsigned_type_node,
++				pointer_addr, gptr_addr);
++
++  /* Emit gimple _X2 = _X1 / sizeof (struct).  */
++  tree step2 = gimplify_build2 (gsi, TRUNC_DIV_EXPR, long_unsigned_type_node,
++				step1, TYPE_SIZE_UNIT (type->newtype[0]));
++
++  /* Emit gimple _X3 = _X2 + 1.  */
++  tree step3 = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node,
++				step2, build_one_cst (long_unsigned_type_node));
++
++  /* Emit _X4 = (compressed_size) _X3.  */
++  tree step4 = gimplify_build1 (gsi, NOP_EXPR,
++				make_unsigned_type (compressed_size), step3);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      print_generic_expr (dump_file, step3);
++      fprintf (dump_file, "\n");
++    }
++  return step4;
++}
++
++/* Emit a series of gimples to decompress the index into the original
++   pointer.  The basic blocks where gsi is located must have at least
++   one stmt.  */
++
++tree
++ipa_struct_reorg::decompress_offset_to_ptr (tree xhs, srtype *type,
++					    gimple_stmt_iterator *gsi)
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nDecompress candidate offset:\n");
++      print_generic_expr (dump_file, xhs);
++      fprintf (dump_file, "\nto pointer:\n");
++    }
++
++  /* Emit _X1 = xhs - 1.  */
++  tree offset = fold_convert (long_unsigned_type_node, xhs);
++  tree step1 = gimplify_build2 (gsi, MINUS_EXPR, long_unsigned_type_node,
++				offset,
++				build_one_cst (long_unsigned_type_node));
++
++  /* Emit _X2 = _X1 * sizeof (struct).  */
++  tree step2 = gimplify_build2 (gsi, MULT_EXPR, long_unsigned_type_node,
++				step1, TYPE_SIZE_UNIT (type->newtype[0]));
++
++  /* Emit _X3 = phead + _X2.  */
++  tree gptr_addr = fold_convert (long_unsigned_type_node, type->pc_gptr);
++  tree step3 = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node,
++				gptr_addr, step2);
++
++  /* Emit _X4 = (struct *) _X3.  */
++  tree step4 = gimplify_build1 (gsi, NOP_EXPR, TREE_TYPE (type->pc_gptr),
++				step3);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      print_generic_expr (dump_file, step3);
++      fprintf (dump_file, "\n");
++    }
++  return step4;
++}
++
++/* Return the compression candidate srtype of SSA_NAME or COMPONENT_REF.  */
++
++srtype *
++ipa_struct_reorg::get_compression_candidate_type (tree xhs)
++{
++  if (xhs == NULL_TREE)
++    return NULL;
++
++  if (TREE_CODE (xhs) == SSA_NAME || TREE_CODE (xhs) == COMPONENT_REF)
++    {
++      srtype *access_type = find_type (inner_type (TREE_TYPE (xhs)));
++      if (access_type != NULL && access_type->pc_candidate)
++	return access_type;
++    }
++  return NULL;
++}
++
++/* True if the input type is the candidate type for pointer compression.  */
++
++bool
++ipa_struct_reorg::pc_candidate_st_type_p (tree type)
++{
++  if (type == NULL_TREE)
++    return false;
++
++  if (TREE_CODE (type) == POINTER_TYPE)
++    {
++      if (TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE)
++	{
++	  srtype *access_type = find_type (TREE_TYPE (type));
++	  if (access_type != NULL && access_type->pc_candidate)
++	    return true;
++	}
++    }
++  return false;
++}
++
++/* True if the input xhs is a candidate for pointer compression.  */
++
++bool
++ipa_struct_reorg::pc_candidate_tree_p (tree xhs)
++{
++  if (xhs == NULL_TREE)
++    return false;
++
++  if (TREE_CODE (xhs) == COMPONENT_REF)
++    {
++      srtype *base_type = find_type (TREE_TYPE (TREE_OPERAND (xhs, 0)));
++      if (base_type == NULL || base_type->has_escaped ())
++	return false;
++
++      return pc_candidate_st_type_p (TREE_TYPE (xhs));
++    }
++  return false;
++}
++
++/* True if xhs is a component_ref that base has escaped but uses a compression
++   candidate type.  */
++
++bool
++ipa_struct_reorg::pc_type_conversion_candidate_p (tree xhs)
++{
++  if (xhs == NULL_TREE)
++    return false;
++
++  if (TREE_CODE (xhs) == COMPONENT_REF)
++    {
++      srtype *base_type = find_type (TREE_TYPE (TREE_OPERAND (xhs, 0)));
++      if (base_type != NULL && base_type->has_escaped ())
++	return pc_candidate_st_type_p (TREE_TYPE (xhs));
++
++    }
++  return false;
++}
++
++/* Creates a new basic block with zero for compressed null pointers.  */
++
++basic_block
++ipa_struct_reorg::create_bb_for_compress_nullptr (basic_block last_bb,
++						  tree &phi)
++{
++  basic_block new_bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (new_bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++
++  /* Emit phi = 0.  */
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  phi = make_ssa_name (make_unsigned_type (compressed_size));
++  tree rhs = build_int_cst (make_unsigned_type (compressed_size), 0);
++  gimple *new_stmt = gimple_build_assign (phi, rhs);
++  gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nCreate bb %d for compress nullptr:\n",
++	       new_bb->index);
++      gimple_dump_bb (dump_file, new_bb, 0, dump_flags);
++    }
++  return new_bb;
++}
++
++/* Create a new basic block to compress the pointer to the index relative to
++   the allocated memory pool header.  */
++
++basic_block
++ipa_struct_reorg::create_bb_for_compress_candidate (basic_block last_bb,
++						    tree new_rhs, srtype *type,
++						    tree &phi)
++{
++  basic_block new_bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (new_bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  /* compress_ptr_to_offset () needs at least one stmt in target bb.  */
++  gsi_insert_after (&gsi, gimple_build_nop (), GSI_NEW_STMT);
++  phi = compress_ptr_to_offset (new_rhs, type, &gsi);
++  /* Remove the NOP created above.  */
++  gsi_remove (&gsi, true);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nCreate bb %d for compress candidate:\n",
++	       new_bb->index);
++      gimple_dump_bb (dump_file, new_bb, 0, dump_flags);
++    }
++  return new_bb;
++}
++
++/* Compression can be simplified by these following cases:
++     1.  if rhs is NULL, uses zero to represent it.
++     2.  if new_rhs has been converted into INTEGER_TYPE in the previous stmt,
++	 just use it here.  For example:
++	    _1 = t->s
++	 -> tt->s = _1.  */
++
++bool
++ipa_struct_reorg::pc_direct_rewrite_chance_p (tree rhs, tree &new_rhs)
++{
++  if (integer_zerop (rhs))
++    {
++      new_rhs = build_int_cst (make_unsigned_type (compressed_size), 0);
++      return true;
++    }
++  else if (new_rhs && TREE_CODE (TREE_TYPE (new_rhs)) == INTEGER_TYPE)
++    {
++      return true;
++    }
++  return false;
++}
++
++/* Perform pointer compression with check.  The conversion will be as shown in
++   the following example:
++     Orig bb:
++     bb <1>:
++     _1->t = _2
++
++     will be transformed to:
++     bb <1>:
++     _3 = _2
++     if (_2 == NULL)
++       goto bb <2>
++     else
++       goto bb <3>
++
++     bb <2>:
++     _3 = 0
++     goto bb <4>
++
++     bb <3>:
++     ...
++     _4 = compress (_2)
++     goto bb <4>
++
++     bb <4>:
++     _5 = PHI (_3, _4)
++     _1->t = _5
++   The gsi will move to the beginning of split dst bb <4>, _1->t = _5 will be
++   emitted by rewrite_assign ().  */
++
++bool
++ipa_struct_reorg::compress_candidate_with_check (gimple_stmt_iterator *gsi,
++						 tree rhs, tree &new_rhs)
++{
++  tree cond_lhs = make_ssa_name (TREE_TYPE (new_rhs));
++  gimple *assign_stmt = gimple_build_assign (cond_lhs, new_rhs);
++  gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
++
++  /* Insert cond stmt.  */
++  tree rhs_pointer_type = build_pointer_type (TREE_TYPE (new_rhs));
++  gcond *cond = gimple_build_cond (EQ_EXPR, cond_lhs,
++				   build_int_cst (rhs_pointer_type, 0),
++				   NULL_TREE, NULL_TREE);
++  gimple_set_location (cond, UNKNOWN_LOCATION);
++  gsi_insert_before (gsi, cond, GSI_SAME_STMT);
++
++  edge e = split_block (cond->bb, cond);
++  basic_block split_src_bb = e->src;
++  basic_block split_dst_bb = e->dest;
++
++  /* Create bb for nullptr.  */
++  tree phi1 = NULL_TREE;
++  basic_block true_bb = create_bb_for_compress_nullptr (split_src_bb, phi1);
++
++  /* Create bb for comprssion.  */
++  srtype *type = get_compression_candidate_type (rhs);
++  gcc_assert (type != NULL);
++  tree phi2 = NULL_TREE;
++  basic_block false_bb = create_bb_for_compress_candidate (true_bb, new_rhs,
++							   type, phi2);
++
++  /* Rebuild and reset cfg.  */
++  remove_edge_raw (e);
++
++  edge etrue = make_edge (split_src_bb, true_bb, EDGE_TRUE_VALUE);
++  etrue->probability = profile_probability::unlikely ();
++  true_bb->count = etrue->count ();
++
++  edge efalse = make_edge (split_src_bb, false_bb, EDGE_FALSE_VALUE);
++  efalse->probability = profile_probability::likely ();
++  false_bb->count = efalse->count ();
++
++  edge e1 = make_single_succ_edge (true_bb, split_dst_bb, EDGE_FALLTHRU);
++  edge e2 = make_single_succ_edge (false_bb, split_dst_bb, EDGE_FALLTHRU);
++
++  tree phi = make_ssa_name (make_unsigned_type (compressed_size));
++  gphi *phi_node = create_phi_node (phi, split_dst_bb);
++  add_phi_arg (phi_node, phi1, e1, UNKNOWN_LOCATION);
++  add_phi_arg (phi_node, phi2, e2, UNKNOWN_LOCATION);
++
++  if (dom_info_available_p (CDI_DOMINATORS))
++    {
++      set_immediate_dominator (CDI_DOMINATORS, split_dst_bb, split_src_bb);
++      set_immediate_dominator (CDI_DOMINATORS, true_bb, split_src_bb);
++      set_immediate_dominator (CDI_DOMINATORS, false_bb, split_src_bb);
++    }
++  *gsi = gsi_start_bb (split_dst_bb);
++  new_rhs = phi;
++  return true;
++}
++
++/* If there is a direct rewrite chance or simplification opportunity, perform
++   the simplified compression rewrite.  Otherwise, create a cond expression and
++   two basic blocks to implement pointer compression.  */
++
++bool
++ipa_struct_reorg::compress_candidate (gassign *stmt, gimple_stmt_iterator *gsi,
++				      tree rhs, tree &new_rhs)
++{
++  if (pc_direct_rewrite_chance_p (rhs, new_rhs))
++    return true;
++
++  return compress_candidate_with_check (gsi, rhs, new_rhs);
++}
++
++/* Create a new basic block to decompress the index to null pointer.  */
++
++basic_block
++ipa_struct_reorg::create_bb_for_decompress_nullptr (basic_block last_bb,
++						    tree new_rhs,
++						    tree &phi_node)
++{
++  basic_block new_bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (new_bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  tree rhs_pointer_type = build_pointer_type (TREE_TYPE (new_rhs));
++  phi_node = make_ssa_name (rhs_pointer_type);
++  gimple *new_stmt = gimple_build_assign (phi_node,
++					  build_int_cst (rhs_pointer_type, 0));
++  gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nCreate bb %d for decompress nullptr:\n",
++	       new_bb->index);
++      gimple_dump_bb (dump_file, new_bb, 0, dump_flags);
++    }
++  return new_bb;
++}
++
++/* Create a new basic block to decompress the index into original pointer.  */
++
++basic_block
++ipa_struct_reorg::create_bb_for_decompress_candidate (basic_block last_bb,
++						      tree lhs, srtype *type,
++						      tree &phi_node)
++{
++  basic_block new_bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (new_bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  /* decompress_ptr_to_offset () needs at least one stmt in target bb.  */
++  gsi_insert_after (&gsi, gimple_build_nop (), GSI_NEW_STMT);
++  phi_node = decompress_offset_to_ptr (lhs, type, &gsi);
++  /* Remove the NOP created above.  */
++  gsi_remove (&gsi, true);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nCreate bb %d for decompress candidate:\n",
++	       new_bb->index);
++      gimple_dump_bb (dump_file, new_bb, 0, dump_flags);
++    }
++  return new_bb;
++}
++
++/* Perform pointer decompression with check.  The conversion will be as shown
++   in the following example:
++     Orig bb:
++     bb <1>:
++     _1 = _2->t
++
++     will be transformed to:
++     bb <1>:
++     _3 = _2->t
++     if (_3 == 0)
++       goto bb <2>
++     else
++       goto bb <3>
++
++     bb <2>:
++     _4 = NULL
++     goto bb <4>
++
++     bb <3>:
++     ...
++     _5 = decompress (_3)
++     goto bb <4>
++
++     bb <4>:
++     _6 = PHI (_4, _5)
++     _1 = _6
++   The gsi will move to the beginning of split dst bb <4>, _1 = _6 will be
++   emitted by rewrite_assign ().  */
++
++bool
++ipa_struct_reorg::decompress_candidate_with_check (gimple_stmt_iterator *gsi,
++						   tree rhs, tree &new_rhs)
++{
++  /* Insert cond stmt.  */
++  tree cond_lhs = make_ssa_name (TREE_TYPE (new_rhs));
++  gassign *cond_assign = gimple_build_assign (cond_lhs, new_rhs);
++  gsi_insert_before (gsi, cond_assign, GSI_SAME_STMT);
++
++  tree pc_type = make_unsigned_type (compressed_size);
++  gcond *cond = gimple_build_cond (EQ_EXPR, cond_lhs,
++				   build_int_cst (pc_type, 0),
++				   NULL_TREE, NULL_TREE);
++  gimple_set_location (cond, UNKNOWN_LOCATION);
++  gsi_insert_before (gsi, cond, GSI_SAME_STMT);
++
++  /* Split bb.  */
++  edge e = split_block (cond->bb, cond);
++  basic_block split_src_bb = e->src;
++  basic_block split_dst_bb = e->dest;
++
++  /* Create bb for decompress nullptr.  */
++  tree phi1 = NULL_TREE;
++  basic_block true_bb = create_bb_for_decompress_nullptr (split_src_bb,
++							  new_rhs, phi1);
++
++  /* Create bb for decomprssion candidate.  */
++  tree phi2 = NULL_TREE;
++  srtype *type = get_compression_candidate_type (rhs);
++  gcc_assert (type != NULL);
++  basic_block false_bb = create_bb_for_decompress_candidate (true_bb, cond_lhs,
++							     type, phi2);
++
++  /* Refresh and reset cfg.  */
++  remove_edge_raw (e);
++
++  edge etrue = make_edge (split_src_bb, true_bb, EDGE_TRUE_VALUE);
++  etrue->probability = profile_probability::unlikely ();
++  true_bb->count = etrue->count ();
++
++  edge efalse = make_edge (split_src_bb, false_bb, EDGE_FALSE_VALUE);
++  efalse->probability = profile_probability::likely ();
++  false_bb->count = efalse->count ();
++
++  edge e1 = make_single_succ_edge (true_bb, split_dst_bb, EDGE_FALLTHRU);
++  edge e2 = make_single_succ_edge (false_bb, split_dst_bb, EDGE_FALLTHRU);
++
++  tree phi = make_ssa_name (build_pointer_type (TREE_TYPE (cond_lhs)));
++  gphi *phi_node = create_phi_node (phi, split_dst_bb);
++  add_phi_arg (phi_node, phi1, e1, UNKNOWN_LOCATION);
++  add_phi_arg (phi_node, phi2, e2, UNKNOWN_LOCATION);
++
++  if (dom_info_available_p (CDI_DOMINATORS))
++    {
++      set_immediate_dominator (CDI_DOMINATORS, split_dst_bb, split_src_bb);
++      set_immediate_dominator (CDI_DOMINATORS, true_bb, split_src_bb);
++      set_immediate_dominator (CDI_DOMINATORS, false_bb, split_src_bb);
++    }
++  *gsi = gsi_start_bb (split_dst_bb);
++  new_rhs = phi;
++  return true;
++}
++
++/* If there is a simplification opportunity, perform the simplified
++   decompression rewrite.  Otherwise, create a cond expression and two basic
++   blocks to implement pointer decompression.  */
++
++bool
++ipa_struct_reorg::decompress_candidate (gimple_stmt_iterator *gsi,
++					tree lhs, tree rhs, tree &new_lhs,
++					tree &new_rhs)
++{
++  // TODO: simplifiy check and rewrite will be pushed in next PR.
++  return decompress_candidate_with_check (gsi, rhs, new_rhs);
++}
++
++/* Try to perform pointer compression and decompression.  */
++
++void
++ipa_struct_reorg::try_rewrite_with_pointer_compression (gassign *stmt,
++							gimple_stmt_iterator
++							*gsi, tree lhs,
++							tree rhs, tree &new_lhs,
++							tree &new_rhs)
++{
++  bool l = pc_candidate_tree_p (lhs);
++  bool r = pc_candidate_tree_p (rhs);
++  if (!l && !r)
++    {
++      tree tmp_rhs = new_rhs == NULL_TREE ? rhs : new_rhs;
++      if (pc_type_conversion_candidate_p (lhs))
++	{
++	  /* Transfer MEM[(struct *)_1].files = _4;
++	     to MEM[(struct *)_1].files = (struct *)_4; */
++	  new_rhs = fold_convert (TREE_TYPE (lhs), tmp_rhs);
++	}
++      else if (pc_type_conversion_candidate_p (rhs))
++	{
++	  /* Transfer _4 = MEM[(struct *)_1].nodes;
++	     to _4  = (new_struct *) MEM[(struct *)_1].nodes; */
++	  new_rhs = fold_convert (TREE_TYPE (new_lhs), tmp_rhs);
++	}
++    }
++  else if (l && r)
++    gcc_unreachable ();
++  else if (l)
++    {
++      if (!compress_candidate (stmt, gsi, rhs, new_rhs))
++	gcc_unreachable ();
++    }
++  else if (r)
++    {
++      if (!decompress_candidate (gsi, lhs, rhs, new_lhs, new_rhs))
++	gcc_unreachable ();
++    }
++}
++
+ bool
+ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ {
+@@ -5880,6 +6560,9 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	fprintf (dump_file, "\nreplaced with:\n");
+       for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++)
+ 	{
++	  if (current_layout_opt_level >= POINTER_COMPRESSION_SAFE)
++	    try_rewrite_with_pointer_compression (stmt, gsi, lhs, rhs,
++						  newlhs[i], newrhs[i]);
+ 	  gimple *newstmt = gimple_build_assign (newlhs[i] ? newlhs[i] : lhs,
+ 						 newrhs[i] ? newrhs[i] : rhs);
+ 	  if (dump_file && (dump_flags & TDF_DETAILS))
+@@ -5956,6 +6639,13 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi)
+ 	    gcc_assert (false);
+ 	  gimple_call_set_lhs (g, decl->newdecl[i]);
+ 	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++	  if (type->pc_candidate)
++	    {
++	      /* Init global header for pointer compression.  */
++	      gassign *gptr
++		= gimple_build_assign (type->pc_gptr, decl->newdecl[i]);
++	      gsi_insert_before (gsi, gptr, GSI_SAME_STMT);
++	    }
+ 	}
+       return true;
+     }
+@@ -6411,6 +7101,12 @@ ipa_struct_reorg::rewrite_functions (void)
+       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+       current_function = f;
+ 
++      if (current_layout_opt_level >= POINTER_COMPRESSION_SAFE)
++	{
++	  calculate_dominance_info (CDI_DOMINATORS);
++	  loop_optimizer_init (0);
++	}
++
+       if (dump_file && (dump_flags & TDF_DETAILS))
+ 	{
+ 	  fprintf (dump_file, "\nBefore rewrite: %dth_%s\n",
+@@ -6486,6 +7182,9 @@ ipa_struct_reorg::rewrite_functions (void)
+ 
+       free_dominance_info (CDI_DOMINATORS);
+ 
++      if (current_layout_opt_level >= POINTER_COMPRESSION_SAFE)
++	loop_optimizer_finalize ();
++
+       if (dump_file)
+ 	{
+ 	  fprintf (dump_file, "\nAfter rewrite: %dth_%s\n",
+@@ -6514,6 +7213,8 @@ ipa_struct_reorg::execute_struct_relayout (void)
+ 	continue;
+       if (types[i]->chain_type)
+ 	continue;
++      if (get_type_name (types[i]->type) == NULL)
++	continue;
+       retval |= ipa_struct_relayout (type, this).execute ();
+     }
+ 
+@@ -6530,6 +7231,131 @@ ipa_struct_reorg::execute_struct_relayout (void)
+   return retval;
+ }
+ 
++/* True if the var with void type is only used to compare with the same
++   target type.  */
++
++bool
++ipa_struct_reorg::safe_void_cmp_p (tree var, srtype *type)
++{
++  imm_use_iterator imm_iter;
++  use_operand_p use_p;
++  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
++    {
++      gimple *use_stmt = USE_STMT (use_p);
++      if (is_gimple_debug (use_stmt))
++	continue;
++
++      if (gimple_code (use_stmt) == GIMPLE_COND)
++	{
++	  tree lhs = gimple_cond_lhs (use_stmt);
++	  tree rhs = gimple_cond_rhs (use_stmt);
++	  tree xhs = lhs == var ? rhs : lhs;
++	  if (types_compatible_p (inner_type (TREE_TYPE (xhs)), type->type))
++	    continue;
++
++	}
++      return false;
++    }
++  return true;
++}
++
++/* Mark the structure that should perform pointer compression.  */
++
++void
++ipa_struct_reorg::check_and_prune_struct_for_pointer_compression (void)
++{
++  unsigned pc_transform_num = 0;
++
++  if (dump_file)
++    fprintf (dump_file, "\nMark the structure that should perform pointer"
++			" compression:\n");
++
++  for (unsigned i = 0; i < types.length (); i++)
++    {
++      srtype *type = types[i];
++      if (dump_file)
++	print_generic_expr (dump_file, type->type);
++
++      if (type->has_escaped ())
++	{
++	  if (dump_file)
++	    fprintf (dump_file, " has escaped by %s, skip compression.\n",
++		     type->escape_reason ());
++	  continue;
++	}
++      if (TYPE_FIELDS (type->type) == NULL)
++	{
++	  if (dump_file)
++	    fprintf (dump_file, " has zero field, skip compression.\n");
++	  continue;
++	}
++      if (type->chain_type)
++	{
++	  if (dump_file)
++	      fprintf (dump_file, " is chain_type, skip compression.\n");
++	  continue;
++	}
++      if (type->has_alloc_array != 1)
++	{
++	  if (dump_file)
++	    fprintf (dump_file, " has alloc number: %d, skip compression.\n",
++		     type->has_alloc_array);
++	  continue;
++	}
++      if (get_type_name (type->type) == NULL)
++	{
++	  if (dump_file)
++	    fprintf (dump_file, " has empty struct name,"
++				" skip compression.\n");
++	  continue;
++	}
++      if ((current_layout_opt_level & POINTER_COMPRESSION_SAFE)
++	  && !type->has_legal_alloc_num)
++	{
++	  if (dump_file)
++	    fprintf (dump_file, " has illegal struct array size,"
++				" skip compression.\n");
++	  continue;
++	}
++      pc_transform_num++;
++      type->pc_candidate = true;
++      if (dump_file)
++	fprintf (dump_file, " attemps to do pointer compression.\n");
++    }
++
++  if (dump_file)
++    {
++      if (pc_transform_num)
++	fprintf (dump_file, "\nNumber of structures to transform in "
++			    "pointer compression is %d\n", pc_transform_num);
++      else
++	fprintf (dump_file, "\nNo structures to transform in "
++			    "pointer compression.\n");
++    }
++}
++
++/* Init pointer size from parameter param_pointer_compression_size.  */
++
++static void
++init_pointer_size_for_pointer_compression (void)
++{
++  switch (param_pointer_compression_size)
++    {
++      case 8:
++	compressed_size = 8; // sizeof (uint8)
++	break;
++      case 16:
++	compressed_size = 16; // sizeof (uint16)
++	break;
++      case 32:
++	compressed_size = 32; // sizeof (uint32)
++	break;
++      default:
++	error ("Invalid pointer compression size, using the following param: "
++	       "\"--param compressed-pointer-size=[8,16,32]\"");
++    }
++}
++
+ unsigned int
+ ipa_struct_reorg::execute (unsigned int opt)
+ {
+@@ -6551,6 +7377,8 @@ ipa_struct_reorg::execute (unsigned int opt)
+       if (current_layout_opt_level == STRUCT_SPLIT)
+ 	analyze_types ();
+ 
++      if (opt >= POINTER_COMPRESSION_SAFE)
++	check_and_prune_struct_for_pointer_compression ();
+       ret = rewrite_functions ();
+     }
+   else
+@@ -6598,6 +7426,8 @@ public:
+     unsigned int level = 0;
+     switch (struct_layout_optimize_level)
+       {
++	case 4: level |= POINTER_COMPRESSION_SAFE;
++	// FALLTHRU
+ 	case 3: level |= DEAD_FIELD_ELIMINATION;
+ 	// FALLTHRU
+ 	case 2: level |= STRUCT_REORDER_FIELDS;
+@@ -6609,6 +7439,10 @@ public:
+ 	case 0: break;
+ 	default: gcc_unreachable ();
+       }
++
++    if (level & POINTER_COMPRESSION_SAFE)
++      init_pointer_size_for_pointer_compression ();
++
+     /* Preserved for backward compatibility, reorder fields needs run before
+        struct split and complete struct relayout.  */
+     if (flag_ipa_reorder_fields && level < STRUCT_REORDER_FIELDS)
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+index 719f7b308..6c4469597 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -121,7 +121,10 @@ private:
+ 
+ public:
+   tree newtype[max_split];
++  tree pc_gptr;
+   bool visited;
++  bool pc_candidate;
++  bool has_legal_alloc_num;
+   /* Negative number means it has illegal allocated arrays
+      that we do not optimize.  */
+   int has_alloc_array;
+@@ -145,6 +148,7 @@ public:
+   void analyze (void);
+   bool has_dead_field (void);
+   void mark_escape (escape_type, gimple *stmt);
++  void create_global_ptr_for_pc ();
+   bool has_escaped (void)
+   {
+     return escapes != does_not_escape;
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 1ddf1343f..d2196dc68 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1205,4 +1205,8 @@ Enum(vrp_mode) String(vrp) Value(VRP_MODE_VRP)
+ EnumValue
+ Enum(vrp_mode) String(ranger) Value(VRP_MODE_RANGER)
+ 
++-param=compressed-pointer-size=
++Common Joined UInteger Var(param_pointer_compression_size) Init(32) IntegerRange(8, 32) Param Optimization
++Target size of compressed pointer, which should be 8, 16 or 32.
++
+ ; This comment is to ensure we retain the blank line above.
+-- 
+2.33.0
+
diff --git a/0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch b/0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch
new file mode 100644
index 0000000..2bca621
--- /dev/null
+++ b/0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch
@@ -0,0 +1,1232 @@
+From 82d6166cd29fb1c3474f29b28cb7e5478d3a551a Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Mon, 25 Dec 2023 11:17:04 +0800
+Subject: [PATCH] [Struct Reorg] Add unsafe structure pointer compression
+
+Unsafe structure pointer compression allows for some dangerous
+conversions for better performance.
+Add flag -fipa-struct-reorg=5 to enable unsafe structure pointer
+compression.
+---
+ gcc/common.opt                                |   6 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc      | 365 ++++++++++++++----
+ gcc/symbol-summary.h                          |  22 +-
+ .../gcc.dg/struct/csr_skip_void_struct_name.c |  53 +++
+ gcc/testsuite/gcc.dg/struct/pc_cast_int.c     |  91 +++++
+ .../gcc.dg/struct/pc_compress_and_decomress.c |  90 +++++
+ gcc/testsuite/gcc.dg/struct/pc_ptr2void.c     |  87 +++++
+ .../gcc.dg/struct/pc_simple_rewrite_pc.c      | 112 ++++++
+ .../gcc.dg/struct/pc_skip_void_struct_name.c  |  53 +++
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |   8 +
+ 10 files changed, 804 insertions(+), 83 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/pc_cast_int.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/pc_ptr2void.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 56b547506..c7c6bc256 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1993,9 +1993,9 @@ Common Var(flag_ipa_struct_reorg) Init(0) Optimization
+ Perform structure layout optimizations.
+ 
+ fipa-struct-reorg=
+-Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 4)
+--fipa-struct-reorg=[0,1,2,3,4] adding none, struct-reorg, reorder-fields,
+-dfe, safe-pointer-compression optimizations.
++Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 5)
++-fipa-struct-reorg=[0,1,2,3,4,5] adding none, struct-reorg, reorder-fields,
++dfe, safe-pointer-compression, unsafe-pointer-compression optimizations.
+ 
+ fipa-vrp
+ Common Var(flag_ipa_vrp) Optimization
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index 5d451c4c8..fa33f2d35 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -293,7 +293,8 @@ enum struct_layout_opt_level
+   COMPLETE_STRUCT_RELAYOUT = 1 << 1,
+   STRUCT_REORDER_FIELDS = 1 << 2,
+   DEAD_FIELD_ELIMINATION = 1 << 3,
+-  POINTER_COMPRESSION_SAFE = 1 << 4
++  POINTER_COMPRESSION_SAFE = 1 << 4,
++  POINTER_COMPRESSION_UNSAFE = 1 << 5
+ };
+ 
+ /* Defines the target pointer size of compressed pointer, which should be 8,
+@@ -1267,10 +1268,10 @@ csrtype::init_type_info (void)
+ 
+   /* Close enough to pad to improve performance.
+      33~63 should pad to 64 but 33~48 (first half) are too far away, and
+-     65~127 should pad to 128 but 65~96 (first half) are too far away.  */
++     70~127 should pad to 128 but 65~70 (first half) are too far away.  */
+   if (old_size > 48 && old_size < 64)
+     new_size = 64;
+-  if (old_size > 96 && old_size < 128)
++  if (old_size > 70 && old_size < 128)
+     new_size = 128;
+ 
+   /* For performance reasons, only allow structure size
+@@ -1423,8 +1424,12 @@ public:
+   bool pc_candidate_tree_p (tree);
+   bool pc_type_conversion_candidate_p (tree);
+   bool pc_direct_rewrite_chance_p (tree, tree &);
++  bool pc_simplify_chance_for_compress_p (gassign *, tree);
++  bool compress_candidate_without_check (gimple_stmt_iterator *, tree, tree &);
+   bool compress_candidate_with_check (gimple_stmt_iterator *, tree, tree &);
+   bool compress_candidate (gassign *, gimple_stmt_iterator *, tree, tree &);
++  bool decompress_candidate_without_check (gimple_stmt_iterator *,
++					   tree, tree, tree &, tree &);
+   bool decompress_candidate_with_check (gimple_stmt_iterator *, tree, tree &);
+   bool decompress_candidate (gimple_stmt_iterator *, tree, tree, tree &,
+ 			     tree &);
+@@ -1924,7 +1929,6 @@ bool
+ ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *gsi,
+ 					HOST_WIDE_INT ×)
+ {
+-  bool ret = false;
+   gcc_assert (TREE_CODE (cst) == INTEGER_CST);
+ 
+   gimple *stmt = gsi_stmt (*gsi);
+@@ -1948,27 +1952,95 @@ ipa_struct_relayout::maybe_rewrite_cst (tree cst, gimple_stmt_iterator *gsi,
+     {
+       if (gsi_one_before_end_p (*gsi))
+ 	return false;
+-      gsi_next (gsi);
+-      gimple *stmt2 = gsi_stmt (*gsi);
+-
+-      if (gimple_code (stmt2) == GIMPLE_ASSIGN
+-	  && gimple_assign_rhs_code (stmt2) == POINTER_PLUS_EXPR)
++      // Check uses.
++      imm_use_iterator imm_iter_lhs;
++      use_operand_p use_p_lhs;
++      FOR_EACH_IMM_USE_FAST (use_p_lhs, imm_iter_lhs, gimple_assign_lhs (stmt))
+ 	{
+-	  tree lhs = gimple_assign_lhs (stmt2);
+-	  tree rhs1 = gimple_assign_rhs1 (stmt2);
+-	  if (types_compatible_p (inner_type (TREE_TYPE (rhs1)), ctype.type)
+-	      || types_compatible_p (inner_type (TREE_TYPE (lhs)), ctype.type))
++	  gimple *stmt2 = USE_STMT (use_p_lhs);
++	  if (gimple_code (stmt2) != GIMPLE_ASSIGN)
++	    continue;
++	  if (gimple_assign_rhs_code (stmt2) == POINTER_PLUS_EXPR)
+ 	    {
+-	      tree num = NULL;
+-	      if (is_result_of_mult (cst, &num, TYPE_SIZE_UNIT (ctype.type)))
++	      tree lhs = gimple_assign_lhs (stmt2);
++	      tree rhs1 = gimple_assign_rhs1 (stmt2);
++	      if (types_compatible_p (inner_type (TREE_TYPE (rhs1)), ctype.type)
++		  || types_compatible_p (inner_type (TREE_TYPE (lhs)),
++					 ctype.type))
+ 		{
+-		  times = TREE_INT_CST_LOW (num);
+-		  ret = true;
++		  tree num = NULL;
++		  if (is_result_of_mult (cst, &num,
++					 TYPE_SIZE_UNIT (ctype.type)))
++		    {
++		      times = TREE_INT_CST_LOW (num);
++		      return true;
++		    }
++		}
++	    }
++	  // For pointer compression, handle plus stmt.
++	  else if (gimple_assign_rhs_code (stmt2) == PLUS_EXPR)
++	    {
++	      // Check uses.
++	      imm_use_iterator imm_iter_cast;
++	      use_operand_p use_p_cast;
++	      FOR_EACH_IMM_USE_FAST (use_p_cast, imm_iter_cast,
++				     gimple_assign_lhs (stmt2))
++		{
++		  gimple *stmt_cast = USE_STMT (use_p_cast);
++		  if (gimple_code (stmt_cast) != GIMPLE_ASSIGN)
++		    continue;
++		  if (gimple_assign_cast_p (stmt_cast))
++		    {
++		      tree lhs_type = inner_type (TREE_TYPE (
++					gimple_assign_lhs (stmt_cast)));
++		      if (types_compatible_p (lhs_type, ctype.type))
++			{
++			  tree num = NULL;
++			  if (is_result_of_mult (cst, &num,
++						 TYPE_SIZE_UNIT (ctype.type)))
++			    {
++			      times = TREE_INT_CST_LOW (num);
++			      return true;
++			    }
++			}
++		    }
+ 		}
+ 	    }
+ 	}
+-      gsi_prev (gsi);
+-      return ret;
++    }
++  // For pointer compression, handle div stmt.
++  if (gimple_assign_rhs_code (stmt) == TRUNC_DIV_EXPR)
++    {
++      imm_use_iterator imm_iter;
++      use_operand_p use_p;
++      tree lhs = gimple_assign_lhs (stmt);
++      if (lhs == NULL_TREE)
++	return false;
++      FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
++	{
++	  gimple *use_stmt = USE_STMT (use_p);
++	  if (is_gimple_debug (use_stmt))
++	    continue;
++	  if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
++	    continue;
++	  if (gimple_assign_cast_p (use_stmt))
++	    {
++	      tree lhs_type = inner_type (TREE_TYPE (
++				gimple_assign_lhs (use_stmt)));
++	      if (TYPE_UNSIGNED (lhs_type)
++		  && TREE_CODE (lhs_type) == INTEGER_TYPE
++		  && TYPE_PRECISION (lhs_type) == compressed_size)
++		{
++		  tree num = NULL;
++		  if (is_result_of_mult (cst, &num,
++					 TYPE_SIZE_UNIT (ctype.type)))
++		    {
++		      times = TREE_INT_CST_LOW (num);
++		      return true;
++		    }
++		}
++ 	    }
++ 	}
+     }
+   return false;
+ }
+@@ -2967,7 +3039,9 @@ ipa_struct_reorg::record_var (tree decl, escape_type escapes, int arg)
+ 	  && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ 	e = escape_separate_instance;
+ 
+-      if (e != does_not_escape)
++      if (e != does_not_escape
++	  && (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT
++	      || replace_type_map.get (type->type) == NULL))
+ 	type->mark_escape (e, NULL);
+     }
+ 
+@@ -3629,7 +3703,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other,
+       if (TREE_CODE (side) == SSA_NAME
+ 	  && VOID_POINTER_P (TREE_TYPE (side)))
+ 	return;
+-      d->type->mark_escape (escape_cast_another_ptr, stmt);
++      if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT
++	  || replace_type_map.get (d->type->type) == NULL)
++	d->type->mark_escape (escape_cast_another_ptr, stmt);
+       return;
+     }
+ 
+@@ -3645,7 +3721,9 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other,
+ 	}
+       else
+ 	/* *_1 = &MEM[(void *)&x + 8B].  */
+-	type->mark_escape (escape_cast_another_ptr, stmt);
++	if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT
++	    || replace_type_map.get (type->type) == NULL)
++	    type->mark_escape (escape_cast_another_ptr, stmt);
+     }
+   else if (type != d->type)
+     {
+@@ -4364,7 +4442,9 @@ ipa_struct_reorg::check_definition_assign (srdecl *decl,
+   /* Casts between pointers and integer are escaping.  */
+   if (gimple_assign_cast_p (stmt))
+     {
+-      type->mark_escape (escape_cast_int, stmt);
++      if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT
++	  || replace_type_map.get (type->type) == NULL)
++	type->mark_escape (escape_cast_int, stmt);
+       return;
+     }
+ 
+@@ -4684,7 +4764,9 @@ ipa_struct_reorg::check_use (srdecl *decl, gimple *stmt,
+   /* Casts between pointers and integer are escaping.  */
+   if (gimple_assign_cast_p (stmt))
+     {
+-      type->mark_escape (escape_cast_int, stmt);
++      if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT
++	  || replace_type_map.get (type->type) == NULL)
++	type->mark_escape (escape_cast_int, stmt);
+       return;
+     }
+ 
+@@ -5364,9 +5446,9 @@ ipa_struct_reorg::prune_escaped_types (void)
+ 
+   /* Prune types that escape, all references to those types
+      will have been removed in the above loops.  */
+-  /* The escape type is not deleted in STRUCT_REORDER_FIELDS,
+-     Then the type that contains the escaped type fields
+-     can find complete information.  */
++  /* The escape type is not deleted in current_layout_opt_level
++     after STRUCT_REORDER_FIELDS, then the type that contains
++     the escaped type fields can find complete information.  */
+   if (current_layout_opt_level < STRUCT_REORDER_FIELDS)
+     {
+       for (unsigned i = 0; i < types.length ();)
+@@ -5842,17 +5924,17 @@ ipa_struct_reorg::compress_ptr_to_offset (tree xhs, srtype *type,
+   tree step2 = gimplify_build2 (gsi, TRUNC_DIV_EXPR, long_unsigned_type_node,
+ 				step1, TYPE_SIZE_UNIT (type->newtype[0]));
+ 
+-  /* Emit gimple _X3 = _X2 + 1.  */
+-  tree step3 = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node,
+-				step2, build_one_cst (long_unsigned_type_node));
++  /* Emit _X3 = (compressed_size) _X2.  */
++  tree pc_type = make_unsigned_type (compressed_size);
++  tree step3 = gimplify_build1 (gsi, NOP_EXPR, pc_type, step2);
+ 
+-  /* Emit _X4 = (compressed_size) _X3.  */
+-  tree step4 = gimplify_build1 (gsi, NOP_EXPR,
+-				make_unsigned_type (compressed_size), step3);
++  /* Emit gimple _X4 = _X3 + 1.  */
++  tree step4 = gimplify_build2 (gsi, PLUS_EXPR, pc_type, step3,
++				build_one_cst (pc_type));
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+-      print_generic_expr (dump_file, step3);
++      print_generic_expr (dump_file, step4);
+       fprintf (dump_file, "\n");
+     }
+   return step4;
+@@ -5894,7 +5976,7 @@ ipa_struct_reorg::decompress_offset_to_ptr (tree xhs, srtype *type,
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+-      print_generic_expr (dump_file, step3);
++      print_generic_expr (dump_file, step4);
+       fprintf (dump_file, "\n");
+     }
+   return step4;
+@@ -5967,7 +6049,10 @@ ipa_struct_reorg::pc_type_conversion_candidate_p (tree xhs)
+ 
+   if (TREE_CODE (xhs) == COMPONENT_REF)
+     {
+-      srtype *base_type = find_type (TREE_TYPE (TREE_OPERAND (xhs, 0)));
++      tree mem = TREE_OPERAND (xhs, 0);
++      if (TREE_CODE (mem) != MEM_REF)
++	return false;
++      srtype *base_type = find_type (TREE_TYPE (mem));
+       if (base_type != NULL && base_type->has_escaped ())
+ 	return pc_candidate_st_type_p (TREE_TYPE (xhs));
+ 
+@@ -6057,6 +6142,49 @@ ipa_struct_reorg::pc_direct_rewrite_chance_p (tree rhs, tree &new_rhs)
+   return false;
+ }
+ 
++/* The following cases can simplify the checking of null pointer:
++     1. rhs defined from POINTER_PLUS_EXPR.
++     2. rhs used as COMPONENT_REF in this basic block.  */
++
++bool
++ipa_struct_reorg::pc_simplify_chance_for_compress_p (gassign *stmt,
++						     tree rhs)
++{
++  imm_use_iterator imm_iter;
++  use_operand_p use_p;
++  gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
++
++  if (def_stmt && is_gimple_assign (def_stmt)
++      && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR)
++    return true;
++
++  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, rhs)
++    {
++      gimple *use_stmt = USE_STMT (use_p);
++      if (use_stmt->bb != stmt->bb || !is_gimple_assign (use_stmt))
++	continue;
++
++      tree use_rhs = gimple_assign_rhs1 (use_stmt);
++      if (TREE_CODE (use_rhs) == COMPONENT_REF
++	  && TREE_OPERAND (TREE_OPERAND (use_rhs, 0), 0) == rhs)
++	return true;
++    }
++  return false;
++}
++
++/* Perform compression directly without checking null pointer.  */
++
++bool
++ipa_struct_reorg::compress_candidate_without_check (gimple_stmt_iterator *gsi,
++						    tree rhs,
++						    tree &new_rhs)
++{
++  srtype *type = get_compression_candidate_type (rhs);
++  gcc_assert (type != NULL);
++  new_rhs = compress_ptr_to_offset (new_rhs, type, gsi);
++  return true;
++}
++
+ /* Perform pointer compression with check.  The conversion will be as shown in
+    the following example:
+      Orig bb:
+@@ -6157,6 +6285,9 @@ ipa_struct_reorg::compress_candidate (gassign *stmt, gimple_stmt_iterator *gsi,
+ {
+   if (pc_direct_rewrite_chance_p (rhs, new_rhs))
+     return true;
++  else if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE
++	   && pc_simplify_chance_for_compress_p (stmt, rhs))
++    return compress_candidate_without_check (gsi, rhs, new_rhs);
+ 
+   return compress_candidate_with_check (gsi, rhs, new_rhs);
+ }
+@@ -6219,6 +6350,80 @@ ipa_struct_reorg::create_bb_for_decompress_candidate (basic_block last_bb,
+   return new_bb;
+ }
+ 
++/* Try decompress candidate without check.  */
++
++bool
++ipa_struct_reorg::decompress_candidate_without_check (gimple_stmt_iterator *gsi,
++						      tree lhs, tree rhs,
++						      tree &new_lhs,
++						      tree &new_rhs)
++{
++  imm_use_iterator imm_iter;
++  use_operand_p use_p;
++  bool processed = false;
++
++  if (!gsi_one_before_end_p (*gsi))
++    {
++      gsi_next (gsi);
++      gimple *next_stmt = gsi_stmt (*gsi);
++      if (gimple_code (next_stmt) == GIMPLE_ASSIGN
++	  && gimple_assign_rhs_class (next_stmt) == GIMPLE_SINGLE_RHS)
++	{
++	  tree next_rhs = gimple_assign_rhs1 (next_stmt);
++	  /* If current lhs is used as rhs in the next stmt:
++	     -> _1 = t->s
++		tt->s = _1.  */
++	  if (lhs == next_rhs)
++	    {
++	      /* Check whether:
++	       1. the lhs is only used in the next stmt.
++	       2. the next lhs is candidate type.  */
++	      if (has_single_use (lhs)
++		  && pc_candidate_tree_p (gimple_assign_lhs (next_stmt)))
++		{
++		  processed = true;
++		  /* Copy directly without conversion after update type.  */
++		  TREE_TYPE (new_lhs)
++		    = make_unsigned_type (compressed_size);
++		}
++	    }
++	  /* -> _1 = t->s
++	        _2 = _1->s
++	     In this case, _1 might not be nullptr, so decompress it without
++	     check.  */
++	  else if (TREE_CODE (next_rhs) == COMPONENT_REF)
++	    {
++	      tree use_base = TREE_OPERAND (TREE_OPERAND (next_rhs, 0), 0);
++	      if (use_base == lhs)
++		{
++		  srtype *type = get_compression_candidate_type (rhs);
++		  gcc_assert (type != NULL);
++		  gsi_prev (gsi);
++		  tree new_ref = NULL_TREE;
++		  if (TREE_CODE (new_rhs) == MEM_REF)
++		    new_ref = new_rhs;
++		  else
++		    {
++		      tree base = TREE_OPERAND (TREE_OPERAND (new_rhs, 0), 0);
++		      tree new_mem_ref = build_simple_mem_ref (base);
++		      new_ref = build3 (COMPONENT_REF,
++					TREE_TYPE (new_rhs),
++					new_mem_ref,
++					TREE_OPERAND (new_rhs, 1),
++					NULL_TREE);
++		    }
++		  new_rhs = decompress_offset_to_ptr (new_ref, type, gsi);
++		  processed = true;
++		  gsi_next (gsi);
++		}
++	    }
++	}
++      gsi_prev (gsi);
++      return processed;
++    }
++  return false;
++}
++
+ /* Perform pointer decompression with check.  The conversion will be as shown
+    in the following example:
+      Orig bb:
+@@ -6320,7 +6525,10 @@ ipa_struct_reorg::decompress_candidate (gimple_stmt_iterator *gsi,
+ 					tree lhs, tree rhs, tree &new_lhs,
+ 					tree &new_rhs)
+ {
+-  // TODO: simplifiy check and rewrite will be pushed in next PR.
++  if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE
++      && decompress_candidate_without_check (gsi, lhs, rhs, new_lhs, new_rhs))
++    return true;
++
+   return decompress_candidate_with_check (gsi, rhs, new_rhs);
+ }
+ 
+@@ -6341,14 +6549,23 @@ ipa_struct_reorg::try_rewrite_with_pointer_compression (gassign *stmt,
+       if (pc_type_conversion_candidate_p (lhs))
+ 	{
+ 	  /* Transfer MEM[(struct *)_1].files = _4;
+-	     to MEM[(struct *)_1].files = (struct *)_4; */
+-	  new_rhs = fold_convert (TREE_TYPE (lhs), tmp_rhs);
++	     to _tmp = (struct *)_4;
++		MEM[(struct *)_1].files = _tmp; */
++	  tree tmp_reg = create_tmp_reg (TREE_TYPE (lhs));
++	  tree tmp_rhs_cvt = fold_convert (TREE_TYPE (lhs), tmp_rhs);
++	  gimple *copy_stmt = gimple_build_assign (tmp_reg, tmp_rhs_cvt);
++	  gsi_insert_before (gsi, copy_stmt, GSI_SAME_STMT);
++	  new_rhs = tmp_reg;
+ 	}
+       else if (pc_type_conversion_candidate_p (rhs))
+ 	{
+ 	  /* Transfer _4 = MEM[(struct *)_1].nodes;
+-	     to _4  = (new_struct *) MEM[(struct *)_1].nodes; */
+-	  new_rhs = fold_convert (TREE_TYPE (new_lhs), tmp_rhs);
++	     to _tmp = MEM[(struct *)_1].nodes;
++		_4  = (new_struct *) _tmp; */
++	  tree tmp_reg = create_tmp_reg (TREE_TYPE (new_lhs));
++	  gimple *copy_stmt = gimple_build_assign (tmp_reg, tmp_rhs);
++	  gsi_insert_before (gsi, copy_stmt, GSI_SAME_STMT);
++	  new_rhs = fold_convert (TREE_TYPE (new_lhs), tmp_reg);
+ 	}
+     }
+   else if (l && r)
+@@ -6544,7 +6761,7 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 
+       if (dump_file && (dump_flags & TDF_DETAILS))
+ 	{
+-	  fprintf (dump_file, "\nrewriting stamtenet:\n");
++	  fprintf (dump_file, "\nrewriting statement:\n");
+ 	  print_gimple_stmt (dump_file, stmt, 0);
+ 	}
+       tree newlhs[max_split];
+@@ -6809,7 +7026,8 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi)
+    old statement is to be removed.  */
+ 
+ bool
+-ipa_struct_reorg::rewrite_cond (gcond *stmt, gimple_stmt_iterator *gsi)
++ipa_struct_reorg::rewrite_cond (gcond *stmt,
++				gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED)
+ {
+   tree_code rhs_code = gimple_cond_code (stmt);
+ 
+@@ -7039,8 +7257,11 @@ ipa_struct_reorg::rewrite_functions (void)
+ 	      if (dump_file && (dump_flags & TDF_DETAILS))
+ 		{
+ 		  fprintf (dump_file, "\nNo rewrite:\n");
+-		  dump_function_to_file (current_function_decl, dump_file,
+-			dump_flags | TDF_VOPS);
++		  if (current_function_decl)
++		    dump_function_to_file (current_function_decl, dump_file,
++					   dump_flags | TDF_VOPS);
++		  else
++		    fprintf (dump_file, " no declaration\n");
+ 		}
+ 	      pop_cfun ();
+ 	    }
+@@ -7073,11 +7294,13 @@ ipa_struct_reorg::rewrite_functions (void)
+ 	  push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ 	  if (dump_file && (dump_flags & TDF_DETAILS))
+ 	    {
+-	      fprintf (dump_file, "==== Before create decls: %dth_%s ====\n\n",
++	      fprintf (dump_file, "==== Before create decls: %dth %s ====\n\n",
+ 		       i, f->node->name ());
+ 	      if (current_function_decl)
+ 		dump_function_to_file (current_function_decl, dump_file,
+ 				       dump_flags | TDF_VOPS);
++	      else
++		fprintf (dump_file, " no declaration\n");
+ 	    }
+ 	  pop_cfun ();
+ 	}
+@@ -7109,10 +7332,13 @@ ipa_struct_reorg::rewrite_functions (void)
+ 
+       if (dump_file && (dump_flags & TDF_DETAILS))
+ 	{
+-	  fprintf (dump_file, "\nBefore rewrite: %dth_%s\n",
++	  fprintf (dump_file, "\nBefore rewrite: %dth %s\n",
+ 		   i, f->node->name ());
+-	  dump_function_to_file (current_function_decl, dump_file,
+-				 dump_flags | TDF_VOPS);
++	  if (current_function_decl)
++	    dump_function_to_file (current_function_decl, dump_file,
++				   dump_flags | TDF_VOPS);
++	  else
++	    fprintf (dump_file, " no declaration\n");
+ 	  fprintf (dump_file, "\n======== Start to rewrite: %dth_%s ========\n",
+ 		   i, f->node->name ());
+ 	}
+@@ -7187,10 +7413,13 @@ ipa_struct_reorg::rewrite_functions (void)
+ 
+       if (dump_file)
+ 	{
+-	  fprintf (dump_file, "\nAfter rewrite: %dth_%s\n",
++	  fprintf (dump_file, "\nAfter rewrite: %dth %s\n",
+ 		   i, f->node->name ());
+-	  dump_function_to_file (current_function_decl, dump_file,
+-				 dump_flags | TDF_VOPS);
++	  if (current_function_decl)
++	    dump_function_to_file (current_function_decl, dump_file,
++				   dump_flags | TDF_VOPS);
++	  else
++	    fprintf (dump_file, " no declaration\n");
+ 	}
+ 
+       pop_cfun ();
+@@ -7309,18 +7538,24 @@ ipa_struct_reorg::check_and_prune_struct_for_pointer_compression (void)
+ 				" skip compression.\n");
+ 	  continue;
+ 	}
+-      if ((current_layout_opt_level & POINTER_COMPRESSION_SAFE)
+-	  && !type->has_legal_alloc_num)
++      if (!type->has_legal_alloc_num)
+ 	{
+-	  if (dump_file)
+-	    fprintf (dump_file, " has illegal struct array size,"
+-				" skip compression.\n");
+-	  continue;
++	  if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE)
++	    if (dump_file)
++	      fprintf (dump_file, " has unknown alloc size, but"
++				  " in unsafe mode, so");
++	  else
++	    {
++	      if (dump_file)
++		fprintf (dump_file, " has illegal struct array size,"
++				    " skip compression.\n");
++	      continue;
++	    }
+ 	}
+       pc_transform_num++;
+       type->pc_candidate = true;
+       if (dump_file)
+-	fprintf (dump_file, " attemps to do pointer compression.\n");
++	fprintf (dump_file, " attempts to do pointer compression.\n");
+     }
+ 
+   if (dump_file)
+@@ -7342,14 +7577,10 @@ init_pointer_size_for_pointer_compression (void)
+   switch (param_pointer_compression_size)
+     {
+       case 8:
+-	compressed_size = 8; // sizeof (uint8)
+-	break;
++      // FALLTHRU
+       case 16:
+-	compressed_size = 16; // sizeof (uint16)
+-	break;
+-      case 32:
+-	compressed_size = 32; // sizeof (uint32)
+-	break;
++      // FALLTHRU
++      case 32: compressed_size = param_pointer_compression_size; break;
+       default:
+ 	error ("Invalid pointer compression size, using the following param: "
+ 	       "\"--param compressed-pointer-size=[8,16,32]\"");
+@@ -7426,6 +7657,8 @@ public:
+     unsigned int level = 0;
+     switch (struct_layout_optimize_level)
+       {
++	case 5: level |= POINTER_COMPRESSION_UNSAFE;
++	// FALLTHRU
+ 	case 4: level |= POINTER_COMPRESSION_SAFE;
+ 	// FALLTHRU
+ 	case 3: level |= DEAD_FIELD_ELIMINATION;
+diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
+index 3fe64047c..4f896f4e4 100644
+--- a/gcc/symbol-summary.h
++++ b/gcc/symbol-summary.h
+@@ -103,16 +103,15 @@ protected:
+   /* Allocates new data that are stored within map.  */
+   T* allocate_new ()
+   {
+-    /* In structure optimizatons, we call new to ensure that
+-       the allocated memory is initialized to 0.  */
+-    if (flag_ipa_struct_reorg)
+-      return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
+-		       : new T ();
+-
+     /* Call gcc_internal_because we do not want to call finalizer for
+        a type T.  We call dtor explicitly.  */
+-    return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
+-		     : m_allocator.allocate () ;
++    T* allocated = is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
++			     : m_allocator.allocate ();
++    /* In structure optimizatons, we call memset to ensure that
++       the allocated memory is initialized to 0.  */
++    if (flag_ipa_struct_reorg)
++      memset (allocated, 0, sizeof (T));
++    return allocated;
+   }
+ 
+   /* Release an item that is stored within map.  */
+@@ -121,12 +120,7 @@ protected:
+     if (is_ggc ())
+       ggc_delete (item);
+     else
+-      {
+-	if (flag_ipa_struct_reorg)
+-	  delete item;
+-	else
+-	  m_allocator.remove (item);
+-      }
++      m_allocator.remove (item);
+   }
+ 
+   /* Unregister all call-graph hooks.  */
+diff --git a/gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c b/gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c
+new file mode 100644
+index 000000000..c5e4968d9
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/csr_skip_void_struct_name.c
+@@ -0,0 +1,53 @@
++// Structures without names should not be optimized
++/* { dg-do compile } */
++#include 
++#include 
++
++typedef struct
++{
++  int a;
++  float b;
++  double s1;
++  double s2;
++  double s3;
++  double s4;
++  double s5;
++  double s6;
++  double s7;
++  double s8;
++} str_t1;
++
++#define N 1000
++
++int num;
++
++int
++main ()
++{
++  int i, r;
++
++  r = rand ();
++  num = r > N ? N : r;
++  str_t1 *p1 = calloc (num, sizeof (str_t1));
++
++  if (p1 == NULL)
++    return 0;
++
++  for (i = 0; i < num; i++)
++    p1[i].a = 1;
++
++  for (i = 0; i < num; i++)
++    p1[i].b = 2;
++
++  for (i = 0; i < num; i++)
++    if (p1[i].a != 1)
++      abort ();
++
++  for (i = 0; i < num; i++)
++    if (fabsf (p1[i].b - 2) > 0.0001)
++      abort ();
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "No structures to transform in Complete Structure Relayout." "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/pc_cast_int.c b/gcc/testsuite/gcc.dg/struct/pc_cast_int.c
+new file mode 100644
+index 000000000..6f67fc556
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/pc_cast_int.c
+@@ -0,0 +1,91 @@
++// Escape cast int for pointer compression
++/* { dg-do compile } */
++
++#include 
++#include 
++
++typedef struct node node_t;
++typedef struct node *node_p;
++
++typedef struct arc arc_t;
++typedef struct arc *arc_p;
++
++typedef struct network
++{
++  arc_p arcs;
++  arc_p sorted_arcs;
++  int x;
++  node_p nodes;
++  node_p stop_nodes;
++} network_t;
++
++struct node
++{
++  int64_t potential;
++  int orientation;
++  node_p child;
++  node_p pred;
++  node_p sibling;
++  node_p sibling_prev;
++  arc_p basic_arc;
++  arc_p firstout;
++  arc_p firstin;
++  arc_p arc_tmp;
++  int64_t flow;
++  int64_t depth;
++  int number;
++  int time;
++};
++
++struct arc
++{
++  int id;
++  int64_t cost;
++  node_p tail;
++  node_p head;
++  short ident;
++  arc_p nextout;
++  arc_p nextin;
++  int64_t flow;
++  int64_t org_cost;
++  network_t* net_add;
++};
++
++
++const int MAX = 100;
++network_t* net;
++node_p node;
++
++int
++main ()
++{
++  net = (network_t*) calloc (1, sizeof(network_t));
++  net->arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->nodes = (node_p) calloc (MAX, sizeof (node_t));
++  net->arcs->id = 100;
++
++  node = net->nodes;
++  node_p n1 = (node_p) 0x123456;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      node->pred = n1;
++      node = node + 1;
++    }
++
++  node = net->nodes;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      if (node->pred != n1)
++	{
++	  abort ();
++	}
++      node = node + 1;
++    }
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "No structures to transform in pointer compression" "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c b/gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c
+new file mode 100644
+index 000000000..d0b8d1afa
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/pc_compress_and_decomress.c
+@@ -0,0 +1,90 @@
++// Support basic pointer compression and decompression
++/* { dg-do compile } */
++
++#include 
++#include 
++
++typedef struct node node_t;
++typedef struct node *node_p;
++
++typedef struct arc arc_t;
++typedef struct arc *arc_p;
++
++typedef struct network
++{
++  arc_p arcs;
++  arc_p sorted_arcs;
++  int x;
++  node_p nodes;
++  node_p stop_nodes;
++} network_t;
++
++struct node
++{
++  int64_t potential;
++  int orientation;
++  node_p child;
++  node_p pred;
++  node_p sibling;
++  node_p sibling_prev;
++  arc_p basic_arc;
++  arc_p firstout;
++  arc_p firstin;
++  arc_p arc_tmp;
++  int64_t flow;
++  int64_t depth;
++  int number;
++  int time;
++};
++
++struct arc
++{
++  int id;
++  int64_t cost;
++  node_p tail;
++  node_p head;
++  short ident;
++  arc_p nextout;
++  arc_p nextin;
++  int64_t flow;
++  int64_t org_cost;
++  network_t* net_add;
++};
++
++
++const int MAX = 100;
++network_t* net;
++node_p node;
++
++int
++main ()
++{
++  net = (network_t*) calloc (1, sizeof(network_t));
++  net->arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->nodes = (node_p) calloc (MAX, sizeof (node_t));
++  net->arcs->id = 100;
++
++  node = net->nodes;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      node->pred = node;
++      node = node + 1;
++    }
++
++  node = net->nodes;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      if (node->pred != node)
++	{
++	  abort ();
++	}
++      node = node + 1;
++    }
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "Number of structures to transform in pointer compression is 1" "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/pc_ptr2void.c b/gcc/testsuite/gcc.dg/struct/pc_ptr2void.c
+new file mode 100644
+index 000000000..5022c1967
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/pc_ptr2void.c
+@@ -0,0 +1,87 @@
++// Partially support escape_cast_void for pointer compression.
++/* { dg-do compile } */
++
++#include 
++#include 
++
++typedef struct node node_t;
++typedef struct node *node_p;
++
++typedef struct arc arc_t;
++typedef struct arc *arc_p;
++
++typedef struct network
++{    
++  arc_p arcs, sorted_arcs;
++  int x;
++  node_p nodes, stop_nodes;
++} network_t;
++
++struct node
++{
++  int64_t potential;
++  int orientation;
++  node_p child;
++  node_p pred;
++  node_p sibling;
++  node_p sibling_prev;
++  arc_p basic_arc;
++  arc_p firstout;
++  arc_p firstin;
++  arc_p arc_tmp;
++  int64_t flow;
++  int64_t depth;
++  int number;
++  int time;
++};
++
++struct arc
++{
++  int id;
++  int64_t cost;
++  node_p tail;
++  node_p head;
++  short ident;
++  arc_p nextout;
++  arc_p nextin;
++  int64_t flow;
++  int64_t org_cost;
++};
++
++const int MAX = 100;
++network_t* net = NULL;
++int cnt = 0;
++
++__attribute__((noinline)) int
++primal_feasible (network_t *net)
++{
++  void* stop;
++  node_t *node;
++
++  node = net->nodes;
++  stop = (void *)net->stop_nodes;
++  for( node++; node < (node_t *)stop; node++ )
++    {
++      net->x = 1;
++      printf( "PRIMAL NETWORK SIMPLEX: ");
++    }
++  return 0;
++}
++
++int
++main ()
++{
++  net = (network_t*) calloc (1, 20);
++  net->nodes = calloc (MAX, sizeof (node_t));
++  net->stop_nodes = net->nodes + MAX - 1;
++  cnt = primal_feasible( net );
++
++  net = (network_t*) calloc (1, 20);
++  if( !(net->arcs) )
++    {
++      return -1;
++    }
++  return cnt;
++}
++
++/* { dg-final { scan-ipa-dump "Number of structures to transform in pointer compression is 1" "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c b/gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c
+new file mode 100644
+index 000000000..98943c9b8
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/pc_simple_rewrite_pc.c
+@@ -0,0 +1,112 @@
++// Check simplify rewrite chance for pointer compression and decompression
++/* { dg-do compile } */
++
++#include 
++#include 
++
++typedef struct node node_t;
++typedef struct node *node_p;
++
++typedef struct arc arc_t;
++typedef struct arc *arc_p;
++
++typedef struct network
++{
++  arc_p arcs;
++  arc_p sorted_arcs;
++  int x;
++  node_p nodes;
++  node_p stop_nodes;
++} network_t;
++
++struct node
++{
++  int64_t potential;
++  int orientation;
++  node_p child;
++  node_p pred;
++  node_p sibling;
++  node_p sibling_prev;
++  arc_p basic_arc;
++  arc_p firstout;
++  arc_p firstin;
++  arc_p arc_tmp;
++  int64_t flow;
++  int64_t depth;
++  int number;
++  int time;
++};
++
++struct arc
++{
++  int id;
++  int64_t cost;
++  node_p tail;
++  node_p head;
++  short ident;
++  arc_p nextout;
++  arc_p nextin;
++  int64_t flow;
++  int64_t org_cost;
++  network_t* net_add;
++};
++
++
++const int MAX = 100;
++network_t* net;
++node_p node;
++arc_p arc;
++
++int
++main ()
++{
++  net = (network_t*) calloc (1, sizeof(network_t));
++  net->arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->nodes = (node_p) calloc (MAX, sizeof (node_t));
++  net->arcs->id = 100;
++
++  node = net->nodes;
++  arc = net->arcs;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      arc->head = node;
++      arc->head->child = node;
++      node->potential = i + 1;
++      arc->cost = arc->head->potential;
++      arc->tail = node->sibling;
++      if (i % 2)
++	node->pred = net->nodes + i;
++      else
++	node->pred = NULL;
++
++      if (node->pred && node->pred->child != NULL)
++	node->number = 0;
++      else
++	node->number = 1;
++
++      node = node + 1;
++      arc = arc + 1;
++    }
++
++  node = net->nodes;
++  arc = net->arcs;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      node_p t = i % 2 ? node : NULL;
++      int tt = i % 2 ? 0 : 1;
++      if (arc->head->pred != t || arc->cost == 0
++	  || arc->tail != node->sibling || node->number != tt)
++	{
++	  abort ();
++	}
++      arc = arc + 1;
++      node = node + 1;
++    }
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "Number of structures to transform in pointer compression is 1" "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c b/gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c
+new file mode 100644
+index 000000000..a0e191267
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/pc_skip_void_struct_name.c
+@@ -0,0 +1,53 @@
++// Structures without names should not be optimized
++/* { dg-do compile } */
++#include 
++#include 
++
++typedef struct
++{
++  int a;
++  float b;
++  double s1;
++  double s2;
++  double s3;
++  double s4;
++  double s5;
++  double s6;
++  double s7;
++  double s8;
++} str_t1;
++
++#define N 1000
++
++int num;
++
++int
++main ()
++{
++  int i, r;
++
++  r = rand ();
++  num = r > N ? N : r;
++  str_t1 *p1 = calloc (num, sizeof (str_t1));
++
++  if (p1 == NULL)
++    return 0;
++
++  for (i = 0; i < num; i++)
++    p1[i].a = 1;
++
++  for (i = 0; i < num; i++)
++    p1[i].b = 2;
++
++  for (i = 0; i < num; i++)
++    if (p1[i].a != 1)
++      abort ();
++
++  for (i = 0; i < num; i++)
++    if (fabsf (p1[i].b - 2) > 0.0001)
++      abort ();
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "No structures to transform in pointer compression" "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index 278c4e4f5..c40474407 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -47,6 +47,14 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \
+ 	"" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
++# -fipa-struct-reorg=4
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \
++	"" "-fipa-struct-reorg=4 -fdump-ipa-all -flto-partition=one -fwhole-program"
++
++# -fipa-struct-reorg=5
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \
++	"" "-fipa-struct-reorg=5 -fdump-ipa-all -flto-partition=one -fwhole-program"
++
+ # All done.
+ torture-finish
+ dg-finish
+-- 
+2.33.0
+
diff --git a/0031-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch b/0031-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch
new file mode 100644
index 0000000..5e16f31
--- /dev/null
+++ b/0031-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch
@@ -0,0 +1,550 @@
+From 72531376df5ed93c2d945469368ba5514eca8407 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Tue, 5 Dec 2023 15:33:08 +0800
+Subject: [PATCH] [AutoBOLT] Support saving feedback count info to ELF segment
+ 1/3
+
+---
+ gcc/common.opt |   8 +
+ gcc/final.cc   | 405 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ gcc/opts.cc    |  61 ++++++++
+ 3 files changed, 473 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index b01df919e..e69947fc2 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2546,6 +2546,14 @@ freorder-functions
+ Common Var(flag_reorder_functions) Optimization
+ Reorder functions to improve code placement.
+ 
++fauto-bolt
++Common Var(flag_auto_bolt)
++Generate profile from AutoFDO or PGO and do BOLT optimization after linkage.
++
++fauto-bolt=
++Common Joined RejectNegative
++Specify the feedback data directory required by BOLT-plugin.  The default is the current directory.
++
+ frerun-cse-after-loop
+ Common Var(flag_rerun_cse_after_loop) Optimization
+ Add a common subexpression elimination pass after loop optimizations.
+diff --git a/gcc/final.cc b/gcc/final.cc
+index a9868861b..d4c4fa08f 100644
+--- a/gcc/final.cc
++++ b/gcc/final.cc
+@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "rtl-iter.h"
+ #include "print-rtl.h"
+ #include "function-abi.h"
++#include "insn-codes.h"
+ #include "common/common-target.h"
+ 
+ #ifdef XCOFF_DEBUGGING_INFO
+@@ -4266,7 +4267,403 @@ leaf_renumber_regs_insn (rtx in_rtx)
+       }
+ }
+ #endif
+-
++
++#define ASM_FDO_SECTION_PREFIX ".text.fdo."
++
++#define ASM_FDO_CALLER_FLAG ".fdo.caller "
++#define ASM_FDO_CALLER_SIZE_FLAG ".fdo.caller.size "
++#define ASM_FDO_CALLER_BIND_FLAG ".fdo.caller.bind"
++
++#define ASM_FDO_CALLEE_FLAG ".fdo.callee"
++
++/* Return the relative offset address of the start instruction of BB,
++   return -1 if it is empty instruction.    */
++
++static int 
++get_bb_start_addr (basic_block bb)
++{
++  rtx_insn *insn;
++  FOR_BB_INSNS (bb, insn)
++    {
++      if (!INSN_P (insn))
++	{
++	  continue;
++	}
++      /* The jump target of call is not in this function, so
++	 it should be excluded.    */
++      if (CALL_P (insn))
++        {
++	  return -1;
++	}
++
++      int insn_code = recog_memoized (insn);
++
++      /* The instruction NOP in llvm-bolt belongs to the previous
++	 BB, so it needs to be skipped.   */
++      if (insn_code != CODE_FOR_nop)
++        {
++	  return INSN_ADDRESSES (INSN_UID (insn));
++	}
++    }
++  return -1;
++}
++
++/* Return the relative offet address of the end instruction of BB,
++   return -1 if it is empty or call instruction.    */
++
++static int
++get_bb_end_addr (basic_block bb)
++{
++  rtx_insn *insn;
++  int num_succs = EDGE_COUNT (bb->succs);
++  FOR_BB_INSNS_REVERSE (bb, insn)
++    {
++      if (!INSN_P (insn))
++        {
++	  continue;
++	}
++      /* The jump target of call is not in this function, so
++	 it should be excluded.     */
++      if (CALL_P (insn))
++        {
++	  return -1;
++	}
++      if ((num_succs == 1)
++	   || ((num_succs == 2) && any_condjump_p (insn)))
++	{
++	  return INSN_ADDRESSES (INSN_UID (insn));
++	}
++      else
++        {
++	  return -1;
++	}
++    }
++  return -1;
++}
++
++/* Return the end address of cfun.    */
++
++static int 
++get_function_end_addr ()
++{
++  rtx_insn *insn = get_last_insn ();
++  for (; insn != get_insns (); insn = PREV_INSN (insn))
++    {
++      if (!INSN_P (insn))
++        {
++	  continue;
++	}
++      return INSN_ADDRESSES (INSN_UID (insn));
++    }
++	  
++  return -1;
++} 
++
++/* Return the function profile status string.    */
++
++static const char * 
++get_function_profile_status () 
++{
++  const char *profile_status[] = {
++    "PROFILE_ABSENT",
++    "PROFILE_GUESSED",
++    "PROFILE_READ",
++    "PROFILE_LAST"     /* Last value, used by profile streaming.    */
++  };
++
++  return profile_status[profile_status_for_fn (cfun)];
++}
++
++/* Return the count from the feedback data, such as PGO or ADDO.    */
++
++inline static gcov_type 
++get_fdo_count (profile_count count)
++{
++  return count.quality () >= GUESSED 
++         ? count.to_gcov_type () : 0;
++}
++
++/* Return the profile quality string.    */
++
++static const char *
++get_fdo_count_quality (profile_count count)
++{
++  const char *profile_quality[] = {
++    "UNINITIALIZED_PROFILE",
++    "GUESSED_LOCAL",
++    "GUESSED_GLOBAL0",
++    "GUESSED_GLOBAL0_ADJUSTED",
++    "GUESSED",
++    "AFDO",
++    "ADJUSTED",
++    "PRECISE"
++  };
++
++  return profile_quality[count.quality ()];
++}
++
++static const char *
++alias_local_functions (const char *fnname)
++{
++  if (TREE_PUBLIC (cfun->decl))
++    {
++      return fnname;
++    }
++  return concat (fnname, "/", lbasename (dump_base_name), NULL);
++}
++
++/* Return function bind type string.    */
++
++static const char * 
++simple_get_function_bind ()
++{
++  const char *function_bind[] = {
++    "GLOBAL",
++    "WEAK",
++    "LOCAL",
++    "UNKNOWN"
++  };
++
++  if (TREE_PUBLIC (cfun->decl))
++    {
++      if (!(DECL_WEAK (cfun->decl)))
++        {
++	  return function_bind[0];
++	}
++      else
++        {
++	  return function_bind[1];
++	}
++    }
++  else  
++    {
++      return function_bind[2];
++    }
++		
++  return function_bind[3];
++}
++
++/* Dumo the callee functions insn in bb by CALL_P (insn).   */
++
++static void 
++dump_direct_callee_info_to_asm (basic_block bb, gcov_type call_count)
++{
++  rtx_insn *insn;
++  FOR_BB_INSNS (bb, insn)
++    {
++      if (insn && CALL_P (insn))
++        {
++	  tree callee = get_call_fndecl (insn);
++
++	  if (callee)
++	    {
++	      fprintf (asm_out_file, "\t.string \"%x\"\n",
++		       INSN_ADDRESSES (INSN_UID (insn)));
++
++	      fprintf (asm_out_file, "\t.string \"%s%s\"\n",
++		       ASM_FDO_CALLEE_FLAG,
++                       alias_local_functions (get_fnname_from_decl (callee)));
++
++              fprintf (asm_out_file,
++                       "\t.string \"" HOST_WIDE_INT_PRINT_DEC "\"\n",
++                       call_count);
++
++              if (dump_file)
++                {
++                  fprintf (dump_file, "call: %x --> %s \n",
++                           INSN_ADDRESSES (INSN_UID (insn)),
++                           alias_local_functions
++                           (get_fnname_from_decl (callee)));
++                }
++            }
++        }
++     } 
++}
++
++/* Dump the edge info into asm.    */
++static int
++dump_edge_jump_info_to_asm (basic_block bb, gcov_type bb_count)
++{
++  edge e;
++  edge_iterator ei;
++  gcov_type edge_total_count = 0;
++
++  FOR_EACH_EDGE (e, ei, bb->succs)
++    {
++      gcov_type edge_count = get_fdo_count (e->count ());
++      edge_total_count += edge_count;
++
++      int edge_start_addr = get_bb_end_addr (e->src);
++      int edge_end_addr = get_bb_start_addr(e->dest);
++
++      if (edge_start_addr == -1 || edge_end_addr == -1)
++        {
++          continue;
++        }
++      
++      /* This is a reserved assert for the original design.    If this
++         assert is found, use the address of the previous instruction
++         as edge_start_addr.   */
++      gcc_assert (edge_start_addr != edge_end_addr);
++
++      if (dump_file)
++        {
++          fprintf (dump_file, "edge: %x --> %x = (%ld)\n",
++                   edge_start_addr, edge_end_addr, edge_count);
++        }
++
++      if (edge_count > 0)
++        {
++          fprintf(asm_out_file, "\t.string \"%x\"\n", edge_start_addr);
++          fprintf(asm_out_file, "\t.string \"%x\"\n", edge_end_addr);
++          fprintf(asm_out_file, "\t.string \"" HOST_WIDE_INT_PRINT_DEC "\"\n",
++                  edge_count);
++        }
++    }
++
++    gcov_type call_count = MAX (edge_total_count, bb_count);
++    if (call_count > 0)
++      {
++        dump_direct_callee_info_to_asm (bb, call_count);
++      }
++}
++
++/* Dump the bb info into asm.    */
++
++static void 
++dump_bb_info_to_asm (basic_block bb, gcov_type bb_count)
++{
++  int bb_start_addr = get_bb_start_addr (bb);
++  if (bb_start_addr != -1)
++    {
++      fprintf (asm_out_file, "\t.string \"%x\"\n", bb_start_addr);
++      fprintf (asm_out_file, "\t.string \"" HOST_WIDE_INT_PRINT_DEC "\"\n",
++               bb_count);
++    }
++}
++
++/* Dump the function info into asm.    */
++
++static void 
++dump_function_info_to_asm (const char *fnname)
++{
++  fprintf (asm_out_file, "\t.string \"%s%s\"\n",
++           ASM_FDO_CALLER_FLAG, alias_local_functions (fnname));
++  fprintf (asm_out_file, "\t.string \"%s%d\"\n",
++           ASM_FDO_CALLER_SIZE_FLAG, get_function_end_addr ());
++  fprintf (asm_out_file, "\t.string \"%s%s\"\n",
++           ASM_FDO_CALLER_BIND_FLAG, simple_get_function_bind ());
++
++  if (dump_file)
++    {
++      fprintf (dump_file, "\n FUNC_NAME: %s\n",
++               alias_local_functions (fnname));
++      fprintf (dump_file, " file: %s\n",
++               dump_base_name);
++      fprintf (dump_file, "profile_status: %s\n",
++               get_function_profile_status ());
++      fprintf (dump_file, " size: %x\n",
++               get_function_end_addr ());
++      fprintf (dump_file, " function_bind: %s\n",
++               simple_get_function_bind ());
++    }
++}
++
++/* Dump function profile into form AutoFDO or PGO to asm.    */
++
++static void
++dump_fdo_info_to_asm (const char *fnname)
++{
++  basic_block bb;
++
++  dump_function_info_to_asm (fnname);
++
++  FOR_EACH_BB_FN (bb, cfun)
++    {
++      gcov_type bb_count = get_fdo_count (bb->count);
++      if (bb_count == 0)
++        {
++          continue;
++        }
++      
++      if (dump_file)
++        {
++          fprintf (dump_file, "BB: %x --> %x = (%ld) [%s]\n",
++                   get_bb_start_addr (bb), get_bb_end_addr (bb),
++                   bb_count, get_fdo_count_quality (bb->count));
++        }
++
++      if (flag_profile_use) 
++        {
++          dump_edge_jump_info_to_asm (bb, bb_count);
++        }
++      else if (flag_auto_profile)
++        {
++          dump_bb_info_to_asm (bb, bb_count);
++        }
++    }
++}
++
++/* When -fauto-bolt option is turnded on, the .text.fdo section 
++   will be generated in the *.s file if there is feedback information
++   from PGO or AutoFDO. This section will parserd in BOLT-plugin.    */
++
++static void 
++dump_profile_to_elf_sections ()
++{
++  if (!flag_function_sections)
++    {
++      error ("-fauto-bolt should work with -ffunction-section");
++      return;
++    }
++  if (!flag_ipa_ra)
++    {
++      error ("-fauto-bolt should work with -fipa-ra");
++      return;
++    }
++  if (flag_align_jumps)
++    {
++      error ("-fauto-bolt is not supported with -falign-jumps");
++      return;
++    }
++  if (flag_align_labels)
++    {
++      error ("-fauto-bolt is not spported with -falign-loops");
++      return;
++    }
++  if (flag_align_loops)
++    {
++      error ("-fauto-bolt is not supported with -falign-loops");
++      return;
++    }
++  
++  /* Return if no feedback data.    */
++  if (!flag_profile_use && !flag_auto_profile)
++    {
++      error ("-fauto-bolt should use with -profile-use or -fauto-profile");
++      return;
++    }
++  
++  /* Avoid empty functions.    */
++  if (TREE_CODE (cfun->decl) != FUNCTION_DECL)
++    {
++      return;
++    }
++  int flags = SECTION_DEBUG | SECTION_EXCLUDE;
++  const char *fnname = get_fnname_from_decl (current_function_decl);
++  char *profile_fnname = NULL;
++
++  asprintf (&profile_fnname, "%s%s", ASM_FDO_SECTION_PREFIX, fnname);
++  switch_to_section (get_section (profile_fnname, flags, NULL));
++  dump_fdo_info_to_asm (fnname);
++
++  if (profile_fnname)
++    {
++      free (profile_fnname);
++      profile_fnname = NULL;
++    }
++}
++
+ /* Turn the RTL into assembly.  */
+ static unsigned int
+ rest_of_handle_final (void)
+@@ -4334,6 +4731,12 @@ rest_of_handle_final (void)
+     targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
+ 				decl_fini_priority_lookup
+ 				  (current_function_decl));
++    
++    if (flag_auto_bolt)
++      {
++        dump_profile_to_elf_sections ();
++      }
++
+   return 0;
+ }
+ 
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index b868d189e..6d57e7d69 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -1279,6 +1279,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
+   if (opts->x_flag_vtable_verify && opts->x_flag_lto)
+     sorry ("vtable verification is not supported with LTO");
+ 
++  /* Currently -fauto-bolt is not supported for LTO.    */
++  if (opts->x_flag_auto_bolt && opts->x_flag_lto)
++    sorry ("%<-fauto-bolt%> is not supported with LTO");
++
+   /* Control IPA optimizations based on different -flive-patching level.  */
+   if (opts->x_flag_live_patching)
+     control_options_for_live_patching (opts, opts_set,
+@@ -1291,6 +1295,58 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
+       = (opts->x_flag_unroll_loops
+          || opts->x_flag_peel_loops
+          || opts->x_optimize >= 3);
++  
++  if (opts->x_flag_auto_bolt)
++    {
++      /* Record the function section to facilitate the feedback
++	 data storage.  */
++      if (!opts->x_flag_function_sections)
++        {
++	  inform (loc,
++	          "%<-fauto-bolt%> should work with %<-ffunction-sections%>,"
++		  " enabling %<-ffunction-sections%>");
++	  opts->x_flag_function_sections = true;
++	}
++
++      /* Cancel the internal alignment of the function.  The binary
++	 optimizer bolt will cancel the internal alignment optimization
++	 of the function, so the alignment is meaningless at this time,
++	 and if not, it will bring trouble to the calculation of the
++	 offset address of the instruction.  */
++      if (opts->x_flag_align_jumps)
++        {
++	  inform (loc,
++		  "%<-fauto-bolt%> should not work with %<-falign-jumps%>,"
++		  " disabling %<-falign-jumps%>");
++	  opts->x_flag_align_jumps = false;
++	}
++
++      if (opts->x_flag_align_labels)
++        {
++	  inform (loc,
++		  "%<-fauto-bolt%> should not work with %<-falign-labels%>,"
++		  " disabling %<-falign-labels%>");
++	          opts->x_flag_align_labels = false;
++	}
++
++      if (opts->x_flag_align_loops)
++        {
++	  inform (loc,
++		  "%<-fauto-bolt%> should not work with %<-falign-loops%>,"
++		  " disabling %<-falign-loops%>");
++	  opts->x_flag_align_loops = false;
++	}
++
++      /* When parsing instructions in RTL phase, we need to know
++	 the call information of instructions to avoid being optimized.  */
++      if (!opts->x_flag_ipa_ra)
++        {
++	  inform (loc,
++		  "%<-fauto-bolt%> should work with %<-fipa-ra%>,"
++		  " enabling %<-fipa-ra%>");
++	  opts->x_flag_ipa_ra = true;
++	}
++    }
+ 
+   /* With -fcx-limited-range, we do cheap and quick complex arithmetic.  */
+   if (opts->x_flag_cx_limited_range)
+@@ -3226,6 +3282,11 @@ common_handle_option (struct gcc_options *opts,
+ 				&opts->x_flag_align_functions,
+ 				&opts->x_str_align_functions);
+       break;
++    
++    case OPT_fauto_bolt_:
++    case OPT_fauto_bolt:
++      /* Deferred.  */  
++      break;  
+ 
+     case OPT_ftabstop_:
+       /* It is documented that we silently ignore silly values.  */
+-- 
+2.33.0
+
diff --git a/0032-AutoBOLT-Add-bolt-linker-plugin-2-3.patch b/0032-AutoBOLT-Add-bolt-linker-plugin-2-3.patch
new file mode 100644
index 0000000..118d1ca
--- /dev/null
+++ b/0032-AutoBOLT-Add-bolt-linker-plugin-2-3.patch
@@ -0,0 +1,34094 @@
+From 82f9f48406955a6150def998b69b4eace4bd51eb Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Thu, 7 Dec 2023 11:43:08 +0800
+Subject: [PATCH] [AutoBOLT] Add bolt linker plugin 2/3
+
+---
+ bolt-plugin/Makefile       |   675 ++
+ bolt-plugin/Makefile.am    |    43 +
+ bolt-plugin/Makefile.in    |   675 ++
+ bolt-plugin/aclocal.m4     | 10250 +++++++++++++++++
+ bolt-plugin/bolt-plugin.cc |  1153 ++
+ bolt-plugin/config.h.in    |   179 +
+ bolt-plugin/configure      | 20909 +++++++++++++++++++++++++++++++++++
+ bolt-plugin/configure.ac   |    60 +
+ gcc/common.opt             |    16 +
+ gcc/opts.cc                |    27 +-
+ 10 files changed, 33985 insertions(+), 2 deletions(-)
+ create mode 100644 bolt-plugin/Makefile
+ create mode 100644 bolt-plugin/Makefile.am
+ create mode 100644 bolt-plugin/Makefile.in
+ create mode 100644 bolt-plugin/aclocal.m4
+ create mode 100644 bolt-plugin/bolt-plugin.cc
+ create mode 100644 bolt-plugin/config.h.in
+ create mode 100755 bolt-plugin/configure
+ create mode 100644 bolt-plugin/configure.ac
+
+diff --git a/bolt-plugin/Makefile b/bolt-plugin/Makefile
+new file mode 100644
+index 000000000..82a4bc2c6
+--- /dev/null
++++ b/bolt-plugin/Makefile
+@@ -0,0 +1,675 @@
++# Makefile.in generated by automake 1.16.5 from Makefile.am.
++# Makefile.  Generated from Makefile.in by configure.
++
++# Copyright (C) 1994-2021 Free Software Foundation, Inc.
++
++# This Makefile.in is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++# PARTICULAR PURPOSE.
++
++
++
++
++am__is_gnu_make = { \
++  if test -z '$(MAKELEVEL)'; then \
++    false; \
++  elif test -n '$(MAKE_HOST)'; then \
++    true; \
++  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
++    true; \
++  else \
++    false; \
++  fi; \
++}
++am__make_running_with_option = \
++  case $${target_option-} in \
++      ?) ;; \
++      *) echo "am__make_running_with_option: internal error: invalid" \
++              "target option '$${target_option-}' specified" >&2; \
++         exit 1;; \
++  esac; \
++  has_opt=no; \
++  sane_makeflags=$$MAKEFLAGS; \
++  if $(am__is_gnu_make); then \
++    sane_makeflags=$$MFLAGS; \
++  else \
++    case $$MAKEFLAGS in \
++      *\\[\ \	]*) \
++        bs=\\; \
++        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
++          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
++    esac; \
++  fi; \
++  skip_next=no; \
++  strip_trailopt () \
++  { \
++    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
++  }; \
++  for flg in $$sane_makeflags; do \
++    test $$skip_next = yes && { skip_next=no; continue; }; \
++    case $$flg in \
++      *=*|--*) continue;; \
++        -*I) strip_trailopt 'I'; skip_next=yes;; \
++      -*I?*) strip_trailopt 'I';; \
++        -*O) strip_trailopt 'O'; skip_next=yes;; \
++      -*O?*) strip_trailopt 'O';; \
++        -*l) strip_trailopt 'l'; skip_next=yes;; \
++      -*l?*) strip_trailopt 'l';; \
++      -[dEDm]) skip_next=yes;; \
++      -[JT]) skip_next=yes;; \
++    esac; \
++    case $$flg in \
++      *$$target_option*) has_opt=yes; break;; \
++    esac; \
++  done; \
++  test $$has_opt = yes
++am__make_dryrun = (target_option=n; $(am__make_running_with_option))
++am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
++pkgdatadir = $(datadir)/bolt-plugin
++pkgincludedir = $(includedir)/bolt-plugin
++pkglibdir = $(libdir)/bolt-plugin
++pkglibexecdir = $(libexecdir)/bolt-plugin
++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
++install_sh_DATA = $(install_sh) -c -m 644
++install_sh_PROGRAM = $(install_sh) -c
++install_sh_SCRIPT = $(install_sh) -c
++INSTALL_HEADER = $(INSTALL_DATA)
++transform = $(program_transform_name)
++NORMAL_INSTALL = :
++PRE_INSTALL = :
++POST_INSTALL = :
++NORMAL_UNINSTALL = :
++PRE_UNINSTALL = :
++POST_UNINSTALL = :
++build_triplet = aarch64-unknown-linux-gnu
++host_triplet = aarch64-unknown-linux-gnu
++target_triplet = aarch64-unknown-linux-gnu
++subdir = .
++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
++am__aclocal_m4_deps = $(top_srcdir)/configure.ac
++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
++	$(ACLOCAL_M4)
++DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
++	$(am__configure_deps)
++am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
++ configure.lineno config.status.lineno
++mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
++CONFIG_HEADER = config.h
++CONFIG_CLEAN_FILES =
++CONFIG_CLEAN_VPATH_FILES =
++am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
++am__vpath_adj = case $$p in \
++    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
++    *) f=$$p;; \
++  esac;
++am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
++am__install_max = 40
++am__nobase_strip_setup = \
++  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
++am__nobase_strip = \
++  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
++am__nobase_list = $(am__nobase_strip_setup); \
++  for p in $$list; do echo "$$p $$p"; done | \
++  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
++  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
++    if (++n[$$2] == $(am__install_max)) \
++      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
++    END { for (dir in files) print dir, files[dir] }'
++am__base_list = \
++  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
++  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
++am__uninstall_files_from_dir = { \
++  test -z "$$files" \
++    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
++    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
++         $(am__cd) "$$dir" && rm -f $$files; }; \
++  }
++am__installdirs = "$(DESTDIR)$(libexecsubdir)"
++LTLIBRARIES = $(libexecsub_LTLIBRARIES)
++am_libbolt_plugin_la_OBJECTS = bolt-plugin.lo
++libbolt_plugin_la_OBJECTS = $(am_libbolt_plugin_la_OBJECTS)
++AM_V_P = $(am__v_P_$(V))
++am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
++am__v_P_0 = false
++am__v_P_1 = :
++AM_V_GEN = $(am__v_GEN_$(V))
++am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
++am__v_GEN_0 = @echo "  GEN     " $@;
++am__v_GEN_1 = 
++AM_V_at = $(am__v_at_$(V))
++am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
++am__v_at_0 = @
++am__v_at_1 = 
++DEFAULT_INCLUDES = -I.
++depcomp =
++am__maybe_remake_depfiles =
++CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
++	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
++AM_V_lt = $(am__v_lt_$(V))
++am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
++am__v_lt_0 = --silent
++am__v_lt_1 = 
++LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
++	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
++	$(AM_CXXFLAGS) $(CXXFLAGS)
++AM_V_CXX = $(am__v_CXX_$(V))
++am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
++am__v_CXX_0 = @echo "  CXX     " $@;
++am__v_CXX_1 = 
++CXXLD = $(CXX)
++CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
++	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
++AM_V_CXXLD = $(am__v_CXXLD_$(V))
++am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
++am__v_CXXLD_0 = @echo "  CXXLD   " $@;
++am__v_CXXLD_1 = 
++SOURCES = $(libbolt_plugin_la_SOURCES)
++am__can_run_installinfo = \
++  case $$AM_UPDATE_INFO_DIR in \
++    n|no|NO) false;; \
++    *) (install-info --version) >/dev/null 2>&1;; \
++  esac
++am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
++	config.h.in
++# Read a list of newline-separated strings from the standard input,
++# and print each of them once, without duplicates.  Input order is
++# *not* preserved.
++am__uniquify_input = $(AWK) '\
++  BEGIN { nonempty = 0; } \
++  { items[$$0] = 1; nonempty = 1; } \
++  END { if (nonempty) { for (i in items) print i; }; } \
++'
++# Make sure the list of sources is unique.  This is necessary because,
++# e.g., the same source file might be shared among _SOURCES variables
++# for different programs/libraries.
++am__define_uniq_tagged_files = \
++  list='$(am__tagged_files)'; \
++  unique=`for i in $$list; do \
++    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
++  done | $(am__uniquify_input)`
++AM_RECURSIVE_TARGETS = cscope
++ACLOCAL = ${SHELL} '/home/zzy/trans/gcc_1/missing' aclocal-1.16
++AMTAR = $${TAR-tar}
++AM_DEFAULT_VERBOSITY = 1
++AR = ar
++AUTOCONF = ${SHELL} '/home/zzy/trans/gcc_1/missing' autoconf
++AUTOHEADER = ${SHELL} '/home/zzy/trans/gcc_1/missing' autoheader
++AUTOMAKE = ${SHELL} '/home/zzy/trans/gcc_1/missing' automake-1.16
++AWK = gawk
++CC = gcc
++CCDEPMODE = depmode=gcc3
++CFLAGS = -g -O2
++CPPFLAGS = 
++CSCOPE = cscope
++CTAGS = ctags
++CXX = g++
++CXXCPP = g++ -E
++CXXDEPMODE = depmode=gcc3
++CXXFLAGS = -g -O2
++CYGPATH_W = echo
++DEFS = -DHAVE_CONFIG_H
++DEPDIR = .deps
++DLLTOOL = false
++DSYMUTIL = 
++DUMPBIN = 
++ECHO_C = 
++ECHO_N = -n
++ECHO_T = 
++EGREP = /usr/bin/grep -E
++ETAGS = etags
++EXEEXT = 
++FGREP = /usr/bin/grep -F
++FILECMD = file
++GREP = /usr/bin/grep
++INSTALL = /usr/bin/install -c
++INSTALL_DATA = ${INSTALL} -m 644
++INSTALL_PROGRAM = ${INSTALL}
++INSTALL_SCRIPT = ${INSTALL}
++INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
++LD = /usr/bin/ld
++LDFLAGS = 
++LIBOBJS = 
++LIBS = 
++LIBTOOL = $(SHELL) $(top_builddir)/libtool
++LIPO = 
++LN_S = ln -s
++LTLIBOBJS = 
++LT_SYS_LIBRARY_PATH = 
++MAINT = #
++MAKEINFO = ${SHELL} '/home/zzy/trans/gcc_1/missing' makeinfo
++MANIFEST_TOOL = :
++MKDIR_P = /usr/bin/mkdir -p
++NM = /usr/bin/nm -B
++NMEDIT = 
++OBJDUMP = objdump
++OBJEXT = o
++OTOOL = 
++OTOOL64 = 
++PACKAGE = bolt-plugin
++PACKAGE_BUGREPORT = 
++PACKAGE_NAME = bolt plugin for ld
++PACKAGE_STRING = bolt plugin for ld 0.1
++PACKAGE_TARNAME = bolt-plugin
++PACKAGE_URL = 
++PACKAGE_VERSION = 0.1
++PATH_SEPARATOR = :
++RANLIB = ranlib
++SED = /usr/bin/sed
++SET_MAKE = 
++SHELL = /bin/sh
++STRIP = strip
++VERSION = 0.1
++abs_builddir = /home/zzy/trans/gcc_1/bolt-plugin
++abs_srcdir = /home/zzy/trans/gcc_1/bolt-plugin
++abs_top_builddir = /home/zzy/trans/gcc_1/bolt-plugin
++abs_top_srcdir = /home/zzy/trans/gcc_1/bolt-plugin
++ac_bolt_plugin_ldflags = -Wc,-static-libgcc
++ac_ct_AR = ar
++ac_ct_CC = gcc
++ac_ct_CXX = g++
++ac_ct_DUMPBIN = 
++accel_dir_suffix = 
++am__include = include
++am__leading_dot = .
++am__quote = 
++am__tar = $${TAR-tar} chof - "$$tardir"
++am__untar = $${TAR-tar} xf -
++bindir = ${exec_prefix}/bin
++build = aarch64-unknown-linux-gnu
++build_alias = 
++build_cpu = aarch64
++build_os = linux-gnu
++build_vendor = unknown
++builddir = .
++datadir = ${datarootdir}
++datarootdir = ${prefix}/share
++docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
++dvidir = ${docdir}
++exec_prefix = ${prefix}
++gcc_build_dir = ../..//gcc
++host = aarch64-unknown-linux-gnu
++host_alias = 
++host_cpu = aarch64
++host_os = linux-gnu
++host_vendor = unknown
++htmldir = ${docdir}
++includedir = ${prefix}/include
++infodir = ${datarootdir}/info
++install_sh = ${SHELL} /home/zzy/trans/gcc_1/install-sh
++libdir = ${exec_prefix}/lib
++libexecdir = ${exec_prefix}/libexec
++localedir = ${datarootdir}/locale
++localstatedir = ${prefix}/var
++mandir = ${datarootdir}/man
++mkdir_p = $(MKDIR_P)
++oldincludedir = /usr/include
++pdfdir = ${docdir}
++prefix = /usr/local
++program_transform_name = s,x,x,
++psdir = ${docdir}
++real_target_noncanonical = 
++runstatedir = ${localstatedir}/run
++sbindir = ${exec_prefix}/sbin
++sharedstatedir = ${prefix}/com
++srcdir = .
++sysconfdir = ${prefix}/etc
++target = aarch64-unknown-linux-gnu
++target_alias = 
++target_cpu = aarch64
++target_noncanonical := 
++target_os = linux-gnu
++target_vendor = unknown
++top_build_prefix = 
++top_builddir = .
++top_srcdir = .
++with_libiberty = ../libiberty
++ACLOCAL_AMFLAGS = -I .. -I ../config
++AUTOMAKE_OPTIONS = no-dependencies
++gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
++libexecsubdir := $(libexecdir)/gcc/$(real_target_noncanonical)/$(gcc_version)$(accel_dir_suffix)
++AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS) -std=c++11
++AM_CXXFLAGS = @ac_bolt_plugin_warn_cflags@ -std=c++11
++AM_LDFLAGS = -Wc,-static-libgcc
++AM_LIBTOOLFLAGS = --tag=disable-static
++libexecsub_LTLIBRARIES = libbolt_plugin.la
++in_gcc_libs = $(foreach lib, $(libexecsub_LTLIBRARIES), $(gcc_build_dir)/$(lib))
++libbolt_plugin_la_SOURCES = bolt-plugin.cc
++# Note that we intentionally override the bindir supplied by ACX_LT_HOST_FLAGS.
++libbolt_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(lt_host_flags) -module \
++	-bindir $(libexecsubdir) $(if $(wildcard \
++	$(libiberty_noasan)),, $(if $(wildcard \
++	$(libiberty_pic)),,-Wc,$(libiberty)))
++# Can be simplified when libiberty becomes a normal convenience library.
++libiberty = $(with_libiberty)/libiberty.a
++libiberty_noasan = $(with_libiberty)/noasan/libiberty.a
++libiberty_pic = $(with_libiberty)/pic/libiberty.a
++Wc = -Wc,
++libbolt_plugin_la_LIBADD = \
++	$(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
++	$(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic),))
++
++libbolt_plugin_la_DEPENDENCIES = \
++	$(if $(wildcard $(libiberty_noasan)),$(libiberty_noasan), \
++	$(if $(wildcard $(libiberty_pic)),$(libiberty_pic),))
++
++LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
++libbolt_plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) ${AM_CPPFLAGS} $(CXXFLAGS) \
++	$(libbolt_plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
++
++all: config.h
++	$(MAKE) $(AM_MAKEFLAGS) all-am
++
++.SUFFIXES:
++.SUFFIXES: .cc .lo .o .obj
++am--refresh: Makefile
++	@:
++$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am  $(am__configure_deps)
++	@for dep in $?; do \
++	  case '$(am__configure_deps)' in \
++	    *$$dep*) \
++	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
++	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
++		&& exit 0; \
++	      exit 1;; \
++	  esac; \
++	done; \
++	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
++	$(am__cd) $(top_srcdir) && \
++	  $(AUTOMAKE) --foreign Makefile
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++	@case '$?' in \
++	  *config.status*) \
++	    echo ' $(SHELL) ./config.status'; \
++	    $(SHELL) ./config.status;; \
++	  *) \
++	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
++	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
++	esac;
++
++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
++	$(SHELL) ./config.status --recheck
++
++$(top_srcdir)/configure: # $(am__configure_deps)
++	$(am__cd) $(srcdir) && $(AUTOCONF)
++$(ACLOCAL_M4): # $(am__aclocal_m4_deps)
++	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
++$(am__aclocal_m4_deps):
++
++config.h: stamp-h1
++	@test -f $@ || rm -f stamp-h1
++	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
++
++stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
++	@rm -f stamp-h1
++	cd $(top_builddir) && $(SHELL) ./config.status config.h
++$(srcdir)/config.h.in: # $(am__configure_deps) 
++	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
++	rm -f stamp-h1
++	touch $@
++
++distclean-hdr:
++	-rm -f config.h stamp-h1
++
++install-libexecsubLTLIBRARIES: $(libexecsub_LTLIBRARIES)
++	@$(NORMAL_INSTALL)
++	@list='$(libexecsub_LTLIBRARIES)'; test -n "$(libexecsubdir)" || list=; \
++	list2=; for p in $$list; do \
++	  if test -f $$p; then \
++	    list2="$$list2 $$p"; \
++	  else :; fi; \
++	done; \
++	test -z "$$list2" || { \
++	  echo " $(MKDIR_P) '$(DESTDIR)$(libexecsubdir)'"; \
++	  $(MKDIR_P) "$(DESTDIR)$(libexecsubdir)" || exit 1; \
++	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libexecsubdir)'"; \
++	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libexecsubdir)"; \
++	}
++
++uninstall-libexecsubLTLIBRARIES:
++	@$(NORMAL_UNINSTALL)
++	@list='$(libexecsub_LTLIBRARIES)'; test -n "$(libexecsubdir)" || list=; \
++	for p in $$list; do \
++	  $(am__strip_dir) \
++	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libexecsubdir)/$$f'"; \
++	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libexecsubdir)/$$f"; \
++	done
++
++clean-libexecsubLTLIBRARIES:
++	-test -z "$(libexecsub_LTLIBRARIES)" || rm -f $(libexecsub_LTLIBRARIES)
++	@list='$(libexecsub_LTLIBRARIES)'; \
++	locs=`for p in $$list; do echo $$p; done | \
++	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
++	      sort -u`; \
++	test -z "$$locs" || { \
++	  echo rm -f $${locs}; \
++	  rm -f $${locs}; \
++	}
++
++libbolt_plugin.la: $(libbolt_plugin_la_OBJECTS) $(libbolt_plugin_la_DEPENDENCIES) $(EXTRA_libbolt_plugin_la_DEPENDENCIES) 
++	$(AM_V_GEN)$(libbolt_plugin_la_LINK) -rpath $(libexecsubdir) $(libbolt_plugin_la_OBJECTS) $(libbolt_plugin_la_LIBADD) $(LIBS)
++
++mostlyclean-compile:
++	-rm -f *.$(OBJEXT)
++
++distclean-compile:
++	-rm -f *.tab.c
++
++.cc.o:
++	$(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $<
++
++.cc.obj:
++	$(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
++
++.cc.lo:
++	$(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $<
++
++mostlyclean-libtool:
++	-rm -f *.lo
++
++clean-libtool:
++	-rm -rf .libs _libs
++
++distclean-libtool:
++	-rm -f libtool config.lt
++
++ID: $(am__tagged_files)
++	$(am__define_uniq_tagged_files); mkid -fID $$unique
++tags: tags-am
++TAGS: tags
++
++tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
++	set x; \
++	here=`pwd`; \
++	$(am__define_uniq_tagged_files); \
++	shift; \
++	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
++	  test -n "$$unique" || unique=$$empty_fix; \
++	  if test $$# -gt 0; then \
++	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
++	      "$$@" $$unique; \
++	  else \
++	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
++	      $$unique; \
++	  fi; \
++	fi
++ctags: ctags-am
++
++CTAGS: ctags
++ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
++	$(am__define_uniq_tagged_files); \
++	test -z "$(CTAGS_ARGS)$$unique" \
++	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
++	     $$unique
++
++GTAGS:
++	here=`$(am__cd) $(top_builddir) && pwd` \
++	  && $(am__cd) $(top_srcdir) \
++	  && gtags -i $(GTAGS_ARGS) "$$here"
++cscope: cscope.files
++	test ! -s cscope.files \
++	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
++clean-cscope:
++	-rm -f cscope.files
++cscope.files: clean-cscope cscopelist
++cscopelist: cscopelist-am
++
++cscopelist-am: $(am__tagged_files)
++	list='$(am__tagged_files)'; \
++	case "$(srcdir)" in \
++	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
++	  *) sdir=$(subdir)/$(srcdir) ;; \
++	esac; \
++	for i in $$list; do \
++	  if test -f "$$i"; then \
++	    echo "$(subdir)/$$i"; \
++	  else \
++	    echo "$$sdir/$$i"; \
++	  fi; \
++	done >> $(top_builddir)/cscope.files
++
++distclean-tags:
++	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
++	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
++check-am: all-am
++check: check-am
++all-am: Makefile $(LTLIBRARIES) config.h
++installdirs:
++	for dir in "$(DESTDIR)$(libexecsubdir)"; do \
++	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
++	done
++install: install-am
++install-exec: install-exec-am
++install-data: install-data-am
++uninstall: uninstall-am
++
++install-am: all-am
++	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
++
++installcheck: installcheck-am
++install-strip:
++	if test -z '$(STRIP)'; then \
++	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
++	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
++	      install; \
++	else \
++	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
++	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
++	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
++	fi
++mostlyclean-generic:
++
++clean-generic:
++
++distclean-generic:
++	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
++	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
++
++maintainer-clean-generic:
++	@echo "This command is intended for maintainers to use"
++	@echo "it deletes files that may require special tools to rebuild."
++clean: clean-am
++
++clean-am: clean-generic clean-libexecsubLTLIBRARIES clean-libtool \
++	mostlyclean-am
++
++distclean: distclean-am
++	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
++	-rm -f Makefile
++distclean-am: clean-am distclean-compile distclean-generic \
++	distclean-hdr distclean-libtool distclean-tags
++
++dvi: dvi-am
++
++dvi-am:
++
++html: html-am
++
++html-am:
++
++info: info-am
++
++info-am:
++
++install-data-am:
++
++install-dvi: install-dvi-am
++
++install-dvi-am:
++
++install-exec-am: install-libexecsubLTLIBRARIES
++
++install-html: install-html-am
++
++install-html-am:
++
++install-info: install-info-am
++
++install-info-am:
++
++install-man:
++
++install-pdf: install-pdf-am
++
++install-pdf-am:
++
++install-ps: install-ps-am
++
++install-ps-am:
++
++installcheck-am:
++
++maintainer-clean: maintainer-clean-am
++	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
++	-rm -rf $(top_srcdir)/autom4te.cache
++	-rm -f Makefile
++maintainer-clean-am: distclean-am maintainer-clean-generic
++
++mostlyclean: mostlyclean-am
++
++mostlyclean-am: mostlyclean-compile mostlyclean-generic \
++	mostlyclean-libtool
++
++pdf: pdf-am
++
++pdf-am:
++
++ps: ps-am
++
++ps-am:
++
++uninstall-am: uninstall-libexecsubLTLIBRARIES
++
++.MAKE: all install-am install-strip
++
++.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
++	clean-cscope clean-generic clean-libexecsubLTLIBRARIES \
++	clean-libtool cscope cscopelist-am ctags ctags-am distclean \
++	distclean-compile distclean-generic distclean-hdr \
++	distclean-libtool distclean-tags dvi dvi-am html html-am info \
++	info-am install install-am install-data install-data-am \
++	install-dvi install-dvi-am install-exec install-exec-am \
++	install-html install-html-am install-info install-info-am \
++	install-libexecsubLTLIBRARIES install-man install-pdf \
++	install-pdf-am install-ps install-ps-am install-strip \
++	installcheck installcheck-am installdirs maintainer-clean \
++	maintainer-clean-generic mostlyclean mostlyclean-compile \
++	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
++	tags tags-am uninstall uninstall-am \
++	uninstall-libexecsubLTLIBRARIES
++
++.PRECIOUS: Makefile
++
++override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
++override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
++
++# Tell versions [3.59,3.63) of GNU make to not export all variables.
++# Otherwise a system limit (for SysV at least) may be exceeded.
++.NOEXPORT:
+diff --git a/bolt-plugin/Makefile.am b/bolt-plugin/Makefile.am
+new file mode 100644
+index 000000000..c21999237
+--- /dev/null
++++ b/bolt-plugin/Makefile.am
+@@ -0,0 +1,43 @@
++## Process this file with automake to produce Makefile.in.
++
++ACLOCAL_AMFLAGS = -I .. -I ../config
++AUTOMAKE_OPTIONS = no-dependencies
++
++gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
++target_noncanonical := @target_noncanonical@
++libexecsubdir := $(libexecdir)/gcc/$(real_target_noncanonical)/$(gcc_version)$(accel_dir_suffix)
++
++AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS) -std=c++11
++AM_CXXFLAGS = @ac_bolt_plugin_warn_cflags@ -std=c++11
++AM_LDFLAGS = @ac_bolt_plugin_ldflags@
++AM_LIBTOOLFLAGS = --tag=disable-static
++override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
++override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
++
++libexecsub_LTLIBRARIES = libbolt_plugin.la
++gcc_build_dir = @gcc_build_dir@
++in_gcc_libs = $(foreach lib, $(libexecsub_LTLIBRARIES), $(gcc_build_dir)/$(lib))
++
++libbolt_plugin_la_SOURCES = bolt-plugin.cc
++# Note that we intentionally override the bindir supplied by ACX_LT_HOST_FLAGS.
++libbolt_plugin_la_LDFLAGS = $(AM_LDFLAGS) \
++	$(lt_host_flags) -module -bindir $(libexecsubdir)
++# Can be simplified when libiberty becomes a normal convenience library.
++libiberty = $(with_libiberty)/libiberty.a
++libiberty_noasan = $(with_libiberty)/noasan/libiberty.a
++libiberty_pic = $(with_libiberty)/pic/libiberty.a
++Wc=-Wc,
++libbolt_plugin_la_LIBADD = \
++	$(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
++	$(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic),))
++libbolt_plugin_la_LDFLAGS += \
++	$(if $(wildcard $(libiberty_noasan)),, \
++	$(if $(wildcard $(libiberty_pic)),,-Wc,$(libiberty)))
++libbolt_plugin_la_DEPENDENCIES = \
++	$(if $(wildcard $(libiberty_noasan)),$(libiberty_noasan), \
++	$(if $(wildcard $(libiberty_pic)),$(libiberty_pic),))
++LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
++libbolt_plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) ${AM_CPPFLAGS} $(CXXFLAGS) \
++	$(libbolt_plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
++
+diff --git a/bolt-plugin/Makefile.in b/bolt-plugin/Makefile.in
+new file mode 100644
+index 000000000..11b59407e
+--- /dev/null
++++ b/bolt-plugin/Makefile.in
+@@ -0,0 +1,675 @@
++# Makefile.in generated by automake 1.16.5 from Makefile.am.
++# @configure_input@
++
++# Copyright (C) 1994-2021 Free Software Foundation, Inc.
++
++# This Makefile.in is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++# PARTICULAR PURPOSE.
++
++@SET_MAKE@
++
++VPATH = @srcdir@
++am__is_gnu_make = { \
++  if test -z '$(MAKELEVEL)'; then \
++    false; \
++  elif test -n '$(MAKE_HOST)'; then \
++    true; \
++  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
++    true; \
++  else \
++    false; \
++  fi; \
++}
++am__make_running_with_option = \
++  case $${target_option-} in \
++      ?) ;; \
++      *) echo "am__make_running_with_option: internal error: invalid" \
++              "target option '$${target_option-}' specified" >&2; \
++         exit 1;; \
++  esac; \
++  has_opt=no; \
++  sane_makeflags=$$MAKEFLAGS; \
++  if $(am__is_gnu_make); then \
++    sane_makeflags=$$MFLAGS; \
++  else \
++    case $$MAKEFLAGS in \
++      *\\[\ \	]*) \
++        bs=\\; \
++        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
++          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
++    esac; \
++  fi; \
++  skip_next=no; \
++  strip_trailopt () \
++  { \
++    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
++  }; \
++  for flg in $$sane_makeflags; do \
++    test $$skip_next = yes && { skip_next=no; continue; }; \
++    case $$flg in \
++      *=*|--*) continue;; \
++        -*I) strip_trailopt 'I'; skip_next=yes;; \
++      -*I?*) strip_trailopt 'I';; \
++        -*O) strip_trailopt 'O'; skip_next=yes;; \
++      -*O?*) strip_trailopt 'O';; \
++        -*l) strip_trailopt 'l'; skip_next=yes;; \
++      -*l?*) strip_trailopt 'l';; \
++      -[dEDm]) skip_next=yes;; \
++      -[JT]) skip_next=yes;; \
++    esac; \
++    case $$flg in \
++      *$$target_option*) has_opt=yes; break;; \
++    esac; \
++  done; \
++  test $$has_opt = yes
++am__make_dryrun = (target_option=n; $(am__make_running_with_option))
++am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
++pkgdatadir = $(datadir)/@PACKAGE@
++pkgincludedir = $(includedir)/@PACKAGE@
++pkglibdir = $(libdir)/@PACKAGE@
++pkglibexecdir = $(libexecdir)/@PACKAGE@
++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
++install_sh_DATA = $(install_sh) -c -m 644
++install_sh_PROGRAM = $(install_sh) -c
++install_sh_SCRIPT = $(install_sh) -c
++INSTALL_HEADER = $(INSTALL_DATA)
++transform = $(program_transform_name)
++NORMAL_INSTALL = :
++PRE_INSTALL = :
++POST_INSTALL = :
++NORMAL_UNINSTALL = :
++PRE_UNINSTALL = :
++POST_UNINSTALL = :
++build_triplet = @build@
++host_triplet = @host@
++target_triplet = @target@
++subdir = .
++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
++am__aclocal_m4_deps = $(top_srcdir)/configure.ac
++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
++	$(ACLOCAL_M4)
++DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
++	$(am__configure_deps)
++am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
++ configure.lineno config.status.lineno
++mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
++CONFIG_HEADER = config.h
++CONFIG_CLEAN_FILES =
++CONFIG_CLEAN_VPATH_FILES =
++am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
++am__vpath_adj = case $$p in \
++    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
++    *) f=$$p;; \
++  esac;
++am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
++am__install_max = 40
++am__nobase_strip_setup = \
++  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
++am__nobase_strip = \
++  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
++am__nobase_list = $(am__nobase_strip_setup); \
++  for p in $$list; do echo "$$p $$p"; done | \
++  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
++  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
++    if (++n[$$2] == $(am__install_max)) \
++      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
++    END { for (dir in files) print dir, files[dir] }'
++am__base_list = \
++  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
++  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
++am__uninstall_files_from_dir = { \
++  test -z "$$files" \
++    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
++    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
++         $(am__cd) "$$dir" && rm -f $$files; }; \
++  }
++am__installdirs = "$(DESTDIR)$(libexecsubdir)"
++LTLIBRARIES = $(libexecsub_LTLIBRARIES)
++am_libbolt_plugin_la_OBJECTS = bolt-plugin.lo
++libbolt_plugin_la_OBJECTS = $(am_libbolt_plugin_la_OBJECTS)
++AM_V_P = $(am__v_P_@AM_V@)
++am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
++am__v_P_0 = false
++am__v_P_1 = :
++AM_V_GEN = $(am__v_GEN_@AM_V@)
++am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
++am__v_GEN_0 = @echo "  GEN     " $@;
++am__v_GEN_1 = 
++AM_V_at = $(am__v_at_@AM_V@)
++am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
++am__v_at_0 = @
++am__v_at_1 = 
++DEFAULT_INCLUDES = -I.@am__isrc@
++depcomp =
++am__maybe_remake_depfiles =
++CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
++	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
++AM_V_lt = $(am__v_lt_@AM_V@)
++am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
++am__v_lt_0 = --silent
++am__v_lt_1 = 
++LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
++	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
++	$(AM_CXXFLAGS) $(CXXFLAGS)
++AM_V_CXX = $(am__v_CXX_@AM_V@)
++am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
++am__v_CXX_0 = @echo "  CXX     " $@;
++am__v_CXX_1 = 
++CXXLD = $(CXX)
++CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
++	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
++AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
++am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
++am__v_CXXLD_0 = @echo "  CXXLD   " $@;
++am__v_CXXLD_1 = 
++SOURCES = $(libbolt_plugin_la_SOURCES)
++am__can_run_installinfo = \
++  case $$AM_UPDATE_INFO_DIR in \
++    n|no|NO) false;; \
++    *) (install-info --version) >/dev/null 2>&1;; \
++  esac
++am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
++	config.h.in
++# Read a list of newline-separated strings from the standard input,
++# and print each of them once, without duplicates.  Input order is
++# *not* preserved.
++am__uniquify_input = $(AWK) '\
++  BEGIN { nonempty = 0; } \
++  { items[$$0] = 1; nonempty = 1; } \
++  END { if (nonempty) { for (i in items) print i; }; } \
++'
++# Make sure the list of sources is unique.  This is necessary because,
++# e.g., the same source file might be shared among _SOURCES variables
++# for different programs/libraries.
++am__define_uniq_tagged_files = \
++  list='$(am__tagged_files)'; \
++  unique=`for i in $$list; do \
++    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
++  done | $(am__uniquify_input)`
++AM_RECURSIVE_TARGETS = cscope
++ACLOCAL = @ACLOCAL@
++AMTAR = @AMTAR@
++AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
++AR = @AR@
++AUTOCONF = @AUTOCONF@
++AUTOHEADER = @AUTOHEADER@
++AUTOMAKE = @AUTOMAKE@
++AWK = @AWK@
++CC = @CC@
++CCDEPMODE = @CCDEPMODE@
++CFLAGS = @CFLAGS@
++CPPFLAGS = @CPPFLAGS@
++CSCOPE = @CSCOPE@
++CTAGS = @CTAGS@
++CXX = @CXX@
++CXXCPP = @CXXCPP@
++CXXDEPMODE = @CXXDEPMODE@
++CXXFLAGS = @CXXFLAGS@
++CYGPATH_W = @CYGPATH_W@
++DEFS = @DEFS@
++DEPDIR = @DEPDIR@
++DLLTOOL = @DLLTOOL@
++DSYMUTIL = @DSYMUTIL@
++DUMPBIN = @DUMPBIN@
++ECHO_C = @ECHO_C@
++ECHO_N = @ECHO_N@
++ECHO_T = @ECHO_T@
++EGREP = @EGREP@
++ETAGS = @ETAGS@
++EXEEXT = @EXEEXT@
++FGREP = @FGREP@
++FILECMD = @FILECMD@
++GREP = @GREP@
++INSTALL = @INSTALL@
++INSTALL_DATA = @INSTALL_DATA@
++INSTALL_PROGRAM = @INSTALL_PROGRAM@
++INSTALL_SCRIPT = @INSTALL_SCRIPT@
++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
++LD = @LD@
++LDFLAGS = @LDFLAGS@
++LIBOBJS = @LIBOBJS@
++LIBS = @LIBS@
++LIBTOOL = @LIBTOOL@
++LIPO = @LIPO@
++LN_S = @LN_S@
++LTLIBOBJS = @LTLIBOBJS@
++LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
++MAINT = @MAINT@
++MAKEINFO = @MAKEINFO@
++MANIFEST_TOOL = @MANIFEST_TOOL@
++MKDIR_P = @MKDIR_P@
++NM = @NM@
++NMEDIT = @NMEDIT@
++OBJDUMP = @OBJDUMP@
++OBJEXT = @OBJEXT@
++OTOOL = @OTOOL@
++OTOOL64 = @OTOOL64@
++PACKAGE = @PACKAGE@
++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
++PACKAGE_NAME = @PACKAGE_NAME@
++PACKAGE_STRING = @PACKAGE_STRING@
++PACKAGE_TARNAME = @PACKAGE_TARNAME@
++PACKAGE_URL = @PACKAGE_URL@
++PACKAGE_VERSION = @PACKAGE_VERSION@
++PATH_SEPARATOR = @PATH_SEPARATOR@
++RANLIB = @RANLIB@
++SED = @SED@
++SET_MAKE = @SET_MAKE@
++SHELL = @SHELL@
++STRIP = @STRIP@
++VERSION = @VERSION@
++abs_builddir = @abs_builddir@
++abs_srcdir = @abs_srcdir@
++abs_top_builddir = @abs_top_builddir@
++abs_top_srcdir = @abs_top_srcdir@
++ac_bolt_plugin_ldflags = @ac_bolt_plugin_ldflags@
++ac_ct_AR = @ac_ct_AR@
++ac_ct_CC = @ac_ct_CC@
++ac_ct_CXX = @ac_ct_CXX@
++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
++accel_dir_suffix = @accel_dir_suffix@
++am__include = @am__include@
++am__leading_dot = @am__leading_dot@
++am__quote = @am__quote@
++am__tar = @am__tar@
++am__untar = @am__untar@
++bindir = @bindir@
++build = @build@
++build_alias = @build_alias@
++build_cpu = @build_cpu@
++build_os = @build_os@
++build_vendor = @build_vendor@
++builddir = @builddir@
++datadir = @datadir@
++datarootdir = @datarootdir@
++docdir = @docdir@
++dvidir = @dvidir@
++exec_prefix = @exec_prefix@
++gcc_build_dir = @gcc_build_dir@
++host = @host@
++host_alias = @host_alias@
++host_cpu = @host_cpu@
++host_os = @host_os@
++host_vendor = @host_vendor@
++htmldir = @htmldir@
++includedir = @includedir@
++infodir = @infodir@
++install_sh = @install_sh@
++libdir = @libdir@
++libexecdir = @libexecdir@
++localedir = @localedir@
++localstatedir = @localstatedir@
++mandir = @mandir@
++mkdir_p = @mkdir_p@
++oldincludedir = @oldincludedir@
++pdfdir = @pdfdir@
++prefix = @prefix@
++program_transform_name = @program_transform_name@
++psdir = @psdir@
++real_target_noncanonical = @real_target_noncanonical@
++runstatedir = @runstatedir@
++sbindir = @sbindir@
++sharedstatedir = @sharedstatedir@
++srcdir = @srcdir@
++sysconfdir = @sysconfdir@
++target = @target@
++target_alias = @target_alias@
++target_cpu = @target_cpu@
++target_noncanonical := @target_noncanonical@
++target_os = @target_os@
++target_vendor = @target_vendor@
++top_build_prefix = @top_build_prefix@
++top_builddir = @top_builddir@
++top_srcdir = @top_srcdir@
++with_libiberty = @with_libiberty@
++ACLOCAL_AMFLAGS = -I .. -I ../config
++AUTOMAKE_OPTIONS = no-dependencies
++gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
++libexecsubdir := $(libexecdir)/gcc/$(real_target_noncanonical)/$(gcc_version)$(accel_dir_suffix)
++AM_CPPFLAGS = -I$(top_srcdir)/../include $(DEFS) -std=c++11
++AM_CXXFLAGS = @ac_bolt_plugin_warn_cflags@ -std=c++11
++AM_LDFLAGS = @ac_bolt_plugin_ldflags@
++AM_LIBTOOLFLAGS = --tag=disable-static
++libexecsub_LTLIBRARIES = libbolt_plugin.la
++in_gcc_libs = $(foreach lib, $(libexecsub_LTLIBRARIES), $(gcc_build_dir)/$(lib))
++libbolt_plugin_la_SOURCES = bolt-plugin.cc
++# Note that we intentionally override the bindir supplied by ACX_LT_HOST_FLAGS.
++libbolt_plugin_la_LDFLAGS = $(AM_LDFLAGS) $(lt_host_flags) -module \
++	-bindir $(libexecsubdir) $(if $(wildcard \
++	$(libiberty_noasan)),, $(if $(wildcard \
++	$(libiberty_pic)),,-Wc,$(libiberty)))
++# Can be simplified when libiberty becomes a normal convenience library.
++libiberty = $(with_libiberty)/libiberty.a
++libiberty_noasan = $(with_libiberty)/noasan/libiberty.a
++libiberty_pic = $(with_libiberty)/pic/libiberty.a
++Wc = -Wc,
++libbolt_plugin_la_LIBADD = \
++	$(if $(wildcard $(libiberty_noasan)),$(Wc)$(libiberty_noasan), \
++	$(if $(wildcard $(libiberty_pic)),$(Wc)$(libiberty_pic),))
++
++libbolt_plugin_la_DEPENDENCIES = \
++	$(if $(wildcard $(libiberty_noasan)),$(libiberty_noasan), \
++	$(if $(wildcard $(libiberty_pic)),$(libiberty_pic),))
++
++LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
++libbolt_plugin_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
++	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) ${AM_CPPFLAGS} $(CXXFLAGS) \
++	$(libbolt_plugin_la_LDFLAGS) $(LTLDFLAGS) -o $@
++
++all: config.h
++	$(MAKE) $(AM_MAKEFLAGS) all-am
++
++.SUFFIXES:
++.SUFFIXES: .cc .lo .o .obj
++am--refresh: Makefile
++	@:
++$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
++	@for dep in $?; do \
++	  case '$(am__configure_deps)' in \
++	    *$$dep*) \
++	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
++	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
++		&& exit 0; \
++	      exit 1;; \
++	  esac; \
++	done; \
++	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
++	$(am__cd) $(top_srcdir) && \
++	  $(AUTOMAKE) --foreign Makefile
++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
++	@case '$?' in \
++	  *config.status*) \
++	    echo ' $(SHELL) ./config.status'; \
++	    $(SHELL) ./config.status;; \
++	  *) \
++	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
++	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
++	esac;
++
++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
++	$(SHELL) ./config.status --recheck
++
++$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
++	$(am__cd) $(srcdir) && $(AUTOCONF)
++$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
++	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
++$(am__aclocal_m4_deps):
++
++config.h: stamp-h1
++	@test -f $@ || rm -f stamp-h1
++	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
++
++stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
++	@rm -f stamp-h1
++	cd $(top_builddir) && $(SHELL) ./config.status config.h
++$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
++	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
++	rm -f stamp-h1
++	touch $@
++
++distclean-hdr:
++	-rm -f config.h stamp-h1
++
++install-libexecsubLTLIBRARIES: $(libexecsub_LTLIBRARIES)
++	@$(NORMAL_INSTALL)
++	@list='$(libexecsub_LTLIBRARIES)'; test -n "$(libexecsubdir)" || list=; \
++	list2=; for p in $$list; do \
++	  if test -f $$p; then \
++	    list2="$$list2 $$p"; \
++	  else :; fi; \
++	done; \
++	test -z "$$list2" || { \
++	  echo " $(MKDIR_P) '$(DESTDIR)$(libexecsubdir)'"; \
++	  $(MKDIR_P) "$(DESTDIR)$(libexecsubdir)" || exit 1; \
++	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libexecsubdir)'"; \
++	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libexecsubdir)"; \
++	}
++
++uninstall-libexecsubLTLIBRARIES:
++	@$(NORMAL_UNINSTALL)
++	@list='$(libexecsub_LTLIBRARIES)'; test -n "$(libexecsubdir)" || list=; \
++	for p in $$list; do \
++	  $(am__strip_dir) \
++	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libexecsubdir)/$$f'"; \
++	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libexecsubdir)/$$f"; \
++	done
++
++clean-libexecsubLTLIBRARIES:
++	-test -z "$(libexecsub_LTLIBRARIES)" || rm -f $(libexecsub_LTLIBRARIES)
++	@list='$(libexecsub_LTLIBRARIES)'; \
++	locs=`for p in $$list; do echo $$p; done | \
++	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
++	      sort -u`; \
++	test -z "$$locs" || { \
++	  echo rm -f $${locs}; \
++	  rm -f $${locs}; \
++	}
++
++libbolt_plugin.la: $(libbolt_plugin_la_OBJECTS) $(libbolt_plugin_la_DEPENDENCIES) $(EXTRA_libbolt_plugin_la_DEPENDENCIES) 
++	$(AM_V_GEN)$(libbolt_plugin_la_LINK) -rpath $(libexecsubdir) $(libbolt_plugin_la_OBJECTS) $(libbolt_plugin_la_LIBADD) $(LIBS)
++
++mostlyclean-compile:
++	-rm -f *.$(OBJEXT)
++
++distclean-compile:
++	-rm -f *.tab.c
++
++.cc.o:
++	$(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $<
++
++.cc.obj:
++	$(AM_V_CXX)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
++
++.cc.lo:
++	$(AM_V_CXX)$(LTCXXCOMPILE) -c -o $@ $<
++
++mostlyclean-libtool:
++	-rm -f *.lo
++
++clean-libtool:
++	-rm -rf .libs _libs
++
++distclean-libtool:
++	-rm -f libtool config.lt
++
++ID: $(am__tagged_files)
++	$(am__define_uniq_tagged_files); mkid -fID $$unique
++tags: tags-am
++TAGS: tags
++
++tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
++	set x; \
++	here=`pwd`; \
++	$(am__define_uniq_tagged_files); \
++	shift; \
++	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
++	  test -n "$$unique" || unique=$$empty_fix; \
++	  if test $$# -gt 0; then \
++	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
++	      "$$@" $$unique; \
++	  else \
++	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
++	      $$unique; \
++	  fi; \
++	fi
++ctags: ctags-am
++
++CTAGS: ctags
++ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
++	$(am__define_uniq_tagged_files); \
++	test -z "$(CTAGS_ARGS)$$unique" \
++	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
++	     $$unique
++
++GTAGS:
++	here=`$(am__cd) $(top_builddir) && pwd` \
++	  && $(am__cd) $(top_srcdir) \
++	  && gtags -i $(GTAGS_ARGS) "$$here"
++cscope: cscope.files
++	test ! -s cscope.files \
++	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
++clean-cscope:
++	-rm -f cscope.files
++cscope.files: clean-cscope cscopelist
++cscopelist: cscopelist-am
++
++cscopelist-am: $(am__tagged_files)
++	list='$(am__tagged_files)'; \
++	case "$(srcdir)" in \
++	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
++	  *) sdir=$(subdir)/$(srcdir) ;; \
++	esac; \
++	for i in $$list; do \
++	  if test -f "$$i"; then \
++	    echo "$(subdir)/$$i"; \
++	  else \
++	    echo "$$sdir/$$i"; \
++	  fi; \
++	done >> $(top_builddir)/cscope.files
++
++distclean-tags:
++	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
++	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
++check-am: all-am
++check: check-am
++all-am: Makefile $(LTLIBRARIES) config.h
++installdirs:
++	for dir in "$(DESTDIR)$(libexecsubdir)"; do \
++	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
++	done
++install: install-am
++install-exec: install-exec-am
++install-data: install-data-am
++uninstall: uninstall-am
++
++install-am: all-am
++	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
++
++installcheck: installcheck-am
++install-strip:
++	if test -z '$(STRIP)'; then \
++	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
++	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
++	      install; \
++	else \
++	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
++	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
++	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
++	fi
++mostlyclean-generic:
++
++clean-generic:
++
++distclean-generic:
++	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
++	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
++
++maintainer-clean-generic:
++	@echo "This command is intended for maintainers to use"
++	@echo "it deletes files that may require special tools to rebuild."
++clean: clean-am
++
++clean-am: clean-generic clean-libexecsubLTLIBRARIES clean-libtool \
++	mostlyclean-am
++
++distclean: distclean-am
++	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
++	-rm -f Makefile
++distclean-am: clean-am distclean-compile distclean-generic \
++	distclean-hdr distclean-libtool distclean-tags
++
++dvi: dvi-am
++
++dvi-am:
++
++html: html-am
++
++html-am:
++
++info: info-am
++
++info-am:
++
++install-data-am:
++
++install-dvi: install-dvi-am
++
++install-dvi-am:
++
++install-exec-am: install-libexecsubLTLIBRARIES
++
++install-html: install-html-am
++
++install-html-am:
++
++install-info: install-info-am
++
++install-info-am:
++
++install-man:
++
++install-pdf: install-pdf-am
++
++install-pdf-am:
++
++install-ps: install-ps-am
++
++install-ps-am:
++
++installcheck-am:
++
++maintainer-clean: maintainer-clean-am
++	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
++	-rm -rf $(top_srcdir)/autom4te.cache
++	-rm -f Makefile
++maintainer-clean-am: distclean-am maintainer-clean-generic
++
++mostlyclean: mostlyclean-am
++
++mostlyclean-am: mostlyclean-compile mostlyclean-generic \
++	mostlyclean-libtool
++
++pdf: pdf-am
++
++pdf-am:
++
++ps: ps-am
++
++ps-am:
++
++uninstall-am: uninstall-libexecsubLTLIBRARIES
++
++.MAKE: all install-am install-strip
++
++.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
++	clean-cscope clean-generic clean-libexecsubLTLIBRARIES \
++	clean-libtool cscope cscopelist-am ctags ctags-am distclean \
++	distclean-compile distclean-generic distclean-hdr \
++	distclean-libtool distclean-tags dvi dvi-am html html-am info \
++	info-am install install-am install-data install-data-am \
++	install-dvi install-dvi-am install-exec install-exec-am \
++	install-html install-html-am install-info install-info-am \
++	install-libexecsubLTLIBRARIES install-man install-pdf \
++	install-pdf-am install-ps install-ps-am install-strip \
++	installcheck installcheck-am installdirs maintainer-clean \
++	maintainer-clean-generic mostlyclean mostlyclean-compile \
++	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
++	tags tags-am uninstall uninstall-am \
++	uninstall-libexecsubLTLIBRARIES
++
++.PRECIOUS: Makefile
++
++override CXXFLAGS := $(filter-out -fsanitize=address,$(CXXFLAGS))
++override LDFLAGS := $(filter-out -fsanitize=address,$(LDFLAGS))
++
++# Tell versions [3.59,3.63) of GNU make to not export all variables.
++# Otherwise a system limit (for SysV at least) may be exceeded.
++.NOEXPORT:
+diff --git a/bolt-plugin/aclocal.m4 b/bolt-plugin/aclocal.m4
+new file mode 100644
+index 000000000..679f2baa4
+--- /dev/null
++++ b/bolt-plugin/aclocal.m4
+@@ -0,0 +1,10250 @@
++# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
++
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
++# PARTICULAR PURPOSE.
++
++m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
++m4_ifndef([AC_AUTOCONF_VERSION],
++  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
++m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
++[m4_warning([this file was generated for autoconf 2.71.
++You have another version of autoconf.  It may work, but is not guaranteed to.
++If you have problems, you may need to regenerate the build system entirely.
++To do so, use the procedure documented by the package, typically 'autoreconf'.])])
++
++# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
++#
++#   Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
++#   Foundation, Inc.
++#   Written by Gordon Matzigkeit, 1996
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++m4_define([_LT_COPYING], [dnl
++# Copyright (C) 2014 Free Software Foundation, Inc.
++# This is free software; see the source for copying conditions.  There is NO
++# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++
++# GNU Libtool 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 2 of of the License, or
++# (at your option) any later version.
++#
++# As a special exception to the GNU General Public License, if you
++# distribute this file as part of a program or library that is built
++# using GNU Libtool, you may include this file under the  same
++# distribution terms that you use for the rest of that program.
++#
++# GNU Libtool is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see .
++])
++
++# serial 59 LT_INIT
++
++
++# LT_PREREQ(VERSION)
++# ------------------
++# Complain and exit if this libtool version is less that VERSION.
++m4_defun([LT_PREREQ],
++[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
++       [m4_default([$3],
++		   [m4_fatal([Libtool version $1 or higher is required],
++		             63)])],
++       [$2])])
++
++
++# _LT_CHECK_BUILDDIR
++# ------------------
++# Complain if the absolute build directory name contains unusual characters
++m4_defun([_LT_CHECK_BUILDDIR],
++[case `pwd` in
++  *\ * | *\	*)
++    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
++esac
++])
++
++
++# LT_INIT([OPTIONS])
++# ------------------
++AC_DEFUN([LT_INIT],
++[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
++AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
++AC_BEFORE([$0], [LT_LANG])dnl
++AC_BEFORE([$0], [LT_OUTPUT])dnl
++AC_BEFORE([$0], [LTDL_INIT])dnl
++m4_require([_LT_CHECK_BUILDDIR])dnl
++
++dnl Autoconf doesn't catch unexpanded LT_ macros by default:
++m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
++m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
++dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
++dnl unless we require an AC_DEFUNed macro:
++AC_REQUIRE([LTOPTIONS_VERSION])dnl
++AC_REQUIRE([LTSUGAR_VERSION])dnl
++AC_REQUIRE([LTVERSION_VERSION])dnl
++AC_REQUIRE([LTOBSOLETE_VERSION])dnl
++m4_require([_LT_PROG_LTMAIN])dnl
++
++_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
++
++dnl Parse OPTIONS
++_LT_SET_OPTIONS([$0], [$1])
++
++# This can be used to rebuild libtool when needed
++LIBTOOL_DEPS=$ltmain
++
++# Always use our own libtool.
++LIBTOOL='$(SHELL) $(top_builddir)/libtool'
++AC_SUBST(LIBTOOL)dnl
++
++_LT_SETUP
++
++# Only expand once:
++m4_define([LT_INIT])
++])# LT_INIT
++
++# Old names:
++AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
++AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
++dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
++
++
++# _LT_PREPARE_CC_BASENAME
++# -----------------------
++m4_defun([_LT_PREPARE_CC_BASENAME], [
++# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
++func_cc_basename ()
++{
++    for cc_temp in @S|@*""; do
++      case $cc_temp in
++        compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
++        distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
++        \-*) ;;
++        *) break;;
++      esac
++    done
++    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
++}
++])# _LT_PREPARE_CC_BASENAME
++
++
++# _LT_CC_BASENAME(CC)
++# -------------------
++# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
++# but that macro is also expanded into generated libtool script, which
++# arranges for $SED and $ECHO to be set by different means.
++m4_defun([_LT_CC_BASENAME],
++[m4_require([_LT_PREPARE_CC_BASENAME])dnl
++AC_REQUIRE([_LT_DECL_SED])dnl
++AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
++func_cc_basename $1
++cc_basename=$func_cc_basename_result
++])
++
++
++# _LT_FILEUTILS_DEFAULTS
++# ----------------------
++# It is okay to use these file commands and assume they have been set
++# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
++m4_defun([_LT_FILEUTILS_DEFAULTS],
++[: ${CP="cp -f"}
++: ${MV="mv -f"}
++: ${RM="rm -f"}
++])# _LT_FILEUTILS_DEFAULTS
++
++
++# _LT_SETUP
++# ---------
++m4_defun([_LT_SETUP],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
++AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
++
++_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
++dnl
++_LT_DECL([], [host_alias], [0], [The host system])dnl
++_LT_DECL([], [host], [0])dnl
++_LT_DECL([], [host_os], [0])dnl
++dnl
++_LT_DECL([], [build_alias], [0], [The build system])dnl
++_LT_DECL([], [build], [0])dnl
++_LT_DECL([], [build_os], [0])dnl
++dnl
++AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([LT_PATH_LD])dnl
++AC_REQUIRE([LT_PATH_NM])dnl
++dnl
++AC_REQUIRE([AC_PROG_LN_S])dnl
++test -z "$LN_S" && LN_S="ln -s"
++_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
++dnl
++AC_REQUIRE([LT_CMD_MAX_LEN])dnl
++_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
++_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
++dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_CHECK_SHELL_FEATURES])dnl
++m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
++m4_require([_LT_CMD_RELOAD])dnl
++m4_require([_LT_DECL_FILECMD])dnl
++m4_require([_LT_CHECK_MAGIC_METHOD])dnl
++m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
++m4_require([_LT_CMD_OLD_ARCHIVE])dnl
++m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
++m4_require([_LT_WITH_SYSROOT])dnl
++m4_require([_LT_CMD_TRUNCATE])dnl
++
++_LT_CONFIG_LIBTOOL_INIT([
++# See if we are running on zsh, and set the options that allow our
++# commands through without removal of \ escapes INIT.
++if test -n "\${ZSH_VERSION+set}"; then
++   setopt NO_GLOB_SUBST
++fi
++])
++if test -n "${ZSH_VERSION+set}"; then
++   setopt NO_GLOB_SUBST
++fi
++
++_LT_CHECK_OBJDIR
++
++m4_require([_LT_TAG_COMPILER])dnl
++
++case $host_os in
++aix3*)
++  # AIX sometimes has problems with the GCC collect2 program.  For some
++  # reason, if we set the COLLECT_NAMES environment variable, the problems
++  # vanish in a puff of smoke.
++  if test set != "${COLLECT_NAMES+set}"; then
++    COLLECT_NAMES=
++    export COLLECT_NAMES
++  fi
++  ;;
++esac
++
++# Global variables:
++ofile=libtool
++can_build_shared=yes
++
++# All known linkers require a '.a' archive for static linking (except MSVC and
++# ICC, which need '.lib').
++libext=a
++
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++old_CC=$CC
++old_CFLAGS=$CFLAGS
++
++# Set sane defaults for various variables
++test -z "$CC" && CC=cc
++test -z "$LTCC" && LTCC=$CC
++test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
++test -z "$LD" && LD=ld
++test -z "$ac_objext" && ac_objext=o
++
++_LT_CC_BASENAME([$compiler])
++
++# Only perform the check for file, if the check method requires it
++test -z "$MAGIC_CMD" && MAGIC_CMD=file
++case $deplibs_check_method in
++file_magic*)
++  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
++    _LT_PATH_MAGIC
++  fi
++  ;;
++esac
++
++# Use C for the default configuration in the libtool script
++LT_SUPPORTED_TAG([CC])
++_LT_LANG_C_CONFIG
++_LT_LANG_DEFAULT_CONFIG
++_LT_CONFIG_COMMANDS
++])# _LT_SETUP
++
++
++# _LT_PREPARE_SED_QUOTE_VARS
++# --------------------------
++# Define a few sed substitution that help us do robust quoting.
++m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
++[# Backslashify metacharacters that are still active within
++# double-quoted strings.
++sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
++
++# Same as above, but do not quote variable references.
++double_quote_subst='s/\([["`\\]]\)/\\\1/g'
++
++# Sed substitution to delay expansion of an escaped shell variable in a
++# double_quote_subst'ed string.
++delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
++
++# Sed substitution to delay expansion of an escaped single quote.
++delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
++
++# Sed substitution to avoid accidental globbing in evaled expressions
++no_glob_subst='s/\*/\\\*/g'
++])
++
++# _LT_PROG_LTMAIN
++# ---------------
++# Note that this code is called both from 'configure', and 'config.status'
++# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
++# 'config.status' has no value for ac_aux_dir unless we are using Automake,
++# so we pass a copy along to make sure it has a sensible value anyway.
++m4_defun([_LT_PROG_LTMAIN],
++[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
++_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
++ltmain=$ac_aux_dir/ltmain.sh
++])# _LT_PROG_LTMAIN
++
++
++
++# So that we can recreate a full libtool script including additional
++# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
++# in macros and then make a single call at the end using the 'libtool'
++# label.
++
++
++# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
++# ----------------------------------------
++# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
++m4_define([_LT_CONFIG_LIBTOOL_INIT],
++[m4_ifval([$1],
++          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
++                     [$1
++])])])
++
++# Initialize.
++m4_define([_LT_OUTPUT_LIBTOOL_INIT])
++
++
++# _LT_CONFIG_LIBTOOL([COMMANDS])
++# ------------------------------
++# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
++m4_define([_LT_CONFIG_LIBTOOL],
++[m4_ifval([$1],
++          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
++                     [$1
++])])])
++
++# Initialize.
++m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
++
++
++# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
++# -----------------------------------------------------
++m4_defun([_LT_CONFIG_SAVE_COMMANDS],
++[_LT_CONFIG_LIBTOOL([$1])
++_LT_CONFIG_LIBTOOL_INIT([$2])
++])
++
++
++# _LT_FORMAT_COMMENT([COMMENT])
++# -----------------------------
++# Add leading comment marks to the start of each line, and a trailing
++# full-stop to the whole comment if one is not present already.
++m4_define([_LT_FORMAT_COMMENT],
++[m4_ifval([$1], [
++m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
++              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
++)])
++
++
++
++
++
++# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
++# -------------------------------------------------------------------
++# CONFIGNAME is the name given to the value in the libtool script.
++# VARNAME is the (base) name used in the configure script.
++# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
++# VARNAME.  Any other value will be used directly.
++m4_define([_LT_DECL],
++[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
++    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
++	[m4_ifval([$1], [$1], [$2])])
++    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
++    m4_ifval([$4],
++	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
++    lt_dict_add_subkey([lt_decl_dict], [$2],
++	[tagged?], [m4_ifval([$5], [yes], [no])])])
++])
++
++
++# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
++# --------------------------------------------------------
++m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
++
++
++# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
++# ------------------------------------------------
++m4_define([lt_decl_tag_varnames],
++[_lt_decl_filter([tagged?], [yes], $@)])
++
++
++# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
++# ---------------------------------------------------------
++m4_define([_lt_decl_filter],
++[m4_case([$#],
++  [0], [m4_fatal([$0: too few arguments: $#])],
++  [1], [m4_fatal([$0: too few arguments: $#: $1])],
++  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
++  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
++  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
++])
++
++
++# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
++# --------------------------------------------------
++m4_define([lt_decl_quote_varnames],
++[_lt_decl_filter([value], [1], $@)])
++
++
++# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
++# ---------------------------------------------------
++m4_define([lt_decl_dquote_varnames],
++[_lt_decl_filter([value], [2], $@)])
++
++
++# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
++# ---------------------------------------------------
++m4_define([lt_decl_varnames_tagged],
++[m4_assert([$# <= 2])dnl
++_$0(m4_quote(m4_default([$1], [[, ]])),
++    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
++    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
++m4_define([_lt_decl_varnames_tagged],
++[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
++
++
++# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
++# ------------------------------------------------
++m4_define([lt_decl_all_varnames],
++[_$0(m4_quote(m4_default([$1], [[, ]])),
++     m4_if([$2], [],
++	   m4_quote(lt_decl_varnames),
++	m4_quote(m4_shift($@))))[]dnl
++])
++m4_define([_lt_decl_all_varnames],
++[lt_join($@, lt_decl_varnames_tagged([$1],
++			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
++])
++
++
++# _LT_CONFIG_STATUS_DECLARE([VARNAME])
++# ------------------------------------
++# Quote a variable value, and forward it to 'config.status' so that its
++# declaration there will have the same value as in 'configure'.  VARNAME
++# must have a single quote delimited value for this to work.
++m4_define([_LT_CONFIG_STATUS_DECLARE],
++[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
++
++
++# _LT_CONFIG_STATUS_DECLARATIONS
++# ------------------------------
++# We delimit libtool config variables with single quotes, so when
++# we write them to config.status, we have to be sure to quote all
++# embedded single quotes properly.  In configure, this macro expands
++# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
++#
++#    ='`$ECHO "$" | $SED "$delay_single_quote_subst"`'
++m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
++[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
++    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
++
++
++# _LT_LIBTOOL_TAGS
++# ----------------
++# Output comment and list of tags supported by the script
++m4_defun([_LT_LIBTOOL_TAGS],
++[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
++available_tags='_LT_TAGS'dnl
++])
++
++
++# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
++# -----------------------------------
++# Extract the dictionary values for VARNAME (optionally with TAG) and
++# expand to a commented shell variable setting:
++#
++#    # Some comment about what VAR is for.
++#    visible_name=$lt_internal_name
++m4_define([_LT_LIBTOOL_DECLARE],
++[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
++					   [description])))[]dnl
++m4_pushdef([_libtool_name],
++    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
++m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
++    [0], [_libtool_name=[$]$1],
++    [1], [_libtool_name=$lt_[]$1],
++    [2], [_libtool_name=$lt_[]$1],
++    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
++m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
++])
++
++
++# _LT_LIBTOOL_CONFIG_VARS
++# -----------------------
++# Produce commented declarations of non-tagged libtool config variables
++# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
++# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
++# section) are produced by _LT_LIBTOOL_TAG_VARS.
++m4_defun([_LT_LIBTOOL_CONFIG_VARS],
++[m4_foreach([_lt_var],
++    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
++    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
++
++
++# _LT_LIBTOOL_TAG_VARS(TAG)
++# -------------------------
++m4_define([_LT_LIBTOOL_TAG_VARS],
++[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
++    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
++
++
++# _LT_TAGVAR(VARNAME, [TAGNAME])
++# ------------------------------
++m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
++
++
++# _LT_CONFIG_COMMANDS
++# -------------------
++# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
++# variables for single and double quote escaping we saved from calls
++# to _LT_DECL, we can put quote escaped variables declarations
++# into 'config.status', and then the shell code to quote escape them in
++# for loops in 'config.status'.  Finally, any additional code accumulated
++# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
++m4_defun([_LT_CONFIG_COMMANDS],
++[AC_PROVIDE_IFELSE([LT_OUTPUT],
++	dnl If the libtool generation code has been placed in $CONFIG_LT,
++	dnl instead of duplicating it all over again into config.status,
++	dnl then we will have config.status run $CONFIG_LT later, so it
++	dnl needs to know what name is stored there:
++        [AC_CONFIG_COMMANDS([libtool],
++            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
++    dnl If the libtool generation code is destined for config.status,
++    dnl expand the accumulated commands and init code now:
++    [AC_CONFIG_COMMANDS([libtool],
++        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
++])#_LT_CONFIG_COMMANDS
++
++
++# Initialize.
++m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
++[
++
++# The HP-UX ksh and POSIX shell print the target directory to stdout
++# if CDPATH is set.
++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
++
++sed_quote_subst='$sed_quote_subst'
++double_quote_subst='$double_quote_subst'
++delay_variable_subst='$delay_variable_subst'
++_LT_CONFIG_STATUS_DECLARATIONS
++LTCC='$LTCC'
++LTCFLAGS='$LTCFLAGS'
++compiler='$compiler_DEFAULT'
++
++# A function that is used when there is no print builtin or printf.
++func_fallback_echo ()
++{
++  eval 'cat <<_LTECHO_EOF
++\$[]1
++_LTECHO_EOF'
++}
++
++# Quote evaled strings.
++for var in lt_decl_all_varnames([[ \
++]], lt_decl_quote_varnames); do
++    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++    *[[\\\\\\\`\\"\\\$]]*)
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++      ;;
++    *)
++      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++      ;;
++    esac
++done
++
++# Double-quote double-evaled strings.
++for var in lt_decl_all_varnames([[ \
++]], lt_decl_dquote_varnames); do
++    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++    *[[\\\\\\\`\\"\\\$]]*)
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++      ;;
++    *)
++      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++      ;;
++    esac
++done
++
++_LT_OUTPUT_LIBTOOL_INIT
++])
++
++# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
++# ------------------------------------
++# Generate a child script FILE with all initialization necessary to
++# reuse the environment learned by the parent script, and make the
++# file executable.  If COMMENT is supplied, it is inserted after the
++# '#!' sequence but before initialization text begins.  After this
++# macro, additional text can be appended to FILE to form the body of
++# the child script.  The macro ends with non-zero status if the
++# file could not be fully written (such as if the disk is full).
++m4_ifdef([AS_INIT_GENERATED],
++[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
++[m4_defun([_LT_GENERATED_FILE_INIT],
++[m4_require([AS_PREPARE])]dnl
++[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
++[lt_write_fail=0
++cat >$1 <<_ASEOF || lt_write_fail=1
++#! $SHELL
++# Generated by $as_me.
++$2
++SHELL=\${CONFIG_SHELL-$SHELL}
++export SHELL
++_ASEOF
++cat >>$1 <<\_ASEOF || lt_write_fail=1
++AS_SHELL_SANITIZE
++_AS_PREPARE
++exec AS_MESSAGE_FD>&1
++_ASEOF
++test 0 = "$lt_write_fail" && chmod +x $1[]dnl
++m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
++
++# LT_OUTPUT
++# ---------
++# This macro allows early generation of the libtool script (before
++# AC_OUTPUT is called), incase it is used in configure for compilation
++# tests.
++AC_DEFUN([LT_OUTPUT],
++[: ${CONFIG_LT=./config.lt}
++AC_MSG_NOTICE([creating $CONFIG_LT])
++_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
++[# Run this file to recreate a libtool stub with the current configuration.])
++
++cat >>"$CONFIG_LT" <<\_LTEOF
++lt_cl_silent=false
++exec AS_MESSAGE_LOG_FD>>config.log
++{
++  echo
++  AS_BOX([Running $as_me.])
++} >&AS_MESSAGE_LOG_FD
++
++lt_cl_help="\
++'$as_me' creates a local libtool stub from the current configuration,
++for use in further configure time tests before the real libtool is
++generated.
++
++Usage: $[0] [[OPTIONS]]
++
++  -h, --help      print this help, then exit
++  -V, --version   print version number, then exit
++  -q, --quiet     do not print progress messages
++  -d, --debug     don't remove temporary files
++
++Report bugs to ."
++
++lt_cl_version="\
++m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
++m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
++configured by $[0], generated by m4_PACKAGE_STRING.
++
++Copyright (C) 2011 Free Software Foundation, Inc.
++This config.lt script is free software; the Free Software Foundation
++gives unlimited permision to copy, distribute and modify it."
++
++while test 0 != $[#]
++do
++  case $[1] in
++    --version | --v* | -V )
++      echo "$lt_cl_version"; exit 0 ;;
++    --help | --h* | -h )
++      echo "$lt_cl_help"; exit 0 ;;
++    --debug | --d* | -d )
++      debug=: ;;
++    --quiet | --q* | --silent | --s* | -q )
++      lt_cl_silent=: ;;
++
++    -*) AC_MSG_ERROR([unrecognized option: $[1]
++Try '$[0] --help' for more information.]) ;;
++
++    *) AC_MSG_ERROR([unrecognized argument: $[1]
++Try '$[0] --help' for more information.]) ;;
++  esac
++  shift
++done
++
++if $lt_cl_silent; then
++  exec AS_MESSAGE_FD>/dev/null
++fi
++_LTEOF
++
++cat >>"$CONFIG_LT" <<_LTEOF
++_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
++_LTEOF
++
++cat >>"$CONFIG_LT" <<\_LTEOF
++AC_MSG_NOTICE([creating $ofile])
++_LT_OUTPUT_LIBTOOL_COMMANDS
++AS_EXIT(0)
++_LTEOF
++chmod +x "$CONFIG_LT"
++
++# configure is writing to config.log, but config.lt does its own redirection,
++# appending to config.log, which fails on DOS, as config.log is still kept
++# open by configure.  Here we exec the FD to /dev/null, effectively closing
++# config.log, so it can be properly (re)opened and appended to by config.lt.
++lt_cl_success=:
++test yes = "$silent" &&
++  lt_config_lt_args="$lt_config_lt_args --quiet"
++exec AS_MESSAGE_LOG_FD>/dev/null
++$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
++exec AS_MESSAGE_LOG_FD>>config.log
++$lt_cl_success || AS_EXIT(1)
++])# LT_OUTPUT
++
++
++# _LT_CONFIG(TAG)
++# ---------------
++# If TAG is the built-in tag, create an initial libtool script with a
++# default configuration from the untagged config vars.  Otherwise add code
++# to config.status for appending the configuration named by TAG from the
++# matching tagged config vars.
++m4_defun([_LT_CONFIG],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++_LT_CONFIG_SAVE_COMMANDS([
++  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
++  m4_if(_LT_TAG, [C], [
++    # See if we are running on zsh, and set the options that allow our
++    # commands through without removal of \ escapes.
++    if test -n "${ZSH_VERSION+set}"; then
++      setopt NO_GLOB_SUBST
++    fi
++
++    cfgfile=${ofile}T
++    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
++    $RM "$cfgfile"
++
++    cat <<_LT_EOF >> "$cfgfile"
++#! $SHELL
++# Generated automatically by $as_me ($PACKAGE) $VERSION
++# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
++# NOTE: Changes made to this file will be lost: look at ltmain.sh.
++
++# Provide generalized library-building support services.
++# Written by Gordon Matzigkeit, 1996
++
++_LT_COPYING
++_LT_LIBTOOL_TAGS
++
++# Configured defaults for sys_lib_dlsearch_path munging.
++: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
++
++# ### BEGIN LIBTOOL CONFIG
++_LT_LIBTOOL_CONFIG_VARS
++_LT_LIBTOOL_TAG_VARS
++# ### END LIBTOOL CONFIG
++
++_LT_EOF
++
++    cat <<'_LT_EOF' >> "$cfgfile"
++
++# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
++
++_LT_PREPARE_MUNGE_PATH_LIST
++_LT_PREPARE_CC_BASENAME
++
++# ### END FUNCTIONS SHARED WITH CONFIGURE
++
++_LT_EOF
++
++  case $host_os in
++  aix3*)
++    cat <<\_LT_EOF >> "$cfgfile"
++# AIX sometimes has problems with the GCC collect2 program.  For some
++# reason, if we set the COLLECT_NAMES environment variable, the problems
++# vanish in a puff of smoke.
++if test set != "${COLLECT_NAMES+set}"; then
++  COLLECT_NAMES=
++  export COLLECT_NAMES
++fi
++_LT_EOF
++    ;;
++  esac
++
++  _LT_PROG_LTMAIN
++
++  # We use sed instead of cat because bash on DJGPP gets confused if
++  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
++  # text mode, it properly converts lines to CR/LF.  This bash problem
++  # is reportedly fixed, but why not run on old versions too?
++  $SED '$q' "$ltmain" >> "$cfgfile" \
++     || (rm -f "$cfgfile"; exit 1)
++
++   mv -f "$cfgfile" "$ofile" ||
++    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
++  chmod +x "$ofile"
++],
++[cat <<_LT_EOF >> "$ofile"
++
++dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
++dnl in a comment (ie after a #).
++# ### BEGIN LIBTOOL TAG CONFIG: $1
++_LT_LIBTOOL_TAG_VARS(_LT_TAG)
++# ### END LIBTOOL TAG CONFIG: $1
++_LT_EOF
++])dnl /m4_if
++],
++[m4_if([$1], [], [
++    PACKAGE='$PACKAGE'
++    VERSION='$VERSION'
++    RM='$RM'
++    ofile='$ofile'], [])
++])dnl /_LT_CONFIG_SAVE_COMMANDS
++])# _LT_CONFIG
++
++
++# LT_SUPPORTED_TAG(TAG)
++# ---------------------
++# Trace this macro to discover what tags are supported by the libtool
++# --tag option, using:
++#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
++AC_DEFUN([LT_SUPPORTED_TAG], [])
++
++
++# C support is built-in for now
++m4_define([_LT_LANG_C_enabled], [])
++m4_define([_LT_TAGS], [])
++
++
++# LT_LANG(LANG)
++# -------------
++# Enable libtool support for the given language if not already enabled.
++AC_DEFUN([LT_LANG],
++[AC_BEFORE([$0], [LT_OUTPUT])dnl
++m4_case([$1],
++  [C],			[_LT_LANG(C)],
++  [C++],		[_LT_LANG(CXX)],
++  [Go],			[_LT_LANG(GO)],
++  [Java],		[_LT_LANG(GCJ)],
++  [Fortran 77],		[_LT_LANG(F77)],
++  [Fortran],		[_LT_LANG(FC)],
++  [Windows Resource],	[_LT_LANG(RC)],
++  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
++    [_LT_LANG($1)],
++    [m4_fatal([$0: unsupported language: "$1"])])])dnl
++])# LT_LANG
++
++
++# _LT_LANG(LANGNAME)
++# ------------------
++m4_defun([_LT_LANG],
++[m4_ifdef([_LT_LANG_]$1[_enabled], [],
++  [LT_SUPPORTED_TAG([$1])dnl
++  m4_append([_LT_TAGS], [$1 ])dnl
++  m4_define([_LT_LANG_]$1[_enabled], [])dnl
++  _LT_LANG_$1_CONFIG($1)])dnl
++])# _LT_LANG
++
++
++m4_ifndef([AC_PROG_GO], [
++# NOTE: This macro has been submitted for inclusion into   #
++#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
++#  a released version of Autoconf we should remove this    #
++#  macro and use it instead.                               #
++m4_defun([AC_PROG_GO],
++[AC_LANG_PUSH(Go)dnl
++AC_ARG_VAR([GOC],     [Go compiler command])dnl
++AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
++_AC_ARG_VAR_LDFLAGS()dnl
++AC_CHECK_TOOL(GOC, gccgo)
++if test -z "$GOC"; then
++  if test -n "$ac_tool_prefix"; then
++    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
++  fi
++fi
++if test -z "$GOC"; then
++  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
++fi
++])#m4_defun
++])#m4_ifndef
++
++
++# _LT_LANG_DEFAULT_CONFIG
++# -----------------------
++m4_defun([_LT_LANG_DEFAULT_CONFIG],
++[AC_PROVIDE_IFELSE([AC_PROG_CXX],
++  [LT_LANG(CXX)],
++  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
++
++AC_PROVIDE_IFELSE([AC_PROG_F77],
++  [LT_LANG(F77)],
++  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
++
++AC_PROVIDE_IFELSE([AC_PROG_FC],
++  [LT_LANG(FC)],
++  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
++
++dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
++dnl pulling things in needlessly.
++AC_PROVIDE_IFELSE([AC_PROG_GCJ],
++  [LT_LANG(GCJ)],
++  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
++    [LT_LANG(GCJ)],
++    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
++      [LT_LANG(GCJ)],
++      [m4_ifdef([AC_PROG_GCJ],
++	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
++       m4_ifdef([A][M_PROG_GCJ],
++	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
++       m4_ifdef([LT_PROG_GCJ],
++	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
++
++AC_PROVIDE_IFELSE([AC_PROG_GO],
++  [LT_LANG(GO)],
++  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
++
++AC_PROVIDE_IFELSE([LT_PROG_RC],
++  [LT_LANG(RC)],
++  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
++])# _LT_LANG_DEFAULT_CONFIG
++
++# Obsolete macros:
++AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
++AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
++AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
++AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
++AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
++dnl AC_DEFUN([AC_LIBTOOL_F77], [])
++dnl AC_DEFUN([AC_LIBTOOL_FC], [])
++dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
++dnl AC_DEFUN([AC_LIBTOOL_RC], [])
++
++
++# _LT_TAG_COMPILER
++# ----------------
++m4_defun([_LT_TAG_COMPILER],
++[AC_REQUIRE([AC_PROG_CC])dnl
++
++_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
++_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
++_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
++_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
++
++# If no C compiler was specified, use CC.
++LTCC=${LTCC-"$CC"}
++
++# If no C compiler flags were specified, use CFLAGS.
++LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
++
++# Allow CC to be a program name with arguments.
++compiler=$CC
++])# _LT_TAG_COMPILER
++
++
++# _LT_COMPILER_BOILERPLATE
++# ------------------------
++# Check for compiler boilerplate output or warnings with
++# the simple compiler test code.
++m4_defun([_LT_COMPILER_BOILERPLATE],
++[m4_require([_LT_DECL_SED])dnl
++ac_outfile=conftest.$ac_objext
++echo "$lt_simple_compile_test_code" >conftest.$ac_ext
++eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_compiler_boilerplate=`cat conftest.err`
++$RM conftest*
++])# _LT_COMPILER_BOILERPLATE
++
++
++# _LT_LINKER_BOILERPLATE
++# ----------------------
++# Check for linker boilerplate output or warnings with
++# the simple link test code.
++m4_defun([_LT_LINKER_BOILERPLATE],
++[m4_require([_LT_DECL_SED])dnl
++ac_outfile=conftest.$ac_objext
++echo "$lt_simple_link_test_code" >conftest.$ac_ext
++eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_linker_boilerplate=`cat conftest.err`
++$RM -r conftest*
++])# _LT_LINKER_BOILERPLATE
++
++# _LT_REQUIRED_DARWIN_CHECKS
++# -------------------------
++m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
++  case $host_os in
++    rhapsody* | darwin*)
++    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
++    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
++    AC_CHECK_TOOL([LIPO], [lipo], [:])
++    AC_CHECK_TOOL([OTOOL], [otool], [:])
++    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
++    _LT_DECL([], [DSYMUTIL], [1],
++      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
++    _LT_DECL([], [NMEDIT], [1],
++      [Tool to change global to local symbols on Mac OS X])
++    _LT_DECL([], [LIPO], [1],
++      [Tool to manipulate fat objects and archives on Mac OS X])
++    _LT_DECL([], [OTOOL], [1],
++      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
++    _LT_DECL([], [OTOOL64], [1],
++      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
++
++    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
++      [lt_cv_apple_cc_single_mod=no
++      if test -z "$LT_MULTI_MODULE"; then
++	# By default we will add the -single_module flag. You can override
++	# by either setting the environment variable LT_MULTI_MODULE
++	# non-empty at configure time, or by adding -multi_module to the
++	# link flags.
++	rm -rf libconftest.dylib*
++	echo "int foo(void){return 1;}" > conftest.c
++	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
++-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
++	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
++	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
++        _lt_result=$?
++	# If there is a non-empty error log, and "single_module"
++	# appears in it, assume the flag caused a linker warning
++        if test -s conftest.err && $GREP single_module conftest.err; then
++	  cat conftest.err >&AS_MESSAGE_LOG_FD
++	# Otherwise, if the output was created with a 0 exit code from
++	# the compiler, it worked.
++	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
++	  lt_cv_apple_cc_single_mod=yes
++	else
++	  cat conftest.err >&AS_MESSAGE_LOG_FD
++	fi
++	rm -rf libconftest.dylib*
++	rm -f conftest.*
++      fi])
++
++    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
++      [lt_cv_ld_exported_symbols_list],
++      [lt_cv_ld_exported_symbols_list=no
++      save_LDFLAGS=$LDFLAGS
++      echo "_main" > conftest.sym
++      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
++      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
++	[lt_cv_ld_exported_symbols_list=yes],
++	[lt_cv_ld_exported_symbols_list=no])
++	LDFLAGS=$save_LDFLAGS
++    ])
++
++    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
++      [lt_cv_ld_force_load=no
++      cat > conftest.c << _LT_EOF
++int forced_loaded() { return 2;}
++_LT_EOF
++      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
++      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
++      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
++      $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
++      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
++      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
++      cat > conftest.c << _LT_EOF
++int main() { return 0;}
++_LT_EOF
++      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
++      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
++      _lt_result=$?
++      if test -s conftest.err && $GREP force_load conftest.err; then
++	cat conftest.err >&AS_MESSAGE_LOG_FD
++      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
++	lt_cv_ld_force_load=yes
++      else
++	cat conftest.err >&AS_MESSAGE_LOG_FD
++      fi
++        rm -f conftest.err libconftest.a conftest conftest.c
++        rm -rf conftest.dSYM
++    ])
++    case $host_os in
++    rhapsody* | darwin1.[[012]])
++      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
++    darwin1.*)
++      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
++    darwin*)
++      case $MACOSX_DEPLOYMENT_TARGET,$host in
++        10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
++          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
++        *)
++          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
++      esac
++    ;;
++  esac
++    if test yes = "$lt_cv_apple_cc_single_mod"; then
++      _lt_dar_single_mod='$single_module'
++    fi
++    if test yes = "$lt_cv_ld_exported_symbols_list"; then
++      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
++    else
++      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
++    fi
++    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
++      _lt_dsymutil='~$DSYMUTIL $lib || :'
++    else
++      _lt_dsymutil=
++    fi
++    ;;
++  esac
++])
++
++
++# _LT_DARWIN_LINKER_FEATURES([TAG])
++# ---------------------------------
++# Checks for linker and compiler features on darwin
++m4_defun([_LT_DARWIN_LINKER_FEATURES],
++[
++  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
++  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++  _LT_TAGVAR(hardcode_direct, $1)=no
++  _LT_TAGVAR(hardcode_automatic, $1)=yes
++  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++  if test yes = "$lt_cv_ld_force_load"; then
++    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
++    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
++                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
++  else
++    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
++  fi
++  _LT_TAGVAR(link_all_deplibs, $1)=yes
++  _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
++  case $cc_basename in
++     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
++     *) _lt_dar_can_shared=$GCC ;;
++  esac
++  if test yes = "$_lt_dar_can_shared"; then
++    output_verbose_link_cmd=func_echo_all
++    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
++    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
++    _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
++    _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
++    m4_if([$1], [CXX],
++[   if test yes != "$lt_cv_apple_cc_single_mod"; then
++      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
++      _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
++    fi
++],[])
++  else
++  _LT_TAGVAR(ld_shlibs, $1)=no
++  fi
++])
++
++# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
++# ----------------------------------
++# Links a minimal program and checks the executable
++# for the system default hardcoded library path. In most cases,
++# this is /usr/lib:/lib, but when the MPI compilers are used
++# the location of the communication and MPI libs are included too.
++# If we don't find anything, use the default library path according
++# to the aix ld manual.
++# Store the results from the different compilers for each TAGNAME.
++# Allow to override them for all tags through lt_cv_aix_libpath.
++m4_defun([_LT_SYS_MODULE_PATH_AIX],
++[m4_require([_LT_DECL_SED])dnl
++if test set = "${lt_cv_aix_libpath+set}"; then
++  aix_libpath=$lt_cv_aix_libpath
++else
++  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
++  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
++  lt_aix_libpath_sed='[
++      /Import File Strings/,/^$/ {
++	  /^0/ {
++	      s/^0  *\([^ ]*\) *$/\1/
++	      p
++	  }
++      }]'
++  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  # Check for a 64-bit object if we didn't find anything.
++  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
++    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  fi],[])
++  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
++    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
++  fi
++  ])
++  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
++fi
++])# _LT_SYS_MODULE_PATH_AIX
++
++
++# _LT_SHELL_INIT(ARG)
++# -------------------
++m4_define([_LT_SHELL_INIT],
++[m4_divert_text([M4SH-INIT], [$1
++])])# _LT_SHELL_INIT
++
++
++
++# _LT_PROG_ECHO_BACKSLASH
++# -----------------------
++# Find how we can fake an echo command that does not interpret backslash.
++# In particular, with Autoconf 2.60 or later we add some code to the start
++# of the generated configure script that will find a shell with a builtin
++# printf (that we can use as an echo command).
++m4_defun([_LT_PROG_ECHO_BACKSLASH],
++[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
++ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
++
++AC_MSG_CHECKING([how to print strings])
++# Test print first, because it will be a builtin if present.
++if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
++   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
++  ECHO='print -r --'
++elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
++  ECHO='printf %s\n'
++else
++  # Use this function as a fallback that always works.
++  func_fallback_echo ()
++  {
++    eval 'cat <<_LTECHO_EOF
++$[]1
++_LTECHO_EOF'
++  }
++  ECHO='func_fallback_echo'
++fi
++
++# func_echo_all arg...
++# Invoke $ECHO with all args, space-separated.
++func_echo_all ()
++{
++    $ECHO "$*"
++}
++
++case $ECHO in
++  printf*) AC_MSG_RESULT([printf]) ;;
++  print*) AC_MSG_RESULT([print -r]) ;;
++  *) AC_MSG_RESULT([cat]) ;;
++esac
++
++m4_ifdef([_AS_DETECT_SUGGESTED],
++[_AS_DETECT_SUGGESTED([
++  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
++    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
++    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
++    PATH=/empty FPATH=/empty; export PATH FPATH
++    test "X`printf %s $ECHO`" = "X$ECHO" \
++      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
++
++_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
++_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
++])# _LT_PROG_ECHO_BACKSLASH
++
++
++# _LT_WITH_SYSROOT
++# ----------------
++AC_DEFUN([_LT_WITH_SYSROOT],
++[m4_require([_LT_DECL_SED])dnl
++AC_MSG_CHECKING([for sysroot])
++AC_ARG_WITH([sysroot],
++[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
++  [Search for dependent libraries within DIR (or the compiler's sysroot
++   if not specified).])],
++[], [with_sysroot=no])
++
++dnl lt_sysroot will always be passed unquoted.  We quote it here
++dnl in case the user passed a directory name.
++lt_sysroot=
++case $with_sysroot in #(
++ yes)
++   if test yes = "$GCC"; then
++     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
++   fi
++   ;; #(
++ /*)
++   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
++   ;; #(
++ no|'')
++   ;; #(
++ *)
++   AC_MSG_RESULT([$with_sysroot])
++   AC_MSG_ERROR([The sysroot must be an absolute path.])
++   ;;
++esac
++
++ AC_MSG_RESULT([${lt_sysroot:-no}])
++_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
++[dependent libraries, and where our libraries should be installed.])])
++
++# _LT_ENABLE_LOCK
++# ---------------
++m4_defun([_LT_ENABLE_LOCK],
++[AC_ARG_ENABLE([libtool-lock],
++  [AS_HELP_STRING([--disable-libtool-lock],
++    [avoid locking (might break parallel builds)])])
++test no = "$enable_libtool_lock" || enable_libtool_lock=yes
++
++# Some flags need to be propagated to the compiler or linker for good
++# libtool support.
++case $host in
++ia64-*-hpux*)
++  # Find out what ABI is being produced by ac_compile, and set mode
++  # options accordingly.
++  echo 'int i;' > conftest.$ac_ext
++  if AC_TRY_EVAL(ac_compile); then
++    case `$FILECMD conftest.$ac_objext` in
++      *ELF-32*)
++	HPUX_IA64_MODE=32
++	;;
++      *ELF-64*)
++	HPUX_IA64_MODE=64
++	;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++*-*-irix6*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.
++  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
++  if AC_TRY_EVAL(ac_compile); then
++    if test yes = "$lt_cv_prog_gnu_ld"; then
++      case `$FILECMD conftest.$ac_objext` in
++	*32-bit*)
++	  LD="${LD-ld} -melf32bsmip"
++	  ;;
++	*N32*)
++	  LD="${LD-ld} -melf32bmipn32"
++	  ;;
++	*64-bit*)
++	  LD="${LD-ld} -melf64bmip"
++	;;
++      esac
++    else
++      case `$FILECMD conftest.$ac_objext` in
++	*32-bit*)
++	  LD="${LD-ld} -32"
++	  ;;
++	*N32*)
++	  LD="${LD-ld} -n32"
++	  ;;
++	*64-bit*)
++	  LD="${LD-ld} -64"
++	  ;;
++      esac
++    fi
++  fi
++  rm -rf conftest*
++  ;;
++
++mips64*-*linux*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.
++  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
++  if AC_TRY_EVAL(ac_compile); then
++    emul=elf
++    case `$FILECMD conftest.$ac_objext` in
++      *32-bit*)
++	emul="${emul}32"
++	;;
++      *64-bit*)
++	emul="${emul}64"
++	;;
++    esac
++    case `$FILECMD conftest.$ac_objext` in
++      *MSB*)
++	emul="${emul}btsmip"
++	;;
++      *LSB*)
++	emul="${emul}ltsmip"
++	;;
++    esac
++    case `$FILECMD conftest.$ac_objext` in
++      *N32*)
++	emul="${emul}n32"
++	;;
++    esac
++    LD="${LD-ld} -m $emul"
++  fi
++  rm -rf conftest*
++  ;;
++
++x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
++s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.  Note that the listed cases only cover the
++  # situations where additional linker options are needed (such as when
++  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
++  # vice versa); the common cases where no linker options are needed do
++  # not appear in the list.
++  echo 'int i;' > conftest.$ac_ext
++  if AC_TRY_EVAL(ac_compile); then
++    case `$FILECMD conftest.o` in
++      *32-bit*)
++	case $host in
++	  x86_64-*kfreebsd*-gnu)
++	    LD="${LD-ld} -m elf_i386_fbsd"
++	    ;;
++	  x86_64-*linux*)
++	    case `$FILECMD conftest.o` in
++	      *x86-64*)
++		LD="${LD-ld} -m elf32_x86_64"
++		;;
++	      *)
++		LD="${LD-ld} -m elf_i386"
++		;;
++	    esac
++	    ;;
++	  powerpc64le-*linux*)
++	    LD="${LD-ld} -m elf32lppclinux"
++	    ;;
++	  powerpc64-*linux*)
++	    LD="${LD-ld} -m elf32ppclinux"
++	    ;;
++	  s390x-*linux*)
++	    LD="${LD-ld} -m elf_s390"
++	    ;;
++	  sparc64-*linux*)
++	    LD="${LD-ld} -m elf32_sparc"
++	    ;;
++	esac
++	;;
++      *64-bit*)
++	case $host in
++	  x86_64-*kfreebsd*-gnu)
++	    LD="${LD-ld} -m elf_x86_64_fbsd"
++	    ;;
++	  x86_64-*linux*)
++	    LD="${LD-ld} -m elf_x86_64"
++	    ;;
++	  powerpcle-*linux*)
++	    LD="${LD-ld} -m elf64lppc"
++	    ;;
++	  powerpc-*linux*)
++	    LD="${LD-ld} -m elf64ppc"
++	    ;;
++	  s390*-*linux*|s390*-*tpf*)
++	    LD="${LD-ld} -m elf64_s390"
++	    ;;
++	  sparc*-*linux*)
++	    LD="${LD-ld} -m elf64_sparc"
++	    ;;
++	esac
++	;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++
++*-*-sco3.2v5*)
++  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
++  SAVE_CFLAGS=$CFLAGS
++  CFLAGS="$CFLAGS -belf"
++  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
++    [AC_LANG_PUSH(C)
++     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
++     AC_LANG_POP])
++  if test yes != "$lt_cv_cc_needs_belf"; then
++    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
++    CFLAGS=$SAVE_CFLAGS
++  fi
++  ;;
++*-*solaris*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.
++  echo 'int i;' > conftest.$ac_ext
++  if AC_TRY_EVAL(ac_compile); then
++    case `$FILECMD conftest.o` in
++    *64-bit*)
++      case $lt_cv_prog_gnu_ld in
++      yes*)
++        case $host in
++        i?86-*-solaris*|x86_64-*-solaris*)
++          LD="${LD-ld} -m elf_x86_64"
++          ;;
++        sparc*-*-solaris*)
++          LD="${LD-ld} -m elf64_sparc"
++          ;;
++        esac
++        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
++        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
++          LD=${LD-ld}_sol2
++        fi
++        ;;
++      *)
++	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
++	  LD="${LD-ld} -64"
++	fi
++	;;
++      esac
++      ;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++esac
++
++need_locks=$enable_libtool_lock
++])# _LT_ENABLE_LOCK
++
++
++# _LT_PROG_AR
++# -----------
++m4_defun([_LT_PROG_AR],
++[AC_CHECK_TOOLS(AR, [ar], false)
++: ${AR=ar}
++_LT_DECL([], [AR], [1], [The archiver])
++
++# Use ARFLAGS variable as AR's operation code to sync the variable naming with
++# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
++# higher priority because thats what people were doing historically (setting
++# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
++# variable obsoleted/removed.
++
++test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
++lt_ar_flags=$AR_FLAGS
++_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
++
++# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
++# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
++_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
++         [Flags to create an archive])
++
++AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
++  [lt_cv_ar_at_file=no
++   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
++     [echo conftest.$ac_objext > conftest.lst
++      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
++      AC_TRY_EVAL([lt_ar_try])
++      if test 0 -eq "$ac_status"; then
++	# Ensure the archiver fails upon bogus file names.
++	rm -f conftest.$ac_objext libconftest.a
++	AC_TRY_EVAL([lt_ar_try])
++	if test 0 -ne "$ac_status"; then
++          lt_cv_ar_at_file=@
++        fi
++      fi
++      rm -f conftest.* libconftest.a
++     ])
++  ])
++
++if test no = "$lt_cv_ar_at_file"; then
++  archiver_list_spec=
++else
++  archiver_list_spec=$lt_cv_ar_at_file
++fi
++_LT_DECL([], [archiver_list_spec], [1],
++  [How to feed a file listing to the archiver])
++])# _LT_PROG_AR
++
++
++# _LT_CMD_OLD_ARCHIVE
++# -------------------
++m4_defun([_LT_CMD_OLD_ARCHIVE],
++[_LT_PROG_AR
++
++AC_CHECK_TOOL(STRIP, strip, :)
++test -z "$STRIP" && STRIP=:
++_LT_DECL([], [STRIP], [1], [A symbol stripping program])
++
++AC_CHECK_TOOL(RANLIB, ranlib, :)
++test -z "$RANLIB" && RANLIB=:
++_LT_DECL([], [RANLIB], [1],
++    [Commands used to install an old-style archive])
++
++# Determine commands to create old-style static archives.
++old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
++old_postinstall_cmds='chmod 644 $oldlib'
++old_postuninstall_cmds=
++
++if test -n "$RANLIB"; then
++  case $host_os in
++  bitrig* | openbsd*)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
++    ;;
++  *)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
++    ;;
++  esac
++  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
++fi
++
++case $host_os in
++  darwin*)
++    lock_old_archive_extraction=yes ;;
++  *)
++    lock_old_archive_extraction=no ;;
++esac
++_LT_DECL([], [old_postinstall_cmds], [2])
++_LT_DECL([], [old_postuninstall_cmds], [2])
++_LT_TAGDECL([], [old_archive_cmds], [2],
++    [Commands used to build an old-style archive])
++_LT_DECL([], [lock_old_archive_extraction], [0],
++    [Whether to use a lock for old archive extraction])
++])# _LT_CMD_OLD_ARCHIVE
++
++
++# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
++#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
++# ----------------------------------------------------------------
++# Check whether the given compiler option works
++AC_DEFUN([_LT_COMPILER_OPTION],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_SED])dnl
++AC_CACHE_CHECK([$1], [$2],
++  [$2=no
++   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++   lt_compiler_flag="$3"  ## exclude from sc_useless_quotes_in_assignment
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   # The option is referenced via a variable to avoid confusing sed.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
++   (eval "$lt_compile" 2>conftest.err)
++   ac_status=$?
++   cat conftest.err >&AS_MESSAGE_LOG_FD
++   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++   if (exit $ac_status) && test -s "$ac_outfile"; then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings other than the usual output.
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
++     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
++       $2=yes
++     fi
++   fi
++   $RM conftest*
++])
++
++if test yes = "[$]$2"; then
++    m4_if([$5], , :, [$5])
++else
++    m4_if([$6], , :, [$6])
++fi
++])# _LT_COMPILER_OPTION
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
++
++
++# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
++#                  [ACTION-SUCCESS], [ACTION-FAILURE])
++# ----------------------------------------------------
++# Check whether the given linker option works
++AC_DEFUN([_LT_LINKER_OPTION],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_SED])dnl
++AC_CACHE_CHECK([$1], [$2],
++  [$2=no
++   save_LDFLAGS=$LDFLAGS
++   LDFLAGS="$LDFLAGS $3"
++   echo "$lt_simple_link_test_code" > conftest.$ac_ext
++   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
++     # The linker can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     if test -s conftest.err; then
++       # Append any errors to the config.log.
++       cat conftest.err 1>&AS_MESSAGE_LOG_FD
++       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
++       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++       if diff conftest.exp conftest.er2 >/dev/null; then
++         $2=yes
++       fi
++     else
++       $2=yes
++     fi
++   fi
++   $RM -r conftest*
++   LDFLAGS=$save_LDFLAGS
++])
++
++if test yes = "[$]$2"; then
++    m4_if([$4], , :, [$4])
++else
++    m4_if([$5], , :, [$5])
++fi
++])# _LT_LINKER_OPTION
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
++
++
++# LT_CMD_MAX_LEN
++#---------------
++AC_DEFUN([LT_CMD_MAX_LEN],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++# find the maximum length of command line arguments
++AC_MSG_CHECKING([the maximum length of command line arguments])
++AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
++  i=0
++  teststring=ABCD
++
++  case $build_os in
++  msdosdjgpp*)
++    # On DJGPP, this test can blow up pretty badly due to problems in libc
++    # (any single argument exceeding 2000 bytes causes a buffer overrun
++    # during glob expansion).  Even if it were fixed, the result of this
++    # check would be larger than it should be.
++    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
++    ;;
++
++  gnu*)
++    # Under GNU Hurd, this test is not required because there is
++    # no limit to the length of command line arguments.
++    # Libtool will interpret -1 as no limit whatsoever
++    lt_cv_sys_max_cmd_len=-1;
++    ;;
++
++  cygwin* | mingw* | cegcc*)
++    # On Win9x/ME, this test blows up -- it succeeds, but takes
++    # about 5 minutes as the teststring grows exponentially.
++    # Worse, since 9x/ME are not pre-emptively multitasking,
++    # you end up with a "frozen" computer, even though with patience
++    # the test eventually succeeds (with a max line length of 256k).
++    # Instead, let's just punt: use the minimum linelength reported by
++    # all of the supported platforms: 8192 (on NT/2K/XP).
++    lt_cv_sys_max_cmd_len=8192;
++    ;;
++
++  mint*)
++    # On MiNT this can take a long time and run out of memory.
++    lt_cv_sys_max_cmd_len=8192;
++    ;;
++
++  amigaos*)
++    # On AmigaOS with pdksh, this test takes hours, literally.
++    # So we just punt and use a minimum line length of 8192.
++    lt_cv_sys_max_cmd_len=8192;
++    ;;
++
++  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
++    # This has been around since 386BSD, at least.  Likely further.
++    if test -x /sbin/sysctl; then
++      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
++    elif test -x /usr/sbin/sysctl; then
++      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
++    else
++      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
++    fi
++    # And add a safety zone
++    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
++    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
++    ;;
++
++  interix*)
++    # We know the value 262144 and hardcode it with a safety zone (like BSD)
++    lt_cv_sys_max_cmd_len=196608
++    ;;
++
++  os2*)
++    # The test takes a long time on OS/2.
++    lt_cv_sys_max_cmd_len=8192
++    ;;
++
++  osf*)
++    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
++    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
++    # nice to cause kernel panics so lets avoid the loop below.
++    # First set a reasonable default.
++    lt_cv_sys_max_cmd_len=16384
++    #
++    if test -x /sbin/sysconfig; then
++      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
++        *1*) lt_cv_sys_max_cmd_len=-1 ;;
++      esac
++    fi
++    ;;
++  sco3.2v5*)
++    lt_cv_sys_max_cmd_len=102400
++    ;;
++  sysv5* | sco5v6* | sysv4.2uw2*)
++    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
++    if test -n "$kargmax"; then
++      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[	 ]]//'`
++    else
++      lt_cv_sys_max_cmd_len=32768
++    fi
++    ;;
++  *)
++    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
++    if test -n "$lt_cv_sys_max_cmd_len" && \
++       test undefined != "$lt_cv_sys_max_cmd_len"; then
++      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
++      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
++    else
++      # Make teststring a little bigger before we do anything with it.
++      # a 1K string should be a reasonable start.
++      for i in 1 2 3 4 5 6 7 8; do
++        teststring=$teststring$teststring
++      done
++      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
++      # If test is not a shell built-in, we'll probably end up computing a
++      # maximum length that is only half of the actual maximum length, but
++      # we can't tell.
++      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
++	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
++	      test 17 != "$i" # 1/2 MB should be enough
++      do
++        i=`expr $i + 1`
++        teststring=$teststring$teststring
++      done
++      # Only check the string length outside the loop.
++      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
++      teststring=
++      # Add a significant safety factor because C++ compilers can tack on
++      # massive amounts of additional arguments before passing them to the
++      # linker.  It appears as though 1/2 is a usable value.
++      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
++    fi
++    ;;
++  esac
++])
++if test -n "$lt_cv_sys_max_cmd_len"; then
++  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
++else
++  AC_MSG_RESULT(none)
++fi
++max_cmd_len=$lt_cv_sys_max_cmd_len
++_LT_DECL([], [max_cmd_len], [0],
++    [What is the maximum length of a command?])
++])# LT_CMD_MAX_LEN
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
++
++
++# _LT_HEADER_DLFCN
++# ----------------
++m4_defun([_LT_HEADER_DLFCN],
++[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
++])# _LT_HEADER_DLFCN
++
++
++# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
++#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
++# ----------------------------------------------------------------
++m4_defun([_LT_TRY_DLOPEN_SELF],
++[m4_require([_LT_HEADER_DLFCN])dnl
++if test yes = "$cross_compiling"; then :
++  [$4]
++else
++  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
++  lt_status=$lt_dlunknown
++  cat > conftest.$ac_ext <<_LT_EOF
++[#line $LINENO "configure"
++#include "confdefs.h"
++
++#if HAVE_DLFCN_H
++#include 
++#endif
++
++#include 
++
++#ifdef RTLD_GLOBAL
++#  define LT_DLGLOBAL		RTLD_GLOBAL
++#else
++#  ifdef DL_GLOBAL
++#    define LT_DLGLOBAL		DL_GLOBAL
++#  else
++#    define LT_DLGLOBAL		0
++#  endif
++#endif
++
++/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
++   find out it does not work in some platform. */
++#ifndef LT_DLLAZY_OR_NOW
++#  ifdef RTLD_LAZY
++#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
++#  else
++#    ifdef DL_LAZY
++#      define LT_DLLAZY_OR_NOW		DL_LAZY
++#    else
++#      ifdef RTLD_NOW
++#        define LT_DLLAZY_OR_NOW	RTLD_NOW
++#      else
++#        ifdef DL_NOW
++#          define LT_DLLAZY_OR_NOW	DL_NOW
++#        else
++#          define LT_DLLAZY_OR_NOW	0
++#        endif
++#      endif
++#    endif
++#  endif
++#endif
++
++/* When -fvisibility=hidden is used, assume the code has been annotated
++   correspondingly for the symbols needed.  */
++#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
++int fnord () __attribute__((visibility("default")));
++#endif
++
++int fnord () { return 42; }
++int main ()
++{
++  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
++  int status = $lt_dlunknown;
++
++  if (self)
++    {
++      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
++      else
++        {
++	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
++          else puts (dlerror ());
++	}
++      /* dlclose (self); */
++    }
++  else
++    puts (dlerror ());
++
++  return status;
++}]
++_LT_EOF
++  if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
++    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
++    lt_status=$?
++    case x$lt_status in
++      x$lt_dlno_uscore) $1 ;;
++      x$lt_dlneed_uscore) $2 ;;
++      x$lt_dlunknown|x*) $3 ;;
++    esac
++  else :
++    # compilation failed
++    $3
++  fi
++fi
++rm -fr conftest*
++])# _LT_TRY_DLOPEN_SELF
++
++
++# LT_SYS_DLOPEN_SELF
++# ------------------
++AC_DEFUN([LT_SYS_DLOPEN_SELF],
++[m4_require([_LT_HEADER_DLFCN])dnl
++if test yes != "$enable_dlopen"; then
++  enable_dlopen=unknown
++  enable_dlopen_self=unknown
++  enable_dlopen_self_static=unknown
++else
++  lt_cv_dlopen=no
++  lt_cv_dlopen_libs=
++
++  case $host_os in
++  beos*)
++    lt_cv_dlopen=load_add_on
++    lt_cv_dlopen_libs=
++    lt_cv_dlopen_self=yes
++    ;;
++
++  mingw* | pw32* | cegcc*)
++    lt_cv_dlopen=LoadLibrary
++    lt_cv_dlopen_libs=
++    ;;
++
++  cygwin*)
++    lt_cv_dlopen=dlopen
++    lt_cv_dlopen_libs=
++    ;;
++
++  darwin*)
++    # if libdl is installed we need to link against it
++    AC_CHECK_LIB([dl], [dlopen],
++		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
++    lt_cv_dlopen=dyld
++    lt_cv_dlopen_libs=
++    lt_cv_dlopen_self=yes
++    ])
++    ;;
++
++  tpf*)
++    # Don't try to run any link tests for TPF.  We know it's impossible
++    # because TPF is a cross-compiler, and we know how we open DSOs.
++    lt_cv_dlopen=dlopen
++    lt_cv_dlopen_libs=
++    lt_cv_dlopen_self=no
++    ;;
++
++  *)
++    AC_CHECK_FUNC([shl_load],
++	  [lt_cv_dlopen=shl_load],
++      [AC_CHECK_LIB([dld], [shl_load],
++	    [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
++	[AC_CHECK_FUNC([dlopen],
++	      [lt_cv_dlopen=dlopen],
++	  [AC_CHECK_LIB([dl], [dlopen],
++		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
++	    [AC_CHECK_LIB([svld], [dlopen],
++		  [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
++	      [AC_CHECK_LIB([dld], [dld_link],
++		    [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
++	      ])
++	    ])
++	  ])
++	])
++      ])
++    ;;
++  esac
++
++  if test no = "$lt_cv_dlopen"; then
++    enable_dlopen=no
++  else
++    enable_dlopen=yes
++  fi
++
++  case $lt_cv_dlopen in
++  dlopen)
++    save_CPPFLAGS=$CPPFLAGS
++    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
++
++    save_LDFLAGS=$LDFLAGS
++    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
++
++    save_LIBS=$LIBS
++    LIBS="$lt_cv_dlopen_libs $LIBS"
++
++    AC_CACHE_CHECK([whether a program can dlopen itself],
++	  lt_cv_dlopen_self, [dnl
++	  _LT_TRY_DLOPEN_SELF(
++	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
++	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
++    ])
++
++    if test yes = "$lt_cv_dlopen_self"; then
++      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
++      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
++	  lt_cv_dlopen_self_static, [dnl
++	  _LT_TRY_DLOPEN_SELF(
++	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
++	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
++      ])
++    fi
++
++    CPPFLAGS=$save_CPPFLAGS
++    LDFLAGS=$save_LDFLAGS
++    LIBS=$save_LIBS
++    ;;
++  esac
++
++  case $lt_cv_dlopen_self in
++  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
++  *) enable_dlopen_self=unknown ;;
++  esac
++
++  case $lt_cv_dlopen_self_static in
++  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
++  *) enable_dlopen_self_static=unknown ;;
++  esac
++fi
++_LT_DECL([dlopen_support], [enable_dlopen], [0],
++	 [Whether dlopen is supported])
++_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
++	 [Whether dlopen of programs is supported])
++_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
++	 [Whether dlopen of statically linked programs is supported])
++])# LT_SYS_DLOPEN_SELF
++
++# Old name:
++AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
++
++
++# _LT_COMPILER_C_O([TAGNAME])
++# ---------------------------
++# Check to see if options -c and -o are simultaneously supported by compiler.
++# This macro does not hard code the compiler like AC_PROG_CC_C_O.
++m4_defun([_LT_COMPILER_C_O],
++[m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_TAG_COMPILER])dnl
++AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
++  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
++  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
++   $RM -r conftest 2>/dev/null
++   mkdir conftest
++   cd conftest
++   mkdir out
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++   lt_compiler_flag="-o out/conftest2.$ac_objext"
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
++   (eval "$lt_compile" 2>out/conftest.err)
++   ac_status=$?
++   cat out/conftest.err >&AS_MESSAGE_LOG_FD
++   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++   if (exit $ac_status) && test -s out/conftest2.$ac_objext
++   then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
++     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
++     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
++       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
++     fi
++   fi
++   chmod u+w . 2>&AS_MESSAGE_LOG_FD
++   $RM conftest*
++   # SGI C++ compiler will create directory out/ii_files/ for
++   # template instantiation
++   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
++   $RM out/* && rmdir out
++   cd ..
++   $RM -r conftest
++   $RM conftest*
++])
++_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
++	[Does compiler simultaneously support -c and -o options?])
++])# _LT_COMPILER_C_O
++
++
++# _LT_COMPILER_FILE_LOCKS([TAGNAME])
++# ----------------------------------
++# Check to see if we can do hard links to lock some files if needed
++m4_defun([_LT_COMPILER_FILE_LOCKS],
++[m4_require([_LT_ENABLE_LOCK])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++_LT_COMPILER_C_O([$1])
++
++hard_links=nottested
++if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
++  # do not overwrite the value of need_locks provided by the user
++  AC_MSG_CHECKING([if we can lock with hard links])
++  hard_links=yes
++  $RM conftest*
++  ln conftest.a conftest.b 2>/dev/null && hard_links=no
++  touch conftest.a
++  ln conftest.a conftest.b 2>&5 || hard_links=no
++  ln conftest.a conftest.b 2>/dev/null && hard_links=no
++  AC_MSG_RESULT([$hard_links])
++  if test no = "$hard_links"; then
++    AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
++    need_locks=warn
++  fi
++else
++  need_locks=no
++fi
++_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
++])# _LT_COMPILER_FILE_LOCKS
++
++
++# _LT_CHECK_OBJDIR
++# ----------------
++m4_defun([_LT_CHECK_OBJDIR],
++[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
++[rm -f .libs 2>/dev/null
++mkdir .libs 2>/dev/null
++if test -d .libs; then
++  lt_cv_objdir=.libs
++else
++  # MS-DOS does not allow filenames that begin with a dot.
++  lt_cv_objdir=_libs
++fi
++rmdir .libs 2>/dev/null])
++objdir=$lt_cv_objdir
++_LT_DECL([], [objdir], [0],
++         [The name of the directory that contains temporary libtool files])dnl
++m4_pattern_allow([LT_OBJDIR])dnl
++AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
++  [Define to the sub-directory where libtool stores uninstalled libraries.])
++])# _LT_CHECK_OBJDIR
++
++
++# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
++# --------------------------------------
++# Check hardcoding attributes.
++m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
++[AC_MSG_CHECKING([how to hardcode library paths into programs])
++_LT_TAGVAR(hardcode_action, $1)=
++if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
++   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
++   test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
++
++  # We can hardcode non-existent directories.
++  if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
++     # If the only mechanism to avoid hardcoding is shlibpath_var, we
++     # have to relink, otherwise we might link with an installed library
++     # when we should be linking with a yet-to-be-installed one
++     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
++     test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
++    # Linking always hardcodes the temporary library directory.
++    _LT_TAGVAR(hardcode_action, $1)=relink
++  else
++    # We can link without hardcoding, and we can hardcode nonexisting dirs.
++    _LT_TAGVAR(hardcode_action, $1)=immediate
++  fi
++else
++  # We cannot hardcode anything, or else we can only hardcode existing
++  # directories.
++  _LT_TAGVAR(hardcode_action, $1)=unsupported
++fi
++AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
++
++if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
++   test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
++  # Fast installation is not supported
++  enable_fast_install=no
++elif test yes = "$shlibpath_overrides_runpath" ||
++     test no = "$enable_shared"; then
++  # Fast installation is not necessary
++  enable_fast_install=needless
++fi
++_LT_TAGDECL([], [hardcode_action], [0],
++    [How to hardcode a shared library path into an executable])
++])# _LT_LINKER_HARDCODE_LIBPATH
++
++
++# _LT_CMD_STRIPLIB
++# ----------------
++m4_defun([_LT_CMD_STRIPLIB],
++[m4_require([_LT_DECL_EGREP])
++striplib=
++old_striplib=
++AC_MSG_CHECKING([whether stripping libraries is possible])
++if test -z "$STRIP"; then
++  AC_MSG_RESULT([no])
++else
++  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
++    old_striplib="$STRIP --strip-debug"
++    striplib="$STRIP --strip-unneeded"
++    AC_MSG_RESULT([yes])
++  else
++    case $host_os in
++    darwin*)
++      # FIXME - insert some real tests, host_os isn't really good enough
++      striplib="$STRIP -x"
++      old_striplib="$STRIP -S"
++      AC_MSG_RESULT([yes])
++      ;;
++    freebsd*)
++      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
++        old_striplib="$STRIP --strip-debug"
++        striplib="$STRIP --strip-unneeded"
++        AC_MSG_RESULT([yes])
++      else
++        AC_MSG_RESULT([no])
++      fi
++      ;;
++    *)
++      AC_MSG_RESULT([no])
++      ;;
++    esac
++  fi
++fi
++_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
++_LT_DECL([], [striplib], [1])
++])# _LT_CMD_STRIPLIB
++
++
++# _LT_PREPARE_MUNGE_PATH_LIST
++# ---------------------------
++# Make sure func_munge_path_list() is defined correctly.
++m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
++[[# func_munge_path_list VARIABLE PATH
++# -----------------------------------
++# VARIABLE is name of variable containing _space_ separated list of
++# directories to be munged by the contents of PATH, which is string
++# having a format:
++# "DIR[:DIR]:"
++#       string "DIR[ DIR]" will be prepended to VARIABLE
++# ":DIR[:DIR]"
++#       string "DIR[ DIR]" will be appended to VARIABLE
++# "DIRP[:DIRP]::[DIRA:]DIRA"
++#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
++#       "DIRA[ DIRA]" will be appended to VARIABLE
++# "DIR[:DIR]"
++#       VARIABLE will be replaced by "DIR[ DIR]"
++func_munge_path_list ()
++{
++    case x@S|@2 in
++    x)
++        ;;
++    *:)
++        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
++        ;;
++    x:*)
++        eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
++        ;;
++    *::*)
++        eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
++        eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
++        ;;
++    *)
++        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
++        ;;
++    esac
++}
++]])# _LT_PREPARE_PATH_LIST
++
++
++# _LT_SYS_DYNAMIC_LINKER([TAG])
++# -----------------------------
++# PORTME Fill in your ld.so characteristics
++m4_defun([_LT_SYS_DYNAMIC_LINKER],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_OBJDUMP])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_CHECK_SHELL_FEATURES])dnl
++m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
++AC_MSG_CHECKING([dynamic linker characteristics])
++m4_if([$1],
++	[], [
++if test yes = "$GCC"; then
++  case $host_os in
++    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
++    *) lt_awk_arg='/^libraries:/' ;;
++  esac
++  case $host_os in
++    mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
++    *) lt_sed_strip_eq='s|=/|/|g' ;;
++  esac
++  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
++  case $lt_search_path_spec in
++  *\;*)
++    # if the path contains ";" then we assume it to be the separator
++    # otherwise default to the standard path separator (i.e. ":") - it is
++    # assumed that no part of a normal pathname contains ";" but that should
++    # okay in the real world where ";" in dirpaths is itself problematic.
++    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
++    ;;
++  *)
++    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
++    ;;
++  esac
++  # Ok, now we have the path, separated by spaces, we can step through it
++  # and add multilib dir if necessary...
++  lt_tmp_lt_search_path_spec=
++  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
++  # ...but if some path component already ends with the multilib dir we assume
++  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
++  case "$lt_multi_os_dir; $lt_search_path_spec " in
++  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
++    lt_multi_os_dir=
++    ;;
++  esac
++  for lt_sys_path in $lt_search_path_spec; do
++    if test -d "$lt_sys_path$lt_multi_os_dir"; then
++      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
++    elif test -n "$lt_multi_os_dir"; then
++      test -d "$lt_sys_path" && \
++	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
++    fi
++  done
++  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
++BEGIN {RS = " "; FS = "/|\n";} {
++  lt_foo = "";
++  lt_count = 0;
++  for (lt_i = NF; lt_i > 0; lt_i--) {
++    if ($lt_i != "" && $lt_i != ".") {
++      if ($lt_i == "..") {
++        lt_count++;
++      } else {
++        if (lt_count == 0) {
++          lt_foo = "/" $lt_i lt_foo;
++        } else {
++          lt_count--;
++        }
++      }
++    }
++  }
++  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
++  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
++}'`
++  # AWK program above erroneously prepends '/' to C:/dos/paths
++  # for these hosts.
++  case $host_os in
++    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
++      $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
++  esac
++  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
++else
++  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++fi])
++library_names_spec=
++libname_spec='lib$name'
++soname_spec=
++shrext_cmds=.so
++postinstall_cmds=
++postuninstall_cmds=
++finish_cmds=
++finish_eval=
++shlibpath_var=
++shlibpath_overrides_runpath=unknown
++version_type=none
++dynamic_linker="$host_os ld.so"
++sys_lib_dlsearch_path_spec="/lib /usr/lib"
++need_lib_prefix=unknown
++hardcode_into_libs=no
++
++# when you set need_version to no, make sure it does not cause -set_version
++# flags to be left without arguments
++need_version=unknown
++
++AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
++[User-defined run-time library search path.])
++
++case $host_os in
++aix3*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
++  shlibpath_var=LIBPATH
++
++  # AIX 3 has no versioning support, so we append a major version to the name.
++  soname_spec='$libname$release$shared_ext$major'
++  ;;
++
++aix[[4-9]]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  hardcode_into_libs=yes
++  if test ia64 = "$host_cpu"; then
++    # AIX 5 supports IA64
++    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
++    shlibpath_var=LD_LIBRARY_PATH
++  else
++    # With GCC up to 2.95.x, collect2 would create an import file
++    # for dependence libraries.  The import file would start with
++    # the line '#! .'.  This would cause the generated library to
++    # depend on '.', always an invalid library.  This was fixed in
++    # development snapshots of GCC prior to 3.0.
++    case $host_os in
++      aix4 | aix4.[[01]] | aix4.[[01]].*)
++      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++	   echo ' yes '
++	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
++	:
++      else
++	can_build_shared=no
++      fi
++      ;;
++    esac
++    # Using Import Files as archive members, it is possible to support
++    # filename-based versioning of shared library archives on AIX. While
++    # this would work for both with and without runtime linking, it will
++    # prevent static linking of such archives. So we do filename-based
++    # shared library versioning with .so extension only, which is used
++    # when both runtime linking and shared linking is enabled.
++    # Unfortunately, runtime linking may impact performance, so we do
++    # not want this to be the default eventually. Also, we use the
++    # versioned .so libs for executables only if there is the -brtl
++    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
++    # To allow for filename-based versioning support, we need to create
++    # libNAME.so.V as an archive file, containing:
++    # *) an Import File, referring to the versioned filename of the
++    #    archive as well as the shared archive member, telling the
++    #    bitwidth (32 or 64) of that shared object, and providing the
++    #    list of exported symbols of that shared object, eventually
++    #    decorated with the 'weak' keyword
++    # *) the shared object with the F_LOADONLY flag set, to really avoid
++    #    it being seen by the linker.
++    # At run time we better use the real file rather than another symlink,
++    # but for link time we create the symlink libNAME.so -> libNAME.so.V
++
++    case $with_aix_soname,$aix_use_runtimelinking in
++    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
++    # soname into executable. Probably we can add versioning support to
++    # collect2, so additional links can be useful in future.
++    aix,yes) # traditional libtool
++      dynamic_linker='AIX unversionable lib.so'
++      # If using run time linking (on AIX 4.2 or later) use lib.so
++      # instead of lib.a to let people know that these are not
++      # typical AIX shared libraries.
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++      ;;
++    aix,no) # traditional AIX only
++      dynamic_linker='AIX lib.a[(]lib.so.V[)]'
++      # We preserve .a as extension for shared libraries through AIX4.2
++      # and later when we are not doing run time linking.
++      library_names_spec='$libname$release.a $libname.a'
++      soname_spec='$libname$release$shared_ext$major'
++      ;;
++    svr4,*) # full svr4 only
++      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
++      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++      # We do not specify a path in Import Files, so LIBPATH fires.
++      shlibpath_overrides_runpath=yes
++      ;;
++    *,yes) # both, prefer svr4
++      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
++      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++      # unpreferred sharedlib libNAME.a needs extra handling
++      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
++      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
++      # We do not specify a path in Import Files, so LIBPATH fires.
++      shlibpath_overrides_runpath=yes
++      ;;
++    *,no) # both, prefer aix
++      dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
++      library_names_spec='$libname$release.a $libname.a'
++      soname_spec='$libname$release$shared_ext$major'
++      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
++      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
++      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
++      ;;
++    esac
++    shlibpath_var=LIBPATH
++  fi
++  ;;
++
++amigaos*)
++  case $host_cpu in
++  powerpc)
++    # Since July 2007 AmigaOS4 officially supports .so libraries.
++    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    ;;
++  m68k)
++    library_names_spec='$libname.ixlibrary $libname.a'
++    # Create ${libname}_ixlibrary.a entries in /sys/libs.
++    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++    ;;
++  esac
++  ;;
++
++beos*)
++  library_names_spec='$libname$shared_ext'
++  dynamic_linker="$host_os ld.so"
++  shlibpath_var=LIBRARY_PATH
++  ;;
++
++bsdi[[45]]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
++  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
++  # the default ld.so.conf also contains /usr/contrib/lib and
++  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
++  # libtool to hard-code these into programs
++  ;;
++
++cygwin* | mingw* | pw32* | cegcc*)
++  version_type=windows
++  shrext_cmds=.dll
++  need_version=no
++  need_lib_prefix=no
++
++  case $GCC,$cc_basename in
++  yes,*)
++    # gcc
++    library_names_spec='$libname.dll.a'
++    # DLL is installed to $(libdir)/../bin by postinstall_cmds
++    postinstall_cmds='base_file=`basename \$file`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++      dldir=$destdir/`dirname \$dlpath`~
++      test -d \$dldir || mkdir -p \$dldir~
++      $install_prog $dir/$dlname \$dldir/$dlname~
++      chmod a+x \$dldir/$dlname~
++      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++      fi'
++    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++      dlpath=$dir/\$dldll~
++       $RM \$dlpath'
++    shlibpath_overrides_runpath=yes
++
++    case $host_os in
++    cygwin*)
++      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
++      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++m4_if([$1], [],[
++      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
++      ;;
++    mingw* | cegcc*)
++      # MinGW DLLs use traditional 'lib' prefix
++      soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++      ;;
++    pw32*)
++      # pw32 DLLs use 'pw' prefix rather than 'lib'
++      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++      ;;
++    esac
++    dynamic_linker='Win32 ld.exe'
++    ;;
++
++  *,cl* | *,icl*)
++    # Native MSVC or ICC
++    libname_spec='$name'
++    soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
++    library_names_spec='$libname.dll.lib'
++
++    case $build_os in
++    mingw*)
++      sys_lib_search_path_spec=
++      lt_save_ifs=$IFS
++      IFS=';'
++      for lt_path in $LIB
++      do
++        IFS=$lt_save_ifs
++        # Let DOS variable expansion print the short 8.3 style file name.
++        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
++        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
++      done
++      IFS=$lt_save_ifs
++      # Convert to MSYS style.
++      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
++      ;;
++    cygwin*)
++      # Convert to unix form, then to dos form, then back to unix form
++      # but this time dos style (no spaces!) so that the unix form looks
++      # like /cygdrive/c/PROGRA~1:/cygdr...
++      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
++      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
++      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++      ;;
++    *)
++      sys_lib_search_path_spec=$LIB
++      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
++        # It is most probably a Windows format PATH.
++        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
++      else
++        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++      fi
++      # FIXME: find the short name or the path components, as spaces are
++      # common. (e.g. "Program Files" -> "PROGRA~1")
++      ;;
++    esac
++
++    # DLL is installed to $(libdir)/../bin by postinstall_cmds
++    postinstall_cmds='base_file=`basename \$file`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++      dldir=$destdir/`dirname \$dlpath`~
++      test -d \$dldir || mkdir -p \$dldir~
++      $install_prog $dir/$dlname \$dldir/$dlname'
++    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++      dlpath=$dir/\$dldll~
++       $RM \$dlpath'
++    shlibpath_overrides_runpath=yes
++    dynamic_linker='Win32 link.exe'
++    ;;
++
++  *)
++    # Assume MSVC and ICC wrapper
++    library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
++    dynamic_linker='Win32 ld.exe'
++    ;;
++  esac
++  # FIXME: first we should search . and the directory the executable is in
++  shlibpath_var=PATH
++  ;;
++
++darwin* | rhapsody*)
++  dynamic_linker="$host_os dyld"
++  version_type=darwin
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
++  soname_spec='$libname$release$major$shared_ext'
++  shlibpath_overrides_runpath=yes
++  shlibpath_var=DYLD_LIBRARY_PATH
++  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
++m4_if([$1], [],[
++  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
++  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
++  ;;
++
++dgux*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++  # DragonFly does not have aout.  When/if they implement a new
++  # versioning mechanism, adjust this.
++  if test -x /usr/bin/objformat; then
++    objformat=`/usr/bin/objformat`
++  else
++    case $host_os in
++    freebsd[[23]].*) objformat=aout ;;
++    *) objformat=elf ;;
++    esac
++  fi
++  version_type=freebsd-$objformat
++  case $version_type in
++    freebsd-elf*)
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++      soname_spec='$libname$release$shared_ext$major'
++      need_version=no
++      need_lib_prefix=no
++      ;;
++    freebsd-*)
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++      need_version=yes
++      ;;
++  esac
++  shlibpath_var=LD_LIBRARY_PATH
++  case $host_os in
++  freebsd2.*)
++    shlibpath_overrides_runpath=yes
++    ;;
++  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
++    shlibpath_overrides_runpath=yes
++    hardcode_into_libs=yes
++    ;;
++  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
++  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
++    shlibpath_overrides_runpath=no
++    hardcode_into_libs=yes
++    ;;
++  *) # from 4.6 on, and DragonFly
++    shlibpath_overrides_runpath=yes
++    hardcode_into_libs=yes
++    ;;
++  esac
++  ;;
++
++haiku*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  dynamic_linker="$host_os runtime_loader"
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
++  hardcode_into_libs=yes
++  ;;
++
++hpux9* | hpux10* | hpux11*)
++  # Give a soname corresponding to the major version so that dld.sl refuses to
++  # link against other versions.
++  version_type=sunos
++  need_lib_prefix=no
++  need_version=no
++  case $host_cpu in
++  ia64*)
++    shrext_cmds='.so'
++    hardcode_into_libs=yes
++    dynamic_linker="$host_os dld.so"
++    shlibpath_var=LD_LIBRARY_PATH
++    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    if test 32 = "$HPUX_IA64_MODE"; then
++      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
++    else
++      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
++    fi
++    ;;
++  hppa*64*)
++    shrext_cmds='.sl'
++    hardcode_into_libs=yes
++    dynamic_linker="$host_os dld.sl"
++    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
++    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++    ;;
++  *)
++    shrext_cmds='.sl'
++    dynamic_linker="$host_os dld.sl"
++    shlibpath_var=SHLIB_PATH
++    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    ;;
++  esac
++  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
++  postinstall_cmds='chmod 555 $lib'
++  # or fails outright, so override atomically:
++  install_override_mode=555
++  ;;
++
++interix[[3-9]]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  ;;
++
++irix5* | irix6* | nonstopux*)
++  case $host_os in
++    nonstopux*) version_type=nonstopux ;;
++    *)
++	if test yes = "$lt_cv_prog_gnu_ld"; then
++		version_type=linux # correct to gnu/linux during the next big refactor
++	else
++		version_type=irix
++	fi ;;
++  esac
++  need_lib_prefix=no
++  need_version=no
++  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
++  case $host_os in
++  irix5* | nonstopux*)
++    libsuff= shlibsuff=
++    ;;
++  *)
++    case $LD in # libtool.m4 will add one of these switches to LD
++    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
++      libsuff= shlibsuff= libmagic=32-bit;;
++    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
++      libsuff=32 shlibsuff=N32 libmagic=N32;;
++    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
++      libsuff=64 shlibsuff=64 libmagic=64-bit;;
++    *) libsuff= shlibsuff= libmagic=never-match;;
++    esac
++    ;;
++  esac
++  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
++  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
++  hardcode_into_libs=yes
++  ;;
++
++# No shared lib support for Linux oldld, aout, or coff.
++linux*oldld* | linux*aout* | linux*coff*)
++  dynamic_linker=no
++  ;;
++
++linux*android*)
++  version_type=none # Android doesn't support versioned libraries.
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext'
++  soname_spec='$libname$release$shared_ext'
++  finish_cmds=
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  hardcode_into_libs=yes
++
++  dynamic_linker='Android linker'
++  # Don't embed -rpath directories since the linker doesn't support them.
++  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++  ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++
++  # Some binutils ld are patched to set DT_RUNPATH
++  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
++    [lt_cv_shlibpath_overrides_runpath=no
++    save_LDFLAGS=$LDFLAGS
++    save_libdir=$libdir
++    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
++	 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
++    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
++      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
++	 [lt_cv_shlibpath_overrides_runpath=yes])])
++    LDFLAGS=$save_LDFLAGS
++    libdir=$save_libdir
++    ])
++  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
++
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  hardcode_into_libs=yes
++
++  # Add ABI-specific directories to the system library path.
++  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
++
++  # Ideally, we could use ldconfig to report *all* directores which are
++  # searched for libraries, however this is still not possible.  Aside from not
++  # being certain /sbin/ldconfig is available, command
++  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
++  # even though it is searched at run-time.  Try to do the best guess by
++  # appending ld.so.conf contents (and includes) to the search path.
++  if test -f /etc/ld.so.conf; then
++    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
++    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
++  fi
++
++  # We used to test for /lib/ld.so.1 and disable shared libraries on
++  # powerpc, because MkLinux only supported shared libraries with the
++  # GNU dynamic linker.  Since this was broken with cross compilers,
++  # most powerpc-linux boxes support dynamic linking these days and
++  # people can always --disable-shared, the test was removed, and we
++  # assume the GNU/Linux dynamic linker is in use.
++  dynamic_linker='GNU/Linux ld.so'
++  ;;
++
++netbsd*)
++  version_type=sunos
++  need_lib_prefix=no
++  need_version=no
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++    dynamic_linker='NetBSD (a.out) ld.so'
++  else
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    dynamic_linker='NetBSD ld.elf_so'
++  fi
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  ;;
++
++newsos6)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  ;;
++
++*nto* | *qnx*)
++  version_type=qnx
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  dynamic_linker='ldqnx.so'
++  ;;
++
++openbsd* | bitrig*)
++  version_type=sunos
++  sys_lib_dlsearch_path_spec=/usr/lib
++  need_lib_prefix=no
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++    need_version=no
++  else
++    need_version=yes
++  fi
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  ;;
++
++os2*)
++  libname_spec='$name'
++  version_type=windows
++  shrext_cmds=.dll
++  need_version=no
++  need_lib_prefix=no
++  # OS/2 can only load a DLL with a base name of 8 characters or less.
++  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
++    v=$($ECHO $release$versuffix | tr -d .-);
++    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
++    $ECHO $n$v`$shared_ext'
++  library_names_spec='${libname}_dll.$libext'
++  dynamic_linker='OS/2 ld.exe'
++  shlibpath_var=BEGINLIBPATH
++  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  postinstall_cmds='base_file=`basename \$file`~
++    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
++    dldir=$destdir/`dirname \$dlpath`~
++    test -d \$dldir || mkdir -p \$dldir~
++    $install_prog $dir/$dlname \$dldir/$dlname~
++    chmod a+x \$dldir/$dlname~
++    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++    fi'
++  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
++    dlpath=$dir/\$dldll~
++    $RM \$dlpath'
++  ;;
++
++osf3* | osf4* | osf5*)
++  version_type=osf
++  need_lib_prefix=no
++  need_version=no
++  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
++  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  ;;
++
++rdos*)
++  dynamic_linker=no
++  ;;
++
++solaris*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  # ldd complains unless libraries are executable
++  postinstall_cmds='chmod +x $lib'
++  ;;
++
++sunos4*)
++  version_type=sunos
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  if test yes = "$with_gnu_ld"; then
++    need_lib_prefix=no
++  fi
++  need_version=yes
++  ;;
++
++sysv4 | sysv4.3*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  case $host_vendor in
++    sni)
++      shlibpath_overrides_runpath=no
++      need_lib_prefix=no
++      runpath_var=LD_RUN_PATH
++      ;;
++    siemens)
++      need_lib_prefix=no
++      ;;
++    motorola)
++      need_lib_prefix=no
++      need_version=no
++      shlibpath_overrides_runpath=no
++      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
++      ;;
++  esac
++  ;;
++
++sysv4*MP*)
++  if test -d /usr/nec; then
++    version_type=linux # correct to gnu/linux during the next big refactor
++    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
++    soname_spec='$libname$shared_ext.$major'
++    shlibpath_var=LD_LIBRARY_PATH
++  fi
++  ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++  version_type=sco
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  if test yes = "$with_gnu_ld"; then
++    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
++  else
++    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
++    case $host_os in
++      sco3.2v5*)
++        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
++	;;
++    esac
++  fi
++  sys_lib_dlsearch_path_spec='/usr/lib'
++  ;;
++
++tpf*)
++  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  ;;
++
++uts4*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  ;;
++
++*)
++  dynamic_linker=no
++  ;;
++esac
++AC_MSG_RESULT([$dynamic_linker])
++test no = "$dynamic_linker" && can_build_shared=no
++
++variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
++if test yes = "$GCC"; then
++  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
++
++if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
++  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
++fi
++
++if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
++  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
++fi
++
++# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
++configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
++
++# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
++func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
++
++# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
++configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
++
++_LT_DECL([], [variables_saved_for_relink], [1],
++    [Variables whose values should be saved in libtool wrapper scripts and
++    restored at link time])
++_LT_DECL([], [need_lib_prefix], [0],
++    [Do we need the "lib" prefix for modules?])
++_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
++_LT_DECL([], [version_type], [0], [Library versioning type])
++_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
++_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
++_LT_DECL([], [shlibpath_overrides_runpath], [0],
++    [Is shlibpath searched before the hard-coded library search path?])
++_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
++_LT_DECL([], [library_names_spec], [1],
++    [[List of archive names.  First name is the real one, the rest are links.
++    The last name is the one that the linker finds with -lNAME]])
++_LT_DECL([], [soname_spec], [1],
++    [[The coded name of the library, if different from the real name]])
++_LT_DECL([], [install_override_mode], [1],
++    [Permission mode override for installation of shared libraries])
++_LT_DECL([], [postinstall_cmds], [2],
++    [Command to use after installation of a shared archive])
++_LT_DECL([], [postuninstall_cmds], [2],
++    [Command to use after uninstallation of a shared archive])
++_LT_DECL([], [finish_cmds], [2],
++    [Commands used to finish a libtool library installation in a directory])
++_LT_DECL([], [finish_eval], [1],
++    [[As "finish_cmds", except a single script fragment to be evaled but
++    not shown]])
++_LT_DECL([], [hardcode_into_libs], [0],
++    [Whether we should hardcode library paths into libraries])
++_LT_DECL([], [sys_lib_search_path_spec], [2],
++    [Compile-time system search path for libraries])
++_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
++    [Detected run-time system search path for libraries])
++_LT_DECL([], [configure_time_lt_sys_library_path], [2],
++    [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
++])# _LT_SYS_DYNAMIC_LINKER
++
++
++# _LT_PATH_TOOL_PREFIX(TOOL)
++# --------------------------
++# find a file program that can recognize shared library
++AC_DEFUN([_LT_PATH_TOOL_PREFIX],
++[m4_require([_LT_DECL_EGREP])dnl
++AC_MSG_CHECKING([for $1])
++AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
++[case $MAGIC_CMD in
++[[\\/*] |  ?:[\\/]*])
++  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
++  ;;
++*)
++  lt_save_MAGIC_CMD=$MAGIC_CMD
++  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++dnl $ac_dummy forces splitting on constant user-supplied paths.
++dnl POSIX.2 word splitting is done only on the output of word expansions,
++dnl not every word.  This closes a longstanding sh security hole.
++  ac_dummy="m4_if([$2], , $PATH, [$2])"
++  for ac_dir in $ac_dummy; do
++    IFS=$lt_save_ifs
++    test -z "$ac_dir" && ac_dir=.
++    if test -f "$ac_dir/$1"; then
++      lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
++      if test -n "$file_magic_test_file"; then
++	case $deplibs_check_method in
++	"file_magic "*)
++	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
++	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
++	    $EGREP "$file_magic_regex" > /dev/null; then
++	    :
++	  else
++	    cat <<_LT_EOF 1>&2
++
++*** Warning: the command libtool uses to detect shared libraries,
++*** $file_magic_cmd, produces output that libtool cannot recognize.
++*** The result is that libtool may fail to recognize shared libraries
++*** as such.  This will affect the creation of libtool libraries that
++*** depend on shared libraries, but programs linked with such libtool
++*** libraries will work regardless of this problem.  Nevertheless, you
++*** may want to report the problem to your system manager and/or to
++*** bug-libtool@gnu.org
++
++_LT_EOF
++	  fi ;;
++	esac
++      fi
++      break
++    fi
++  done
++  IFS=$lt_save_ifs
++  MAGIC_CMD=$lt_save_MAGIC_CMD
++  ;;
++esac])
++MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++if test -n "$MAGIC_CMD"; then
++  AC_MSG_RESULT($MAGIC_CMD)
++else
++  AC_MSG_RESULT(no)
++fi
++_LT_DECL([], [MAGIC_CMD], [0],
++	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
++])# _LT_PATH_TOOL_PREFIX
++
++# Old name:
++AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
++
++
++# _LT_PATH_MAGIC
++# --------------
++# find a file program that can recognize a shared library
++m4_defun([_LT_PATH_MAGIC],
++[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
++if test -z "$lt_cv_path_MAGIC_CMD"; then
++  if test -n "$ac_tool_prefix"; then
++    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
++  else
++    MAGIC_CMD=:
++  fi
++fi
++])# _LT_PATH_MAGIC
++
++
++# LT_PATH_LD
++# ----------
++# find the pathname to the GNU or non-GNU linker
++AC_DEFUN([LT_PATH_LD],
++[AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
++
++AC_ARG_WITH([gnu-ld],
++    [AS_HELP_STRING([--with-gnu-ld],
++	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
++    [test no = "$withval" || with_gnu_ld=yes],
++    [with_gnu_ld=no])dnl
++
++ac_prog=ld
++if test yes = "$GCC"; then
++  # Check if gcc -print-prog-name=ld gives a path.
++  AC_MSG_CHECKING([for ld used by $CC])
++  case $host in
++  *-*-mingw*)
++    # gcc leaves a trailing carriage return, which upsets mingw
++    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
++  *)
++    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
++  esac
++  case $ac_prog in
++    # Accept absolute paths.
++    [[\\/]]* | ?:[[\\/]]*)
++      re_direlt='/[[^/]][[^/]]*/\.\./'
++      # Canonicalize the pathname of ld
++      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
++      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
++	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
++      done
++      test -z "$LD" && LD=$ac_prog
++      ;;
++  "")
++    # If it fails, then pretend we aren't using GCC.
++    ac_prog=ld
++    ;;
++  *)
++    # If it is relative, then search for the first ld in PATH.
++    with_gnu_ld=unknown
++    ;;
++  esac
++elif test yes = "$with_gnu_ld"; then
++  AC_MSG_CHECKING([for GNU ld])
++else
++  AC_MSG_CHECKING([for non-GNU ld])
++fi
++AC_CACHE_VAL(lt_cv_path_LD,
++[if test -z "$LD"; then
++  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  for ac_dir in $PATH; do
++    IFS=$lt_save_ifs
++    test -z "$ac_dir" && ac_dir=.
++    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
++      lt_cv_path_LD=$ac_dir/$ac_prog
++      # Check to see if the program is GNU ld.  I'd rather use --version,
++      # but apparently some variants of GNU ld only accept -v.
++      # Break only if it was the GNU/non-GNU ld that we prefer.
++      case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i
++cat conftest.i conftest.i >conftest2.i
++: ${lt_DD:=$DD}
++AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
++[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
++  cmp -s conftest.i conftest.out \
++  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
++fi])
++rm -f conftest.i conftest2.i conftest.out])
++])# _LT_PATH_DD
++
++
++# _LT_CMD_TRUNCATE
++# ----------------
++# find command to truncate a binary pipe
++m4_defun([_LT_CMD_TRUNCATE],
++[m4_require([_LT_PATH_DD])
++AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
++[printf 0123456789abcdef0123456789abcdef >conftest.i
++cat conftest.i conftest.i >conftest2.i
++lt_cv_truncate_bin=
++if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
++  cmp -s conftest.i conftest.out \
++  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
++fi
++rm -f conftest.i conftest2.i conftest.out
++test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
++_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
++  [Command to truncate a binary pipe])
++])# _LT_CMD_TRUNCATE
++
++
++# _LT_CHECK_MAGIC_METHOD
++# ----------------------
++# how to check for library dependencies
++#  -- PORTME fill in with the dynamic library characteristics
++m4_defun([_LT_CHECK_MAGIC_METHOD],
++[m4_require([_LT_DECL_EGREP])
++m4_require([_LT_DECL_OBJDUMP])
++AC_CACHE_CHECK([how to recognize dependent libraries],
++lt_cv_deplibs_check_method,
++[lt_cv_file_magic_cmd='$MAGIC_CMD'
++lt_cv_file_magic_test_file=
++lt_cv_deplibs_check_method='unknown'
++# Need to set the preceding variable on all platforms that support
++# interlibrary dependencies.
++# 'none' -- dependencies not supported.
++# 'unknown' -- same as none, but documents that we really don't know.
++# 'pass_all' -- all dependencies passed with no checks.
++# 'test_compile' -- check by making test program.
++# 'file_magic [[regex]]' -- check by looking for files in library path
++# that responds to the $file_magic_cmd with a given extended regex.
++# If you have 'file' or equivalent on your system and you're not sure
++# whether 'pass_all' will *always* work, you probably want this one.
++
++case $host_os in
++aix[[4-9]]*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++beos*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++bsdi[[45]]*)
++  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
++  lt_cv_file_magic_cmd='$FILECMD -L'
++  lt_cv_file_magic_test_file=/shlib/libc.so
++  ;;
++
++cygwin*)
++  # func_win32_libid is a shell function defined in ltmain.sh
++  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++  lt_cv_file_magic_cmd='func_win32_libid'
++  ;;
++
++mingw* | pw32*)
++  # Base MSYS/MinGW do not provide the 'file' command needed by
++  # func_win32_libid shell function, so use a weaker test based on 'objdump',
++  # unless we find 'file', for example because we are cross-compiling.
++  if ( file / ) >/dev/null 2>&1; then
++    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++    lt_cv_file_magic_cmd='func_win32_libid'
++  else
++    # Keep this pattern in sync with the one in func_win32_libid.
++    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
++    lt_cv_file_magic_cmd='$OBJDUMP -f'
++  fi
++  ;;
++
++cegcc*)
++  # use the weaker test based on 'objdump'. See mingw*.
++  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
++  lt_cv_file_magic_cmd='$OBJDUMP -f'
++  ;;
++
++darwin* | rhapsody*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
++    case $host_cpu in
++    i*86 )
++      # Not sure whether the presence of OpenBSD here was a mistake.
++      # Let's accept both of them until this is cleared up.
++      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
++      lt_cv_file_magic_cmd=$FILECMD
++      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++      ;;
++    esac
++  else
++    lt_cv_deplibs_check_method=pass_all
++  fi
++  ;;
++
++haiku*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++hpux10.20* | hpux11*)
++  lt_cv_file_magic_cmd=$FILECMD
++  case $host_cpu in
++  ia64*)
++    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
++    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
++    ;;
++  hppa*64*)
++    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
++    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
++    ;;
++  *)
++    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
++    lt_cv_file_magic_test_file=/usr/lib/libc.sl
++    ;;
++  esac
++  ;;
++
++interix[[3-9]]*)
++  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
++  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
++  ;;
++
++irix5* | irix6* | nonstopux*)
++  case $LD in
++  *-32|*"-32 ") libmagic=32-bit;;
++  *-n32|*"-n32 ") libmagic=N32;;
++  *-64|*"-64 ") libmagic=64-bit;;
++  *) libmagic=never-match;;
++  esac
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++netbsd*)
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
++    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
++  else
++    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
++  fi
++  ;;
++
++newos6*)
++  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
++  lt_cv_file_magic_cmd=$FILECMD
++  lt_cv_file_magic_test_file=/usr/lib/libnls.so
++  ;;
++
++*nto* | *qnx*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++openbsd* | bitrig*)
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
++  else
++    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
++  fi
++  ;;
++
++osf3* | osf4* | osf5*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++rdos*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++solaris*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++sysv4 | sysv4.3*)
++  case $host_vendor in
++  motorola)
++    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
++    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
++    ;;
++  ncr)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  sequent)
++    lt_cv_file_magic_cmd='/bin/file'
++    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
++    ;;
++  sni)
++    lt_cv_file_magic_cmd='/bin/file'
++    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
++    lt_cv_file_magic_test_file=/lib/libc.so
++    ;;
++  siemens)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  pc)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  esac
++  ;;
++
++tpf*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++os2*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++esac
++])
++
++file_magic_glob=
++want_nocaseglob=no
++if test "$build" = "$host"; then
++  case $host_os in
++  mingw* | pw32*)
++    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
++      want_nocaseglob=yes
++    else
++      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
++    fi
++    ;;
++  esac
++fi
++
++file_magic_cmd=$lt_cv_file_magic_cmd
++deplibs_check_method=$lt_cv_deplibs_check_method
++test -z "$deplibs_check_method" && deplibs_check_method=unknown
++
++_LT_DECL([], [deplibs_check_method], [1],
++    [Method to check whether dependent libraries are shared objects])
++_LT_DECL([], [file_magic_cmd], [1],
++    [Command to use when deplibs_check_method = "file_magic"])
++_LT_DECL([], [file_magic_glob], [1],
++    [How to find potential files when deplibs_check_method = "file_magic"])
++_LT_DECL([], [want_nocaseglob], [1],
++    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
++])# _LT_CHECK_MAGIC_METHOD
++
++
++# LT_PATH_NM
++# ----------
++# find the pathname to a BSD- or MS-compatible name lister
++AC_DEFUN([LT_PATH_NM],
++[AC_REQUIRE([AC_PROG_CC])dnl
++AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
++[if test -n "$NM"; then
++  # Let the user override the test.
++  lt_cv_path_NM=$NM
++else
++  lt_nm_to_check=${ac_tool_prefix}nm
++  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
++    lt_nm_to_check="$lt_nm_to_check nm"
++  fi
++  for lt_tmp_nm in $lt_nm_to_check; do
++    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
++      IFS=$lt_save_ifs
++      test -z "$ac_dir" && ac_dir=.
++      tmp_nm=$ac_dir/$lt_tmp_nm
++      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
++	# Check to see if the nm accepts a BSD-compat flag.
++	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
++	#   nm: unknown option "B" ignored
++	# Tru64's nm complains that /dev/null is an invalid object file
++	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
++	case $build_os in
++	mingw*) lt_bad_file=conftest.nm/nofile ;;
++	*) lt_bad_file=/dev/null ;;
++	esac
++	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
++	*$lt_bad_file* | *'Invalid file or object type'*)
++	  lt_cv_path_NM="$tmp_nm -B"
++	  break 2
++	  ;;
++	*)
++	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
++	  */dev/null*)
++	    lt_cv_path_NM="$tmp_nm -p"
++	    break 2
++	    ;;
++	  *)
++	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
++	    continue # so that we can try to find one that supports BSD flags
++	    ;;
++	  esac
++	  ;;
++	esac
++      fi
++    done
++    IFS=$lt_save_ifs
++  done
++  : ${lt_cv_path_NM=no}
++fi])
++if test no != "$lt_cv_path_NM"; then
++  NM=$lt_cv_path_NM
++else
++  # Didn't find any BSD compatible name lister, look for dumpbin.
++  if test -n "$DUMPBIN"; then :
++    # Let the user override the test.
++  else
++    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
++    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
++    *COFF*)
++      DUMPBIN="$DUMPBIN -symbols -headers"
++      ;;
++    *)
++      DUMPBIN=:
++      ;;
++    esac
++  fi
++  AC_SUBST([DUMPBIN])
++  if test : != "$DUMPBIN"; then
++    NM=$DUMPBIN
++  fi
++fi
++test -z "$NM" && NM=nm
++AC_SUBST([NM])
++_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
++
++AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
++  [lt_cv_nm_interface="BSD nm"
++  echo "int some_variable = 0;" > conftest.$ac_ext
++  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
++  (eval "$ac_compile" 2>conftest.err)
++  cat conftest.err >&AS_MESSAGE_LOG_FD
++  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
++  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
++  cat conftest.err >&AS_MESSAGE_LOG_FD
++  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
++  cat conftest.out >&AS_MESSAGE_LOG_FD
++  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
++    lt_cv_nm_interface="MS dumpbin"
++  fi
++  rm -f conftest*])
++])# LT_PATH_NM
++
++# Old names:
++AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
++AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_PROG_NM], [])
++dnl AC_DEFUN([AC_PROG_NM], [])
++
++# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
++# --------------------------------
++# how to determine the name of the shared library
++# associated with a specific link library.
++#  -- PORTME fill in with the dynamic library characteristics
++m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
++[m4_require([_LT_DECL_EGREP])
++m4_require([_LT_DECL_OBJDUMP])
++m4_require([_LT_DECL_DLLTOOL])
++AC_CACHE_CHECK([how to associate runtime and link libraries],
++lt_cv_sharedlib_from_linklib_cmd,
++[lt_cv_sharedlib_from_linklib_cmd='unknown'
++
++case $host_os in
++cygwin* | mingw* | pw32* | cegcc*)
++  # two different shell functions defined in ltmain.sh;
++  # decide which one to use based on capabilities of $DLLTOOL
++  case `$DLLTOOL --help 2>&1` in
++  *--identify-strict*)
++    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
++    ;;
++  *)
++    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
++    ;;
++  esac
++  ;;
++*)
++  # fallback: assume linklib IS sharedlib
++  lt_cv_sharedlib_from_linklib_cmd=$ECHO
++  ;;
++esac
++])
++sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
++test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
++
++_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
++    [Command to associate shared and link libraries])
++])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
++
++
++# _LT_PATH_MANIFEST_TOOL
++# ----------------------
++# locate the manifest tool
++m4_defun([_LT_PATH_MANIFEST_TOOL],
++[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
++test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
++AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
++  [lt_cv_path_mainfest_tool=no
++  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
++  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
++  cat conftest.err >&AS_MESSAGE_LOG_FD
++  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
++    lt_cv_path_mainfest_tool=yes
++  fi
++  rm -f conftest*])
++if test yes != "$lt_cv_path_mainfest_tool"; then
++  MANIFEST_TOOL=:
++fi
++_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
++])# _LT_PATH_MANIFEST_TOOL
++
++
++# _LT_DLL_DEF_P([FILE])
++# ---------------------
++# True iff FILE is a Windows DLL '.def' file.
++# Keep in sync with func_dll_def_p in the libtool script
++AC_DEFUN([_LT_DLL_DEF_P],
++[dnl
++  test DEF = "`$SED -n dnl
++    -e '\''s/^[[	 ]]*//'\'' dnl Strip leading whitespace
++    -e '\''/^\(;.*\)*$/d'\'' dnl      Delete empty lines and comments
++    -e '\''s/^\(EXPORTS\|LIBRARY\)\([[	 ]].*\)*$/DEF/p'\'' dnl
++    -e q dnl                          Only consider the first "real" line
++    $1`" dnl
++])# _LT_DLL_DEF_P
++
++
++# LT_LIB_M
++# --------
++# check for math library
++AC_DEFUN([LT_LIB_M],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++LIBM=
++case $host in
++*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
++  # These system don't have libm, or don't need it
++  ;;
++*-ncr-sysv4.3*)
++  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
++  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
++  ;;
++*)
++  AC_CHECK_LIB(m, cos, LIBM=-lm)
++  ;;
++esac
++AC_SUBST([LIBM])
++])# LT_LIB_M
++
++# Old name:
++AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_CHECK_LIBM], [])
++
++
++# _LT_COMPILER_NO_RTTI([TAGNAME])
++# -------------------------------
++m4_defun([_LT_COMPILER_NO_RTTI],
++[m4_require([_LT_TAG_COMPILER])dnl
++
++_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
++
++if test yes = "$GCC"; then
++  case $cc_basename in
++  nvcc*)
++    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
++  *)
++    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
++  esac
++
++  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
++    lt_cv_prog_compiler_rtti_exceptions,
++    [-fno-rtti -fno-exceptions], [],
++    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
++fi
++_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
++	[Compiler flag to turn off builtin functions])
++])# _LT_COMPILER_NO_RTTI
++
++
++# _LT_CMD_GLOBAL_SYMBOLS
++# ----------------------
++m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_PROG_CC])dnl
++AC_REQUIRE([AC_PROG_AWK])dnl
++AC_REQUIRE([LT_PATH_NM])dnl
++AC_REQUIRE([LT_PATH_LD])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_TAG_COMPILER])dnl
++
++# Check for command to grab the raw symbol name followed by C symbol from nm.
++AC_MSG_CHECKING([command to parse $NM output from $compiler object])
++AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
++[
++# These are sane defaults that work on at least a few old systems.
++# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
++
++# Character class describing NM global symbol codes.
++symcode='[[BCDEGRST]]'
++
++# Regexp to match symbols that can be accessed directly from C.
++sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
++
++# Define system-specific variables.
++case $host_os in
++aix*)
++  symcode='[[BCDT]]'
++  ;;
++cygwin* | mingw* | pw32* | cegcc*)
++  symcode='[[ABCDGISTW]]'
++  ;;
++hpux*)
++  if test ia64 = "$host_cpu"; then
++    symcode='[[ABCDEGRST]]'
++  fi
++  ;;
++irix* | nonstopux*)
++  symcode='[[BCDEGRST]]'
++  ;;
++osf*)
++  symcode='[[BCDEGQRST]]'
++  ;;
++solaris*)
++  symcode='[[BDRT]]'
++  ;;
++sco3.2v5*)
++  symcode='[[DT]]'
++  ;;
++sysv4.2uw2*)
++  symcode='[[DT]]'
++  ;;
++sysv5* | sco5v6* | unixware* | OpenUNIX*)
++  symcode='[[ABDT]]'
++  ;;
++sysv4)
++  symcode='[[DFNSTU]]'
++  ;;
++esac
++
++# If we're using GNU nm, then use its standard symbol codes.
++case `$NM -V 2>&1` in
++*GNU* | *'with BFD'*)
++  symcode='[[ABCDGIRSTW]]' ;;
++esac
++
++if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++  # Gets list of data symbols to import.
++  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
++  # Adjust the below global symbol transforms to fixup imported variables.
++  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
++  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
++  lt_c_name_lib_hook="\
++  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
++  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
++else
++  # Disable hooks by default.
++  lt_cv_sys_global_symbol_to_import=
++  lt_cdecl_hook=
++  lt_c_name_hook=
++  lt_c_name_lib_hook=
++fi
++
++# Transform an extracted symbol line into a proper C declaration.
++# Some systems (esp. on ia64) link data and code symbols differently,
++# so use this general approach.
++lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
++$lt_cdecl_hook\
++" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
++
++# Transform an extracted symbol line into symbol name and symbol address
++lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
++$lt_c_name_hook\
++" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
++
++# Transform an extracted symbol line into symbol name with lib prefix and
++# symbol address.
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
++$lt_c_name_lib_hook\
++" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
++" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
++
++# Handle CRLF in mingw tool chain
++opt_cr=
++case $build_os in
++mingw*)
++  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
++  ;;
++esac
++
++# Try without a prefix underscore, then with it.
++for ac_symprfx in "" "_"; do
++
++  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
++  symxfrm="\\1 $ac_symprfx\\2 \\2"
++
++  # Write the raw and C identifiers.
++  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++    # Fake it for dumpbin and say T for any non-static function,
++    # D for any global variable and I for any imported variable.
++    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
++    # which start with @ or ?.
++    lt_cv_sys_global_symbol_pipe="$AWK ['"\
++"     {last_section=section; section=\$ 3};"\
++"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
++"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
++"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
++"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
++"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
++"     \$ 0!~/External *\|/{next};"\
++"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
++"     {if(hide[section]) next};"\
++"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
++"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
++"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
++"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
++"     ' prfx=^$ac_symprfx]"
++  else
++    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
++  fi
++  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
++
++  # Check to see that the pipe works correctly.
++  pipe_works=no
++
++  rm -f conftest*
++  cat > conftest.$ac_ext <<_LT_EOF
++#ifdef __cplusplus
++extern "C" {
++#endif
++char nm_test_var;
++void nm_test_func(void);
++void nm_test_func(void){}
++#ifdef __cplusplus
++}
++#endif
++int main(){nm_test_var='a';nm_test_func();return(0);}
++_LT_EOF
++
++  if AC_TRY_EVAL(ac_compile); then
++    # Now try to grab the symbols.
++    nlist=conftest.nm
++    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
++      # Try sorting and uniquifying the output.
++      if sort "$nlist" | uniq > "$nlist"T; then
++	mv -f "$nlist"T "$nlist"
++      else
++	rm -f "$nlist"T
++      fi
++
++      # Make sure that we snagged all the symbols we need.
++      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
++	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
++	  cat <<_LT_EOF > conftest.$ac_ext
++/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
++#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
++/* DATA imports from DLLs on WIN32 can't be const, because runtime
++   relocations are performed -- see ld's documentation on pseudo-relocs.  */
++# define LT@&t@_DLSYM_CONST
++#elif defined __osf__
++/* This system does not cope well with relocations in const data.  */
++# define LT@&t@_DLSYM_CONST
++#else
++# define LT@&t@_DLSYM_CONST const
++#endif
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++_LT_EOF
++	  # Now generate the symbol file.
++	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
++
++	  cat <<_LT_EOF >> conftest.$ac_ext
++
++/* The mapping between symbol names and symbols.  */
++LT@&t@_DLSYM_CONST struct {
++  const char *name;
++  void       *address;
++}
++lt__PROGRAM__LTX_preloaded_symbols[[]] =
++{
++  { "@PROGRAM@", (void *) 0 },
++_LT_EOF
++	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
++	  cat <<\_LT_EOF >> conftest.$ac_ext
++  {0, (void *) 0}
++};
++
++/* This works around a problem in FreeBSD linker */
++#ifdef FREEBSD_WORKAROUND
++static const void *lt_preloaded_setup() {
++  return lt__PROGRAM__LTX_preloaded_symbols;
++}
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++_LT_EOF
++	  # Now try linking the two files.
++	  mv conftest.$ac_objext conftstm.$ac_objext
++	  lt_globsym_save_LIBS=$LIBS
++	  lt_globsym_save_CFLAGS=$CFLAGS
++	  LIBS=conftstm.$ac_objext
++	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
++	  if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
++	    pipe_works=yes
++	  fi
++	  LIBS=$lt_globsym_save_LIBS
++	  CFLAGS=$lt_globsym_save_CFLAGS
++	else
++	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
++	fi
++      else
++	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
++      fi
++    else
++      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
++    fi
++  else
++    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
++    cat conftest.$ac_ext >&5
++  fi
++  rm -rf conftest* conftst*
++
++  # Do not use the global_symbol_pipe unless it works.
++  if test yes = "$pipe_works"; then
++    break
++  else
++    lt_cv_sys_global_symbol_pipe=
++  fi
++done
++])
++if test -z "$lt_cv_sys_global_symbol_pipe"; then
++  lt_cv_sys_global_symbol_to_cdecl=
++fi
++if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
++  AC_MSG_RESULT(failed)
++else
++  AC_MSG_RESULT(ok)
++fi
++
++# Response file support.
++if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++  nm_file_list_spec='@'
++elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
++  nm_file_list_spec='@'
++fi
++
++_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
++    [Take the output of nm and produce a listing of raw symbols and C names])
++_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
++    [Transform the output of nm in a proper C declaration])
++_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
++    [Transform the output of nm into a list of symbols to manually relocate])
++_LT_DECL([global_symbol_to_c_name_address],
++    [lt_cv_sys_global_symbol_to_c_name_address], [1],
++    [Transform the output of nm in a C name address pair])
++_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
++    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
++    [Transform the output of nm in a C name address pair when lib prefix is needed])
++_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
++    [The name lister interface])
++_LT_DECL([], [nm_file_list_spec], [1],
++    [Specify filename containing input files for $NM])
++]) # _LT_CMD_GLOBAL_SYMBOLS
++
++
++# _LT_COMPILER_PIC([TAGNAME])
++# ---------------------------
++m4_defun([_LT_COMPILER_PIC],
++[m4_require([_LT_TAG_COMPILER])dnl
++_LT_TAGVAR(lt_prog_compiler_wl, $1)=
++_LT_TAGVAR(lt_prog_compiler_pic, $1)=
++_LT_TAGVAR(lt_prog_compiler_static, $1)=
++
++m4_if([$1], [CXX], [
++  # C++ specific cases for pic, static, wl, etc.
++  if test yes = "$GXX"; then
++    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++
++    case $host_os in
++    aix*)
++      # All AIX code is PIC.
++      if test ia64 = "$host_cpu"; then
++	# AIX 5 now supports IA64 processor
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      fi
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++        ;;
++      m68k)
++            # FIXME: we need at least 68020 code to build shared libraries, but
++            # adding the '-m68020' flag to GCC prevents building anything better,
++            # like '-m68040'.
++            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
++        ;;
++      esac
++      ;;
++
++    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++      # PIC is the default for these OSes.
++      ;;
++    mingw* | cygwin* | os2* | pw32* | cegcc*)
++      # This hack is so that the source file can tell whether it is being
++      # built for inclusion in a dll (and should export symbols for example).
++      # Although the cygwin gcc ignores -fPIC, still need this for old-style
++      # (--disable-auto-import) libraries
++      m4_if([$1], [GCJ], [],
++	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++      case $host_os in
++      os2*)
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
++	;;
++      esac
++      ;;
++    darwin* | rhapsody*)
++      # PIC is the default on this platform
++      # Common symbols not allowed in MH_DYLIB files
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++      ;;
++    *djgpp*)
++      # DJGPP does not support shared libraries at all
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++      ;;
++    haiku*)
++      # PIC is the default for Haiku.
++      # The "-static" flag exists, but is broken.
++      _LT_TAGVAR(lt_prog_compiler_static, $1)=
++      ;;
++    interix[[3-9]]*)
++      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
++      # Instead, we relocate shared libraries at runtime.
++      ;;
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
++      fi
++      ;;
++    hpux*)
++      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
++      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
++      # sets the default TLS model and affects inlining.
++      case $host_cpu in
++      hppa*64*)
++	;;
++      *)
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	;;
++      esac
++      ;;
++    *qnx* | *nto*)
++      # QNX uses GNU C++, but need to define -shared option too, otherwise
++      # it will coredump.
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++      ;;
++    *)
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++      ;;
++    esac
++  else
++    case $host_os in
++      aix[[4-9]]*)
++	# All AIX code is PIC.
++	if test ia64 = "$host_cpu"; then
++	  # AIX 5 now supports IA64 processor
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	else
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
++	fi
++	;;
++      chorus*)
++	case $cc_basename in
++	cxch68*)
++	  # Green Hills C++ Compiler
++	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
++	  ;;
++	esac
++	;;
++      mingw* | cygwin* | os2* | pw32* | cegcc*)
++	# This hack is so that the source file can tell whether it is being
++	# built for inclusion in a dll (and should export symbols for example).
++	m4_if([$1], [GCJ], [],
++	  [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++	;;
++      dgux*)
++	case $cc_basename in
++	  ec++*)
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	    ;;
++	  ghcx*)
++	    # Green Hills C++ Compiler
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      freebsd* | dragonfly* | midnightbsd*)
++	# FreeBSD uses GNU C++
++	;;
++      hpux9* | hpux10* | hpux11*)
++	case $cc_basename in
++	  CC*)
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
++	    if test ia64 != "$host_cpu"; then
++	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++	    fi
++	    ;;
++	  aCC*)
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
++	    case $host_cpu in
++	    hppa*64*|ia64*)
++	      # +Z the default
++	      ;;
++	    *)
++	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++	      ;;
++	    esac
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      interix*)
++	# This is c89, which is MS Visual C++ (no shared libs)
++	# Anyone wants to do a port?
++	;;
++      irix5* | irix6* | nonstopux*)
++	case $cc_basename in
++	  CC*)
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++	    # CC pic flag -KPIC is the default.
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++	case $cc_basename in
++	  KCC*)
++	    # KAI C++ Compiler
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	    ;;
++	  ecpc* )
++	    # old Intel C++ for x86_64, which still supported -KPIC.
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++	    ;;
++	  icpc* )
++	    # Intel C++, used to be incompatible with GCC.
++	    # ICC 10 doesn't accept -KPIC any more.
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++	    ;;
++	  pgCC* | pgcpp*)
++	    # Portland Group C++ compiler
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	    ;;
++	  cxx*)
++	    # Compaq C++
++	    # Make sure the PIC flag is empty.  It appears that all Alpha
++	    # Linux and Compaq Tru64 Unix objects are PIC.
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++	    ;;
++	  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
++	    # IBM XL 8.0, 9.0 on PPC and BlueGene
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
++	    ;;
++	  *)
++	    case `$CC -V 2>&1 | $SED 5q` in
++	    *Sun\ C*)
++	      # Sun C++ 5.9
++	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++	      ;;
++	    esac
++	    ;;
++	esac
++	;;
++      lynxos*)
++	;;
++      m88k*)
++	;;
++      mvs*)
++	case $cc_basename in
++	  cxx*)
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      netbsd*)
++	;;
++      *qnx* | *nto*)
++        # QNX uses GNU C++, but need to define -shared option too, otherwise
++        # it will coredump.
++        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++        ;;
++      osf3* | osf4* | osf5*)
++	case $cc_basename in
++	  KCC*)
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
++	    ;;
++	  RCC*)
++	    # Rational C++ 2.4.1
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++	    ;;
++	  cxx*)
++	    # Digital/Compaq C++
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    # Make sure the PIC flag is empty.  It appears that all Alpha
++	    # Linux and Compaq Tru64 Unix objects are PIC.
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      psos*)
++	;;
++      solaris*)
++	case $cc_basename in
++	  CC* | sunCC*)
++	    # Sun C++ 4.2, 5.x and Centerline C++
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++	    ;;
++	  gcx*)
++	    # Green Hills C++ Compiler
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      sunos4*)
++	case $cc_basename in
++	  CC*)
++	    # Sun C++ 4.x
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	    ;;
++	  lcc*)
++	    # Lucid
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
++	case $cc_basename in
++	  CC*)
++	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	    ;;
++	esac
++	;;
++      tandem*)
++	case $cc_basename in
++	  NCC*)
++	    # NonStop-UX NCC 3.20
++	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      vxworks*)
++	;;
++      *)
++	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++	;;
++    esac
++  fi
++],
++[
++  if test yes = "$GCC"; then
++    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++
++    case $host_os in
++      aix*)
++      # All AIX code is PIC.
++      if test ia64 = "$host_cpu"; then
++	# AIX 5 now supports IA64 processor
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      fi
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++        ;;
++      m68k)
++            # FIXME: we need at least 68020 code to build shared libraries, but
++            # adding the '-m68020' flag to GCC prevents building anything better,
++            # like '-m68040'.
++            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
++        ;;
++      esac
++      ;;
++
++    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++      # PIC is the default for these OSes.
++      ;;
++
++    mingw* | cygwin* | pw32* | os2* | cegcc*)
++      # This hack is so that the source file can tell whether it is being
++      # built for inclusion in a dll (and should export symbols for example).
++      # Although the cygwin gcc ignores -fPIC, still need this for old-style
++      # (--disable-auto-import) libraries
++      m4_if([$1], [GCJ], [],
++	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++      case $host_os in
++      os2*)
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
++	;;
++      esac
++      ;;
++
++    darwin* | rhapsody*)
++      # PIC is the default on this platform
++      # Common symbols not allowed in MH_DYLIB files
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++      ;;
++
++    haiku*)
++      # PIC is the default for Haiku.
++      # The "-static" flag exists, but is broken.
++      _LT_TAGVAR(lt_prog_compiler_static, $1)=
++      ;;
++
++    hpux*)
++      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
++      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
++      # sets the default TLS model and affects inlining.
++      case $host_cpu in
++      hppa*64*)
++	# +Z the default
++	;;
++      *)
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	;;
++      esac
++      ;;
++
++    interix[[3-9]]*)
++      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
++      # Instead, we relocate shared libraries at runtime.
++      ;;
++
++    msdosdjgpp*)
++      # Just because we use GCC doesn't mean we suddenly get shared libraries
++      # on systems that don't support them.
++      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++      enable_shared=no
++      ;;
++
++    *nto* | *qnx*)
++      # QNX uses GNU C++, but need to define -shared option too, otherwise
++      # it will coredump.
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++      ;;
++
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
++      fi
++      ;;
++
++    *)
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++      ;;
++    esac
++
++    case $cc_basename in
++    nvcc*) # Cuda Compiler Driver 2.2
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
++      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
++        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
++      fi
++      ;;
++    esac
++  else
++    # PORTME Check for flag to pass linker flags through the system compiler.
++    case $host_os in
++    aix*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      if test ia64 = "$host_cpu"; then
++	# AIX 5 now supports IA64 processor
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      else
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
++      fi
++      ;;
++
++    darwin* | rhapsody*)
++      # PIC is the default on this platform
++      # Common symbols not allowed in MH_DYLIB files
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
++      case $cc_basename in
++      nagfor*)
++        # NAG Fortran compiler
++        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
++        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++        _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++        ;;
++      esac
++      ;;
++
++    mingw* | cygwin* | pw32* | os2* | cegcc*)
++      # This hack is so that the source file can tell whether it is being
++      # built for inclusion in a dll (and should export symbols for example).
++      m4_if([$1], [GCJ], [],
++	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
++      case $host_os in
++      os2*)
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
++	;;
++      esac
++      ;;
++
++    hpux9* | hpux10* | hpux11*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
++      # not for PA HP-UX.
++      case $host_cpu in
++      hppa*64*|ia64*)
++	# +Z the default
++	;;
++      *)
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
++	;;
++      esac
++      # Is there a better lt_prog_compiler_static that works with the bundled CC?
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
++      ;;
++
++    irix5* | irix6* | nonstopux*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      # PIC (with -KPIC) is the default.
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++      ;;
++
++    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++      case $cc_basename in
++      # old Intel for x86_64, which still supported -KPIC.
++      ecc*)
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++        ;;
++      # icc used to be incompatible with GCC.
++      # ICC 10 doesn't accept -KPIC any more.
++      icc* | ifort*)
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++        ;;
++      # Lahey Fortran 8.1.
++      lf95*)
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
++	;;
++      nagfor*)
++	# NAG Fortran compiler
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	;;
++      tcc*)
++	# Fabrice Bellard et al's Tiny C Compiler
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++	;;
++      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
++        # Portland Group compilers (*not* the Pentium gcc compiler,
++	# which looks to be a dead project)
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++        ;;
++      ccc*)
++        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++        # All Alpha code is PIC.
++        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++        ;;
++      xl* | bgxl* | bgf* | mpixl*)
++	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
++	;;
++      *)
++	case `$CC -V 2>&1 | $SED 5q` in
++	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
++	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
++	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
++	  ;;
++	*Sun\ F* | *Sun*Fortran*)
++	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++	  ;;
++	*Sun\ C*)
++	  # Sun C 5.9
++	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	  ;;
++        *Intel*\ [[CF]]*Compiler*)
++	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
++	  ;;
++	*Portland\ Group*)
++	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
++	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++	  ;;
++	esac
++	;;
++      esac
++      ;;
++
++    newsos6)
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      ;;
++
++    *nto* | *qnx*)
++      # QNX uses GNU C++, but need to define -shared option too, otherwise
++      # it will coredump.
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
++      ;;
++
++    osf3* | osf4* | osf5*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      # All OSF/1 code is PIC.
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++      ;;
++
++    rdos*)
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
++      ;;
++
++    solaris*)
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      case $cc_basename in
++      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
++      *)
++	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
++      esac
++      ;;
++
++    sunos4*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      ;;
++
++    sysv4 | sysv4.2uw2* | sysv4.3*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      ;;
++
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
++	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      fi
++      ;;
++
++    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      ;;
++
++    unicos*)
++      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
++      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++      ;;
++
++    uts4*)
++      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
++      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
++      ;;
++
++    *)
++      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
++      ;;
++    esac
++  fi
++])
++case $host_os in
++  # For platforms that do not support PIC, -DPIC is meaningless:
++  *djgpp*)
++    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
++    ;;
++  *)
++    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
++    ;;
++esac
++
++AC_CACHE_CHECK([for $compiler option to produce PIC],
++  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
++  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
++_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
++
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
++  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
++    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
++    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
++    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
++     "" | " "*) ;;
++     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
++     esac],
++    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
++     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
++fi
++_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
++	[Additional compiler flags for building library objects])
++
++_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
++	[How to pass a linker flag through the compiler])
++#
++# Check to make sure the static flag actually works.
++#
++wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
++_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
++  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
++  $lt_tmp_static_flag,
++  [],
++  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
++_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
++	[Compiler flag to prevent dynamic linking])
++])# _LT_COMPILER_PIC
++
++
++# _LT_LINKER_SHLIBS([TAGNAME])
++# ----------------------------
++# See if the linker supports building shared libraries.
++m4_defun([_LT_LINKER_SHLIBS],
++[AC_REQUIRE([LT_PATH_LD])dnl
++AC_REQUIRE([LT_PATH_NM])dnl
++m4_require([_LT_PATH_MANIFEST_TOOL])dnl
++m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_DECL_SED])dnl
++m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
++m4_require([_LT_TAG_COMPILER])dnl
++AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
++m4_if([$1], [CXX], [
++  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
++  case $host_os in
++  aix[[4-9]]*)
++    # If we're using GNU nm, then we don't want the "-C" option.
++    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
++    # Without the "-l" option, or with the "-B" option, AIX nm treats
++    # weak defined symbols like other global defined symbols, whereas
++    # GNU nm marks them as "W".
++    # While the 'weak' keyword is ignored in the Export File, we need
++    # it in the Import File for the 'aix-soname' feature, so we have
++    # to replace the "-B" option with "-P" for AIX nm.
++    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
++      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++    else
++      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++    fi
++    ;;
++  pw32*)
++    _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
++    ;;
++  cygwin* | mingw* | cegcc*)
++    case $cc_basename in
++    cl* | icl*)
++      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
++      ;;
++    *)
++      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
++      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
++      ;;
++    esac
++    ;;
++  *)
++    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++    ;;
++  esac
++], [
++  runpath_var=
++  _LT_TAGVAR(allow_undefined_flag, $1)=
++  _LT_TAGVAR(always_export_symbols, $1)=no
++  _LT_TAGVAR(archive_cmds, $1)=
++  _LT_TAGVAR(archive_expsym_cmds, $1)=
++  _LT_TAGVAR(compiler_needs_object, $1)=no
++  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
++  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++  _LT_TAGVAR(hardcode_automatic, $1)=no
++  _LT_TAGVAR(hardcode_direct, $1)=no
++  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
++  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++  _LT_TAGVAR(hardcode_libdir_separator, $1)=
++  _LT_TAGVAR(hardcode_minus_L, $1)=no
++  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++  _LT_TAGVAR(inherit_rpath, $1)=no
++  _LT_TAGVAR(link_all_deplibs, $1)=unknown
++  _LT_TAGVAR(module_cmds, $1)=
++  _LT_TAGVAR(module_expsym_cmds, $1)=
++  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
++  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
++  _LT_TAGVAR(thread_safe_flag_spec, $1)=
++  _LT_TAGVAR(whole_archive_flag_spec, $1)=
++  # include_expsyms should be a list of space-separated symbols to be *always*
++  # included in the symbol list
++  _LT_TAGVAR(include_expsyms, $1)=
++  # exclude_expsyms can be an extended regexp of symbols to exclude
++  # it will be wrapped by ' (' and ')$', so one must not match beginning or
++  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
++  # as well as any symbol that contains 'd'.
++  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
++  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
++  # platforms (ab)use it in PIC code, but their linkers get confused if
++  # the symbol is explicitly referenced.  Since portable code cannot
++  # rely on this symbol name, it's probably fine to never include it in
++  # preloaded symbol tables.
++  # Exclude shared library initialization/finalization symbols.
++dnl Note also adjust exclude_expsyms for C++ above.
++  extract_expsyms_cmds=
++
++  case $host_os in
++  cygwin* | mingw* | pw32* | cegcc*)
++    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
++    # When not using gcc, we currently assume that we are using
++    # Microsoft Visual C++ or Intel C++ Compiler.
++    if test yes != "$GCC"; then
++      with_gnu_ld=no
++    fi
++    ;;
++  interix*)
++    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
++    with_gnu_ld=yes
++    ;;
++  openbsd* | bitrig*)
++    with_gnu_ld=no
++    ;;
++  esac
++
++  _LT_TAGVAR(ld_shlibs, $1)=yes
++
++  # On some targets, GNU ld is compatible enough with the native linker
++  # that we're better off using the native interface for both.
++  lt_use_gnu_ld_interface=no
++  if test yes = "$with_gnu_ld"; then
++    case $host_os in
++      aix*)
++	# The AIX port of GNU ld has always aspired to compatibility
++	# with the native linker.  However, as the warning in the GNU ld
++	# block says, versions before 2.19.5* couldn't really create working
++	# shared libraries, regardless of the interface used.
++	case `$LD -v 2>&1` in
++	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
++	  *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
++	  *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
++	  *)
++	    lt_use_gnu_ld_interface=yes
++	    ;;
++	esac
++	;;
++      *)
++	lt_use_gnu_ld_interface=yes
++	;;
++    esac
++  fi
++
++  if test yes = "$lt_use_gnu_ld_interface"; then
++    # If archive_cmds runs LD, not CC, wlarc should be empty
++    wlarc='$wl'
++
++    # Set some defaults for GNU ld with shared library support. These
++    # are reset later if shared libraries are not supported. Putting them
++    # here allows them to be overridden if necessary.
++    runpath_var=LD_RUN_PATH
++    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++    # ancient GNU ld didn't support --whole-archive et. al.
++    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
++      _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++    else
++      _LT_TAGVAR(whole_archive_flag_spec, $1)=
++    fi
++    supports_anon_versioning=no
++    case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
++      *GNU\ gold*) supports_anon_versioning=yes ;;
++      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
++      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
++      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
++      *\ 2.11.*) ;; # other 2.11 versions
++      *) supports_anon_versioning=yes ;;
++    esac
++
++    # See if GNU ld supports shared libraries.
++    case $host_os in
++    aix[[3-9]]*)
++      # On AIX/PPC, the GNU linker is very broken
++      if test ia64 != "$host_cpu"; then
++	_LT_TAGVAR(ld_shlibs, $1)=no
++	cat <<_LT_EOF 1>&2
++
++*** Warning: the GNU linker, at least up to release 2.19, is reported
++*** to be unable to reliably create shared libraries on AIX.
++*** Therefore, libtool is disabling shared libraries support.  If you
++*** really care for shared libraries, you may want to install binutils
++*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
++*** You will then need to restart the configuration process.
++
++_LT_EOF
++      fi
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++            _LT_TAGVAR(archive_expsym_cmds, $1)=''
++        ;;
++      m68k)
++            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++            _LT_TAGVAR(hardcode_minus_L, $1)=yes
++        ;;
++      esac
++      ;;
++
++    beos*)
++      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	# Joseph Beckenbach  says some releases of gcc
++	# support --undefined.  This deserves some investigation.  FIXME
++	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++      else
++	_LT_TAGVAR(ld_shlibs, $1)=no
++      fi
++      ;;
++
++    cygwin* | mingw* | pw32* | cegcc*)
++      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
++      # as there is no search path for DLLs.
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
++      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++      _LT_TAGVAR(always_export_symbols, $1)=no
++      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
++      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
++
++      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	# If the export-symbols file already is a .def file, use it as
++	# is; otherwise, prepend EXPORTS...
++	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++          cp $export_symbols $output_objdir/$soname.def;
++        else
++          echo EXPORTS > $output_objdir/$soname.def;
++          cat $export_symbols >> $output_objdir/$soname.def;
++        fi~
++        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++      else
++	_LT_TAGVAR(ld_shlibs, $1)=no
++      fi
++      ;;
++
++    haiku*)
++      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++      _LT_TAGVAR(link_all_deplibs, $1)=yes
++      ;;
++
++    os2*)
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++      _LT_TAGVAR(hardcode_minus_L, $1)=yes
++      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++      shrext_cmds=.dll
++      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	prefix_cmds="$SED"~
++	if test EXPORTS = "`$SED 1q $export_symbols`"; then
++	  prefix_cmds="$prefix_cmds -e 1d";
++	fi~
++	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++      _LT_TAGVAR(file_list_spec, $1)='@'
++      ;;
++
++    interix[[3-9]]*)
++      _LT_TAGVAR(hardcode_direct, $1)=no
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
++      # Instead, shared libraries are loaded at an image base (0x10000000 by
++      # default) and relocated if they conflict, which is a slow very memory
++      # consuming and fragmenting process.  To avoid this, we pick a random,
++      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
++      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
++      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++      _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++      ;;
++
++    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
++      tmp_diet=no
++      if test linux-dietlibc = "$host_os"; then
++	case $cc_basename in
++	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
++	esac
++      fi
++      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
++	 && test no = "$tmp_diet"
++      then
++	tmp_addflag=' $pic_flag'
++	tmp_sharedflag='-shared'
++	case $cc_basename,$host_cpu in
++        pgcc*)				# Portland Group C compiler
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  tmp_addflag=' $pic_flag'
++	  ;;
++	pgf77* | pgf90* | pgf95* | pgfortran*)
++					# Portland Group f77 and f90 compilers
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  tmp_addflag=' $pic_flag -Mnomain' ;;
++	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
++	  tmp_addflag=' -i_dynamic' ;;
++	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
++	  tmp_addflag=' -i_dynamic -nofor_main' ;;
++	ifc* | ifort*)			# Intel Fortran compiler
++	  tmp_addflag=' -nofor_main' ;;
++	lf95*)				# Lahey Fortran 8.1
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
++	  tmp_sharedflag='--shared' ;;
++        nagfor*)                        # NAGFOR 5.3
++          tmp_sharedflag='-Wl,-shared' ;;
++	xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
++	  tmp_sharedflag='-qmkshrobj'
++	  tmp_addflag= ;;
++	nvcc*)	# Cuda Compiler Driver 2.2
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  _LT_TAGVAR(compiler_needs_object, $1)=yes
++	  ;;
++	esac
++	case `$CC -V 2>&1 | $SED 5q` in
++	*Sun\ C*)			# Sun C 5.9
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  _LT_TAGVAR(compiler_needs_object, $1)=yes
++	  tmp_sharedflag='-G' ;;
++	*Sun\ F*)			# Sun Fortran 8.3
++	  tmp_sharedflag='-G' ;;
++	esac
++	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++
++        if test yes = "$supports_anon_versioning"; then
++          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
++            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++            echo "local: *; };" >> $output_objdir/$libname.ver~
++            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++        fi
++
++	case $cc_basename in
++	tcc*)
++	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
++	  ;;
++	xlf* | bgf* | bgxlf* | mpixlf*)
++	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
++	  if test yes = "$supports_anon_versioning"; then
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
++              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++              echo "local: *; };" >> $output_objdir/$libname.ver~
++              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
++	  fi
++	  ;;
++	esac
++      else
++        _LT_TAGVAR(ld_shlibs, $1)=no
++      fi
++      ;;
++
++    netbsd*)
++      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
++	wlarc=
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      fi
++      ;;
++
++    solaris*)
++      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
++	_LT_TAGVAR(ld_shlibs, $1)=no
++	cat <<_LT_EOF 1>&2
++
++*** Warning: The releases 2.8.* of the GNU linker cannot reliably
++*** create shared libraries on Solaris systems.  Therefore, libtool
++*** is disabling shared libraries support.  We urge you to upgrade GNU
++*** binutils to release 2.9.1 or newer.  Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
++
++_LT_EOF
++      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      else
++	_LT_TAGVAR(ld_shlibs, $1)=no
++      fi
++      ;;
++
++    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
++      case `$LD -v 2>&1` in
++        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
++	_LT_TAGVAR(ld_shlibs, $1)=no
++	cat <<_LT_EOF 1>&2
++
++*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
++*** reliably create shared libraries on SCO systems.  Therefore, libtool
++*** is disabling shared libraries support.  We urge you to upgrade GNU
++*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
++
++_LT_EOF
++	;;
++	*)
++	  # For security reasons, it is highly recommended that you always
++	  # use absolute paths for naming shared libraries, and exclude the
++	  # DT_RUNPATH tag from executables and libraries.  But doing so
++	  # requires that you compile everything twice, which is a pain.
++	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	  else
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	  fi
++	;;
++      esac
++      ;;
++
++    sunos4*)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++      wlarc=
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    *)
++      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      else
++	_LT_TAGVAR(ld_shlibs, $1)=no
++      fi
++      ;;
++    esac
++
++    if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
++      runpath_var=
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
++      _LT_TAGVAR(whole_archive_flag_spec, $1)=
++    fi
++  else
++    # PORTME fill in a description of your system's linker (not GNU ld)
++    case $host_os in
++    aix3*)
++      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++      _LT_TAGVAR(always_export_symbols, $1)=yes
++      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
++      # Note: this linker hardcodes the directories in LIBPATH if there
++      # are no directories specified by -L.
++      _LT_TAGVAR(hardcode_minus_L, $1)=yes
++      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
++	# Neither direct hardcoding nor static linking is supported with a
++	# broken collect2.
++	_LT_TAGVAR(hardcode_direct, $1)=unsupported
++      fi
++      ;;
++
++    aix[[4-9]]*)
++      if test ia64 = "$host_cpu"; then
++	# On IA64, the linker does run time linking by default, so we don't
++	# have to do anything special.
++	aix_use_runtimelinking=no
++	exp_sym_flag='-Bexport'
++	no_entry_flag=
++      else
++	# If we're using GNU nm, then we don't want the "-C" option.
++	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
++	# Without the "-l" option, or with the "-B" option, AIX nm treats
++	# weak defined symbols like other global defined symbols, whereas
++	# GNU nm marks them as "W".
++	# While the 'weak' keyword is ignored in the Export File, we need
++	# it in the Import File for the 'aix-soname' feature, so we have
++	# to replace the "-B" option with "-P" for AIX nm.
++	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
++	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++	else
++	  _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++	fi
++	aix_use_runtimelinking=no
++
++	# Test if we are trying to use run time linking or normal
++	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
++	# have runtime linking enabled, and use it for executables.
++	# For shared libraries, we enable/disable runtime linking
++	# depending on the kind of the shared library created -
++	# when "with_aix_soname,aix_use_runtimelinking" is:
++	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
++	# "aix,yes"  lib.so          shared, rtl:yes, for executables
++	#            lib.a           static archive
++	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
++	#            lib.a(lib.so.V) shared, rtl:no,  for executables
++	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
++	#            lib.a(lib.so.V) shared, rtl:no
++	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
++	#            lib.a           static archive
++	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
++	  for ld_flag in $LDFLAGS; do
++	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
++	    aix_use_runtimelinking=yes
++	    break
++	  fi
++	  done
++	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
++	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
++	    # so we don't have lib.a shared libs to link our executables.
++	    # We have to force runtime linking in this case.
++	    aix_use_runtimelinking=yes
++	    LDFLAGS="$LDFLAGS -Wl,-brtl"
++	  fi
++	  ;;
++	esac
++
++	exp_sym_flag='-bexport'
++	no_entry_flag='-bnoentry'
++      fi
++
++      # When large executables or shared objects are built, AIX ld can
++      # have problems creating the table of contents.  If linking a library
++      # or program results in "error TOC overflow" add -mminimal-toc to
++      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
++      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++      _LT_TAGVAR(archive_cmds, $1)=''
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++      _LT_TAGVAR(link_all_deplibs, $1)=yes
++      _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
++      case $with_aix_soname,$aix_use_runtimelinking in
++      aix,*) ;; # traditional, no import file
++      svr4,* | *,yes) # use import file
++	# The Import File defines what to hardcode.
++	_LT_TAGVAR(hardcode_direct, $1)=no
++	_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++	;;
++      esac
++
++      if test yes = "$GCC"; then
++	case $host_os in aix4.[[012]]|aix4.[[012]].*)
++	# We only want to do this on AIX 4.2 and lower, the check
++	# below for broken collect2 doesn't work under 4.3+
++	  collect2name=`$CC -print-prog-name=collect2`
++	  if test -f "$collect2name" &&
++	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
++	  then
++	  # We have reworked collect2
++	  :
++	  else
++	  # We have old collect2
++	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
++	  # It fails to find uninstalled libraries when the uninstalled
++	  # path is not listed in the libpath.  Setting hardcode_minus_L
++	  # to unsupported forces relinking
++	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
++	  fi
++	  ;;
++	esac
++	shared_flag='-shared'
++	if test yes = "$aix_use_runtimelinking"; then
++	  shared_flag="$shared_flag "'$wl-G'
++	fi
++	# Need to ensure runtime linking is disabled for the traditional
++	# shared library, or the linker may eventually find shared libraries
++	# /with/ Import File - we do not want to mix them.
++	shared_flag_aix='-shared'
++	shared_flag_svr4='-shared $wl-G'
++      else
++	# not using gcc
++	if test ia64 = "$host_cpu"; then
++	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++	# chokes on -Wl,-G. The following line is correct:
++	  shared_flag='-G'
++	else
++	  if test yes = "$aix_use_runtimelinking"; then
++	    shared_flag='$wl-G'
++	  else
++	    shared_flag='$wl-bM:SRE'
++	  fi
++	  shared_flag_aix='$wl-bM:SRE'
++	  shared_flag_svr4='$wl-G'
++	fi
++      fi
++
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
++      # It seems that -bexpall does not export symbols beginning with
++      # underscore (_), so it is better to generate a list of symbols to export.
++      _LT_TAGVAR(always_export_symbols, $1)=yes
++      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++	# Warning - without using the other runtime loading flags (-brtl),
++	# -berok will link without error, but may produce a broken library.
++	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
++        # Determine the default libpath from the value encoded in an
++        # empty executable.
++        _LT_SYS_MODULE_PATH_AIX([$1])
++        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++      else
++	if test ia64 = "$host_cpu"; then
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
++	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
++	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++	else
++	 # Determine the default libpath from the value encoded in an
++	 # empty executable.
++	 _LT_SYS_MODULE_PATH_AIX([$1])
++	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++	  # Warning - without using the other run time loading flags,
++	  # -berok will link without error, but may produce a broken library.
++	  _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
++	  _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
++	  if test yes = "$with_gnu_ld"; then
++	    # We only use this code for GNU lds that support --whole-archive.
++	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
++	  else
++	    # Exported symbols can be pulled into shared objects from archives
++	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
++	  fi
++	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
++	  # -brtl affects multiple linker settings, -berok does not and is overridden later
++	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
++	  if test svr4 != "$with_aix_soname"; then
++	    # This is similar to how AIX traditionally builds its shared libraries.
++	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
++	  fi
++	  if test aix != "$with_aix_soname"; then
++	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
++	  else
++	    # used by -dlpreopen to get the symbols
++	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
++	  fi
++	  _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
++	fi
++      fi
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++            _LT_TAGVAR(archive_expsym_cmds, $1)=''
++        ;;
++      m68k)
++            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++            _LT_TAGVAR(hardcode_minus_L, $1)=yes
++        ;;
++      esac
++      ;;
++
++    bsdi[[45]]*)
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
++      ;;
++
++    cygwin* | mingw* | pw32* | cegcc*)
++      # When not using gcc, we currently assume that we are using
++      # Microsoft Visual C++ or Intel C++ Compiler.
++      # hardcode_libdir_flag_spec is actually meaningless, as there is
++      # no search path for DLLs.
++      case $cc_basename in
++      cl* | icl*)
++	# Native MSVC or ICC
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	_LT_TAGVAR(always_export_symbols, $1)=yes
++	_LT_TAGVAR(file_list_spec, $1)='@'
++	# Tell ltmain to make .lib files, not .a files.
++	libext=lib
++	# Tell ltmain to make .dll files, not .so files.
++	shrext_cmds=.dll
++	# FIXME: Setting linknames here is a bad hack.
++	_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
++	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++            cp "$export_symbols" "$output_objdir/$soname.def";
++            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
++          else
++            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
++          fi~
++          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
++          linknames='
++	# The linker will not automatically build a static lib if we build a DLL.
++	# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
++	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++	_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
++	_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
++	# Don't use ranlib
++	_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
++	_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
++          lt_tool_outputfile="@TOOL_OUTPUT@"~
++          case $lt_outputfile in
++            *.exe|*.EXE) ;;
++            *)
++              lt_outputfile=$lt_outputfile.exe
++              lt_tool_outputfile=$lt_tool_outputfile.exe
++              ;;
++          esac~
++          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
++            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
++            $RM "$lt_outputfile.manifest";
++          fi'
++	;;
++      *)
++	# Assume MSVC and ICC wrapper
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	# Tell ltmain to make .lib files, not .a files.
++	libext=lib
++	# Tell ltmain to make .dll files, not .so files.
++	shrext_cmds=.dll
++	# FIXME: Setting linknames here is a bad hack.
++	_LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
++	# The linker will automatically build a .lib file if we build a DLL.
++	_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
++	# FIXME: Should let the user specify the lib program.
++	_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
++	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++	;;
++      esac
++      ;;
++
++    darwin* | rhapsody*)
++      _LT_DARWIN_LINKER_FEATURES($1)
++      ;;
++
++    dgux*)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
++    # support.  Future versions do this automatically, but an explicit c++rt0.o
++    # does not break anything, and helps significantly (at the cost of a little
++    # extra space).
++    freebsd2.2*)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
++    freebsd2.*)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_minus_L, $1)=yes
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
++    freebsd* | dragonfly* | midnightbsd*)
++      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    hpux9*)
++      if test yes = "$GCC"; then
++	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++      fi
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++
++      # hardcode_minus_L: Not really in the search PATH,
++      # but as the default location of the library.
++      _LT_TAGVAR(hardcode_minus_L, $1)=yes
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++      ;;
++
++    hpux10*)
++      if test yes,no = "$GCC,$with_gnu_ld"; then
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
++      fi
++      if test no = "$with_gnu_ld"; then
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
++	_LT_TAGVAR(hardcode_direct, $1)=yes
++	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++	# hardcode_minus_L: Not really in the search PATH,
++	# but as the default location of the library.
++	_LT_TAGVAR(hardcode_minus_L, $1)=yes
++      fi
++      ;;
++
++    hpux11*)
++      if test yes,no = "$GCC,$with_gnu_ld"; then
++	case $host_cpu in
++	hppa*64*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	ia64*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	esac
++      else
++	case $host_cpu in
++	hppa*64*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	ia64*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	*)
++	m4_if($1, [], [
++	  # Older versions of the 11.00 compiler do not understand -b yet
++	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
++	  _LT_LINKER_OPTION([if $CC understands -b],
++	    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
++	    [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
++	    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
++	  [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
++	  ;;
++	esac
++      fi
++      if test no = "$with_gnu_ld"; then
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++	case $host_cpu in
++	hppa*64*|ia64*)
++	  _LT_TAGVAR(hardcode_direct, $1)=no
++	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	  ;;
++	*)
++	  _LT_TAGVAR(hardcode_direct, $1)=yes
++	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++
++	  # hardcode_minus_L: Not really in the search PATH,
++	  # but as the default location of the library.
++	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
++	  ;;
++	esac
++      fi
++      ;;
++
++    irix5* | irix6* | nonstopux*)
++      if test yes = "$GCC"; then
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	# Try to use the -exported_symbol ld option, if it does not
++	# work, assume that -exports_file does not work either and
++	# implicitly export all symbols.
++	# This should be the same for all languages, so no per-tag cache variable.
++	AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
++	  [lt_cv_irix_exported_symbol],
++	  [save_LDFLAGS=$LDFLAGS
++	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
++	   AC_LINK_IFELSE(
++	     [AC_LANG_SOURCE(
++	        [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
++			      [C++], [[int foo (void) { return 0; }]],
++			      [Fortran 77], [[
++      subroutine foo
++      end]],
++			      [Fortran], [[
++      subroutine foo
++      end]])])],
++	      [lt_cv_irix_exported_symbol=yes],
++	      [lt_cv_irix_exported_symbol=no])
++           LDFLAGS=$save_LDFLAGS])
++	if test yes = "$lt_cv_irix_exported_symbol"; then
++          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
++	fi
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
++      fi
++      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++      _LT_TAGVAR(inherit_rpath, $1)=yes
++      _LT_TAGVAR(link_all_deplibs, $1)=yes
++      ;;
++
++    linux*)
++      case $cc_basename in
++      tcc*)
++	# Fabrice Bellard et al's Tiny C Compiler
++	_LT_TAGVAR(ld_shlibs, $1)=yes
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	;;
++      esac
++      ;;
++
++    netbsd*)
++      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
++      fi
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    newsos6)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    *nto* | *qnx*)
++      ;;
++
++    openbsd* | bitrig*)
++      if test -f /usr/libexec/ld.so; then
++	_LT_TAGVAR(hardcode_direct, $1)=yes
++	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++	else
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	fi
++      else
++	_LT_TAGVAR(ld_shlibs, $1)=no
++      fi
++      ;;
++
++    os2*)
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++      _LT_TAGVAR(hardcode_minus_L, $1)=yes
++      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++      shrext_cmds=.dll
++      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	prefix_cmds="$SED"~
++	if test EXPORTS = "`$SED 1q $export_symbols`"; then
++	  prefix_cmds="$prefix_cmds -e 1d";
++	fi~
++	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++      _LT_TAGVAR(file_list_spec, $1)='@'
++      ;;
++
++    osf3*)
++      if test yes = "$GCC"; then
++	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++      else
++	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++      fi
++      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++      ;;
++
++    osf4* | osf5*)	# as osf3* with the addition of -msym flag
++      if test yes = "$GCC"; then
++	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++      else
++	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
++          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
++
++	# Both c and cxx compiler support -rpath directly
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++      fi
++      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++      ;;
++
++    solaris*)
++      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
++      if test yes = "$GCC"; then
++	wlarc='$wl'
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++      else
++	case `$CC -V 2>&1` in
++	*"Compilers 5.0"*)
++	  wlarc=''
++	  _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
++	  ;;
++	*)
++	  wlarc='$wl'
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++	  ;;
++	esac
++      fi
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      case $host_os in
++      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++      *)
++	# The compiler driver will combine and reorder linker options,
++	# but understands '-z linker_flag'.  GCC discards it without '$wl',
++	# but is careful enough not to reorder.
++	# Supported since Solaris 2.6 (maybe 2.5.1?)
++	if test yes = "$GCC"; then
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++	else
++	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
++	fi
++	;;
++      esac
++      _LT_TAGVAR(link_all_deplibs, $1)=yes
++      ;;
++
++    sunos4*)
++      if test sequent = "$host_vendor"; then
++	# Use $CC to link under sequent, because it throws in some extra .o
++	# files that make .init and .fini sections work.
++	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
++      fi
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++      _LT_TAGVAR(hardcode_direct, $1)=yes
++      _LT_TAGVAR(hardcode_minus_L, $1)=yes
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    sysv4)
++      case $host_vendor in
++	sni)
++	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
++	;;
++	siemens)
++	  ## LD is ld it makes a PLAMLIB
++	  ## CC just makes a GrossModule.
++	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
++	  _LT_TAGVAR(hardcode_direct, $1)=no
++        ;;
++	motorola)
++	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
++	;;
++      esac
++      runpath_var='LD_RUN_PATH'
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    sysv4.3*)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
++      ;;
++
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	runpath_var=LD_RUN_PATH
++	hardcode_runpath_var=yes
++	_LT_TAGVAR(ld_shlibs, $1)=yes
++      fi
++      ;;
++
++    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
++      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      runpath_var='LD_RUN_PATH'
++
++      if test yes = "$GCC"; then
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      fi
++      ;;
++
++    sysv5* | sco3.2v5* | sco5v6*)
++      # Note: We CANNOT use -z defs as we might desire, because we do not
++      # link with -lc, and that would cause any symbols used from libc to
++      # always be unresolved, which means just about no library would
++      # ever link correctly.  If we're not using GNU ld we use -z text
++      # though, which does catch some bad symbols but isn't as heavy-handed
++      # as -z defs.
++      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++      _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
++      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
++      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++      _LT_TAGVAR(link_all_deplibs, $1)=yes
++      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
++      runpath_var='LD_RUN_PATH'
++
++      if test yes = "$GCC"; then
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      fi
++      ;;
++
++    uts4*)
++      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      ;;
++
++    *)
++      _LT_TAGVAR(ld_shlibs, $1)=no
++      ;;
++    esac
++
++    if test sni = "$host_vendor"; then
++      case $host in
++      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
++	;;
++      esac
++    fi
++  fi
++])
++AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
++test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
++
++_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
++
++_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
++_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
++_LT_DECL([], [extract_expsyms_cmds], [2],
++    [The commands to extract the exported symbol list from a shared archive])
++
++#
++# Do we need to explicitly link libc?
++#
++case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
++x|xyes)
++  # Assume -lc should be added
++  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++
++  if test yes,yes = "$GCC,$enable_shared"; then
++    case $_LT_TAGVAR(archive_cmds, $1) in
++    *'~'*)
++      # FIXME: we may have to deal with multi-command sequences.
++      ;;
++    '$CC '*)
++      # Test whether the compiler implicitly links with -lc since on some
++      # systems, -lgcc has to come before -lc. If gcc already passes -lc
++      # to ld, don't add -lc before -lgcc.
++      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
++	[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
++	[$RM conftest*
++	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++	if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
++	  soname=conftest
++	  lib=conftest
++	  libobjs=conftest.$ac_objext
++	  deplibs=
++	  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
++	  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
++	  compiler_flags=-v
++	  linker_flags=-v
++	  verstring=
++	  output_objdir=.
++	  libname=conftest
++	  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
++	  _LT_TAGVAR(allow_undefined_flag, $1)=
++	  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
++	  then
++	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++	  else
++	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++	  fi
++	  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
++	else
++	  cat conftest.err 1>&5
++	fi
++	$RM conftest*
++	])
++      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
++      ;;
++    esac
++  fi
++  ;;
++esac
++
++_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
++    [Whether or not to add -lc for building shared libraries])
++_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
++    [enable_shared_with_static_runtimes], [0],
++    [Whether or not to disallow shared libs when runtime libs are static])
++_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
++    [Compiler flag to allow reflexive dlopens])
++_LT_TAGDECL([], [whole_archive_flag_spec], [1],
++    [Compiler flag to generate shared objects directly from archives])
++_LT_TAGDECL([], [compiler_needs_object], [1],
++    [Whether the compiler copes with passing no objects directly])
++_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
++    [Create an old-style archive from a shared archive])
++_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
++    [Create a temporary old-style archive to link instead of a shared archive])
++_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
++_LT_TAGDECL([], [archive_expsym_cmds], [2])
++_LT_TAGDECL([], [module_cmds], [2],
++    [Commands used to build a loadable module if different from building
++    a shared archive.])
++_LT_TAGDECL([], [module_expsym_cmds], [2])
++_LT_TAGDECL([], [with_gnu_ld], [1],
++    [Whether we are building with GNU ld or not])
++_LT_TAGDECL([], [allow_undefined_flag], [1],
++    [Flag that allows shared libraries with undefined symbols to be built])
++_LT_TAGDECL([], [no_undefined_flag], [1],
++    [Flag that enforces no undefined symbols])
++_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
++    [Flag to hardcode $libdir into a binary during linking.
++    This must work even if $libdir does not exist])
++_LT_TAGDECL([], [hardcode_libdir_separator], [1],
++    [Whether we need a single "-rpath" flag with a separated argument])
++_LT_TAGDECL([], [hardcode_direct], [0],
++    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
++    DIR into the resulting binary])
++_LT_TAGDECL([], [hardcode_direct_absolute], [0],
++    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
++    DIR into the resulting binary and the resulting library dependency is
++    "absolute", i.e impossible to change by setting $shlibpath_var if the
++    library is relocated])
++_LT_TAGDECL([], [hardcode_minus_L], [0],
++    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
++    into the resulting binary])
++_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
++    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
++    into the resulting binary])
++_LT_TAGDECL([], [hardcode_automatic], [0],
++    [Set to "yes" if building a shared library automatically hardcodes DIR
++    into the library and all subsequent libraries and executables linked
++    against it])
++_LT_TAGDECL([], [inherit_rpath], [0],
++    [Set to yes if linker adds runtime paths of dependent libraries
++    to runtime path list])
++_LT_TAGDECL([], [link_all_deplibs], [0],
++    [Whether libtool must link a program against all its dependency libraries])
++_LT_TAGDECL([], [always_export_symbols], [0],
++    [Set to "yes" if exported symbols are required])
++_LT_TAGDECL([], [export_symbols_cmds], [2],
++    [The commands to list exported symbols])
++_LT_TAGDECL([], [exclude_expsyms], [1],
++    [Symbols that should not be listed in the preloaded symbols])
++_LT_TAGDECL([], [include_expsyms], [1],
++    [Symbols that must always be exported])
++_LT_TAGDECL([], [prelink_cmds], [2],
++    [Commands necessary for linking programs (against libraries) with templates])
++_LT_TAGDECL([], [postlink_cmds], [2],
++    [Commands necessary for finishing linking programs])
++_LT_TAGDECL([], [file_list_spec], [1],
++    [Specify filename containing input files])
++dnl FIXME: Not yet implemented
++dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
++dnl    [Compiler flag to generate thread safe objects])
++])# _LT_LINKER_SHLIBS
++
++
++# _LT_LANG_C_CONFIG([TAG])
++# ------------------------
++# Ensure that the configuration variables for a C compiler are suitably
++# defined.  These variables are subsequently used by _LT_CONFIG to write
++# the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_C_CONFIG],
++[m4_require([_LT_DECL_EGREP])dnl
++lt_save_CC=$CC
++AC_LANG_PUSH(C)
++
++# Source file extension for C test sources.
++ac_ext=c
++
++# Object file extension for compiled C test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="int some_variable = 0;"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='int main(){return(0);}'
++
++_LT_TAG_COMPILER
++# Save the default compiler, since it gets overwritten when the other
++# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
++compiler_DEFAULT=$CC
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++if test -n "$compiler"; then
++  _LT_COMPILER_NO_RTTI($1)
++  _LT_COMPILER_PIC($1)
++  _LT_COMPILER_C_O($1)
++  _LT_COMPILER_FILE_LOCKS($1)
++  _LT_LINKER_SHLIBS($1)
++  _LT_SYS_DYNAMIC_LINKER($1)
++  _LT_LINKER_HARDCODE_LIBPATH($1)
++  LT_SYS_DLOPEN_SELF
++  _LT_CMD_STRIPLIB
++
++  # Report what library types will actually be built
++  AC_MSG_CHECKING([if libtool supports shared libraries])
++  AC_MSG_RESULT([$can_build_shared])
++
++  AC_MSG_CHECKING([whether to build shared libraries])
++  test no = "$can_build_shared" && enable_shared=no
++
++  # On AIX, shared libraries and static libraries use the same namespace, and
++  # are all built from PIC.
++  case $host_os in
++  aix3*)
++    test yes = "$enable_shared" && enable_static=no
++    if test -n "$RANLIB"; then
++      archive_cmds="$archive_cmds~\$RANLIB \$lib"
++      postinstall_cmds='$RANLIB $lib'
++    fi
++    ;;
++
++  aix[[4-9]]*)
++    if test ia64 != "$host_cpu"; then
++      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++      yes,aix,yes) ;;			# shared object as lib.so file only
++      yes,svr4,*) ;;			# shared object as lib.so archive member only
++      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
++      esac
++    fi
++    ;;
++  esac
++  AC_MSG_RESULT([$enable_shared])
++
++  AC_MSG_CHECKING([whether to build static libraries])
++  # Make sure either enable_shared or enable_static is yes.
++  test yes = "$enable_shared" || enable_static=yes
++  AC_MSG_RESULT([$enable_static])
++
++  _LT_CONFIG($1)
++fi
++AC_LANG_POP
++CC=$lt_save_CC
++])# _LT_LANG_C_CONFIG
++
++
++# _LT_LANG_CXX_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for a C++ compiler are suitably
++# defined.  These variables are subsequently used by _LT_CONFIG to write
++# the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_CXX_CONFIG],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++m4_require([_LT_DECL_EGREP])dnl
++m4_require([_LT_PATH_MANIFEST_TOOL])dnl
++if test -n "$CXX" && ( test no != "$CXX" &&
++    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
++    (test g++ != "$CXX"))); then
++  AC_PROG_CXXCPP
++else
++  _lt_caught_CXX_error=yes
++fi
++
++AC_LANG_PUSH(C++)
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_TAGVAR(allow_undefined_flag, $1)=
++_LT_TAGVAR(always_export_symbols, $1)=no
++_LT_TAGVAR(archive_expsym_cmds, $1)=
++_LT_TAGVAR(compiler_needs_object, $1)=no
++_LT_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_TAGVAR(hardcode_direct, $1)=no
++_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_TAGVAR(hardcode_minus_L, $1)=no
++_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
++_LT_TAGVAR(hardcode_automatic, $1)=no
++_LT_TAGVAR(inherit_rpath, $1)=no
++_LT_TAGVAR(module_cmds, $1)=
++_LT_TAGVAR(module_expsym_cmds, $1)=
++_LT_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++_LT_TAGVAR(no_undefined_flag, $1)=
++_LT_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for C++ test sources.
++ac_ext=cpp
++
++# Object file extension for compiled C++ test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# No sense in running all these tests if we already determined that
++# the CXX compiler isn't working.  Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_caught_CXX_error"; then
++  # Code to be used in simple compile tests
++  lt_simple_compile_test_code="int some_variable = 0;"
++
++  # Code to be used in simple link tests
++  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
++
++  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++  _LT_TAG_COMPILER
++
++  # save warnings/boilerplate of simple test code
++  _LT_COMPILER_BOILERPLATE
++  _LT_LINKER_BOILERPLATE
++
++  # Allow CC to be a program name with arguments.
++  lt_save_CC=$CC
++  lt_save_CFLAGS=$CFLAGS
++  lt_save_LD=$LD
++  lt_save_GCC=$GCC
++  GCC=$GXX
++  lt_save_with_gnu_ld=$with_gnu_ld
++  lt_save_path_LD=$lt_cv_path_LD
++  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
++    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
++  else
++    $as_unset lt_cv_prog_gnu_ld
++  fi
++  if test -n "${lt_cv_path_LDCXX+set}"; then
++    lt_cv_path_LD=$lt_cv_path_LDCXX
++  else
++    $as_unset lt_cv_path_LD
++  fi
++  test -z "${LDCXX+set}" || LD=$LDCXX
++  CC=${CXX-"c++"}
++  CFLAGS=$CXXFLAGS
++  compiler=$CC
++  _LT_TAGVAR(compiler, $1)=$CC
++  _LT_CC_BASENAME([$compiler])
++
++  if test -n "$compiler"; then
++    # We don't want -fno-exception when compiling C++ code, so set the
++    # no_builtin_flag separately
++    if test yes = "$GXX"; then
++      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
++    else
++      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
++    fi
++
++    if test yes = "$GXX"; then
++      # Set up default GNU C++ configuration
++
++      LT_PATH_LD
++
++      # Check if GNU C++ uses GNU ld as the underlying linker, since the
++      # archiving commands below assume that GNU ld is being used.
++      if test yes = "$with_gnu_ld"; then
++        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++
++        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++
++        # If archive_cmds runs LD, not CC, wlarc should be empty
++        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
++        #     investigate it a little bit more. (MM)
++        wlarc='$wl'
++
++        # ancient GNU ld didn't support --whole-archive et. al.
++        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
++	  $GREP 'no-whole-archive' > /dev/null; then
++          _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++        else
++          _LT_TAGVAR(whole_archive_flag_spec, $1)=
++        fi
++      else
++        with_gnu_ld=no
++        wlarc=
++
++        # A generic and very simple default shared library creation
++        # command for GNU C++ for the case where it uses the native
++        # linker, instead of GNU ld.  If possible, this setting should
++        # overridden to take advantage of the native linker features on
++        # the platform it is being used on.
++        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++      fi
++
++      # Commands to make compiler produce verbose output that lists
++      # what "hidden" libraries, object files and flags are used when
++      # linking a shared library.
++      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++
++    else
++      GXX=no
++      with_gnu_ld=no
++      wlarc=
++    fi
++
++    # PORTME: fill in a description of your system's C++ link characteristics
++    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
++    _LT_TAGVAR(ld_shlibs, $1)=yes
++    case $host_os in
++      aix3*)
++        # FIXME: insert proper C++ library support
++        _LT_TAGVAR(ld_shlibs, $1)=no
++        ;;
++      aix[[4-9]]*)
++        if test ia64 = "$host_cpu"; then
++          # On IA64, the linker does run time linking by default, so we don't
++          # have to do anything special.
++          aix_use_runtimelinking=no
++          exp_sym_flag='-Bexport'
++          no_entry_flag=
++        else
++          aix_use_runtimelinking=no
++
++          # Test if we are trying to use run time linking or normal
++          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++          # have runtime linking enabled, and use it for executables.
++          # For shared libraries, we enable/disable runtime linking
++          # depending on the kind of the shared library created -
++          # when "with_aix_soname,aix_use_runtimelinking" is:
++          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
++          # "aix,yes"  lib.so          shared, rtl:yes, for executables
++          #            lib.a           static archive
++          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
++          #            lib.a(lib.so.V) shared, rtl:no,  for executables
++          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
++          #            lib.a(lib.so.V) shared, rtl:no
++          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
++          #            lib.a           static archive
++          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
++	    for ld_flag in $LDFLAGS; do
++	      case $ld_flag in
++	      *-brtl*)
++	        aix_use_runtimelinking=yes
++	        break
++	        ;;
++	      esac
++	    done
++	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
++	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
++	      # so we don't have lib.a shared libs to link our executables.
++	      # We have to force runtime linking in this case.
++	      aix_use_runtimelinking=yes
++	      LDFLAGS="$LDFLAGS -Wl,-brtl"
++	    fi
++	    ;;
++          esac
++
++          exp_sym_flag='-bexport'
++          no_entry_flag='-bnoentry'
++        fi
++
++        # When large executables or shared objects are built, AIX ld can
++        # have problems creating the table of contents.  If linking a library
++        # or program results in "error TOC overflow" add -mminimal-toc to
++        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
++        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++        _LT_TAGVAR(archive_cmds, $1)=''
++        _LT_TAGVAR(hardcode_direct, $1)=yes
++        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++        _LT_TAGVAR(link_all_deplibs, $1)=yes
++        _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
++        case $with_aix_soname,$aix_use_runtimelinking in
++        aix,*) ;;	# no import file
++        svr4,* | *,yes) # use import file
++          # The Import File defines what to hardcode.
++          _LT_TAGVAR(hardcode_direct, $1)=no
++          _LT_TAGVAR(hardcode_direct_absolute, $1)=no
++          ;;
++        esac
++
++        if test yes = "$GXX"; then
++          case $host_os in aix4.[[012]]|aix4.[[012]].*)
++          # We only want to do this on AIX 4.2 and lower, the check
++          # below for broken collect2 doesn't work under 4.3+
++	  collect2name=`$CC -print-prog-name=collect2`
++	  if test -f "$collect2name" &&
++	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
++	  then
++	    # We have reworked collect2
++	    :
++	  else
++	    # We have old collect2
++	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
++	    # It fails to find uninstalled libraries when the uninstalled
++	    # path is not listed in the libpath.  Setting hardcode_minus_L
++	    # to unsupported forces relinking
++	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
++	  fi
++          esac
++          shared_flag='-shared'
++	  if test yes = "$aix_use_runtimelinking"; then
++	    shared_flag=$shared_flag' $wl-G'
++	  fi
++	  # Need to ensure runtime linking is disabled for the traditional
++	  # shared library, or the linker may eventually find shared libraries
++	  # /with/ Import File - we do not want to mix them.
++	  shared_flag_aix='-shared'
++	  shared_flag_svr4='-shared $wl-G'
++        else
++          # not using gcc
++          if test ia64 = "$host_cpu"; then
++	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++	  # chokes on -Wl,-G. The following line is correct:
++	  shared_flag='-G'
++          else
++	    if test yes = "$aix_use_runtimelinking"; then
++	      shared_flag='$wl-G'
++	    else
++	      shared_flag='$wl-bM:SRE'
++	    fi
++	    shared_flag_aix='$wl-bM:SRE'
++	    shared_flag_svr4='$wl-G'
++          fi
++        fi
++
++        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
++        # It seems that -bexpall does not export symbols beginning with
++        # underscore (_), so it is better to generate a list of symbols to
++	# export.
++        _LT_TAGVAR(always_export_symbols, $1)=yes
++	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++          # Warning - without using the other runtime loading flags (-brtl),
++          # -berok will link without error, but may produce a broken library.
++          # The "-G" linker flag allows undefined symbols.
++          _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
++          # Determine the default libpath from the value encoded in an empty
++          # executable.
++          _LT_SYS_MODULE_PATH_AIX([$1])
++          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++
++          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++        else
++          if test ia64 = "$host_cpu"; then
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
++	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
++	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++          else
++	    # Determine the default libpath from the value encoded in an
++	    # empty executable.
++	    _LT_SYS_MODULE_PATH_AIX([$1])
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
++	    # Warning - without using the other run time loading flags,
++	    # -berok will link without error, but may produce a broken library.
++	    _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
++	    _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
++	    if test yes = "$with_gnu_ld"; then
++	      # We only use this code for GNU lds that support --whole-archive.
++	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
++	    else
++	      # Exported symbols can be pulled into shared objects from archives
++	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
++	    fi
++	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
++	    # -brtl affects multiple linker settings, -berok does not and is overridden later
++	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
++	    if test svr4 != "$with_aix_soname"; then
++	      # This is similar to how AIX traditionally builds its shared
++	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
++	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
++	    fi
++	    if test aix != "$with_aix_soname"; then
++	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
++	    else
++	      # used by -dlpreopen to get the symbols
++	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
++	    fi
++	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
++          fi
++        fi
++        ;;
++
++      beos*)
++	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	  # Joseph Beckenbach  says some releases of gcc
++	  # support --undefined.  This deserves some investigation.  FIXME
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	else
++	  _LT_TAGVAR(ld_shlibs, $1)=no
++	fi
++	;;
++
++      chorus*)
++        case $cc_basename in
++          *)
++	  # FIXME: insert proper C++ library support
++	  _LT_TAGVAR(ld_shlibs, $1)=no
++	  ;;
++        esac
++        ;;
++
++      cygwin* | mingw* | pw32* | cegcc*)
++	case $GXX,$cc_basename in
++	,cl* | no,cl* | ,icl* | no,icl*)
++	  # Native MSVC or ICC
++	  # hardcode_libdir_flag_spec is actually meaningless, as there is
++	  # no search path for DLLs.
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
++	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	  _LT_TAGVAR(always_export_symbols, $1)=yes
++	  _LT_TAGVAR(file_list_spec, $1)='@'
++	  # Tell ltmain to make .lib files, not .a files.
++	  libext=lib
++	  # Tell ltmain to make .dll files, not .so files.
++	  shrext_cmds=.dll
++	  # FIXME: Setting linknames here is a bad hack.
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++              cp "$export_symbols" "$output_objdir/$soname.def";
++              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
++            else
++              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
++            fi~
++            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
++            linknames='
++	  # The linker will not automatically build a static lib if we build a DLL.
++	  # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
++	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++	  # Don't use ranlib
++	  _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
++	  _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
++            lt_tool_outputfile="@TOOL_OUTPUT@"~
++            case $lt_outputfile in
++              *.exe|*.EXE) ;;
++              *)
++                lt_outputfile=$lt_outputfile.exe
++                lt_tool_outputfile=$lt_tool_outputfile.exe
++                ;;
++            esac~
++            func_to_tool_file "$lt_outputfile"~
++            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
++              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
++              $RM "$lt_outputfile.manifest";
++            fi'
++	  ;;
++	*)
++	  # g++
++	  # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
++	  # as there is no search path for DLLs.
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
++	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	  _LT_TAGVAR(always_export_symbols, $1)=no
++	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++
++	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	    # If the export-symbols file already is a .def file, use it as
++	    # is; otherwise, prepend EXPORTS...
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
++              cp $export_symbols $output_objdir/$soname.def;
++            else
++              echo EXPORTS > $output_objdir/$soname.def;
++              cat $export_symbols >> $output_objdir/$soname.def;
++            fi~
++            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	  else
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	  fi
++	  ;;
++	esac
++	;;
++      darwin* | rhapsody*)
++        _LT_DARWIN_LINKER_FEATURES($1)
++	;;
++
++      os2*)
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
++	_LT_TAGVAR(hardcode_minus_L, $1)=yes
++	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
++	shrext_cmds=.dll
++	_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	  $ECHO EXPORTS >> $output_objdir/$libname.def~
++	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	  emximp -o $lib $output_objdir/$libname.def'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	  $ECHO EXPORTS >> $output_objdir/$libname.def~
++	  prefix_cmds="$SED"~
++	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
++	    prefix_cmds="$prefix_cmds -e 1d";
++	  fi~
++	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	  emximp -o $lib $output_objdir/$libname.def'
++	_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
++	_LT_TAGVAR(file_list_spec, $1)='@'
++	;;
++
++      dgux*)
++        case $cc_basename in
++          ec++*)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          ghcx*)
++	    # Green Hills C++ Compiler
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          *)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++        esac
++        ;;
++
++      freebsd2.*)
++        # C++ shared libraries reported to be fairly broken before
++	# switch to ELF
++        _LT_TAGVAR(ld_shlibs, $1)=no
++        ;;
++
++      freebsd-elf*)
++        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++        ;;
++
++      freebsd* | dragonfly* | midnightbsd*)
++        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
++        # conventions
++        _LT_TAGVAR(ld_shlibs, $1)=yes
++        ;;
++
++      haiku*)
++        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++        _LT_TAGVAR(link_all_deplibs, $1)=yes
++        ;;
++
++      hpux9*)
++        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++        _LT_TAGVAR(hardcode_direct, $1)=yes
++        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++				             # but as the default
++				             # location of the library.
++
++        case $cc_basename in
++          CC*)
++            # FIXME: insert proper C++ library support
++            _LT_TAGVAR(ld_shlibs, $1)=no
++            ;;
++          aCC*)
++            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++            # Commands to make compiler produce verbose output that lists
++            # what "hidden" libraries, object files and flags are used when
++            # linking a shared library.
++            #
++            # There doesn't appear to be a way to prevent this compiler from
++            # explicitly linking system object files so we need to strip them
++            # from the output so that they don't get included in the library
++            # dependencies.
++            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++            ;;
++          *)
++            if test yes = "$GXX"; then
++              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++            else
++              # FIXME: insert proper C++ library support
++              _LT_TAGVAR(ld_shlibs, $1)=no
++            fi
++            ;;
++        esac
++        ;;
++
++      hpux10*|hpux11*)
++        if test no = "$with_gnu_ld"; then
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
++	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++          case $host_cpu in
++            hppa*64*|ia64*)
++              ;;
++            *)
++	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++              ;;
++          esac
++        fi
++        case $host_cpu in
++          hppa*64*|ia64*)
++            _LT_TAGVAR(hardcode_direct, $1)=no
++            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++            ;;
++          *)
++            _LT_TAGVAR(hardcode_direct, $1)=yes
++            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
++					         # but as the default
++					         # location of the library.
++            ;;
++        esac
++
++        case $cc_basename in
++          CC*)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          aCC*)
++	    case $host_cpu in
++	      hppa*64*)
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        ;;
++	      ia64*)
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        ;;
++	      *)
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        ;;
++	    esac
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    ;;
++          *)
++	    if test yes = "$GXX"; then
++	      if test no = "$with_gnu_ld"; then
++	        case $host_cpu in
++	          hppa*64*)
++	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            ;;
++	          ia64*)
++	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            ;;
++	          *)
++	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            ;;
++	        esac
++	      fi
++	    else
++	      # FIXME: insert proper C++ library support
++	      _LT_TAGVAR(ld_shlibs, $1)=no
++	    fi
++	    ;;
++        esac
++        ;;
++
++      interix[[3-9]]*)
++	_LT_TAGVAR(hardcode_direct, $1)=no
++	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
++	# Instead, shared libraries are loaded at an image base (0x10000000 by
++	# default) and relocated if they conflict, which is a slow very memory
++	# consuming and fragmenting process.  To avoid this, we pick a random,
++	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
++	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
++	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++	_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++	;;
++      irix5* | irix6*)
++        case $cc_basename in
++          CC*)
++	    # SGI C++
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++
++	    # Archives containing C++ object files must be created using
++	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
++	    # necessary to make sure instantiated templates are included
++	    # in the archive.
++	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
++	    ;;
++          *)
++	    if test yes = "$GXX"; then
++	      if test no = "$with_gnu_ld"; then
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	      else
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
++	      fi
++	    fi
++	    _LT_TAGVAR(link_all_deplibs, $1)=yes
++	    ;;
++        esac
++        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++        _LT_TAGVAR(inherit_rpath, $1)=yes
++        ;;
++
++      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++        case $cc_basename in
++          KCC*)
++	    # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++	    # KCC will only create a shared library if the output file
++	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
++	    # to its proper name (with version) after linking.
++	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++
++	    # Archives containing C++ object files must be created using
++	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
++	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
++	    ;;
++	  icpc* | ecpc* )
++	    # Intel C++
++	    with_gnu_ld=yes
++	    # version 8.0 and above of icpc choke on multiply defined symbols
++	    # if we add $predep_objects and $postdep_objects, however 7.1 and
++	    # earlier do not add the objects themselves.
++	    case `$CC -V 2>&1` in
++	      *"Version 7."*)
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++		;;
++	      *)  # Version 8.0 or newer
++	        tmp_idyn=
++	        case $host_cpu in
++		  ia64*) tmp_idyn=' -i_dynamic';;
++		esac
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++		;;
++	    esac
++	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
++	    ;;
++          pgCC* | pgcpp*)
++            # Portland Group C++ compiler
++	    case `$CC -V` in
++	    *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
++	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
++               rm -rf $tpldir~
++               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
++               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
++	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
++                rm -rf $tpldir~
++                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
++                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
++                $RANLIB $oldlib'
++	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
++                rm -rf $tpldir~
++                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
++                rm -rf $tpldir~
++                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	      ;;
++	    *) # Version 6 and above use weak symbols
++	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	      ;;
++	    esac
++
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
++	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++            ;;
++	  cxx*)
++	    # Compaq C++
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
++
++	    runpath_var=LD_RUN_PATH
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
++	    ;;
++	  xl* | mpixl* | bgxl*)
++	    # IBM XL 8.0 on PPC, with GNU ld
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	    if test yes = "$supports_anon_versioning"; then
++	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
++                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++                echo "local: *; };" >> $output_objdir/$libname.ver~
++                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++	    fi
++	    ;;
++	  *)
++	    case `$CC -V 2>&1 | $SED 5q` in
++	    *Sun\ C*)
++	      # Sun C++ 5.9
++	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
++	      _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
++	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	      _LT_TAGVAR(compiler_needs_object, $1)=yes
++
++	      # Not sure whether something based on
++	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
++	      # would be better.
++	      output_verbose_link_cmd='func_echo_all'
++
++	      # Archives containing C++ object files must be created using
++	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
++	      # necessary to make sure instantiated templates are included
++	      # in the archive.
++	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
++	      ;;
++	    esac
++	    ;;
++	esac
++	;;
++
++      lynxos*)
++        # FIXME: insert proper C++ library support
++	_LT_TAGVAR(ld_shlibs, $1)=no
++	;;
++
++      m88k*)
++        # FIXME: insert proper C++ library support
++        _LT_TAGVAR(ld_shlibs, $1)=no
++	;;
++
++      mvs*)
++        case $cc_basename in
++          cxx*)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++	  *)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++	esac
++	;;
++
++      netbsd*)
++        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
++	  wlarc=
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++	  _LT_TAGVAR(hardcode_direct, $1)=yes
++	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	fi
++	# Workaround some broken pre-1.5 toolchains
++	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
++	;;
++
++      *nto* | *qnx*)
++        _LT_TAGVAR(ld_shlibs, $1)=yes
++	;;
++
++      openbsd* | bitrig*)
++	if test -f /usr/libexec/ld.so; then
++	  _LT_TAGVAR(hardcode_direct, $1)=yes
++	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
++	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
++	    _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++	  fi
++	  output_verbose_link_cmd=func_echo_all
++	else
++	  _LT_TAGVAR(ld_shlibs, $1)=no
++	fi
++	;;
++
++      osf3* | osf4* | osf5*)
++        case $cc_basename in
++          KCC*)
++	    # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++	    # KCC will only create a shared library if the output file
++	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
++	    # to its proper name (with version) after linking.
++	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
++	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++	    # Archives containing C++ object files must be created using
++	    # the KAI C++ compiler.
++	    case $host in
++	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
++	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
++	    esac
++	    ;;
++          RCC*)
++	    # Rational C++ 2.4.1
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          cxx*)
++	    case $host in
++	      osf3*)
++	        _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++		;;
++	      *)
++	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
++                  echo "-hidden">> $lib.exp~
++                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
++                  $RM $lib.exp'
++	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
++		;;
++	    esac
++
++	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    ;;
++	  *)
++	    if test yes,no = "$GXX,$with_gnu_ld"; then
++	      _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
++	      case $host in
++	        osf3*)
++	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++		  ;;
++	        *)
++	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++		  ;;
++	      esac
++
++	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
++	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
++
++	      # Commands to make compiler produce verbose output that lists
++	      # what "hidden" libraries, object files and flags are used when
++	      # linking a shared library.
++	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++
++	    else
++	      # FIXME: insert proper C++ library support
++	      _LT_TAGVAR(ld_shlibs, $1)=no
++	    fi
++	    ;;
++        esac
++        ;;
++
++      psos*)
++        # FIXME: insert proper C++ library support
++        _LT_TAGVAR(ld_shlibs, $1)=no
++        ;;
++
++      sunos4*)
++        case $cc_basename in
++          CC*)
++	    # Sun C++ 4.x
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          lcc*)
++	    # Lucid
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          *)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++        esac
++        ;;
++
++      solaris*)
++        case $cc_basename in
++          CC* | sunCC*)
++	    # Sun C++ 4.2, 5.x and Centerline C++
++            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
++	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
++	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	    case $host_os in
++	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++	      *)
++		# The compiler driver will combine and reorder linker options,
++		# but understands '-z linker_flag'.
++	        # Supported since Solaris 2.6 (maybe 2.5.1?)
++		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
++	        ;;
++	    esac
++	    _LT_TAGVAR(link_all_deplibs, $1)=yes
++
++	    output_verbose_link_cmd='func_echo_all'
++
++	    # Archives containing C++ object files must be created using
++	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
++	    # necessary to make sure instantiated templates are included
++	    # in the archive.
++	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
++	    ;;
++          gcx*)
++	    # Green Hills C++ Compiler
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++
++	    # The C++ compiler must be used to create the archive.
++	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
++	    ;;
++          *)
++	    # GNU C++ compiler with Solaris linker
++	    if test yes,no = "$GXX,$with_gnu_ld"; then
++	      _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
++	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++	        # Commands to make compiler produce verbose output that lists
++	        # what "hidden" libraries, object files and flags are used when
++	        # linking a shared library.
++	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++	      else
++	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
++	        # platform.
++	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++	        # Commands to make compiler produce verbose output that lists
++	        # what "hidden" libraries, object files and flags are used when
++	        # linking a shared library.
++	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++	      fi
++
++	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
++	      case $host_os in
++		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
++		*)
++		  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++		  ;;
++	      esac
++	    fi
++	    ;;
++        esac
++        ;;
++
++    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
++      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
++      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++      runpath_var='LD_RUN_PATH'
++
++      case $cc_basename in
++        CC*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	*)
++	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++      esac
++      ;;
++
++      sysv5* | sco3.2v5* | sco5v6*)
++	# Note: We CANNOT use -z defs as we might desire, because we do not
++	# link with -lc, and that would cause any symbols used from libc to
++	# always be unresolved, which means just about no library would
++	# ever link correctly.  If we're not using GNU ld we use -z text
++	# though, which does catch some bad symbols but isn't as heavy-handed
++	# as -z defs.
++	_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
++	_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
++	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
++	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
++	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
++	_LT_TAGVAR(link_all_deplibs, $1)=yes
++	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
++	runpath_var='LD_RUN_PATH'
++
++	case $cc_basename in
++          CC*)
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
++              '"$_LT_TAGVAR(old_archive_cmds, $1)"
++	    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
++              '"$_LT_TAGVAR(reload_cmds, $1)"
++	    ;;
++	  *)
++	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    ;;
++	esac
++      ;;
++
++      tandem*)
++        case $cc_basename in
++          NCC*)
++	    # NonStop-UX NCC 3.20
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++          *)
++	    # FIXME: insert proper C++ library support
++	    _LT_TAGVAR(ld_shlibs, $1)=no
++	    ;;
++        esac
++        ;;
++
++      vxworks*)
++        # FIXME: insert proper C++ library support
++        _LT_TAGVAR(ld_shlibs, $1)=no
++        ;;
++
++      *)
++        # FIXME: insert proper C++ library support
++        _LT_TAGVAR(ld_shlibs, $1)=no
++        ;;
++    esac
++
++    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
++    test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
++
++    _LT_TAGVAR(GCC, $1)=$GXX
++    _LT_TAGVAR(LD, $1)=$LD
++
++    ## CAVEAT EMPTOR:
++    ## There is no encapsulation within the following macros, do not change
++    ## the running order or otherwise move them around unless you know exactly
++    ## what you are doing...
++    _LT_SYS_HIDDEN_LIBDEPS($1)
++    _LT_COMPILER_PIC($1)
++    _LT_COMPILER_C_O($1)
++    _LT_COMPILER_FILE_LOCKS($1)
++    _LT_LINKER_SHLIBS($1)
++    _LT_SYS_DYNAMIC_LINKER($1)
++    _LT_LINKER_HARDCODE_LIBPATH($1)
++
++    _LT_CONFIG($1)
++  fi # test -n "$compiler"
++
++  CC=$lt_save_CC
++  CFLAGS=$lt_save_CFLAGS
++  LDCXX=$LD
++  LD=$lt_save_LD
++  GCC=$lt_save_GCC
++  with_gnu_ld=$lt_save_with_gnu_ld
++  lt_cv_path_LDCXX=$lt_cv_path_LD
++  lt_cv_path_LD=$lt_save_path_LD
++  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
++  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
++fi # test yes != "$_lt_caught_CXX_error"
++
++AC_LANG_POP
++])# _LT_LANG_CXX_CONFIG
++
++
++# _LT_FUNC_STRIPNAME_CNF
++# ----------------------
++# func_stripname_cnf prefix suffix name
++# strip PREFIX and SUFFIX off of NAME.
++# PREFIX and SUFFIX must not contain globbing or regex special
++# characters, hashes, percent signs, but SUFFIX may contain a leading
++# dot (in which case that matches only a dot).
++#
++# This function is identical to the (non-XSI) version of func_stripname,
++# except this one can be used by m4 code that may be executed by configure,
++# rather than the libtool script.
++m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
++AC_REQUIRE([_LT_DECL_SED])
++AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
++func_stripname_cnf ()
++{
++  case @S|@2 in
++  .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
++  *)  func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
++  esac
++} # func_stripname_cnf
++])# _LT_FUNC_STRIPNAME_CNF
++
++
++# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
++# ---------------------------------
++# Figure out "hidden" library dependencies from verbose
++# compiler output when linking a shared library.
++# Parse the compiler output and extract the necessary
++# objects, libraries and library flags.
++m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
++[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
++AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
++# Dependencies to place before and after the object being linked:
++_LT_TAGVAR(predep_objects, $1)=
++_LT_TAGVAR(postdep_objects, $1)=
++_LT_TAGVAR(predeps, $1)=
++_LT_TAGVAR(postdeps, $1)=
++_LT_TAGVAR(compiler_lib_search_path, $1)=
++
++dnl we can't use the lt_simple_compile_test_code here,
++dnl because it contains code intended for an executable,
++dnl not a library.  It's possible we should let each
++dnl tag define a new lt_????_link_test_code variable,
++dnl but it's only used here...
++m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
++int a;
++void foo (void) { a = 0; }
++_LT_EOF
++], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
++class Foo
++{
++public:
++  Foo (void) { a = 0; }
++private:
++  int a;
++};
++_LT_EOF
++], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
++      subroutine foo
++      implicit none
++      integer*4 a
++      a=0
++      return
++      end
++_LT_EOF
++], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
++      subroutine foo
++      implicit none
++      integer a
++      a=0
++      return
++      end
++_LT_EOF
++], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
++public class foo {
++  private int a;
++  public void bar (void) {
++    a = 0;
++  }
++};
++_LT_EOF
++], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
++package foo
++func foo() {
++}
++_LT_EOF
++])
++
++_lt_libdeps_save_CFLAGS=$CFLAGS
++case "$CC $CFLAGS " in #(
++*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
++*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
++*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
++esac
++
++dnl Parse the compiler output and extract the necessary
++dnl objects, libraries and library flags.
++if AC_TRY_EVAL(ac_compile); then
++  # Parse the compiler output and extract the necessary
++  # objects, libraries and library flags.
++
++  # Sentinel used to keep track of whether or not we are before
++  # the conftest object file.
++  pre_test_object_deps_done=no
++
++  for p in `eval "$output_verbose_link_cmd"`; do
++    case $prev$p in
++
++    -L* | -R* | -l*)
++       # Some compilers place space between "-{L,R}" and the path.
++       # Remove the space.
++       if test x-L = "$p" ||
++          test x-R = "$p"; then
++	 prev=$p
++	 continue
++       fi
++
++       # Expand the sysroot to ease extracting the directories later.
++       if test -z "$prev"; then
++         case $p in
++         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
++         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
++         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
++         esac
++       fi
++       case $p in
++       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
++       esac
++       if test no = "$pre_test_object_deps_done"; then
++	 case $prev in
++	 -L | -R)
++	   # Internal compiler library paths should come after those
++	   # provided the user.  The postdeps already come after the
++	   # user supplied libs so there is no need to process them.
++	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
++	     _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
++	   else
++	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
++	   fi
++	   ;;
++	 # The "-l" case would never come before the object being
++	 # linked, so don't bother handling this case.
++	 esac
++       else
++	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
++	   _LT_TAGVAR(postdeps, $1)=$prev$p
++	 else
++	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
++	 fi
++       fi
++       prev=
++       ;;
++
++    *.lto.$objext) ;; # Ignore GCC LTO objects
++    *.$objext)
++       # This assumes that the test object file only shows up
++       # once in the compiler output.
++       if test "$p" = "conftest.$objext"; then
++	 pre_test_object_deps_done=yes
++	 continue
++       fi
++
++       if test no = "$pre_test_object_deps_done"; then
++	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
++	   _LT_TAGVAR(predep_objects, $1)=$p
++	 else
++	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
++	 fi
++       else
++	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
++	   _LT_TAGVAR(postdep_objects, $1)=$p
++	 else
++	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
++	 fi
++       fi
++       ;;
++
++    *) ;; # Ignore the rest.
++
++    esac
++  done
++
++  # Clean up.
++  rm -f a.out a.exe
++else
++  echo "libtool.m4: error: problem compiling $1 test program"
++fi
++
++$RM -f confest.$objext
++CFLAGS=$_lt_libdeps_save_CFLAGS
++
++# PORTME: override above test on systems where it is broken
++m4_if([$1], [CXX],
++[case $host_os in
++interix[[3-9]]*)
++  # Interix 3.5 installs completely hosed .la files for C++, so rather than
++  # hack all around it, let's just trust "g++" to DTRT.
++  _LT_TAGVAR(predep_objects,$1)=
++  _LT_TAGVAR(postdep_objects,$1)=
++  _LT_TAGVAR(postdeps,$1)=
++  ;;
++esac
++])
++
++case " $_LT_TAGVAR(postdeps, $1) " in
++*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
++esac
++ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
++if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
++ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
++fi
++_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
++    [The directories searched by this compiler when creating a shared library])
++_LT_TAGDECL([], [predep_objects], [1],
++    [Dependencies to place before and after the objects being linked to
++    create a shared library])
++_LT_TAGDECL([], [postdep_objects], [1])
++_LT_TAGDECL([], [predeps], [1])
++_LT_TAGDECL([], [postdeps], [1])
++_LT_TAGDECL([], [compiler_lib_search_path], [1],
++    [The library search path used internally by the compiler when linking
++    a shared library])
++])# _LT_SYS_HIDDEN_LIBDEPS
++
++
++# _LT_LANG_F77_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for a Fortran 77 compiler are
++# suitably defined.  These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_F77_CONFIG],
++[AC_LANG_PUSH(Fortran 77)
++if test -z "$F77" || test no = "$F77"; then
++  _lt_disable_F77=yes
++fi
++
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_TAGVAR(allow_undefined_flag, $1)=
++_LT_TAGVAR(always_export_symbols, $1)=no
++_LT_TAGVAR(archive_expsym_cmds, $1)=
++_LT_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_TAGVAR(hardcode_direct, $1)=no
++_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_TAGVAR(hardcode_minus_L, $1)=no
++_LT_TAGVAR(hardcode_automatic, $1)=no
++_LT_TAGVAR(inherit_rpath, $1)=no
++_LT_TAGVAR(module_cmds, $1)=
++_LT_TAGVAR(module_expsym_cmds, $1)=
++_LT_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++_LT_TAGVAR(no_undefined_flag, $1)=
++_LT_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for f77 test sources.
++ac_ext=f
++
++# Object file extension for compiled f77 test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# No sense in running all these tests if we already determined that
++# the F77 compiler isn't working.  Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_disable_F77"; then
++  # Code to be used in simple compile tests
++  lt_simple_compile_test_code="\
++      subroutine t
++      return
++      end
++"
++
++  # Code to be used in simple link tests
++  lt_simple_link_test_code="\
++      program t
++      end
++"
++
++  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++  _LT_TAG_COMPILER
++
++  # save warnings/boilerplate of simple test code
++  _LT_COMPILER_BOILERPLATE
++  _LT_LINKER_BOILERPLATE
++
++  # Allow CC to be a program name with arguments.
++  lt_save_CC=$CC
++  lt_save_GCC=$GCC
++  lt_save_CFLAGS=$CFLAGS
++  CC=${F77-"f77"}
++  CFLAGS=$FFLAGS
++  compiler=$CC
++  _LT_TAGVAR(compiler, $1)=$CC
++  _LT_CC_BASENAME([$compiler])
++  GCC=$G77
++  if test -n "$compiler"; then
++    AC_MSG_CHECKING([if libtool supports shared libraries])
++    AC_MSG_RESULT([$can_build_shared])
++
++    AC_MSG_CHECKING([whether to build shared libraries])
++    test no = "$can_build_shared" && enable_shared=no
++
++    # On AIX, shared libraries and static libraries use the same namespace, and
++    # are all built from PIC.
++    case $host_os in
++      aix3*)
++        test yes = "$enable_shared" && enable_static=no
++        if test -n "$RANLIB"; then
++          archive_cmds="$archive_cmds~\$RANLIB \$lib"
++          postinstall_cmds='$RANLIB $lib'
++        fi
++        ;;
++      aix[[4-9]]*)
++	if test ia64 != "$host_cpu"; then
++	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++	  yes,aix,yes) ;;		# shared object as lib.so file only
++	  yes,svr4,*) ;;		# shared object as lib.so archive member only
++	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
++	  esac
++	fi
++        ;;
++    esac
++    AC_MSG_RESULT([$enable_shared])
++
++    AC_MSG_CHECKING([whether to build static libraries])
++    # Make sure either enable_shared or enable_static is yes.
++    test yes = "$enable_shared" || enable_static=yes
++    AC_MSG_RESULT([$enable_static])
++
++    _LT_TAGVAR(GCC, $1)=$G77
++    _LT_TAGVAR(LD, $1)=$LD
++
++    ## CAVEAT EMPTOR:
++    ## There is no encapsulation within the following macros, do not change
++    ## the running order or otherwise move them around unless you know exactly
++    ## what you are doing...
++    _LT_COMPILER_PIC($1)
++    _LT_COMPILER_C_O($1)
++    _LT_COMPILER_FILE_LOCKS($1)
++    _LT_LINKER_SHLIBS($1)
++    _LT_SYS_DYNAMIC_LINKER($1)
++    _LT_LINKER_HARDCODE_LIBPATH($1)
++
++    _LT_CONFIG($1)
++  fi # test -n "$compiler"
++
++  GCC=$lt_save_GCC
++  CC=$lt_save_CC
++  CFLAGS=$lt_save_CFLAGS
++fi # test yes != "$_lt_disable_F77"
++
++AC_LANG_POP
++])# _LT_LANG_F77_CONFIG
++
++
++# _LT_LANG_FC_CONFIG([TAG])
++# -------------------------
++# Ensure that the configuration variables for a Fortran compiler are
++# suitably defined.  These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_FC_CONFIG],
++[AC_LANG_PUSH(Fortran)
++
++if test -z "$FC" || test no = "$FC"; then
++  _lt_disable_FC=yes
++fi
++
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++_LT_TAGVAR(allow_undefined_flag, $1)=
++_LT_TAGVAR(always_export_symbols, $1)=no
++_LT_TAGVAR(archive_expsym_cmds, $1)=
++_LT_TAGVAR(export_dynamic_flag_spec, $1)=
++_LT_TAGVAR(hardcode_direct, $1)=no
++_LT_TAGVAR(hardcode_direct_absolute, $1)=no
++_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
++_LT_TAGVAR(hardcode_libdir_separator, $1)=
++_LT_TAGVAR(hardcode_minus_L, $1)=no
++_LT_TAGVAR(hardcode_automatic, $1)=no
++_LT_TAGVAR(inherit_rpath, $1)=no
++_LT_TAGVAR(module_cmds, $1)=
++_LT_TAGVAR(module_expsym_cmds, $1)=
++_LT_TAGVAR(link_all_deplibs, $1)=unknown
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++_LT_TAGVAR(no_undefined_flag, $1)=
++_LT_TAGVAR(whole_archive_flag_spec, $1)=
++_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
++
++# Source file extension for fc test sources.
++ac_ext=${ac_fc_srcext-f}
++
++# Object file extension for compiled fc test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# No sense in running all these tests if we already determined that
++# the FC compiler isn't working.  Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_disable_FC"; then
++  # Code to be used in simple compile tests
++  lt_simple_compile_test_code="\
++      subroutine t
++      return
++      end
++"
++
++  # Code to be used in simple link tests
++  lt_simple_link_test_code="\
++      program t
++      end
++"
++
++  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++  _LT_TAG_COMPILER
++
++  # save warnings/boilerplate of simple test code
++  _LT_COMPILER_BOILERPLATE
++  _LT_LINKER_BOILERPLATE
++
++  # Allow CC to be a program name with arguments.
++  lt_save_CC=$CC
++  lt_save_GCC=$GCC
++  lt_save_CFLAGS=$CFLAGS
++  CC=${FC-"f95"}
++  CFLAGS=$FCFLAGS
++  compiler=$CC
++  GCC=$ac_cv_fc_compiler_gnu
++
++  _LT_TAGVAR(compiler, $1)=$CC
++  _LT_CC_BASENAME([$compiler])
++
++  if test -n "$compiler"; then
++    AC_MSG_CHECKING([if libtool supports shared libraries])
++    AC_MSG_RESULT([$can_build_shared])
++
++    AC_MSG_CHECKING([whether to build shared libraries])
++    test no = "$can_build_shared" && enable_shared=no
++
++    # On AIX, shared libraries and static libraries use the same namespace, and
++    # are all built from PIC.
++    case $host_os in
++      aix3*)
++        test yes = "$enable_shared" && enable_static=no
++        if test -n "$RANLIB"; then
++          archive_cmds="$archive_cmds~\$RANLIB \$lib"
++          postinstall_cmds='$RANLIB $lib'
++        fi
++        ;;
++      aix[[4-9]]*)
++	if test ia64 != "$host_cpu"; then
++	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++	  yes,aix,yes) ;;		# shared object as lib.so file only
++	  yes,svr4,*) ;;		# shared object as lib.so archive member only
++	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
++	  esac
++	fi
++        ;;
++    esac
++    AC_MSG_RESULT([$enable_shared])
++
++    AC_MSG_CHECKING([whether to build static libraries])
++    # Make sure either enable_shared or enable_static is yes.
++    test yes = "$enable_shared" || enable_static=yes
++    AC_MSG_RESULT([$enable_static])
++
++    _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
++    _LT_TAGVAR(LD, $1)=$LD
++
++    ## CAVEAT EMPTOR:
++    ## There is no encapsulation within the following macros, do not change
++    ## the running order or otherwise move them around unless you know exactly
++    ## what you are doing...
++    _LT_SYS_HIDDEN_LIBDEPS($1)
++    _LT_COMPILER_PIC($1)
++    _LT_COMPILER_C_O($1)
++    _LT_COMPILER_FILE_LOCKS($1)
++    _LT_LINKER_SHLIBS($1)
++    _LT_SYS_DYNAMIC_LINKER($1)
++    _LT_LINKER_HARDCODE_LIBPATH($1)
++
++    _LT_CONFIG($1)
++  fi # test -n "$compiler"
++
++  GCC=$lt_save_GCC
++  CC=$lt_save_CC
++  CFLAGS=$lt_save_CFLAGS
++fi # test yes != "$_lt_disable_FC"
++
++AC_LANG_POP
++])# _LT_LANG_FC_CONFIG
++
++
++# _LT_LANG_GCJ_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for the GNU Java Compiler compiler
++# are suitably defined.  These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_GCJ_CONFIG],
++[AC_REQUIRE([LT_PROG_GCJ])dnl
++AC_LANG_SAVE
++
++# Source file extension for Java test sources.
++ac_ext=java
++
++# Object file extension for compiled Java test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="class foo {}"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_TAG_COMPILER
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_CFLAGS=$CFLAGS
++lt_save_GCC=$GCC
++GCC=yes
++CC=${GCJ-"gcj"}
++CFLAGS=$GCJFLAGS
++compiler=$CC
++_LT_TAGVAR(compiler, $1)=$CC
++_LT_TAGVAR(LD, $1)=$LD
++_LT_CC_BASENAME([$compiler])
++
++# GCJ did not exist at the time GCC didn't implicitly link libc in.
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++
++if test -n "$compiler"; then
++  _LT_COMPILER_NO_RTTI($1)
++  _LT_COMPILER_PIC($1)
++  _LT_COMPILER_C_O($1)
++  _LT_COMPILER_FILE_LOCKS($1)
++  _LT_LINKER_SHLIBS($1)
++  _LT_LINKER_HARDCODE_LIBPATH($1)
++
++  _LT_CONFIG($1)
++fi
++
++AC_LANG_RESTORE
++
++GCC=$lt_save_GCC
++CC=$lt_save_CC
++CFLAGS=$lt_save_CFLAGS
++])# _LT_LANG_GCJ_CONFIG
++
++
++# _LT_LANG_GO_CONFIG([TAG])
++# --------------------------
++# Ensure that the configuration variables for the GNU Go compiler
++# are suitably defined.  These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_GO_CONFIG],
++[AC_REQUIRE([LT_PROG_GO])dnl
++AC_LANG_SAVE
++
++# Source file extension for Go test sources.
++ac_ext=go
++
++# Object file extension for compiled Go test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="package main; func main() { }"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='package main; func main() { }'
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_TAG_COMPILER
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_CFLAGS=$CFLAGS
++lt_save_GCC=$GCC
++GCC=yes
++CC=${GOC-"gccgo"}
++CFLAGS=$GOFLAGS
++compiler=$CC
++_LT_TAGVAR(compiler, $1)=$CC
++_LT_TAGVAR(LD, $1)=$LD
++_LT_CC_BASENAME([$compiler])
++
++# Go did not exist at the time GCC didn't implicitly link libc in.
++_LT_TAGVAR(archive_cmds_need_lc, $1)=no
++
++_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
++_LT_TAGVAR(reload_flag, $1)=$reload_flag
++_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
++
++if test -n "$compiler"; then
++  _LT_COMPILER_NO_RTTI($1)
++  _LT_COMPILER_PIC($1)
++  _LT_COMPILER_C_O($1)
++  _LT_COMPILER_FILE_LOCKS($1)
++  _LT_LINKER_SHLIBS($1)
++  _LT_LINKER_HARDCODE_LIBPATH($1)
++
++  _LT_CONFIG($1)
++fi
++
++AC_LANG_RESTORE
++
++GCC=$lt_save_GCC
++CC=$lt_save_CC
++CFLAGS=$lt_save_CFLAGS
++])# _LT_LANG_GO_CONFIG
++
++
++# _LT_LANG_RC_CONFIG([TAG])
++# -------------------------
++# Ensure that the configuration variables for the Windows resource compiler
++# are suitably defined.  These variables are subsequently used by _LT_CONFIG
++# to write the compiler configuration to 'libtool'.
++m4_defun([_LT_LANG_RC_CONFIG],
++[AC_REQUIRE([LT_PROG_RC])dnl
++AC_LANG_SAVE
++
++# Source file extension for RC test sources.
++ac_ext=rc
++
++# Object file extension for compiled RC test sources.
++objext=o
++_LT_TAGVAR(objext, $1)=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
++
++# Code to be used in simple link tests
++lt_simple_link_test_code=$lt_simple_compile_test_code
++
++# ltmain only uses $CC for tagged configurations so make sure $CC is set.
++_LT_TAG_COMPILER
++
++# save warnings/boilerplate of simple test code
++_LT_COMPILER_BOILERPLATE
++_LT_LINKER_BOILERPLATE
++
++# Allow CC to be a program name with arguments.
++lt_save_CC=$CC
++lt_save_CFLAGS=$CFLAGS
++lt_save_GCC=$GCC
++GCC=
++CC=${RC-"windres"}
++CFLAGS=
++compiler=$CC
++_LT_TAGVAR(compiler, $1)=$CC
++_LT_CC_BASENAME([$compiler])
++_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
++
++if test -n "$compiler"; then
++  :
++  _LT_CONFIG($1)
++fi
++
++GCC=$lt_save_GCC
++AC_LANG_RESTORE
++CC=$lt_save_CC
++CFLAGS=$lt_save_CFLAGS
++])# _LT_LANG_RC_CONFIG
++
++
++# LT_PROG_GCJ
++# -----------
++AC_DEFUN([LT_PROG_GCJ],
++[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
++  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
++    [AC_CHECK_TOOL(GCJ, gcj,)
++      test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
++      AC_SUBST(GCJFLAGS)])])[]dnl
++])
++
++# Old name:
++AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
++
++
++# LT_PROG_GO
++# ----------
++AC_DEFUN([LT_PROG_GO],
++[AC_CHECK_TOOL(GOC, gccgo,)
++])
++
++
++# LT_PROG_RC
++# ----------
++AC_DEFUN([LT_PROG_RC],
++[AC_CHECK_TOOL(RC, windres,)
++])
++
++# Old name:
++AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([LT_AC_PROG_RC], [])
++
++
++# _LT_DECL_EGREP
++# --------------
++# If we don't have a new enough Autoconf to choose the best grep
++# available, choose the one first in the user's PATH.
++m4_defun([_LT_DECL_EGREP],
++[AC_REQUIRE([AC_PROG_EGREP])dnl
++AC_REQUIRE([AC_PROG_FGREP])dnl
++test -z "$GREP" && GREP=grep
++_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
++_LT_DECL([], [EGREP], [1], [An ERE matcher])
++_LT_DECL([], [FGREP], [1], [A literal string matcher])
++dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
++AC_SUBST([GREP])
++])
++
++
++# _LT_DECL_OBJDUMP
++# --------------
++# If we don't have a new enough Autoconf to choose the best objdump
++# available, choose the one first in the user's PATH.
++m4_defun([_LT_DECL_OBJDUMP],
++[AC_CHECK_TOOL(OBJDUMP, objdump, false)
++test -z "$OBJDUMP" && OBJDUMP=objdump
++_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
++AC_SUBST([OBJDUMP])
++])
++
++# _LT_DECL_DLLTOOL
++# ----------------
++# Ensure DLLTOOL variable is set.
++m4_defun([_LT_DECL_DLLTOOL],
++[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
++test -z "$DLLTOOL" && DLLTOOL=dlltool
++_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
++AC_SUBST([DLLTOOL])
++])
++
++# _LT_DECL_FILECMD
++# ----------------
++# Check for a file(cmd) program that can be used to detect file type and magic
++m4_defun([_LT_DECL_FILECMD],
++[AC_CHECK_TOOL([FILECMD], [file], [:])
++_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
++])# _LD_DECL_FILECMD
++
++# _LT_DECL_SED
++# ------------
++# Check for a fully-functional sed program, that truncates
++# as few characters as possible.  Prefer GNU sed if found.
++m4_defun([_LT_DECL_SED],
++[AC_PROG_SED
++test -z "$SED" && SED=sed
++Xsed="$SED -e 1s/^X//"
++_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
++_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
++    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
++])# _LT_DECL_SED
++
++m4_ifndef([AC_PROG_SED], [
++# NOTE: This macro has been submitted for inclusion into   #
++#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
++#  a released version of Autoconf we should remove this    #
++#  macro and use it instead.                               #
++
++m4_defun([AC_PROG_SED],
++[AC_MSG_CHECKING([for a sed that does not truncate output])
++AC_CACHE_VAL(lt_cv_path_SED,
++[# Loop through the user's path and test for sed and gsed.
++# Then use that list of sed's as ones to test for truncation.
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++  for lt_ac_prog in sed gsed; do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
++        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
++      fi
++    done
++  done
++done
++IFS=$as_save_IFS
++lt_ac_max=0
++lt_ac_count=0
++# Add /usr/xpg4/bin/sed as it is typically found on Solaris
++# along with /bin/sed that truncates output.
++for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
++  test ! -f "$lt_ac_sed" && continue
++  cat /dev/null > conftest.in
++  lt_ac_count=0
++  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
++  # Check for GNU sed and select it if it is found.
++  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
++    lt_cv_path_SED=$lt_ac_sed
++    break
++  fi
++  while true; do
++    cat conftest.in conftest.in >conftest.tmp
++    mv conftest.tmp conftest.in
++    cp conftest.in conftest.nl
++    echo >>conftest.nl
++    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
++    cmp -s conftest.out conftest.nl || break
++    # 10000 chars as input seems more than enough
++    test 10 -lt "$lt_ac_count" && break
++    lt_ac_count=`expr $lt_ac_count + 1`
++    if test "$lt_ac_count" -gt "$lt_ac_max"; then
++      lt_ac_max=$lt_ac_count
++      lt_cv_path_SED=$lt_ac_sed
++    fi
++  done
++done
++])
++SED=$lt_cv_path_SED
++AC_SUBST([SED])
++AC_MSG_RESULT([$SED])
++])#AC_PROG_SED
++])#m4_ifndef
++
++# Old name:
++AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([LT_AC_PROG_SED], [])
++
++
++# _LT_CHECK_SHELL_FEATURES
++# ------------------------
++# Find out whether the shell is Bourne or XSI compatible,
++# or has some other useful features.
++m4_defun([_LT_CHECK_SHELL_FEATURES],
++[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
++  lt_unset=unset
++else
++  lt_unset=false
++fi
++_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
++
++# test EBCDIC or ASCII
++case `echo X|tr X '\101'` in
++ A) # ASCII based system
++    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
++  lt_SP2NL='tr \040 \012'
++  lt_NL2SP='tr \015\012 \040\040'
++  ;;
++ *) # EBCDIC based system
++  lt_SP2NL='tr \100 \n'
++  lt_NL2SP='tr \r\n \100\100'
++  ;;
++esac
++_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
++_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
++])# _LT_CHECK_SHELL_FEATURES
++
++
++# _LT_PATH_CONVERSION_FUNCTIONS
++# -----------------------------
++# Determine what file name conversion functions should be used by
++# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
++# for certain cross-compile configurations and native mingw.
++m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++AC_REQUIRE([AC_CANONICAL_BUILD])dnl
++AC_MSG_CHECKING([how to convert $build file names to $host format])
++AC_CACHE_VAL(lt_cv_to_host_file_cmd,
++[case $host in
++  *-*-mingw* )
++    case $build in
++      *-*-mingw* ) # actually msys
++        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
++        ;;
++      *-*-cygwin* )
++        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
++        ;;
++      * ) # otherwise, assume *nix
++        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
++        ;;
++    esac
++    ;;
++  *-*-cygwin* )
++    case $build in
++      *-*-mingw* ) # actually msys
++        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
++        ;;
++      *-*-cygwin* )
++        lt_cv_to_host_file_cmd=func_convert_file_noop
++        ;;
++      * ) # otherwise, assume *nix
++        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
++        ;;
++    esac
++    ;;
++  * ) # unhandled hosts (and "normal" native builds)
++    lt_cv_to_host_file_cmd=func_convert_file_noop
++    ;;
++esac
++])
++to_host_file_cmd=$lt_cv_to_host_file_cmd
++AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
++_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
++         [0], [convert $build file names to $host format])dnl
++
++AC_MSG_CHECKING([how to convert $build file names to toolchain format])
++AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
++[#assume ordinary cross tools, or native build.
++lt_cv_to_tool_file_cmd=func_convert_file_noop
++case $host in
++  *-*-mingw* )
++    case $build in
++      *-*-mingw* ) # actually msys
++        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
++        ;;
++    esac
++    ;;
++esac
++])
++to_tool_file_cmd=$lt_cv_to_tool_file_cmd
++AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
++_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
++         [0], [convert $build files to toolchain format])dnl
++])# _LT_PATH_CONVERSION_FUNCTIONS
++
++# Helper functions for option handling.                    -*- Autoconf -*-
++#
++#   Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
++#   Software Foundation, Inc.
++#   Written by Gary V. Vaughan, 2004
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# serial 8 ltoptions.m4
++
++# This is to help aclocal find these macros, as it can't see m4_define.
++AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
++
++
++# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
++# ------------------------------------------
++m4_define([_LT_MANGLE_OPTION],
++[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
++
++
++# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
++# ---------------------------------------
++# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
++# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
++# saved as a flag.
++m4_define([_LT_SET_OPTION],
++[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
++m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
++        _LT_MANGLE_DEFUN([$1], [$2]),
++    [m4_warning([Unknown $1 option '$2'])])[]dnl
++])
++
++
++# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
++# ------------------------------------------------------------
++# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
++m4_define([_LT_IF_OPTION],
++[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
++
++
++# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
++# -------------------------------------------------------
++# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
++# are set.
++m4_define([_LT_UNLESS_OPTIONS],
++[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
++	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
++		      [m4_define([$0_found])])])[]dnl
++m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
++])[]dnl
++])
++
++
++# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
++# ----------------------------------------
++# OPTION-LIST is a space-separated list of Libtool options associated
++# with MACRO-NAME.  If any OPTION has a matching handler declared with
++# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
++# the unknown option and exit.
++m4_defun([_LT_SET_OPTIONS],
++[# Set options
++m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
++    [_LT_SET_OPTION([$1], _LT_Option)])
++
++m4_if([$1],[LT_INIT],[
++  dnl
++  dnl Simply set some default values (i.e off) if boolean options were not
++  dnl specified:
++  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
++  ])
++  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
++  ])
++  dnl
++  dnl If no reference was made to various pairs of opposing options, then
++  dnl we run the default mode handler for the pair.  For example, if neither
++  dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
++  dnl archives by default:
++  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
++  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
++  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
++  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
++		   [_LT_ENABLE_FAST_INSTALL])
++  _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
++		   [_LT_WITH_AIX_SONAME([aix])])
++  ])
++])# _LT_SET_OPTIONS
++
++
++
++# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
++# -----------------------------------------
++m4_define([_LT_MANGLE_DEFUN],
++[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
++
++
++# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
++# -----------------------------------------------
++m4_define([LT_OPTION_DEFINE],
++[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
++])# LT_OPTION_DEFINE
++
++
++# dlopen
++# ------
++LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
++])
++
++AU_DEFUN([AC_LIBTOOL_DLOPEN],
++[_LT_SET_OPTION([LT_INIT], [dlopen])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you
++put the 'dlopen' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
++
++
++# win32-dll
++# ---------
++# Declare package support for building win32 dll's.
++LT_OPTION_DEFINE([LT_INIT], [win32-dll],
++[enable_win32_dll=yes
++
++case $host in
++*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
++  AC_CHECK_TOOL(AS, as, false)
++  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
++  AC_CHECK_TOOL(OBJDUMP, objdump, false)
++  ;;
++esac
++
++test -z "$AS" && AS=as
++_LT_DECL([], [AS],      [1], [Assembler program])dnl
++
++test -z "$DLLTOOL" && DLLTOOL=dlltool
++_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
++
++test -z "$OBJDUMP" && OBJDUMP=objdump
++_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
++])# win32-dll
++
++AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
++[AC_REQUIRE([AC_CANONICAL_HOST])dnl
++_LT_SET_OPTION([LT_INIT], [win32-dll])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you
++put the 'win32-dll' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
++
++
++# _LT_ENABLE_SHARED([DEFAULT])
++# ----------------------------
++# implement the --enable-shared flag, and supports the 'shared' and
++# 'disable-shared' LT_INIT options.
++# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
++m4_define([_LT_ENABLE_SHARED],
++[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
++AC_ARG_ENABLE([shared],
++    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
++	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
++    [p=${PACKAGE-default}
++    case $enableval in
++    yes) enable_shared=yes ;;
++    no) enable_shared=no ;;
++    *)
++      enable_shared=no
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for pkg in $enableval; do
++	IFS=$lt_save_ifs
++	if test "X$pkg" = "X$p"; then
++	  enable_shared=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac],
++    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
++
++    _LT_DECL([build_libtool_libs], [enable_shared], [0],
++	[Whether or not to build shared libraries])
++])# _LT_ENABLE_SHARED
++
++LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
++LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
++
++# Old names:
++AC_DEFUN([AC_ENABLE_SHARED],
++[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
++])
++
++AC_DEFUN([AC_DISABLE_SHARED],
++[_LT_SET_OPTION([LT_INIT], [disable-shared])
++])
++
++AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
++AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_ENABLE_SHARED], [])
++dnl AC_DEFUN([AM_DISABLE_SHARED], [])
++
++
++
++# _LT_ENABLE_STATIC([DEFAULT])
++# ----------------------------
++# implement the --enable-static flag, and support the 'static' and
++# 'disable-static' LT_INIT options.
++# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
++m4_define([_LT_ENABLE_STATIC],
++[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
++AC_ARG_ENABLE([static],
++    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
++	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
++    [p=${PACKAGE-default}
++    case $enableval in
++    yes) enable_static=yes ;;
++    no) enable_static=no ;;
++    *)
++     enable_static=no
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for pkg in $enableval; do
++	IFS=$lt_save_ifs
++	if test "X$pkg" = "X$p"; then
++	  enable_static=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac],
++    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
++
++    _LT_DECL([build_old_libs], [enable_static], [0],
++	[Whether or not to build static libraries])
++])# _LT_ENABLE_STATIC
++
++LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
++LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
++
++# Old names:
++AC_DEFUN([AC_ENABLE_STATIC],
++[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
++])
++
++AC_DEFUN([AC_DISABLE_STATIC],
++[_LT_SET_OPTION([LT_INIT], [disable-static])
++])
++
++AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
++AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AM_ENABLE_STATIC], [])
++dnl AC_DEFUN([AM_DISABLE_STATIC], [])
++
++
++
++# _LT_ENABLE_FAST_INSTALL([DEFAULT])
++# ----------------------------------
++# implement the --enable-fast-install flag, and support the 'fast-install'
++# and 'disable-fast-install' LT_INIT options.
++# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
++m4_define([_LT_ENABLE_FAST_INSTALL],
++[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
++AC_ARG_ENABLE([fast-install],
++    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
++    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
++    [p=${PACKAGE-default}
++    case $enableval in
++    yes) enable_fast_install=yes ;;
++    no) enable_fast_install=no ;;
++    *)
++      enable_fast_install=no
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for pkg in $enableval; do
++	IFS=$lt_save_ifs
++	if test "X$pkg" = "X$p"; then
++	  enable_fast_install=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac],
++    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
++
++_LT_DECL([fast_install], [enable_fast_install], [0],
++	 [Whether or not to optimize for fast installation])dnl
++])# _LT_ENABLE_FAST_INSTALL
++
++LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
++LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
++
++# Old names:
++AU_DEFUN([AC_ENABLE_FAST_INSTALL],
++[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you put
++the 'fast-install' option into LT_INIT's first parameter.])
++])
++
++AU_DEFUN([AC_DISABLE_FAST_INSTALL],
++[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you put
++the 'disable-fast-install' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
++dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
++
++
++# _LT_WITH_AIX_SONAME([DEFAULT])
++# ----------------------------------
++# implement the --with-aix-soname flag, and support the `aix-soname=aix'
++# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
++# is either `aix', `both' or `svr4'.  If omitted, it defaults to `aix'.
++m4_define([_LT_WITH_AIX_SONAME],
++[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
++shared_archive_member_spec=
++case $host,$enable_shared in
++power*-*-aix[[5-9]]*,yes)
++  AC_MSG_CHECKING([which variant of shared library versioning to provide])
++  AC_ARG_WITH([aix-soname],
++    [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
++      [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
++    [case $withval in
++    aix|svr4|both)
++      ;;
++    *)
++      AC_MSG_ERROR([Unknown argument to --with-aix-soname])
++      ;;
++    esac
++    lt_cv_with_aix_soname=$with_aix_soname],
++    [AC_CACHE_VAL([lt_cv_with_aix_soname],
++      [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
++    with_aix_soname=$lt_cv_with_aix_soname])
++  AC_MSG_RESULT([$with_aix_soname])
++  if test aix != "$with_aix_soname"; then
++    # For the AIX way of multilib, we name the shared archive member
++    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
++    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
++    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
++    # the AIX toolchain works better with OBJECT_MODE set (default 32).
++    if test 64 = "${OBJECT_MODE-32}"; then
++      shared_archive_member_spec=shr_64
++    else
++      shared_archive_member_spec=shr
++    fi
++  fi
++  ;;
++*)
++  with_aix_soname=aix
++  ;;
++esac
++
++_LT_DECL([], [shared_archive_member_spec], [0],
++    [Shared archive member basename, for filename based shared library versioning on AIX])dnl
++])# _LT_WITH_AIX_SONAME
++
++LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
++LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
++LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
++
++
++# _LT_WITH_PIC([MODE])
++# --------------------
++# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
++# LT_INIT options.
++# MODE is either 'yes' or 'no'.  If omitted, it defaults to 'both'.
++m4_define([_LT_WITH_PIC],
++[AC_ARG_WITH([pic],
++    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
++	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
++    [lt_p=${PACKAGE-default}
++    case $withval in
++    yes|no) pic_mode=$withval ;;
++    *)
++      pic_mode=default
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for lt_pkg in $withval; do
++	IFS=$lt_save_ifs
++	if test "X$lt_pkg" = "X$lt_p"; then
++	  pic_mode=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac],
++    [pic_mode=m4_default([$1], [default])])
++
++_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
++])# _LT_WITH_PIC
++
++LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
++LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
++
++# Old name:
++AU_DEFUN([AC_LIBTOOL_PICMODE],
++[_LT_SET_OPTION([LT_INIT], [pic-only])
++AC_DIAGNOSE([obsolete],
++[$0: Remove this warning and the call to _LT_SET_OPTION when you
++put the 'pic-only' option into LT_INIT's first parameter.])
++])
++
++dnl aclocal-1.4 backwards compatibility:
++dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
++
++
++m4_define([_LTDL_MODE], [])
++LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
++		 [m4_define([_LTDL_MODE], [nonrecursive])])
++LT_OPTION_DEFINE([LTDL_INIT], [recursive],
++		 [m4_define([_LTDL_MODE], [recursive])])
++LT_OPTION_DEFINE([LTDL_INIT], [subproject],
++		 [m4_define([_LTDL_MODE], [subproject])])
++
++m4_define([_LTDL_TYPE], [])
++LT_OPTION_DEFINE([LTDL_INIT], [installable],
++		 [m4_define([_LTDL_TYPE], [installable])])
++LT_OPTION_DEFINE([LTDL_INIT], [convenience],
++		 [m4_define([_LTDL_TYPE], [convenience])])
++
++# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
++#
++# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
++# Foundation, Inc.
++# Written by Gary V. Vaughan, 2004
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# serial 6 ltsugar.m4
++
++# This is to help aclocal find these macros, as it can't see m4_define.
++AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
++
++
++# lt_join(SEP, ARG1, [ARG2...])
++# -----------------------------
++# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
++# associated separator.
++# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
++# versions in m4sugar had bugs.
++m4_define([lt_join],
++[m4_if([$#], [1], [],
++       [$#], [2], [[$2]],
++       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
++m4_define([_lt_join],
++[m4_if([$#$2], [2], [],
++       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
++
++
++# lt_car(LIST)
++# lt_cdr(LIST)
++# ------------
++# Manipulate m4 lists.
++# These macros are necessary as long as will still need to support
++# Autoconf-2.59, which quotes differently.
++m4_define([lt_car], [[$1]])
++m4_define([lt_cdr],
++[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
++       [$#], 1, [],
++       [m4_dquote(m4_shift($@))])])
++m4_define([lt_unquote], $1)
++
++
++# lt_append(MACRO-NAME, STRING, [SEPARATOR])
++# ------------------------------------------
++# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
++# Note that neither SEPARATOR nor STRING are expanded; they are appended
++# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
++# No SEPARATOR is output if MACRO-NAME was previously undefined (different
++# than defined and empty).
++#
++# This macro is needed until we can rely on Autoconf 2.62, since earlier
++# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
++m4_define([lt_append],
++[m4_define([$1],
++	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
++
++
++
++# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
++# ----------------------------------------------------------
++# Produce a SEP delimited list of all paired combinations of elements of
++# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
++# has the form PREFIXmINFIXSUFFIXn.
++# Needed until we can rely on m4_combine added in Autoconf 2.62.
++m4_define([lt_combine],
++[m4_if(m4_eval([$# > 3]), [1],
++       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
++[[m4_foreach([_Lt_prefix], [$2],
++	     [m4_foreach([_Lt_suffix],
++		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
++	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
++
++
++# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
++# -----------------------------------------------------------------------
++# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
++# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
++m4_define([lt_if_append_uniq],
++[m4_ifdef([$1],
++	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
++		 [lt_append([$1], [$2], [$3])$4],
++		 [$5])],
++	  [lt_append([$1], [$2], [$3])$4])])
++
++
++# lt_dict_add(DICT, KEY, VALUE)
++# -----------------------------
++m4_define([lt_dict_add],
++[m4_define([$1($2)], [$3])])
++
++
++# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
++# --------------------------------------------
++m4_define([lt_dict_add_subkey],
++[m4_define([$1($2:$3)], [$4])])
++
++
++# lt_dict_fetch(DICT, KEY, [SUBKEY])
++# ----------------------------------
++m4_define([lt_dict_fetch],
++[m4_ifval([$3],
++	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
++    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
++
++
++# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
++# -----------------------------------------------------------------
++m4_define([lt_if_dict_fetch],
++[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
++	[$5],
++    [$6])])
++
++
++# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
++# --------------------------------------------------------------
++m4_define([lt_dict_filter],
++[m4_if([$5], [], [],
++  [lt_join(m4_quote(m4_default([$4], [[, ]])),
++           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
++		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
++])
++
++# ltversion.m4 -- version numbers			-*- Autoconf -*-
++#
++#   Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
++#   Inc.
++#   Written by Scott James Remnant, 2004
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# @configure_input@
++
++# serial 4245 ltversion.m4
++# This file is part of GNU Libtool
++
++m4_define([LT_PACKAGE_VERSION], [2.4.7])
++m4_define([LT_PACKAGE_REVISION], [2.4.7])
++
++AC_DEFUN([LTVERSION_VERSION],
++[macro_version='2.4.7'
++macro_revision='2.4.7'
++_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
++_LT_DECL(, macro_revision, 0)
++])
++
++# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
++#
++#   Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
++#   Software Foundation, Inc.
++#   Written by Scott James Remnant, 2004.
++#
++# This file is free software; the Free Software Foundation gives
++# unlimited permission to copy and/or distribute it, with or without
++# modifications, as long as this notice is preserved.
++
++# serial 5 lt~obsolete.m4
++
++# These exist entirely to fool aclocal when bootstrapping libtool.
++#
++# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
++# which have later been changed to m4_define as they aren't part of the
++# exported API, or moved to Autoconf or Automake where they belong.
++#
++# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
++# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
++# using a macro with the same name in our local m4/libtool.m4 it'll
++# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
++# and doesn't know about Autoconf macros at all.)
++#
++# So we provide this file, which has a silly filename so it's always
++# included after everything else.  This provides aclocal with the
++# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
++# because those macros already exist, or will be overwritten later.
++# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
++#
++# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
++# Yes, that means every name once taken will need to remain here until
++# we give up compatibility with versions before 1.7, at which point
++# we need to keep only those names which we still refer to.
++
++# This is to help aclocal find these macros, as it can't see m4_define.
++AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
++
++m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
++m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
++m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
++m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
++m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
++m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
++m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
++m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
++m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
++m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
++m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
++m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
++m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
++m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
++m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
++m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
++m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
++m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
++m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
++m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
++m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
++m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
++m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
++m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
++m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
++m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
++m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
++m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
++m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
++m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
++m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
++m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
++m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
++m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
++m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
++m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
++m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
++m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
++m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
++m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
++m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
++m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
++m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
++m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
++m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
++m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
++m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
++m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
++m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
++m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
++m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
++m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],	[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
++m4_ifndef([_LT_AC_PROG_CXXCPP],		[AC_DEFUN([_LT_AC_PROG_CXXCPP])])
++m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],	[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
++m4_ifndef([_LT_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
++m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
++m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
++m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
++
++# Copyright (C) 2002-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_AUTOMAKE_VERSION(VERSION)
++# ----------------------------
++# Automake X.Y traces this macro to ensure aclocal.m4 has been
++# generated from the m4 files accompanying Automake X.Y.
++# (This private macro should not be called outside this file.)
++AC_DEFUN([AM_AUTOMAKE_VERSION],
++[am__api_version='1.16'
++dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
++dnl require some minimum version.  Point them to the right macro.
++m4_if([$1], [1.16.5], [],
++      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
++])
++
++# _AM_AUTOCONF_VERSION(VERSION)
++# -----------------------------
++# aclocal traces this macro to find the Autoconf version.
++# This is a private macro too.  Using m4_define simplifies
++# the logic in aclocal, which can simply ignore this definition.
++m4_define([_AM_AUTOCONF_VERSION], [])
++
++# AM_SET_CURRENT_AUTOMAKE_VERSION
++# -------------------------------
++# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
++# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
++AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
++[AM_AUTOMAKE_VERSION([1.16.5])dnl
++m4_ifndef([AC_AUTOCONF_VERSION],
++  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
++_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
++
++# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
++
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
++# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
++# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
++#
++# Of course, Automake must honor this variable whenever it calls a
++# tool from the auxiliary directory.  The problem is that $srcdir (and
++# therefore $ac_aux_dir as well) can be either absolute or relative,
++# depending on how configure is run.  This is pretty annoying, since
++# it makes $ac_aux_dir quite unusable in subdirectories: in the top
++# source directory, any form will work fine, but in subdirectories a
++# relative path needs to be adjusted first.
++#
++# $ac_aux_dir/missing
++#    fails when called from a subdirectory if $ac_aux_dir is relative
++# $top_srcdir/$ac_aux_dir/missing
++#    fails if $ac_aux_dir is absolute,
++#    fails when called from a subdirectory in a VPATH build with
++#          a relative $ac_aux_dir
++#
++# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
++# are both prefixed by $srcdir.  In an in-source build this is usually
++# harmless because $srcdir is '.', but things will broke when you
++# start a VPATH build or use an absolute $srcdir.
++#
++# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
++# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
++#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
++# and then we would define $MISSING as
++#   MISSING="\${SHELL} $am_aux_dir/missing"
++# This will work as long as MISSING is not called from configure, because
++# unfortunately $(top_srcdir) has no meaning in configure.
++# However there are other variables, like CC, which are often used in
++# configure, and could therefore not use this "fixed" $ac_aux_dir.
++#
++# Another solution, used here, is to always expand $ac_aux_dir to an
++# absolute PATH.  The drawback is that using absolute paths prevent a
++# configured tree to be moved without reconfiguration.
++
++AC_DEFUN([AM_AUX_DIR_EXPAND],
++[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
++# Expand $ac_aux_dir to an absolute path.
++am_aux_dir=`cd "$ac_aux_dir" && pwd`
++])
++
++# AM_CONDITIONAL                                            -*- Autoconf -*-
++
++# Copyright (C) 1997-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_CONDITIONAL(NAME, SHELL-CONDITION)
++# -------------------------------------
++# Define a conditional.
++AC_DEFUN([AM_CONDITIONAL],
++[AC_PREREQ([2.52])dnl
++ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
++       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
++AC_SUBST([$1_TRUE])dnl
++AC_SUBST([$1_FALSE])dnl
++_AM_SUBST_NOTMAKE([$1_TRUE])dnl
++_AM_SUBST_NOTMAKE([$1_FALSE])dnl
++m4_define([_AM_COND_VALUE_$1], [$2])dnl
++if $2; then
++  $1_TRUE=
++  $1_FALSE='#'
++else
++  $1_TRUE='#'
++  $1_FALSE=
++fi
++AC_CONFIG_COMMANDS_PRE(
++[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
++  AC_MSG_ERROR([[conditional "$1" was never defined.
++Usually this means the macro was only invoked conditionally.]])
++fi])])
++
++# Copyright (C) 1999-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++
++# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
++# written in clear, in which case automake, when reading aclocal.m4,
++# will think it sees a *use*, and therefore will trigger all it's
++# C support machinery.  Also note that it means that autoscan, seeing
++# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
++
++
++# _AM_DEPENDENCIES(NAME)
++# ----------------------
++# See how the compiler implements dependency checking.
++# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
++# We try a few techniques and use that to set a single cache variable.
++#
++# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
++# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
++# dependency, and given that the user is not expected to run this macro,
++# just rely on AC_PROG_CC.
++AC_DEFUN([_AM_DEPENDENCIES],
++[AC_REQUIRE([AM_SET_DEPDIR])dnl
++AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
++AC_REQUIRE([AM_MAKE_INCLUDE])dnl
++AC_REQUIRE([AM_DEP_TRACK])dnl
++
++m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
++      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
++      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
++      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
++      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
++      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
++                    [depcc="$$1"   am_compiler_list=])
++
++AC_CACHE_CHECK([dependency style of $depcc],
++               [am_cv_$1_dependencies_compiler_type],
++[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
++  # We make a subdir and do the tests there.  Otherwise we can end up
++  # making bogus files that we don't know about and never remove.  For
++  # instance it was reported that on HP-UX the gcc test will end up
++  # making a dummy file named 'D' -- because '-MD' means "put the output
++  # in D".
++  rm -rf conftest.dir
++  mkdir conftest.dir
++  # Copy depcomp to subdir because otherwise we won't find it if we're
++  # using a relative directory.
++  cp "$am_depcomp" conftest.dir
++  cd conftest.dir
++  # We will build objects and dependencies in a subdirectory because
++  # it helps to detect inapplicable dependency modes.  For instance
++  # both Tru64's cc and ICC support -MD to output dependencies as a
++  # side effect of compilation, but ICC will put the dependencies in
++  # the current directory while Tru64 will put them in the object
++  # directory.
++  mkdir sub
++
++  am_cv_$1_dependencies_compiler_type=none
++  if test "$am_compiler_list" = ""; then
++     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
++  fi
++  am__universal=false
++  m4_case([$1], [CC],
++    [case " $depcc " in #(
++     *\ -arch\ *\ -arch\ *) am__universal=true ;;
++     esac],
++    [CXX],
++    [case " $depcc " in #(
++     *\ -arch\ *\ -arch\ *) am__universal=true ;;
++     esac])
++
++  for depmode in $am_compiler_list; do
++    # Setup a source with many dependencies, because some compilers
++    # like to wrap large dependency lists on column 80 (with \), and
++    # we should not choose a depcomp mode which is confused by this.
++    #
++    # We need to recreate these files for each test, as the compiler may
++    # overwrite some of them when testing with obscure command lines.
++    # This happens at least with the AIX C compiler.
++    : > sub/conftest.c
++    for i in 1 2 3 4 5 6; do
++      echo '#include "conftst'$i'.h"' >> sub/conftest.c
++      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
++      # Solaris 10 /bin/sh.
++      echo '/* dummy */' > sub/conftst$i.h
++    done
++    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
++
++    # We check with '-c' and '-o' for the sake of the "dashmstdout"
++    # mode.  It turns out that the SunPro C++ compiler does not properly
++    # handle '-M -o', and we need to detect this.  Also, some Intel
++    # versions had trouble with output in subdirs.
++    am__obj=sub/conftest.${OBJEXT-o}
++    am__minus_obj="-o $am__obj"
++    case $depmode in
++    gcc)
++      # This depmode causes a compiler race in universal mode.
++      test "$am__universal" = false || continue
++      ;;
++    nosideeffect)
++      # After this tag, mechanisms are not by side-effect, so they'll
++      # only be used when explicitly requested.
++      if test "x$enable_dependency_tracking" = xyes; then
++	continue
++      else
++	break
++      fi
++      ;;
++    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
++      # This compiler won't grok '-c -o', but also, the minuso test has
++      # not run yet.  These depmodes are late enough in the game, and
++      # so weak that their functioning should not be impacted.
++      am__obj=conftest.${OBJEXT-o}
++      am__minus_obj=
++      ;;
++    none) break ;;
++    esac
++    if depmode=$depmode \
++       source=sub/conftest.c object=$am__obj \
++       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
++       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
++         >/dev/null 2>conftest.err &&
++       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
++       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
++      # icc doesn't choke on unknown options, it will just issue warnings
++      # or remarks (even with -Werror).  So we grep stderr for any message
++      # that says an option was ignored or not supported.
++      # When given -MP, icc 7.0 and 7.1 complain thusly:
++      #   icc: Command line warning: ignoring option '-M'; no argument required
++      # The diagnosis changed in icc 8.0:
++      #   icc: Command line remark: option '-MP' not supported
++      if (grep 'ignoring option' conftest.err ||
++          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
++        am_cv_$1_dependencies_compiler_type=$depmode
++        break
++      fi
++    fi
++  done
++
++  cd ..
++  rm -rf conftest.dir
++else
++  am_cv_$1_dependencies_compiler_type=none
++fi
++])
++AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
++AM_CONDITIONAL([am__fastdep$1], [
++  test "x$enable_dependency_tracking" != xno \
++  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
++])
++
++
++# AM_SET_DEPDIR
++# -------------
++# Choose a directory name for dependency files.
++# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
++AC_DEFUN([AM_SET_DEPDIR],
++[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
++AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
++])
++
++
++# AM_DEP_TRACK
++# ------------
++AC_DEFUN([AM_DEP_TRACK],
++[AC_ARG_ENABLE([dependency-tracking], [dnl
++AS_HELP_STRING(
++  [--enable-dependency-tracking],
++  [do not reject slow dependency extractors])
++AS_HELP_STRING(
++  [--disable-dependency-tracking],
++  [speeds up one-time build])])
++if test "x$enable_dependency_tracking" != xno; then
++  am_depcomp="$ac_aux_dir/depcomp"
++  AMDEPBACKSLASH='\'
++  am__nodep='_no'
++fi
++AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
++AC_SUBST([AMDEPBACKSLASH])dnl
++_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
++AC_SUBST([am__nodep])dnl
++_AM_SUBST_NOTMAKE([am__nodep])dnl
++])
++
++# Generate code to set up dependency tracking.              -*- Autoconf -*-
++
++# Copyright (C) 1999-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# _AM_OUTPUT_DEPENDENCY_COMMANDS
++# ------------------------------
++AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
++[{
++  # Older Autoconf quotes --file arguments for eval, but not when files
++  # are listed without --file.  Let's play safe and only enable the eval
++  # if we detect the quoting.
++  # TODO: see whether this extra hack can be removed once we start
++  # requiring Autoconf 2.70 or later.
++  AS_CASE([$CONFIG_FILES],
++          [*\'*], [eval set x "$CONFIG_FILES"],
++          [*], [set x $CONFIG_FILES])
++  shift
++  # Used to flag and report bootstrapping failures.
++  am_rc=0
++  for am_mf
++  do
++    # Strip MF so we end up with the name of the file.
++    am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
++    # Check whether this is an Automake generated Makefile which includes
++    # dependency-tracking related rules and includes.
++    # Grep'ing the whole file directly is not great: AIX grep has a line
++    # limit of 2048, but all sed's we know have understand at least 4000.
++    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
++      || continue
++    am_dirpart=`AS_DIRNAME(["$am_mf"])`
++    am_filepart=`AS_BASENAME(["$am_mf"])`
++    AM_RUN_LOG([cd "$am_dirpart" \
++      && sed -e '/# am--include-marker/d' "$am_filepart" \
++        | $MAKE -f - am--depfiles]) || am_rc=$?
++  done
++  if test $am_rc -ne 0; then
++    AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
++    for automatic dependency tracking.  If GNU make was not used, consider
++    re-running the configure script with MAKE="gmake" (or whatever is
++    necessary).  You can also try re-running configure with the
++    '--disable-dependency-tracking' option to at least be able to build
++    the package (albeit without support for automatic dependency tracking).])
++  fi
++  AS_UNSET([am_dirpart])
++  AS_UNSET([am_filepart])
++  AS_UNSET([am_mf])
++  AS_UNSET([am_rc])
++  rm -f conftest-deps.mk
++}
++])# _AM_OUTPUT_DEPENDENCY_COMMANDS
++
++
++# AM_OUTPUT_DEPENDENCY_COMMANDS
++# -----------------------------
++# This macro should only be invoked once -- use via AC_REQUIRE.
++#
++# This code is only required when automatic dependency tracking is enabled.
++# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
++# order to bootstrap the dependency handling code.
++AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
++[AC_CONFIG_COMMANDS([depfiles],
++     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
++     [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
++
++# Do all the work for Automake.                             -*- Autoconf -*-
++
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# This macro actually does too much.  Some checks are only needed if
++# your package does certain things.  But this isn't really a big deal.
++
++dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
++m4_define([AC_PROG_CC],
++m4_defn([AC_PROG_CC])
++[_AM_PROG_CC_C_O
++])
++
++# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
++# AM_INIT_AUTOMAKE([OPTIONS])
++# -----------------------------------------------
++# The call with PACKAGE and VERSION arguments is the old style
++# call (pre autoconf-2.50), which is being phased out.  PACKAGE
++# and VERSION should now be passed to AC_INIT and removed from
++# the call to AM_INIT_AUTOMAKE.
++# We support both call styles for the transition.  After
++# the next Automake release, Autoconf can make the AC_INIT
++# arguments mandatory, and then we can depend on a new Autoconf
++# release and drop the old call support.
++AC_DEFUN([AM_INIT_AUTOMAKE],
++[AC_PREREQ([2.65])dnl
++m4_ifdef([_$0_ALREADY_INIT],
++  [m4_fatal([$0 expanded multiple times
++]m4_defn([_$0_ALREADY_INIT]))],
++  [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
++dnl Autoconf wants to disallow AM_ names.  We explicitly allow
++dnl the ones we care about.
++m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
++AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
++AC_REQUIRE([AC_PROG_INSTALL])dnl
++if test "`cd $srcdir && pwd`" != "`pwd`"; then
++  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
++  # is not polluted with repeated "-I."
++  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
++  # test to see if srcdir already configured
++  if test -f $srcdir/config.status; then
++    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
++  fi
++fi
++
++# test whether we have cygpath
++if test -z "$CYGPATH_W"; then
++  if (cygpath --version) >/dev/null 2>/dev/null; then
++    CYGPATH_W='cygpath -w'
++  else
++    CYGPATH_W=echo
++  fi
++fi
++AC_SUBST([CYGPATH_W])
++
++# Define the identity of the package.
++dnl Distinguish between old-style and new-style calls.
++m4_ifval([$2],
++[AC_DIAGNOSE([obsolete],
++             [$0: two- and three-arguments forms are deprecated.])
++m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
++ AC_SUBST([PACKAGE], [$1])dnl
++ AC_SUBST([VERSION], [$2])],
++[_AM_SET_OPTIONS([$1])dnl
++dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
++m4_if(
++  m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
++  [ok:ok],,
++  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
++ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
++ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
++
++_AM_IF_OPTION([no-define],,
++[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
++ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
++
++# Some tools Automake needs.
++AC_REQUIRE([AM_SANITY_CHECK])dnl
++AC_REQUIRE([AC_ARG_PROGRAM])dnl
++AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
++AM_MISSING_PROG([AUTOCONF], [autoconf])
++AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
++AM_MISSING_PROG([AUTOHEADER], [autoheader])
++AM_MISSING_PROG([MAKEINFO], [makeinfo])
++AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
++AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
++AC_REQUIRE([AC_PROG_MKDIR_P])dnl
++# For better backward compatibility.  To be removed once Automake 1.9.x
++# dies out for good.  For more background, see:
++# 
++# 
++AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
++# We need awk for the "check" target (and possibly the TAP driver).  The
++# system "awk" is bad on some platforms.
++AC_REQUIRE([AC_PROG_AWK])dnl
++AC_REQUIRE([AC_PROG_MAKE_SET])dnl
++AC_REQUIRE([AM_SET_LEADING_DOT])dnl
++_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
++	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
++			     [_AM_PROG_TAR([v7])])])
++_AM_IF_OPTION([no-dependencies],,
++[AC_PROVIDE_IFELSE([AC_PROG_CC],
++		  [_AM_DEPENDENCIES([CC])],
++		  [m4_define([AC_PROG_CC],
++			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
++AC_PROVIDE_IFELSE([AC_PROG_CXX],
++		  [_AM_DEPENDENCIES([CXX])],
++		  [m4_define([AC_PROG_CXX],
++			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
++AC_PROVIDE_IFELSE([AC_PROG_OBJC],
++		  [_AM_DEPENDENCIES([OBJC])],
++		  [m4_define([AC_PROG_OBJC],
++			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
++AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
++		  [_AM_DEPENDENCIES([OBJCXX])],
++		  [m4_define([AC_PROG_OBJCXX],
++			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
++])
++# Variables for tags utilities; see am/tags.am
++if test -z "$CTAGS"; then
++  CTAGS=ctags
++fi
++AC_SUBST([CTAGS])
++if test -z "$ETAGS"; then
++  ETAGS=etags
++fi
++AC_SUBST([ETAGS])
++if test -z "$CSCOPE"; then
++  CSCOPE=cscope
++fi
++AC_SUBST([CSCOPE])
++
++AC_REQUIRE([AM_SILENT_RULES])dnl
++dnl The testsuite driver may need to know about EXEEXT, so add the
++dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
++dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
++AC_CONFIG_COMMANDS_PRE(dnl
++[m4_provide_if([_AM_COMPILER_EXEEXT],
++  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
++
++# POSIX will say in a future version that running "rm -f" with no argument
++# is OK; and we want to be able to make that assumption in our Makefile
++# recipes.  So use an aggressive probe to check that the usage we want is
++# actually supported "in the wild" to an acceptable degree.
++# See automake bug#10828.
++# To make any issue more visible, cause the running configure to be aborted
++# by default if the 'rm' program in use doesn't match our expectations; the
++# user can still override this though.
++if rm -f && rm -fr && rm -rf; then : OK; else
++  cat >&2 <<'END'
++Oops!
++
++Your 'rm' program seems unable to run without file operands specified
++on the command line, even when the '-f' option is present.  This is contrary
++to the behaviour of most rm programs out there, and not conforming with
++the upcoming POSIX standard: 
++
++Please tell bug-automake@gnu.org about your system, including the value
++of your $PATH and any error possibly output before this message.  This
++can help us improve future automake versions.
++
++END
++  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
++    echo 'Configuration will proceed anyway, since you have set the' >&2
++    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
++    echo >&2
++  else
++    cat >&2 <<'END'
++Aborting the configuration process, to ensure you take notice of the issue.
++
++You can download and install GNU coreutils to get an 'rm' implementation
++that behaves properly: .
++
++If you want to complete the configuration process using your problematic
++'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
++to "yes", and re-run configure.
++
++END
++    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
++  fi
++fi
++dnl The trailing newline in this macro's definition is deliberate, for
++dnl backward compatibility and to allow trailing 'dnl'-style comments
++dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
++])
++
++dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
++dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
++dnl mangled by Autoconf and run in a shell conditional statement.
++m4_define([_AC_COMPILER_EXEEXT],
++m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
++
++# When config.status generates a header, we must update the stamp-h file.
++# This file resides in the same directory as the config header
++# that is generated.  The stamp files are numbered to have different names.
++
++# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
++# loop where config.status creates the headers, so we can generate
++# our stamp files there.
++AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
++[# Compute $1's index in $config_headers.
++_am_arg=$1
++_am_stamp_count=1
++for _am_header in $config_headers :; do
++  case $_am_header in
++    $_am_arg | $_am_arg:* )
++      break ;;
++    * )
++      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
++  esac
++done
++echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
++
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_PROG_INSTALL_SH
++# ------------------
++# Define $install_sh.
++AC_DEFUN([AM_PROG_INSTALL_SH],
++[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
++if test x"${install_sh+set}" != xset; then
++  case $am_aux_dir in
++  *\ * | *\	*)
++    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
++  *)
++    install_sh="\${SHELL} $am_aux_dir/install-sh"
++  esac
++fi
++AC_SUBST([install_sh])])
++
++# Copyright (C) 2003-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# Check whether the underlying file-system supports filenames
++# with a leading dot.  For instance MS-DOS doesn't.
++AC_DEFUN([AM_SET_LEADING_DOT],
++[rm -rf .tst 2>/dev/null
++mkdir .tst 2>/dev/null
++if test -d .tst; then
++  am__leading_dot=.
++else
++  am__leading_dot=_
++fi
++rmdir .tst 2>/dev/null
++AC_SUBST([am__leading_dot])])
++
++# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
++# From Jim Meyering
++
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_MAINTAINER_MODE([DEFAULT-MODE])
++# ----------------------------------
++# Control maintainer-specific portions of Makefiles.
++# Default is to disable them, unless 'enable' is passed literally.
++# For symmetry, 'disable' may be passed as well.  Anyway, the user
++# can override the default with the --enable/--disable switch.
++AC_DEFUN([AM_MAINTAINER_MODE],
++[m4_case(m4_default([$1], [disable]),
++       [enable], [m4_define([am_maintainer_other], [disable])],
++       [disable], [m4_define([am_maintainer_other], [enable])],
++       [m4_define([am_maintainer_other], [enable])
++        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
++AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
++  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
++  AC_ARG_ENABLE([maintainer-mode],
++    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
++      am_maintainer_other[ make rules and dependencies not useful
++      (and sometimes confusing) to the casual installer])],
++    [USE_MAINTAINER_MODE=$enableval],
++    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
++  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
++  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
++  MAINT=$MAINTAINER_MODE_TRUE
++  AC_SUBST([MAINT])dnl
++]
++)
++
++# Check to see how 'make' treats includes.	            -*- Autoconf -*-
++
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_MAKE_INCLUDE()
++# -----------------
++# Check whether make has an 'include' directive that can support all
++# the idioms we need for our automatic dependency tracking code.
++AC_DEFUN([AM_MAKE_INCLUDE],
++[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
++cat > confinc.mk << 'END'
++am__doit:
++	@echo this is the am__doit target >confinc.out
++.PHONY: am__doit
++END
++am__include="#"
++am__quote=
++# BSD make does it like this.
++echo '.include "confinc.mk" # ignored' > confmf.BSD
++# Other make implementations (GNU, Solaris 10, AIX) do it like this.
++echo 'include confinc.mk # ignored' > confmf.GNU
++_am_result=no
++for s in GNU BSD; do
++  AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
++  AS_CASE([$?:`cat confinc.out 2>/dev/null`],
++      ['0:this is the am__doit target'],
++      [AS_CASE([$s],
++          [BSD], [am__include='.include' am__quote='"'],
++          [am__include='include' am__quote=''])])
++  if test "$am__include" != "#"; then
++    _am_result="yes ($s style)"
++    break
++  fi
++done
++rm -f confinc.* confmf.*
++AC_MSG_RESULT([${_am_result}])
++AC_SUBST([am__include])])
++AC_SUBST([am__quote])])
++
++# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
++
++# Copyright (C) 1997-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_MISSING_PROG(NAME, PROGRAM)
++# ------------------------------
++AC_DEFUN([AM_MISSING_PROG],
++[AC_REQUIRE([AM_MISSING_HAS_RUN])
++$1=${$1-"${am_missing_run}$2"}
++AC_SUBST($1)])
++
++# AM_MISSING_HAS_RUN
++# ------------------
++# Define MISSING if not defined so far and test if it is modern enough.
++# If it is, set am_missing_run to use it, otherwise, to nothing.
++AC_DEFUN([AM_MISSING_HAS_RUN],
++[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
++AC_REQUIRE_AUX_FILE([missing])dnl
++if test x"${MISSING+set}" != xset; then
++  MISSING="\${SHELL} '$am_aux_dir/missing'"
++fi
++# Use eval to expand $SHELL
++if eval "$MISSING --is-lightweight"; then
++  am_missing_run="$MISSING "
++else
++  am_missing_run=
++  AC_MSG_WARN(['missing' script is too old or missing])
++fi
++])
++
++# Helper functions for option handling.                     -*- Autoconf -*-
++
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# _AM_MANGLE_OPTION(NAME)
++# -----------------------
++AC_DEFUN([_AM_MANGLE_OPTION],
++[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
++
++# _AM_SET_OPTION(NAME)
++# --------------------
++# Set option NAME.  Presently that only means defining a flag for this option.
++AC_DEFUN([_AM_SET_OPTION],
++[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
++
++# _AM_SET_OPTIONS(OPTIONS)
++# ------------------------
++# OPTIONS is a space-separated list of Automake options.
++AC_DEFUN([_AM_SET_OPTIONS],
++[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
++
++# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
++# -------------------------------------------
++# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
++AC_DEFUN([_AM_IF_OPTION],
++[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
++
++# Copyright (C) 1999-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# _AM_PROG_CC_C_O
++# ---------------
++# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
++# to automatically call this.
++AC_DEFUN([_AM_PROG_CC_C_O],
++[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
++AC_REQUIRE_AUX_FILE([compile])dnl
++AC_LANG_PUSH([C])dnl
++AC_CACHE_CHECK(
++  [whether $CC understands -c and -o together],
++  [am_cv_prog_cc_c_o],
++  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
++  # Make sure it works both with $CC and with simple cc.
++  # Following AC_PROG_CC_C_O, we do the test twice because some
++  # compilers refuse to overwrite an existing .o file with -o,
++  # though they will create one.
++  am_cv_prog_cc_c_o=yes
++  for am_i in 1 2; do
++    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
++         && test -f conftest2.$ac_objext; then
++      : OK
++    else
++      am_cv_prog_cc_c_o=no
++      break
++    fi
++  done
++  rm -f core conftest*
++  unset am_i])
++if test "$am_cv_prog_cc_c_o" != yes; then
++   # Losing compiler, so override with the script.
++   # FIXME: It is wrong to rewrite CC.
++   # But if we don't then we get into trouble of one sort or another.
++   # A longer-term fix would be to have automake use am__CC in this case,
++   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
++   CC="$am_aux_dir/compile $CC"
++fi
++AC_LANG_POP([C])])
++
++# For backward compatibility.
++AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
++
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_RUN_LOG(COMMAND)
++# -------------------
++# Run COMMAND, save the exit status in ac_status, and log it.
++# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
++AC_DEFUN([AM_RUN_LOG],
++[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
++   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
++   ac_status=$?
++   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
++   (exit $ac_status); }])
++
++# Check to make sure that the build environment is sane.    -*- Autoconf -*-
++
++# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_SANITY_CHECK
++# ---------------
++AC_DEFUN([AM_SANITY_CHECK],
++[AC_MSG_CHECKING([whether build environment is sane])
++# Reject unsafe characters in $srcdir or the absolute working directory
++# name.  Accept space and tab only in the latter.
++am_lf='
++'
++case `pwd` in
++  *[[\\\"\#\$\&\'\`$am_lf]]*)
++    AC_MSG_ERROR([unsafe absolute working directory name]);;
++esac
++case $srcdir in
++  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
++    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
++esac
++
++# Do 'set' in a subshell so we don't clobber the current shell's
++# arguments.  Must try -L first in case configure is actually a
++# symlink; some systems play weird games with the mod time of symlinks
++# (eg FreeBSD returns the mod time of the symlink's containing
++# directory).
++if (
++   am_has_slept=no
++   for am_try in 1 2; do
++     echo "timestamp, slept: $am_has_slept" > conftest.file
++     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
++     if test "$[*]" = "X"; then
++	# -L didn't work.
++	set X `ls -t "$srcdir/configure" conftest.file`
++     fi
++     if test "$[*]" != "X $srcdir/configure conftest.file" \
++	&& test "$[*]" != "X conftest.file $srcdir/configure"; then
++
++	# If neither matched, then we have a broken ls.  This can happen
++	# if, for instance, CONFIG_SHELL is bash and it inherits a
++	# broken ls alias from the environment.  This has actually
++	# happened.  Such a system could not be considered "sane".
++	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
++  alias in your environment])
++     fi
++     if test "$[2]" = conftest.file || test $am_try -eq 2; then
++       break
++     fi
++     # Just in case.
++     sleep 1
++     am_has_slept=yes
++   done
++   test "$[2]" = conftest.file
++   )
++then
++   # Ok.
++   :
++else
++   AC_MSG_ERROR([newly created file is older than distributed files!
++Check your system clock])
++fi
++AC_MSG_RESULT([yes])
++# If we didn't sleep, we still need to ensure time stamps of config.status and
++# generated files are strictly newer.
++am_sleep_pid=
++if grep 'slept: no' conftest.file >/dev/null 2>&1; then
++  ( sleep 1 ) &
++  am_sleep_pid=$!
++fi
++AC_CONFIG_COMMANDS_PRE(
++  [AC_MSG_CHECKING([that generated files are newer than configure])
++   if test -n "$am_sleep_pid"; then
++     # Hide warnings about reused PIDs.
++     wait $am_sleep_pid 2>/dev/null
++   fi
++   AC_MSG_RESULT([done])])
++rm -f conftest.file
++])
++
++# Copyright (C) 2009-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_SILENT_RULES([DEFAULT])
++# --------------------------
++# Enable less verbose build rules; with the default set to DEFAULT
++# ("yes" being less verbose, "no" or empty being verbose).
++AC_DEFUN([AM_SILENT_RULES],
++[AC_ARG_ENABLE([silent-rules], [dnl
++AS_HELP_STRING(
++  [--enable-silent-rules],
++  [less verbose build output (undo: "make V=1")])
++AS_HELP_STRING(
++  [--disable-silent-rules],
++  [verbose build output (undo: "make V=0")])dnl
++])
++case $enable_silent_rules in @%:@ (((
++  yes) AM_DEFAULT_VERBOSITY=0;;
++   no) AM_DEFAULT_VERBOSITY=1;;
++    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
++esac
++dnl
++dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
++dnl do not support nested variable expansions.
++dnl See automake bug#9928 and bug#10237.
++am_make=${MAKE-make}
++AC_CACHE_CHECK([whether $am_make supports nested variables],
++   [am_cv_make_support_nested_variables],
++   [if AS_ECHO([['TRUE=$(BAR$(V))
++BAR0=false
++BAR1=true
++V=1
++am__doit:
++	@$(TRUE)
++.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
++  am_cv_make_support_nested_variables=yes
++else
++  am_cv_make_support_nested_variables=no
++fi])
++if test $am_cv_make_support_nested_variables = yes; then
++  dnl Using '$V' instead of '$(V)' breaks IRIX make.
++  AM_V='$(V)'
++  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
++else
++  AM_V=$AM_DEFAULT_VERBOSITY
++  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
++fi
++AC_SUBST([AM_V])dnl
++AM_SUBST_NOTMAKE([AM_V])dnl
++AC_SUBST([AM_DEFAULT_V])dnl
++AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
++AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
++AM_BACKSLASH='\'
++AC_SUBST([AM_BACKSLASH])dnl
++_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
++])
++
++# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# AM_PROG_INSTALL_STRIP
++# ---------------------
++# One issue with vendor 'install' (even GNU) is that you can't
++# specify the program used to strip binaries.  This is especially
++# annoying in cross-compiling environments, where the build's strip
++# is unlikely to handle the host's binaries.
++# Fortunately install-sh will honor a STRIPPROG variable, so we
++# always use install-sh in "make install-strip", and initialize
++# STRIPPROG with the value of the STRIP variable (set by the user).
++AC_DEFUN([AM_PROG_INSTALL_STRIP],
++[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
++# Installed binaries are usually stripped using 'strip' when the user
++# run "make install-strip".  However 'strip' might not be the right
++# tool to use in cross-compilation environments, therefore Automake
++# will honor the 'STRIP' environment variable to overrule this program.
++dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
++if test "$cross_compiling" != no; then
++  AC_CHECK_TOOL([STRIP], [strip], :)
++fi
++INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
++AC_SUBST([INSTALL_STRIP_PROGRAM])])
++
++# Copyright (C) 2006-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# _AM_SUBST_NOTMAKE(VARIABLE)
++# ---------------------------
++# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
++# This macro is traced by Automake.
++AC_DEFUN([_AM_SUBST_NOTMAKE])
++
++# AM_SUBST_NOTMAKE(VARIABLE)
++# --------------------------
++# Public sister of _AM_SUBST_NOTMAKE.
++AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
++
++# Check how to create a tarball.                            -*- Autoconf -*-
++
++# Copyright (C) 2004-2021 Free Software Foundation, Inc.
++#
++# This file is free software; the Free Software Foundation
++# gives unlimited permission to copy and/or distribute it,
++# with or without modifications, as long as this notice is preserved.
++
++# _AM_PROG_TAR(FORMAT)
++# --------------------
++# Check how to create a tarball in format FORMAT.
++# FORMAT should be one of 'v7', 'ustar', or 'pax'.
++#
++# Substitute a variable $(am__tar) that is a command
++# writing to stdout a FORMAT-tarball containing the directory
++# $tardir.
++#     tardir=directory && $(am__tar) > result.tar
++#
++# Substitute a variable $(am__untar) that extract such
++# a tarball read from stdin.
++#     $(am__untar) < result.tar
++#
++AC_DEFUN([_AM_PROG_TAR],
++[# Always define AMTAR for backward compatibility.  Yes, it's still used
++# in the wild :-(  We should find a proper way to deprecate it ...
++AC_SUBST([AMTAR], ['$${TAR-tar}'])
++
++# We'll loop over all known methods to create a tar archive until one works.
++_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
++
++m4_if([$1], [v7],
++  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
++
++  [m4_case([$1],
++    [ustar],
++     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
++      # There is notably a 21 bits limit for the UID and the GID.  In fact,
++      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
++      # and bug#13588).
++      am_max_uid=2097151 # 2^21 - 1
++      am_max_gid=$am_max_uid
++      # The $UID and $GID variables are not portable, so we need to resort
++      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
++      # below are definitely unexpected, so allow the users to see them
++      # (that is, avoid stderr redirection).
++      am_uid=`id -u || echo unknown`
++      am_gid=`id -g || echo unknown`
++      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
++      if test $am_uid -le $am_max_uid; then
++         AC_MSG_RESULT([yes])
++      else
++         AC_MSG_RESULT([no])
++         _am_tools=none
++      fi
++      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
++      if test $am_gid -le $am_max_gid; then
++         AC_MSG_RESULT([yes])
++      else
++        AC_MSG_RESULT([no])
++        _am_tools=none
++      fi],
++
++  [pax],
++    [],
++
++  [m4_fatal([Unknown tar format])])
++
++  AC_MSG_CHECKING([how to create a $1 tar archive])
++
++  # Go ahead even if we have the value already cached.  We do so because we
++  # need to set the values for the 'am__tar' and 'am__untar' variables.
++  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
++
++  for _am_tool in $_am_tools; do
++    case $_am_tool in
++    gnutar)
++      for _am_tar in tar gnutar gtar; do
++        AM_RUN_LOG([$_am_tar --version]) && break
++      done
++      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
++      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
++      am__untar="$_am_tar -xf -"
++      ;;
++    plaintar)
++      # Must skip GNU tar: if it does not support --format= it doesn't create
++      # ustar tarball either.
++      (tar --version) >/dev/null 2>&1 && continue
++      am__tar='tar chf - "$$tardir"'
++      am__tar_='tar chf - "$tardir"'
++      am__untar='tar xf -'
++      ;;
++    pax)
++      am__tar='pax -L -x $1 -w "$$tardir"'
++      am__tar_='pax -L -x $1 -w "$tardir"'
++      am__untar='pax -r'
++      ;;
++    cpio)
++      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
++      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
++      am__untar='cpio -i -H $1 -d'
++      ;;
++    none)
++      am__tar=false
++      am__tar_=false
++      am__untar=false
++      ;;
++    esac
++
++    # If the value was cached, stop now.  We just wanted to have am__tar
++    # and am__untar set.
++    test -n "${am_cv_prog_tar_$1}" && break
++
++    # tar/untar a dummy directory, and stop if the command works.
++    rm -rf conftest.dir
++    mkdir conftest.dir
++    echo GrepMe > conftest.dir/file
++    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
++    rm -rf conftest.dir
++    if test -s conftest.tar; then
++      AM_RUN_LOG([$am__untar /dev/null 2>&1 && break
++    fi
++  done
++  rm -rf conftest.dir
++
++  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
++  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
++
++AC_SUBST([am__tar])
++AC_SUBST([am__untar])
++]) # _AM_PROG_TAR
++
+diff --git a/bolt-plugin/bolt-plugin.cc b/bolt-plugin/bolt-plugin.cc
+new file mode 100644
+index 000000000..f65011fd1
+--- /dev/null
++++ b/bolt-plugin/bolt-plugin.cc
+@@ -0,0 +1,1153 @@
++/* bolt plugin for gold and/or GNU ld.
++   Copyright (C) 2022-2023 Free Software Foundation, Inc.
++   Contributed by Majin and Liyancheng.
++
++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, or (at your option)
++any later version.
++
++This program is distributed in the hope that it will be useful, but
++WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program; see the file COPYING3.  If not see
++.  */
++
++/* The plugin has only one external function: onload.  Gold passes it an
++   array of function that the plugin uses to communicate back to gold.
++
++   With the functions provided by gold, the plugin can be notified when
++   gold first analyzes a file and passes a symbol table back to gold.  The
++   plugin is also notified when all symbols have been read and it is time
++   to generate machine code for the necessary symbols.
++
++   More information at http://gcc.gnu.org/wiki/whopr/driver.  */
++
++/* Firstly, this plugin read profile info from .text.fdo.func_name section from
++   each claim file and parse it into BOLT profile.
++
++   The section read from the claim file will follow the following example.
++   .section .text.fdo.sort_array	// Section name
++   .string ".fdo.caller sort_array"	// Function name
++   .string ".fdo.caller.size 492"	// Function size
++   .string ".fdo.caller.bind GLOBAL"	// Bind type
++   .string "58"				// branch source address
++   .string "0"				// branch destination address
++   .string "336"			// count
++
++   The above is the case where the profile data comes from PGO.
++   If the data comes from AutoFDO, branch source address will be
++   BB address and branch destination address will be disabled. e.g.
++   .string "58"				// BB address
++   .string "336"			// count
++
++   The BOLT profile file format follows the syntax below which defined in
++   llvm-bolt.
++
++   Branch info mode when profile collect from PGO:
++     
++     
++    
++
++   Examples:
++
++   1 main 58 1 main 78 0 100
++
++   BB info mode when profile collect from AutoFDO:
++      
++
++   Examples:
++
++   1 main 58 100
++
++   Secondly, it also receive BOLT profile generated by perf2bolt.
++
++   Finally, this plugin calls llvm-bolt to do optimizations after linkage.
++
++*/
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++#if HAVE_STDINT_H
++#include 
++#endif
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#ifdef HAVE_SYS_WAIT_H
++#include 
++#endif
++#include 
++#include 
++#include "simple-object.h"
++#include "plugin-api.h"
++
++namespace LIBIBERTY
++{
++#include 
++}
++using LIBIBERTY::xmalloc;
++using LIBIBERTY::lbasename;
++using LIBIBERTY::xstrdup;
++using LIBIBERTY::concat;
++using LIBIBERTY::lrealpath;
++
++#include 
++#include 
++#include 
++#include 
++
++using std::vector;
++using std::string;
++using std::map;
++using std::set;
++
++static ld_plugin_register_claim_file register_claim_file = NULL;
++static ld_plugin_register_all_symbols_read register_all_symbols_read = NULL;
++static ld_plugin_register_cleanup register_cleanup = NULL;
++static ld_plugin_message message = NULL;
++
++static enum ld_plugin_output_file_type linker_output;
++
++extern "C"
++{
++  enum ld_plugin_status onload (struct ld_plugin_tv *tv);
++}
++
++/* C99 bool type cannot coerce parm 'gate' range, so use int here.  */
++
++static void
++check_gate (int gate, enum ld_plugin_level level, const char *text)
++{
++  if (gate)
++    {
++      return;
++    }
++
++  if (message)
++    {
++      message (level, text);
++    }
++  else
++    {
++      /* Print msg to stderr if there is no nicer way to inform the user.  */
++      fprintf (stderr, "%s\n", text);
++      if (level == LDPL_FATAL)
++	{
++	  abort ();
++	}
++    }
++}
++
++/* This wrapper allows macro CHECK to be called with a non-integer argument
++   GATE.  For pointer cases, GATE should be no-Null.  */
++
++#define CHECK(GATE, LEVEL, TEXT) check_gate (((GATE) != 0), (LEVEL), (TEXT))
++
++#define __MSG_INFO__
++#define __MSG_WARN__
++#define __MSG_ERROR__
++
++#ifdef __MSG_INFO__
++#define MSG_INFO(...)						\
++  if (message)							\
++    {								\
++      message (LDPL_INFO, "BOLT-PLUGIN-INFO: " __VA_ARGS__);	\
++    }								\
++  else								\
++    {								\
++      fprintf (stderr, "BOLT-PLUGIN-INFO: " __VA_ARGS__);	\
++    }
++#else
++#define MSG_INFO(...)
++#endif
++
++#ifdef __MSG_WARN__
++#define MSG_WARN(...)							\
++  if (message)								\
++    {									\
++      message (LDPL_WARNING, "BOLT-PLUGIN-WARNING: " __VA_ARGS__);	\
++    }									\
++  else									\
++    {									\
++      fprintf (stderr, "BOLT-PLUGIN-WARNING: " __VA_ARGS__);		\
++    }
++#else
++#define MSG_WARN(...)
++#endif
++
++#ifdef __MSG_ERROR__
++#define MSG_ERROR(...)						\
++  if (message)							\
++    {								\
++      message (LDPL_FATAL, "BOLT-PLUGIN-ERROR: " __VA_ARGS__);	\
++    }								\
++  else								\
++    {								\
++      fprintf (stderr, "BOLT-PLUGIN-ERROR: " __VA_ARGS__);	\
++      abort ();							\
++    }
++#else
++#define MSG_ERROR(...)
++#endif
++
++#if HAVE_DOS_BASED_FILE_SYSTEM
++const char *separator = "\\";
++#else
++const char *separator = "/";
++#endif
++
++/* Encapsulates object file data during symbol scan.  */
++struct plugin_objfile
++{
++  simple_object_read *objfile;
++  const struct ld_plugin_input_file *file;
++};
++
++struct jump_info
++{
++  string des_func_name;
++  string src_addr_offset;
++  string dst_addr_offset;
++  string count;
++};
++
++struct func_info
++{
++  string function_name;
++  string bind_type; /* "GLOBAL","WEAK","LOCAL","UNKNOWN".  */
++  string size;
++  vector edges;
++};
++
++/* Define feedback data type.  */
++enum feedback_type
++{
++  NULL_TYPE,  /* No feedback data.  */
++  PGO_TYPE,   /* Feedback data from PGO.  */
++  AFDO_TYPE,  /* Feedback data from AutoFDO.  */
++  BOLT_TYPE,  /* Feedback data from BOLT.  */
++};
++
++#define DEFAULT_BOLT_OUT_DIR (get_current_dir_name ())
++#define DEFAULT_BOLT_OUT_NAME "default.fdata"
++#define DEFAULT_BOLT_OUT_NAME_SUFFIX ".fdata"
++
++/* The FDO section's special prefix names.  */
++#define ASM_FDO_SECTION_PREFIX ".text.fdo."
++#define ASM_FDO_CALLER_FLAG ".fdo.caller "
++#define ASM_FDO_CALLER_BIND_FLAG ".fdo.caller.bind "
++#define ASM_FDO_CALLER_SIZE_FLAG ".fdo.caller.size "
++#define ASM_FDO_CALLEE_FLAG ".fdo.callee "
++
++static int linker_output_set;
++
++/* BOLT profile name generated by -fauto-bolt or
++   read from -fbolt-use.  */
++static string bolt_profile_name;
++
++/* Path to save configuration file generated by -fauto-bolt.  */
++static string bolt_dir_path;
++
++/* BOLT profile file FD generated by -fauto-bolt.  */
++static FILE *bolt_file_fd = NULL;
++
++/* Temporary binary or dynamic file with reloc info.  */
++static string tmp_out_file_name = "a.out";
++
++/* Binary or dynamic file after BOLT.  */
++static string bolt_opt_target;
++
++/* Format of bolt_optimize_options should be "reorder-functions=hfsort+ ...",
++   command 'llvm-bolt' has been added here.  */
++static string bolt_optimize_options ("llvm-bolt ");
++
++static enum feedback_type fdo_type = feedback_type::NULL_TYPE;
++
++static vector gcc_options;
++
++/* Map of >  */
++static map> weak_functions;
++
++/* Returns 1 if two strings have the same prefix.  */
++
++inline static int
++is_prefix_of (const char *prefix, const char *str)
++{
++  return strncmp (prefix, str, strlen (prefix)) == 0;
++}
++
++static bool
++file_exist (const char *file_name)
++{
++  if (file_name == nullptr)
++    {
++      MSG_ERROR ("file_exist get empty input file name.");
++      return false;
++    }
++  struct stat buffer;
++  if (stat (file_name, &buffer) == 0)
++    {
++      return true;
++    }
++
++  MSG_WARN ("file_exist check failed: %s does not exist!", file_name);
++  return false;
++}
++
++/* Popen run cmd, use safe character set for whitelist verification.  */
++
++static void
++popen_run (const string& cmd)
++{
++  for (const char &ch : cmd)
++    {
++      if ((ch >= '0' && ch <= '9')
++	  || (ch >= 'A' && ch <= 'Z')
++	  || (ch >= 'a' && ch <= 'z')
++	  || (ch == ' ' || ch == '_')
++	  || (ch == '-' || ch == '/')
++	  || (ch == '.' || ch == '+')
++	  || (ch == '=' || ch == '#'))
++	{
++	  continue;
++	}
++      else
++	{
++	  MSG_WARN ("Unsafe command: %s", cmd.c_str ());
++	  MSG_ERROR ("The command can only contain the following characters "
++		     "0-9, A-Z, a-z, '_', '-', '/', ' ', '.', '+', '=', '#' ");
++	}
++    }
++  MSG_INFO ("Execute command: %s", cmd.c_str ());
++  FILE *fd = popen (cmd.c_str (), "r");
++  if (fd == nullptr)
++    {
++      MSG_WARN ("Execute command faild!");
++    }
++  else
++    {
++      char result_buf[1024];
++      while (fgets (result_buf, sizeof (result_buf), fd) != NULL)
++	{
++	  if (result_buf[strlen (result_buf) - 1] == '\n')
++	    {
++	      result_buf[strlen (result_buf) - 1] = '\0';
++	    }
++	  MSG_INFO ("%s", result_buf);
++	}
++      pclose (fd);
++    }
++}
++
++/* Generate bolt optimize command.  */
++
++static string
++generate_bolt_cmd ()
++{
++  string new_binary = tmp_out_file_name + ".bolt";
++  string cmd;
++
++  /* bolt_optimize_options != "llvm-bolt "
++     means that the user uses custom input options.  */
++  if (bolt_optimize_options != "llvm-bolt ")
++    {
++      cmd = bolt_optimize_options + " " + tmp_out_file_name
++	+ " -o " + new_binary
++	+ " -data=" + bolt_profile_name;
++    }
++  else
++    {
++      if (fdo_type == feedback_type::AFDO_TYPE)
++	{
++	  cmd = string ("llvm-bolt  -reorder-functions=hfsort+ ")
++	    + tmp_out_file_name + " -o " + new_binary
++	    + " -data=" + bolt_profile_name;
++	}
++      else if (fdo_type == feedback_type::PGO_TYPE
++	  || fdo_type == feedback_type::BOLT_TYPE)
++	{
++	  cmd = string ("llvm-bolt -reorder-blocks=cache+ ")
++	    + string (" -reorder-functions=hfsort+ ")
++	    + string (" -split-functions=3 -split-all-cold ")
++	    + string (" -dyno-stats -icf=1 -use-gnu-stack ")
++	    + tmp_out_file_name + " -o " + new_binary
++	    + " -data=" + bolt_profile_name;
++	}
++      else
++	{
++	  MSG_ERROR ("Invalid profile type!");
++	  return string ();
++	}
++      MSG_INFO ("Using the default llvm-bolt optimization option,"
++		" manually specify this option by -fbolt-option.  ");
++    }
++  return cmd;
++}
++
++/* Execute BOLT optimization, backup original binary with .orig .  */
++
++static void
++do_bolt_opt ()
++{
++  string cmd = generate_bolt_cmd ();
++  if (cmd.empty ())
++    {
++      return;
++    }
++  popen_run (cmd);
++  string new_binary = tmp_out_file_name + ".bolt";
++  if (file_exist (new_binary.c_str ()))
++    {
++      cmd = "mv -f " + tmp_out_file_name + " " + tmp_out_file_name + ".orig";
++      popen_run (cmd);
++
++      cmd = "cp -f " + new_binary + " " + tmp_out_file_name;
++      popen_run (cmd);
++    }
++  else
++    {
++      MSG_ERROR ("BOLT optimization fail!"
++		 " Try installing llvm-bolt or"
++		 " enabling relocation info with flag -Wl,-q");
++    }
++}
++
++/* If -fbolt-target is set and this binary is the target, return true.  */
++
++inline static bool
++is_bolt_opt_target ()
++{
++  if (!bolt_opt_target.empty ()
++      && strcmp (lbasename (tmp_out_file_name.c_str ()),
++      lbasename (bolt_opt_target.c_str ())) != 0)
++    {
++      MSG_INFO ("BOLT optmization target is %s, processing %s, skip.",
++		bolt_opt_target.c_str (), tmp_out_file_name.c_str ());
++      return false;
++    }
++  return true;
++}
++
++/* Remove temporary files after linkage, and do BOLT optimization.  */
++
++static enum ld_plugin_status
++cleanup_handler ()
++{
++  if (bolt_file_fd)
++    {
++      fclose (bolt_file_fd);
++    }
++
++  if (file_exist (tmp_out_file_name.c_str ())
++      && file_exist (bolt_profile_name.c_str ())
++      && is_bolt_opt_target ())
++    {
++      do_bolt_opt ();
++    }
++
++  return LDPS_OK;
++}
++
++/* Open BOLT profile file generated by -fauto-bolt.  */
++
++static void
++open_bolt_profile_file (const char *file_name)
++{
++  if (file_name == NULL)
++    {
++      MSG_ERROR ("Empty BOLT profile name, exit!");
++    }
++
++  if (bolt_file_fd == NULL)
++    {
++      MSG_INFO ("Generate profile file for BOLT: %s", file_name);
++      bolt_file_fd = fopen (file_name, "wt");
++      if (!bolt_file_fd)
++	{
++	  MSG_ERROR ("Failed to open the file: %s."
++		     " Please check whether the target path exists.",
++		     file_name);
++	}
++      return;
++    }
++  else
++    {
++      MSG_WARN ("BOLT profile file: %s is open, skip.", file_name);
++    }
++}
++
++/* In BOLT profile, function with same name represent as func_name/file_name/1,
++   also, `/` has been added in gcc/final.c, so add /1 if this function is same
++   name function.  */
++
++static string
++add_suffix (string str)
++{
++  if (str.empty () || (strstr (str.c_str (), "/") == NULL))
++    {
++      return str;
++    }
++
++  return str + "/1";
++}
++
++/* Dump function info to BOLT profile, bolt_file_fd does not need
++   to be closed here.  */
++
++static void
++dump_func_to_bolt_profile_file (const struct func_info &func)
++{
++  if (func.edges.empty ())
++    {
++      return;
++    }
++
++  if (!bolt_file_fd)
++    {
++      open_bolt_profile_file (bolt_profile_name.c_str ());
++
++      /* Check whether the feedback data is from AutoFDO.  */
++      if (fdo_type == feedback_type::AFDO_TYPE)
++       {
++	 fprintf (bolt_file_fd, "no_lbr cycles:u:\n");
++       }
++    }
++
++  for (const auto &edge: func.edges)
++    {
++      if (fdo_type == feedback_type::PGO_TYPE)
++	{
++	  fprintf (bolt_file_fd, "1 %s %s 1 %s %s 0 %s\n",
++		   add_suffix (func.function_name).c_str (),
++		   edge.src_addr_offset.c_str (),
++		   add_suffix (edge.des_func_name).c_str (),
++		   edge.dst_addr_offset.c_str (), edge.count.c_str ());
++	}
++      else if (fdo_type == feedback_type::AFDO_TYPE)
++	{
++	  fprintf (bolt_file_fd, "1 %s %s %s\n",
++		   add_suffix (func.function_name).c_str (),
++		   edge.src_addr_offset.c_str (),
++		   edge.count.c_str ());
++	}
++    }
++
++  fflush (bolt_file_fd);
++}
++
++/* Called by the linker when all symbols have been read.  */
++
++static enum ld_plugin_status
++all_symbols_read_handler ()
++{
++  for (const auto &functions: weak_functions)
++    {
++      /* More than one weak function.  */
++      if (functions.second.size () > 1)
++	{
++	  MSG_WARN ("The weak function: %s is confusing, take the first one.",
++		    functions.first.c_str ());
++	}
++
++      dump_func_to_bolt_profile_file (functions.second[0]);
++    }
++  return LDPS_OK;
++}
++
++/* Move pointer p to end and return end.  */
++
++static char *
++get_next_content (char *p, char *end)
++{
++  while (*p && p < end)
++    {
++      p++;
++    }
++  p++;
++
++  return p;
++}
++
++/* Process function head info.  */
++
++static char *
++process_function_head (char *data , char *end, struct func_info *func)
++{
++  CHECK (is_prefix_of (ASM_FDO_CALLER_FLAG, data), LDPL_FATAL,
++	 "The function name is missing.");
++  func->function_name = xstrdup (data + strlen (ASM_FDO_CALLER_FLAG));
++  data = get_next_content (data, end);
++
++  CHECK (is_prefix_of (ASM_FDO_CALLER_SIZE_FLAG, data), LDPL_FATAL,
++	 "The function size is missing.");
++  func->size = xstrdup (data + strlen (ASM_FDO_CALLER_SIZE_FLAG));
++  data = get_next_content (data, end);
++
++  CHECK (is_prefix_of (ASM_FDO_CALLER_BIND_FLAG, data), LDPL_FATAL,
++	 "The function bind type is missing.");
++  func->bind_type = xstrdup (data + strlen (ASM_FDO_CALLER_BIND_FLAG));
++  data = get_next_content (data, end);
++  return data;
++}
++
++/* Read profile info from the symbol table located between data and end.  */
++
++static void
++process_section (char *data, char *end)
++{
++  struct func_info func;
++
++  data = process_function_head (data, end, &func);
++
++  while (*data && data < end)
++    {
++      struct jump_info jump;
++
++      CHECK (data, LDPL_FATAL, "data is NULL");
++      jump.src_addr_offset = xstrdup (data);
++
++      data = get_next_content (data, end);
++      CHECK (data, LDPL_FATAL, "data is NULL");
++      if (is_prefix_of (ASM_FDO_CALLEE_FLAG, data))
++	{
++	  jump.des_func_name = xstrdup (data + strlen (ASM_FDO_CALLEE_FLAG));
++	  jump.dst_addr_offset = "0";
++	  data = get_next_content (data, end);
++	  CHECK (data, LDPL_FATAL, "data is NULL");
++	}
++      else if (fdo_type == feedback_type::PGO_TYPE)
++	{
++	  jump.des_func_name = func.function_name;
++	  jump.dst_addr_offset = xstrdup (data);
++	  data = get_next_content (data, end);
++	  CHECK (data, LDPL_FATAL, "data is NULL");
++	}
++      else
++	{
++	  jump.des_func_name = func.function_name;
++	}
++
++      jump.count = xstrdup (data);
++      data = get_next_content (data, end);
++
++      func.edges.push_back (jump);
++    }
++
++  if (is_prefix_of ("WEAK", func.bind_type.c_str ()))
++    {
++      weak_functions[func.function_name].push_back (func);
++    }
++  else
++    {
++      dump_func_to_bolt_profile_file (func);
++    }
++}
++
++/* Process error when calling function process_symtab.  */
++
++static int
++process_symtab_error (struct plugin_objfile *obj, char *secdatastart)
++{
++  MSG_ERROR ("%s: corrupt object file.", obj->file->name);
++
++  /* Force claim_file_handler to abandon this file.  */
++  if (secdatastart != NULL)
++    {
++      free (secdatastart);
++    }
++  return 0;
++}
++
++/* Process one section of an object file.  Return to 1 to continue processing
++   other sections which define in simple_object_find_sections.  */
++
++static int
++process_symtab (void *data, const char *name, off_t offset, off_t length)
++{
++  if (data == NULL)
++    {
++      MSG_WARN ("Empty symtab! skip it.");
++      return 0;
++    }
++  if (name == NULL)
++    {
++      MSG_WARN ("Empty symtab name! skip it.");
++      return 0;
++    }
++  struct plugin_objfile *obj = (struct plugin_objfile *)data;
++  char *secdatastart;
++  char *secdata;
++
++  if (!is_prefix_of (ASM_FDO_SECTION_PREFIX, name))
++    {
++      return 1;
++    }
++
++  secdata = secdatastart = (char *)xmalloc (length * sizeof (char));
++  offset += obj->file->offset;
++  if (offset != lseek (obj->file->fd, offset, SEEK_SET))
++    {
++      return process_symtab_error (obj, secdatastart);
++    }
++
++  do
++    {
++      ssize_t got = read (obj->file->fd, secdata, length);
++
++      if (got == 0)
++	{
++	  break;
++	}
++      else if (got > 0)
++	{
++	  secdata += got;
++	  length -= got;
++	}
++      else if (errno != EINTR)
++	{
++	  return process_symtab_error (obj, secdatastart);
++	}
++     }
++  while (length > 0);
++
++  if (length > 0)
++    {
++      return process_symtab_error (obj, secdatastart);
++    }
++
++  process_section (secdatastart, secdata);
++  free (secdatastart);
++  return 1;
++}
++
++/* Callback used by gold to check if the plugin will claim FILE.  Writes
++   the result in CLAIMED.  */
++
++static enum ld_plugin_status
++claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
++{
++  struct plugin_objfile obj;
++  int err;
++  const char *errmsg = NULL;
++  /* If file is empty, bolt plugin do nothing and return ok.  */
++  if (file == NULL)
++    {
++      return LDPS_OK;
++    }
++  /* BOLT plugin does not need claimd number, so set *claimed to 0.  */
++  *claimed = 0;
++
++  obj.file = file;
++  obj.objfile = simple_object_start_read (file->fd, file->offset, NULL,
++					  &errmsg, &err);
++
++  /* No file, but also no error code means unrecognized format,
++     skip it.  */
++  if (!obj.objfile && !err)
++    {
++      return LDPS_OK;
++    }
++
++  if (obj.objfile)
++    {
++      simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
++      simple_object_release_read (obj.objfile);
++    }
++
++  return LDPS_OK;
++}
++
++/* Mangle filename path of BASE and output new allocated pointer with
++   mangled path.  */
++
++static string
++mangle_path (const string &base)
++{
++  if (base.empty ())
++    {
++      return base;
++    }
++
++  /* Convert '/' to '#', convert '..' to '^',
++     convert ':' to '~' on DOS based file system.  */
++
++  string new_path;
++  int base_len = base.size ();
++  int l = 0;
++  int r = 0;
++  while (l < base_len)
++    {
++      while (r < base_len && base[r] != '/')
++	{
++	  r++;
++	}
++
++      int len = r - l;
++      if (len == 2 && base[r - 2] == '.' && base[r - 1] == '.')
++	{
++	  new_path += '^';
++	}
++      else
++	{
++	  new_path += base.substr (l, r - l);
++	}
++      if (r < base_len)
++	{
++	  new_path += '#';
++	}
++
++      r++;
++      l = r;
++    }
++  return new_path;
++}
++
++/* Generate BOLT profile name from file_name.  */
++
++static string
++generate_bolt_profile_name (string file_name)
++{
++  if (!IS_ABSOLUTE_PATH (file_name.c_str ()))
++    {
++      if (!bolt_dir_path.empty ())
++	{
++	  file_name = concat (get_current_dir_name (),
++			      separator, file_name.c_str (), NULL);
++	  file_name = mangle_path (file_name);
++	}
++      else
++	{
++	  bolt_dir_path = DEFAULT_BOLT_OUT_DIR;
++	}
++    }
++  file_name = concat (bolt_dir_path.c_str (), separator, file_name.c_str (),
++		      NULL);
++  return file_name;
++}
++
++/* Match option_prefix from gcc_options, return the index of gcc_options.  */
++
++static int
++match_gcc_option (const char *option_prefix)
++{
++  if (option_prefix == NULL)
++    {
++      return -1;
++    }
++
++  for (size_t i = 0; i < gcc_options.size (); i++)
++    {
++      if (is_prefix_of (option_prefix, gcc_options[i].c_str ()))
++	{
++	  return i;
++	}
++    }
++
++  return -1;
++}
++
++/* Get options form environment COLLECT_GCC_OPTIONS.  */
++
++static void
++get_options_from_collect_gcc_options (const char *collect_gcc,
++				      const char *collect_gcc_options)
++{
++  /* When using GCC, collect_gcc will not be empty.  */
++  if (collect_gcc == NULL || collect_gcc_options == NULL)
++    {
++      return;
++    }
++
++  size_t len = strlen (collect_gcc_options);
++  size_t r = 0;
++  while (r < len && collect_gcc_options[r] != '\0')
++    {
++      if (collect_gcc_options[r] == '\'')
++	{
++	  string option;
++	  ++r;
++	  do
++	    {
++	      if (collect_gcc_options[r] == '\0')
++		{
++		  MSG_ERROR ("Malformed COLLECT_GCC_OPTIONS");
++		}
++	      else if (is_prefix_of ("'\\''", &collect_gcc_options[r]))
++		{
++		  option.push_back ('\'');
++		  r += 4;
++		}
++	      else if (collect_gcc_options[r] == '\'')
++		{
++		  break;
++		}
++	      else
++		{
++		  option.push_back (collect_gcc_options[r]);
++		  ++r;
++		}
++	    }
++	  while (1);
++
++	  if (!option.empty ())
++	    {
++	      gcc_options.push_back (option);
++	    }
++	}
++      ++r;
++    }
++}
++
++/* Substitute comma with space in RAW_STRING, used for parser
++  -fbolt-option.  */
++
++static string
++parser_bolt_optimize_option (string raw_string)
++{
++  for (auto &ch : raw_string)
++    {
++      if (ch == ',')
++	{
++	  ch = ' ';
++	}
++    }
++
++  return raw_string;
++}
++
++/* Process option -fauto-bolt.  */
++
++static void
++process_auto_bolt_option (const string &flag_auto_bolt)
++{
++  const int auto_bolt_index = match_gcc_option (flag_auto_bolt.c_str ());
++
++  if (auto_bolt_index != -1)
++    {
++      if (gcc_options[auto_bolt_index] == "-fauto-bolt")
++	{
++	  MSG_INFO ("Use default output directory %s, ", DEFAULT_BOLT_OUT_DIR);
++	  MSG_INFO ("Specify it using -fauto-bolt= if needed.");
++	}
++      else
++	{
++	  string flag_auto_bolt_equal = "-fauto-bolt=";
++	  bolt_dir_path = lrealpath (gcc_options[auto_bolt_index].substr (
++			  flag_auto_bolt_equal.size ()).c_str ());
++	  MSG_INFO ("Get bolt profile path: %s", bolt_dir_path.c_str ());
++	}
++      bolt_profile_name = generate_bolt_profile_name(bolt_profile_name);
++    }
++}
++
++/* Process option -fbolt-use=.  */
++
++static void
++process_bolt_use_option (const string &flag_bolt_use)
++{
++  const int bolt_use_index = match_gcc_option (flag_bolt_use.c_str ());
++
++  if (bolt_use_index != -1)
++    {
++      /* bolt_profile_name may be initialized in
++	 function process_output_option.  */
++      bolt_profile_name = gcc_options[bolt_use_index].substr (
++			  flag_bolt_use.size ()).c_str ();
++      if (bolt_profile_name.empty ())
++	{
++	  bolt_profile_name = DEFAULT_BOLT_OUT_NAME;
++	}
++      MSG_INFO ("Get bolt profile: %s", bolt_profile_name.c_str ());
++    }
++}
++
++/* Process option -fbolt-target=.  */
++
++static void
++process_bolt_target_option (const string &flag_bolt_target)
++{
++  const int bolt_target_index = match_gcc_option (flag_bolt_target.c_str ());
++  if (bolt_target_index != -1)
++    {
++      bolt_opt_target = gcc_options[bolt_target_index].substr (
++	flag_bolt_target.size ()).c_str ();
++      MSG_INFO ("Get bolt target: %s", bolt_opt_target.c_str ());
++    }
++}
++
++/* Process option -fbolt-option=.  */
++
++static void
++process_bolt_option (const string &flag_bolt_optimize_options)
++{
++  const int bolt_optimize_options_index
++    = match_gcc_option (flag_bolt_optimize_options.c_str ());
++
++  if (bolt_optimize_options_index != -1)
++    {
++      bolt_optimize_options.append (parser_bolt_optimize_option (
++	gcc_options[bolt_optimize_options_index].substr (
++	flag_bolt_optimize_options.size ()).c_str ()));
++
++      MSG_INFO ("Get bolt optimize options is %s",
++	bolt_optimize_options.c_str ());
++    }
++}
++
++/* If -o is specified, set binary name and bolt profile name.  This
++   function must be called before the process_bolt_use_option function.  */
++
++static void
++process_output_option (const string &flag_o)
++{
++  const int o_index = match_gcc_option (flag_o.c_str ());
++  if (o_index != -1)
++    {
++      tmp_out_file_name = gcc_options[o_index + 1];
++      /* bolt_profile_name may be overridden in
++	 function process_auto_bolt_option and
++	 process_bolt_use_option.  */
++      bolt_profile_name = gcc_options[o_index + 1];
++      bolt_profile_name.append (DEFAULT_BOLT_OUT_NAME_SUFFIX);
++    }
++  else
++    {
++      bolt_profile_name = DEFAULT_BOLT_OUT_NAME;
++      MSG_INFO ("Use default file name %s, specify it using -o if needed.",
++		DEFAULT_BOLT_OUT_NAME);
++    }
++}
++
++/* Parse the plugin options.  */
++
++static void
++process_gcc_option ()
++{
++  string flag_profile_use = "-fprofile-use";
++  string flag_auto_profile = "-fauto-profile";
++  string flag_auto_bolt = "-fauto-bolt";
++  string flag_bolt_use = "-fbolt-use=";
++  string flag_bolt_target = "-fbolt-target=";
++  string flag_bolt_optimize_options = "-fbolt-option=";
++  string flag_o = "-o";
++
++  char *collect_gcc = getenv ("COLLECT_GCC");
++  char *collect_gcc_option = getenv ("COLLECT_GCC_OPTIONS");
++
++  get_options_from_collect_gcc_options (collect_gcc, collect_gcc_option);
++
++  /* Function process_output_option should be processed before
++     process_auto_bolt_option to obtain correct bolt_profile_name.  */
++  process_output_option (flag_o);
++  process_auto_bolt_option (flag_auto_bolt);
++  process_bolt_use_option (flag_bolt_use);
++  process_bolt_target_option (flag_bolt_target);
++  process_bolt_option (flag_bolt_optimize_options);
++  
++  if (match_gcc_option (flag_profile_use.c_str ()) != -1)
++    {
++      fdo_type = feedback_type::PGO_TYPE;
++    }
++  else if (match_gcc_option (flag_auto_profile.c_str ()) != -1)
++    {
++      fdo_type = feedback_type::AFDO_TYPE;
++    }
++
++  if (match_gcc_option (flag_bolt_use.c_str ()) != -1)
++    {
++      fdo_type = feedback_type::BOLT_TYPE;
++    }
++
++  if (fdo_type == feedback_type::NULL_TYPE)
++    {
++      MSG_ERROR ("No feedback data, maybe use -fprofile-use "
++		 "-fbolt-use or -fauto-profile.");
++    }
++}
++
++/* Register callback function including all_symbols_read_handler,
++   cleanup_handler and claim_file_handler.  */
++
++static void
++register_callback_function ()
++{
++  enum ld_plugin_status status;
++
++  if (linker_output_set && linker_output != LDPO_EXEC)
++    {
++      MSG_INFO ("This linker[%d] is not for exec, just skip.", linker_output);
++      return;
++    }
++
++  CHECK (register_claim_file, LDPL_FATAL, "register_claim_file not found");
++  status = register_claim_file (claim_file_handler);
++  CHECK (status == LDPS_OK, LDPL_FATAL,
++	 "could not register the claim_file callback");
++
++  if (register_cleanup)
++    {
++      status = register_cleanup (cleanup_handler);
++      CHECK (status == LDPS_OK, LDPL_FATAL,
++	     "could not register the cleanup callback");
++    }
++
++  if (register_all_symbols_read)
++    {
++      status = register_all_symbols_read (all_symbols_read_handler);
++      CHECK (status == LDPS_OK, LDPL_FATAL,
++	     "could not register the all_symbols_read callback");
++    }
++}
++
++/* Called by gold after loading the plugin.  TV is the transfer vector.  */
++
++enum ld_plugin_status
++onload (struct ld_plugin_tv *tv)
++{
++  struct ld_plugin_tv *p;
++
++  p = tv;
++  while (p->tv_tag)
++    {
++      switch (p->tv_tag)
++	{
++	  case LDPT_MESSAGE:
++	    message = p->tv_u.tv_message;
++	    break;
++	  case LDPT_REGISTER_CLAIM_FILE_HOOK:
++	    register_claim_file = p->tv_u.tv_register_claim_file;
++	    break;
++	  case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
++	    register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
++	    break;
++	  case LDPT_REGISTER_CLEANUP_HOOK:
++	    register_cleanup = p->tv_u.tv_register_cleanup;
++	    break;
++	  case LDPT_LINKER_OUTPUT:
++	    linker_output = (enum ld_plugin_output_file_type)p->tv_u.tv_val;
++	    linker_output_set = 1;
++	    break;
++	  default:
++	    break;
++	}
++      p++;
++    }
++
++  register_callback_function ();
++  process_gcc_option ();
++
++  return LDPS_OK;
++}
++
+diff --git a/bolt-plugin/config.h.in b/bolt-plugin/config.h.in
+new file mode 100644
+index 000000000..9e9d316ec
+--- /dev/null
++++ b/bolt-plugin/config.h.in
+@@ -0,0 +1,179 @@
++/* config.h.in.  Generated from configure.ac by autoheader.  */
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_DLFCN_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_INTTYPES_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_MINIX_CONFIG_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_STDINT_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_STDIO_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_STDLIB_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_STRINGS_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_STRING_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_SYS_STAT_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_SYS_TYPES_H
++
++/* Define to 1 if you have  that is POSIX.1 compatible. */
++#undef HAVE_SYS_WAIT_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_UNISTD_H
++
++/* Define to 1 if you have the  header file. */
++#undef HAVE_WCHAR_H
++
++/* Define to the sub-directory where libtool stores uninstalled libraries. */
++#undef LT_OBJDIR
++
++/* Name of package */
++#undef PACKAGE
++
++/* Define to the address where bug reports for this package should be sent. */
++#undef PACKAGE_BUGREPORT
++
++/* Define to the full name of this package. */
++#undef PACKAGE_NAME
++
++/* Define to the full name and version of this package. */
++#undef PACKAGE_STRING
++
++/* Define to the one symbol short name of this package. */
++#undef PACKAGE_TARNAME
++
++/* Define to the home page for this package. */
++#undef PACKAGE_URL
++
++/* Define to the version of this package. */
++#undef PACKAGE_VERSION
++
++/* Define to 1 if all of the C90 standard headers exist (not just the ones
++   required in a freestanding environment). This macro is provided for
++   backward compatibility; new code need not use it. */
++#undef STDC_HEADERS
++
++/* Enable extensions on AIX 3, Interix.  */
++#ifndef _ALL_SOURCE
++# undef _ALL_SOURCE
++#endif
++/* Enable general extensions on macOS.  */
++#ifndef _DARWIN_C_SOURCE
++# undef _DARWIN_C_SOURCE
++#endif
++/* Enable general extensions on Solaris.  */
++#ifndef __EXTENSIONS__
++# undef __EXTENSIONS__
++#endif
++/* Enable GNU extensions on systems that have them.  */
++#ifndef _GNU_SOURCE
++# undef _GNU_SOURCE
++#endif
++/* Enable X/Open compliant socket functions that do not require linking
++   with -lxnet on HP-UX 11.11.  */
++#ifndef _HPUX_ALT_XOPEN_SOCKET_API
++# undef _HPUX_ALT_XOPEN_SOCKET_API
++#endif
++/* Identify the host operating system as Minix.
++   This macro does not affect the system headers' behavior.
++   A future release of Autoconf may stop defining this macro.  */
++#ifndef _MINIX
++# undef _MINIX
++#endif
++/* Enable general extensions on NetBSD.
++   Enable NetBSD compatibility extensions on Minix.  */
++#ifndef _NETBSD_SOURCE
++# undef _NETBSD_SOURCE
++#endif
++/* Enable OpenBSD compatibility extensions on NetBSD.
++   Oddly enough, this does nothing on OpenBSD.  */
++#ifndef _OPENBSD_SOURCE
++# undef _OPENBSD_SOURCE
++#endif
++/* Define to 1 if needed for POSIX-compatible behavior.  */
++#ifndef _POSIX_SOURCE
++# undef _POSIX_SOURCE
++#endif
++/* Define to 2 if needed for POSIX-compatible behavior.  */
++#ifndef _POSIX_1_SOURCE
++# undef _POSIX_1_SOURCE
++#endif
++/* Enable POSIX-compatible threading on Solaris.  */
++#ifndef _POSIX_PTHREAD_SEMANTICS
++# undef _POSIX_PTHREAD_SEMANTICS
++#endif
++/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
++#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
++# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
++#endif
++/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
++#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
++# undef __STDC_WANT_IEC_60559_BFP_EXT__
++#endif
++/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
++#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
++# undef __STDC_WANT_IEC_60559_DFP_EXT__
++#endif
++/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
++#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
++# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
++#endif
++/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
++#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
++# undef __STDC_WANT_IEC_60559_TYPES_EXT__
++#endif
++/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
++#ifndef __STDC_WANT_LIB_EXT2__
++# undef __STDC_WANT_LIB_EXT2__
++#endif
++/* Enable extensions specified by ISO/IEC 24747:2009.  */
++#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
++# undef __STDC_WANT_MATH_SPEC_FUNCS__
++#endif
++/* Enable extensions on HP NonStop.  */
++#ifndef _TANDEM_SOURCE
++# undef _TANDEM_SOURCE
++#endif
++/* Enable X/Open extensions.  Define to 500 only if necessary
++   to make mbstate_t available.  */
++#ifndef _XOPEN_SOURCE
++# undef _XOPEN_SOURCE
++#endif
++
++
++/* Version number of package */
++#undef VERSION
++
++/* Number of bits in a file offset, on hosts where this is settable. */
++#undef _FILE_OFFSET_BITS
++
++/* Define for large files, on AIX-style hosts. */
++#undef _LARGE_FILES
++
++/* Define for Solaris 2.5.1 so the uint64_t typedef from ,
++   , or  is not used. If the typedef were allowed, the
++   #define below would cause a syntax error. */
++#undef _UINT64_T
++
++/* Define to the type of a signed integer type of width exactly 64 bits if
++   such a type exists and the standard includes do not define it. */
++#undef int64_t
++
++/* Define to the type of an unsigned integer type of width exactly 64 bits if
++   such a type exists and the standard includes do not define it. */
++#undef uint64_t
+diff --git a/bolt-plugin/configure b/bolt-plugin/configure
+new file mode 100755
+index 000000000..63bde9a41
+--- /dev/null
++++ b/bolt-plugin/configure
+@@ -0,0 +1,20909 @@
++#! /bin/sh
++# Guess values for system-dependent variables and create Makefiles.
++# Generated by GNU Autoconf 2.71 for bolt plugin for ld 0.1.
++#
++#
++# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
++# Inc.
++#
++#
++# This configure script is free software; the Free Software Foundation
++# gives unlimited permission to copy, distribute and modify it.
++## -------------------- ##
++## M4sh Initialization. ##
++## -------------------- ##
++
++# Be more Bourne compatible
++DUALCASE=1; export DUALCASE # for MKS sh
++as_nop=:
++if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
++then :
++  emulate sh
++  NULLCMD=:
++  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
++  # is contrary to our usage.  Disable this feature.
++  alias -g '${1+"$@"}'='"$@"'
++  setopt NO_GLOB_SUBST
++else $as_nop
++  case `(set -o) 2>/dev/null` in #(
++  *posix*) :
++    set -o posix ;; #(
++  *) :
++     ;;
++esac
++fi
++
++
++
++# Reset variables that may have inherited troublesome values from
++# the environment.
++
++# IFS needs to be set, to space, tab, and newline, in precisely that order.
++# (If _AS_PATH_WALK were called with IFS unset, it would have the
++# side effect of setting IFS to empty, thus disabling word splitting.)
++# Quoting is to prevent editors from complaining about space-tab.
++as_nl='
++'
++export as_nl
++IFS=" ""	$as_nl"
++
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# Ensure predictable behavior from utilities with locale-dependent output.
++LC_ALL=C
++export LC_ALL
++LANGUAGE=C
++export LANGUAGE
++
++# We cannot yet rely on "unset" to work, but we need these variables
++# to be unset--not just set to an empty or harmless value--now, to
++# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
++# also avoids known problems related to "unset" and subshell syntax
++# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
++for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
++do eval test \${$as_var+y} \
++  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
++done
++
++# Ensure that fds 0, 1, and 2 are open.
++if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
++if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
++
++# The user is always right.
++if ${PATH_SEPARATOR+false} :; then
++  PATH_SEPARATOR=:
++  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
++    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
++      PATH_SEPARATOR=';'
++  }
++fi
++
++
++# Find who we are.  Look in the path if we contain no directory separator.
++as_myself=
++case $0 in #((
++  *[\\/]* ) as_myself=$0 ;;
++  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
++  done
++IFS=$as_save_IFS
++
++     ;;
++esac
++# We did not find ourselves, most probably we were run as `sh COMMAND'
++# in which case we are not to be found in the path.
++if test "x$as_myself" = x; then
++  as_myself=$0
++fi
++if test ! -f "$as_myself"; then
++  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
++  exit 1
++fi
++
++
++# Use a proper internal environment variable to ensure we don't fall
++  # into an infinite loop, continuously re-executing ourselves.
++  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
++    _as_can_reexec=no; export _as_can_reexec;
++    # We cannot yet assume a decent shell, so we have to provide a
++# neutralization value for shells without unset; and this also
++# works around shells that cannot unset nonexistent variables.
++# Preserve -v and -x to the replacement shell.
++BASH_ENV=/dev/null
++ENV=/dev/null
++(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
++case $- in # ((((
++  *v*x* | *x*v* ) as_opts=-vx ;;
++  *v* ) as_opts=-v ;;
++  *x* ) as_opts=-x ;;
++  * ) as_opts= ;;
++esac
++exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
++# Admittedly, this is quite paranoid, since all the known shells bail
++# out after a failed `exec'.
++printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
++exit 255
++  fi
++  # We don't want this to propagate to other subprocesses.
++          { _as_can_reexec=; unset _as_can_reexec;}
++if test "x$CONFIG_SHELL" = x; then
++  as_bourne_compatible="as_nop=:
++if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
++then :
++  emulate sh
++  NULLCMD=:
++  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
++  # is contrary to our usage.  Disable this feature.
++  alias -g '\${1+\"\$@\"}'='\"\$@\"'
++  setopt NO_GLOB_SUBST
++else \$as_nop
++  case \`(set -o) 2>/dev/null\` in #(
++  *posix*) :
++    set -o posix ;; #(
++  *) :
++     ;;
++esac
++fi
++"
++  as_required="as_fn_return () { (exit \$1); }
++as_fn_success () { as_fn_return 0; }
++as_fn_failure () { as_fn_return 1; }
++as_fn_ret_success () { return 0; }
++as_fn_ret_failure () { return 1; }
++
++exitcode=0
++as_fn_success || { exitcode=1; echo as_fn_success failed.; }
++as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
++as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
++as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
++if ( set x; as_fn_ret_success y && test x = \"\$1\" )
++then :
++
++else \$as_nop
++  exitcode=1; echo positional parameters were not saved.
++fi
++test x\$exitcode = x0 || exit 1
++blah=\$(echo \$(echo blah))
++test x\"\$blah\" = xblah || exit 1
++test -x / || exit 1"
++  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
++  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
++  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
++  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
++
++  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
++    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
++    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
++    PATH=/empty FPATH=/empty; export PATH FPATH
++    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
++      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
++test \$(( 1 + 1 )) = 2 || exit 1"
++  if (eval "$as_required") 2>/dev/null
++then :
++  as_have_required=yes
++else $as_nop
++  as_have_required=no
++fi
++  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
++then :
++
++else $as_nop
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++as_found=false
++for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++  as_found=:
++  case $as_dir in #(
++	 /*)
++	   for as_base in sh bash ksh sh5; do
++	     # Try only shells that exist, to save several forks.
++	     as_shell=$as_dir$as_base
++	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
++		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
++then :
++  CONFIG_SHELL=$as_shell as_have_required=yes
++		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
++then :
++  break 2
++fi
++fi
++	   done;;
++       esac
++  as_found=false
++done
++IFS=$as_save_IFS
++if $as_found
++then :
++
++else $as_nop
++  if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
++	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
++then :
++  CONFIG_SHELL=$SHELL as_have_required=yes
++fi
++fi
++
++
++      if test "x$CONFIG_SHELL" != x
++then :
++  export CONFIG_SHELL
++             # We cannot yet assume a decent shell, so we have to provide a
++# neutralization value for shells without unset; and this also
++# works around shells that cannot unset nonexistent variables.
++# Preserve -v and -x to the replacement shell.
++BASH_ENV=/dev/null
++ENV=/dev/null
++(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
++case $- in # ((((
++  *v*x* | *x*v* ) as_opts=-vx ;;
++  *v* ) as_opts=-v ;;
++  *x* ) as_opts=-x ;;
++  * ) as_opts= ;;
++esac
++exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
++# Admittedly, this is quite paranoid, since all the known shells bail
++# out after a failed `exec'.
++printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
++exit 255
++fi
++
++    if test x$as_have_required = xno
++then :
++  printf "%s\n" "$0: This script requires a shell more modern than all"
++  printf "%s\n" "$0: the shells that I found on your system."
++  if test ${ZSH_VERSION+y} ; then
++    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
++    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
++  else
++    printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
++$0: including any error possibly output before this
++$0: message. Then install a modern shell, or manually run
++$0: the script under such a shell if you do have one."
++  fi
++  exit 1
++fi
++fi
++fi
++SHELL=${CONFIG_SHELL-/bin/sh}
++export SHELL
++# Unset more variables known to interfere with behavior of common tools.
++CLICOLOR_FORCE= GREP_OPTIONS=
++unset CLICOLOR_FORCE GREP_OPTIONS
++
++## --------------------- ##
++## M4sh Shell Functions. ##
++## --------------------- ##
++# as_fn_unset VAR
++# ---------------
++# Portably unset VAR.
++as_fn_unset ()
++{
++  { eval $1=; unset $1;}
++}
++as_unset=as_fn_unset
++
++
++# as_fn_set_status STATUS
++# -----------------------
++# Set $? to STATUS, without forking.
++as_fn_set_status ()
++{
++  return $1
++} # as_fn_set_status
++
++# as_fn_exit STATUS
++# -----------------
++# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
++as_fn_exit ()
++{
++  set +e
++  as_fn_set_status $1
++  exit $1
++} # as_fn_exit
++# as_fn_nop
++# ---------
++# Do nothing but, unlike ":", preserve the value of $?.
++as_fn_nop ()
++{
++  return $?
++}
++as_nop=as_fn_nop
++
++# as_fn_mkdir_p
++# -------------
++# Create "$as_dir" as a directory, including parents if necessary.
++as_fn_mkdir_p ()
++{
++
++  case $as_dir in #(
++  -*) as_dir=./$as_dir;;
++  esac
++  test -d "$as_dir" || eval $as_mkdir_p || {
++    as_dirs=
++    while :; do
++      case $as_dir in #(
++      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
++      *) as_qdir=$as_dir;;
++      esac
++      as_dirs="'$as_qdir' $as_dirs"
++      as_dir=`$as_dirname -- "$as_dir" ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$as_dir" : 'X\(//\)[^/]' \| \
++	 X"$as_dir" : 'X\(//\)$' \| \
++	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X"$as_dir" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)[^/].*/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++      test -d "$as_dir" && break
++    done
++    test -z "$as_dirs" || eval "mkdir $as_dirs"
++  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
++
++
++} # as_fn_mkdir_p
++
++# as_fn_executable_p FILE
++# -----------------------
++# Test if FILE is an executable regular file.
++as_fn_executable_p ()
++{
++  test -f "$1" && test -x "$1"
++} # as_fn_executable_p
++# as_fn_append VAR VALUE
++# ----------------------
++# Append the text in VALUE to the end of the definition contained in VAR. Take
++# advantage of any shell optimizations that allow amortized linear growth over
++# repeated appends, instead of the typical quadratic growth present in naive
++# implementations.
++if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
++then :
++  eval 'as_fn_append ()
++  {
++    eval $1+=\$2
++  }'
++else $as_nop
++  as_fn_append ()
++  {
++    eval $1=\$$1\$2
++  }
++fi # as_fn_append
++
++# as_fn_arith ARG...
++# ------------------
++# Perform arithmetic evaluation on the ARGs, and store the result in the
++# global $as_val. Take advantage of shells that can avoid forks. The arguments
++# must be portable across $(()) and expr.
++if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
++then :
++  eval 'as_fn_arith ()
++  {
++    as_val=$(( $* ))
++  }'
++else $as_nop
++  as_fn_arith ()
++  {
++    as_val=`expr "$@" || test $? -eq 1`
++  }
++fi # as_fn_arith
++
++# as_fn_nop
++# ---------
++# Do nothing but, unlike ":", preserve the value of $?.
++as_fn_nop ()
++{
++  return $?
++}
++as_nop=as_fn_nop
++
++# as_fn_error STATUS ERROR [LINENO LOG_FD]
++# ----------------------------------------
++# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
++# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
++# script with STATUS, using 1 if that was 0.
++as_fn_error ()
++{
++  as_status=$1; test $as_status -eq 0 && as_status=1
++  if test "$4"; then
++    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
++  fi
++  printf "%s\n" "$as_me: error: $2" >&2
++  as_fn_exit $as_status
++} # as_fn_error
++
++if expr a : '\(a\)' >/dev/null 2>&1 &&
++   test "X`expr 00001 : '.*\(...\)'`" = X001; then
++  as_expr=expr
++else
++  as_expr=false
++fi
++
++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
++  as_basename=basename
++else
++  as_basename=false
++fi
++
++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
++  as_dirname=dirname
++else
++  as_dirname=false
++fi
++
++as_me=`$as_basename -- "$0" ||
++$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
++	 X"$0" : 'X\(//\)$' \| \
++	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X/"$0" |
++    sed '/^.*\/\([^/][^/]*\)\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\/\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\/\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++
++# Avoid depending upon Character Ranges.
++as_cr_letters='abcdefghijklmnopqrstuvwxyz'
++as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
++as_cr_Letters=$as_cr_letters$as_cr_LETTERS
++as_cr_digits='0123456789'
++as_cr_alnum=$as_cr_Letters$as_cr_digits
++
++
++  as_lineno_1=$LINENO as_lineno_1a=$LINENO
++  as_lineno_2=$LINENO as_lineno_2a=$LINENO
++  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
++  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
++  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
++  sed -n '
++    p
++    /[$]LINENO/=
++  ' <$as_myself |
++    sed '
++      s/[$]LINENO.*/&-/
++      t lineno
++      b
++      :lineno
++      N
++      :loop
++      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
++      t loop
++      s/-\n.*//
++    ' >$as_me.lineno &&
++  chmod +x "$as_me.lineno" ||
++    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
++
++  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
++  # already done that, so ensure we don't try to do so again and fall
++  # in an infinite loop.  This has already happened in practice.
++  _as_can_reexec=no; export _as_can_reexec
++  # Don't try to exec as it changes $[0], causing all sort of problems
++  # (the dirname of $[0] is not the place where we might find the
++  # original and so on.  Autoconf is especially sensitive to this).
++  . "./$as_me.lineno"
++  # Exit status is that of the last command.
++  exit
++}
++
++
++# Determine whether it's possible to make 'echo' print without a newline.
++# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
++# for compatibility with existing Makefiles.
++ECHO_C= ECHO_N= ECHO_T=
++case `echo -n x` in #(((((
++-n*)
++  case `echo 'xy\c'` in
++  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
++  xy)  ECHO_C='\c';;
++  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
++       ECHO_T='	';;
++  esac;;
++*)
++  ECHO_N='-n';;
++esac
++
++# For backward compatibility with old third-party macros, we provide
++# the shell variables $as_echo and $as_echo_n.  New code should use
++# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
++as_echo='printf %s\n'
++as_echo_n='printf %s'
++
++
++rm -f conf$$ conf$$.exe conf$$.file
++if test -d conf$$.dir; then
++  rm -f conf$$.dir/conf$$.file
++else
++  rm -f conf$$.dir
++  mkdir conf$$.dir 2>/dev/null
++fi
++if (echo >conf$$.file) 2>/dev/null; then
++  if ln -s conf$$.file conf$$ 2>/dev/null; then
++    as_ln_s='ln -s'
++    # ... but there are two gotchas:
++    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
++    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
++    # In both cases, we have to default to `cp -pR'.
++    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
++      as_ln_s='cp -pR'
++  elif ln conf$$.file conf$$ 2>/dev/null; then
++    as_ln_s=ln
++  else
++    as_ln_s='cp -pR'
++  fi
++else
++  as_ln_s='cp -pR'
++fi
++rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
++rmdir conf$$.dir 2>/dev/null
++
++if mkdir -p . 2>/dev/null; then
++  as_mkdir_p='mkdir -p "$as_dir"'
++else
++  test -d ./-p && rmdir ./-p
++  as_mkdir_p=false
++fi
++
++as_test_x='test -x'
++as_executable_p=as_fn_executable_p
++
++# Sed expression to map a string onto a valid CPP name.
++as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
++
++# Sed expression to map a string onto a valid variable name.
++as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
++
++SHELL=${CONFIG_SHELL-/bin/sh}
++
++
++test -n "$DJDIR" || exec 7<&0 &1
++
++# Name of the host.
++# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
++# so uname gets run too.
++ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
++
++#
++# Initializations.
++#
++ac_default_prefix=/usr/local
++ac_clean_files=
++ac_config_libobj_dir=.
++LIBOBJS=
++cross_compiling=no
++subdirs=
++MFLAGS=
++MAKEFLAGS=
++
++# Identity of this package.
++PACKAGE_NAME='bolt plugin for ld'
++PACKAGE_TARNAME='bolt-plugin'
++PACKAGE_VERSION='0.1'
++PACKAGE_STRING='bolt plugin for ld 0.1'
++PACKAGE_BUGREPORT=''
++PACKAGE_URL=''
++
++# Factoring default headers for most tests.
++ac_includes_default="\
++#include 
++#ifdef HAVE_STDIO_H
++# include 
++#endif
++#ifdef HAVE_STDLIB_H
++# include 
++#endif
++#ifdef HAVE_STRING_H
++# include 
++#endif
++#ifdef HAVE_INTTYPES_H
++# include 
++#endif
++#ifdef HAVE_STDINT_H
++# include 
++#endif
++#ifdef HAVE_STRINGS_H
++# include 
++#endif
++#ifdef HAVE_SYS_TYPES_H
++# include 
++#endif
++#ifdef HAVE_SYS_STAT_H
++# include 
++#endif
++#ifdef HAVE_UNISTD_H
++# include 
++#endif"
++
++ac_header_c_list=
++ac_subst_vars='am__EXEEXT_FALSE
++am__EXEEXT_TRUE
++LTLIBOBJS
++LIBOBJS
++target_noncanonical
++CXXCPP
++LT_SYS_LIBRARY_PATH
++OTOOL64
++OTOOL
++LIPO
++NMEDIT
++DSYMUTIL
++MANIFEST_TOOL
++RANLIB
++ac_ct_AR
++AR
++DLLTOOL
++OBJDUMP
++FILECMD
++LN_S
++NM
++ac_ct_DUMPBIN
++DUMPBIN
++LD
++FGREP
++EGREP
++GREP
++SED
++LIBTOOL
++real_target_noncanonical
++accel_dir_suffix
++gcc_build_dir
++ac_bolt_plugin_ldflags
++am__fastdepCXX_FALSE
++am__fastdepCXX_TRUE
++CXXDEPMODE
++ac_ct_CXX
++CXXFLAGS
++CXX
++am__fastdepCC_FALSE
++am__fastdepCC_TRUE
++CCDEPMODE
++am__nodep
++AMDEPBACKSLASH
++AMDEP_FALSE
++AMDEP_TRUE
++am__include
++DEPDIR
++OBJEXT
++EXEEXT
++ac_ct_CC
++CPPFLAGS
++LDFLAGS
++CFLAGS
++CC
++with_libiberty
++MAINT
++MAINTAINER_MODE_FALSE
++MAINTAINER_MODE_TRUE
++AM_BACKSLASH
++AM_DEFAULT_VERBOSITY
++AM_DEFAULT_V
++AM_V
++CSCOPE
++ETAGS
++CTAGS
++am__untar
++am__tar
++AMTAR
++am__leading_dot
++SET_MAKE
++AWK
++mkdir_p
++MKDIR_P
++INSTALL_STRIP_PROGRAM
++STRIP
++install_sh
++MAKEINFO
++AUTOHEADER
++AUTOMAKE
++AUTOCONF
++ACLOCAL
++VERSION
++PACKAGE
++CYGPATH_W
++am__isrc
++INSTALL_DATA
++INSTALL_SCRIPT
++INSTALL_PROGRAM
++target_os
++target_vendor
++target_cpu
++target
++host_os
++host_vendor
++host_cpu
++host
++build_os
++build_vendor
++build_cpu
++build
++target_alias
++host_alias
++build_alias
++LIBS
++ECHO_T
++ECHO_N
++ECHO_C
++DEFS
++mandir
++localedir
++libdir
++psdir
++pdfdir
++dvidir
++htmldir
++infodir
++docdir
++oldincludedir
++includedir
++runstatedir
++localstatedir
++sharedstatedir
++sysconfdir
++datadir
++datarootdir
++libexecdir
++sbindir
++bindir
++program_transform_name
++prefix
++exec_prefix
++PACKAGE_URL
++PACKAGE_BUGREPORT
++PACKAGE_STRING
++PACKAGE_VERSION
++PACKAGE_TARNAME
++PACKAGE_NAME
++PATH_SEPARATOR
++SHELL
++am__quote'
++ac_subst_files=''
++ac_user_opts='
++enable_option_checking
++enable_silent_rules
++enable_maintainer_mode
++with_libiberty
++enable_dependency_tracking
++enable_largefile
++enable_shared
++enable_static
++with_pic
++enable_fast_install
++with_aix_soname
++with_gnu_ld
++with_sysroot
++enable_libtool_lock
++'
++      ac_precious_vars='build_alias
++host_alias
++target_alias
++CC
++CFLAGS
++LDFLAGS
++LIBS
++CPPFLAGS
++CXX
++CXXFLAGS
++CCC
++LT_SYS_LIBRARY_PATH
++CXXCPP'
++
++
++# Initialize some variables set by options.
++ac_init_help=
++ac_init_version=false
++ac_unrecognized_opts=
++ac_unrecognized_sep=
++# The variables have the same names as the options, with
++# dashes changed to underlines.
++cache_file=/dev/null
++exec_prefix=NONE
++no_create=
++no_recursion=
++prefix=NONE
++program_prefix=NONE
++program_suffix=NONE
++program_transform_name=s,x,x,
++silent=
++site=
++srcdir=
++verbose=
++x_includes=NONE
++x_libraries=NONE
++
++# Installation directory options.
++# These are left unexpanded so users can "make install exec_prefix=/foo"
++# and all the variables that are supposed to be based on exec_prefix
++# by default will actually change.
++# Use braces instead of parens because sh, perl, etc. also accept them.
++# (The list follows the same order as the GNU Coding Standards.)
++bindir='${exec_prefix}/bin'
++sbindir='${exec_prefix}/sbin'
++libexecdir='${exec_prefix}/libexec'
++datarootdir='${prefix}/share'
++datadir='${datarootdir}'
++sysconfdir='${prefix}/etc'
++sharedstatedir='${prefix}/com'
++localstatedir='${prefix}/var'
++runstatedir='${localstatedir}/run'
++includedir='${prefix}/include'
++oldincludedir='/usr/include'
++docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
++infodir='${datarootdir}/info'
++htmldir='${docdir}'
++dvidir='${docdir}'
++pdfdir='${docdir}'
++psdir='${docdir}'
++libdir='${exec_prefix}/lib'
++localedir='${datarootdir}/locale'
++mandir='${datarootdir}/man'
++
++ac_prev=
++ac_dashdash=
++for ac_option
++do
++  # If the previous option needs an argument, assign it.
++  if test -n "$ac_prev"; then
++    eval $ac_prev=\$ac_option
++    ac_prev=
++    continue
++  fi
++
++  case $ac_option in
++  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
++  *=)   ac_optarg= ;;
++  *)    ac_optarg=yes ;;
++  esac
++
++  case $ac_dashdash$ac_option in
++  --)
++    ac_dashdash=yes ;;
++
++  -bindir | --bindir | --bindi | --bind | --bin | --bi)
++    ac_prev=bindir ;;
++  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
++    bindir=$ac_optarg ;;
++
++  -build | --build | --buil | --bui | --bu)
++    ac_prev=build_alias ;;
++  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
++    build_alias=$ac_optarg ;;
++
++  -cache-file | --cache-file | --cache-fil | --cache-fi \
++  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
++    ac_prev=cache_file ;;
++  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
++  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
++    cache_file=$ac_optarg ;;
++
++  --config-cache | -C)
++    cache_file=config.cache ;;
++
++  -datadir | --datadir | --datadi | --datad)
++    ac_prev=datadir ;;
++  -datadir=* | --datadir=* | --datadi=* | --datad=*)
++    datadir=$ac_optarg ;;
++
++  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
++  | --dataroo | --dataro | --datar)
++    ac_prev=datarootdir ;;
++  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
++  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
++    datarootdir=$ac_optarg ;;
++
++  -disable-* | --disable-*)
++    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
++    # Reject names that are not valid shell variable names.
++    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
++      as_fn_error $? "invalid feature name: \`$ac_useropt'"
++    ac_useropt_orig=$ac_useropt
++    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    case $ac_user_opts in
++      *"
++"enable_$ac_useropt"
++"*) ;;
++      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
++	 ac_unrecognized_sep=', ';;
++    esac
++    eval enable_$ac_useropt=no ;;
++
++  -docdir | --docdir | --docdi | --doc | --do)
++    ac_prev=docdir ;;
++  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
++    docdir=$ac_optarg ;;
++
++  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
++    ac_prev=dvidir ;;
++  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
++    dvidir=$ac_optarg ;;
++
++  -enable-* | --enable-*)
++    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
++    # Reject names that are not valid shell variable names.
++    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
++      as_fn_error $? "invalid feature name: \`$ac_useropt'"
++    ac_useropt_orig=$ac_useropt
++    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    case $ac_user_opts in
++      *"
++"enable_$ac_useropt"
++"*) ;;
++      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
++	 ac_unrecognized_sep=', ';;
++    esac
++    eval enable_$ac_useropt=\$ac_optarg ;;
++
++  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
++  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
++  | --exec | --exe | --ex)
++    ac_prev=exec_prefix ;;
++  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
++  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
++  | --exec=* | --exe=* | --ex=*)
++    exec_prefix=$ac_optarg ;;
++
++  -gas | --gas | --ga | --g)
++    # Obsolete; use --with-gas.
++    with_gas=yes ;;
++
++  -help | --help | --hel | --he | -h)
++    ac_init_help=long ;;
++  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
++    ac_init_help=recursive ;;
++  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
++    ac_init_help=short ;;
++
++  -host | --host | --hos | --ho)
++    ac_prev=host_alias ;;
++  -host=* | --host=* | --hos=* | --ho=*)
++    host_alias=$ac_optarg ;;
++
++  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
++    ac_prev=htmldir ;;
++  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
++  | --ht=*)
++    htmldir=$ac_optarg ;;
++
++  -includedir | --includedir | --includedi | --included | --include \
++  | --includ | --inclu | --incl | --inc)
++    ac_prev=includedir ;;
++  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
++  | --includ=* | --inclu=* | --incl=* | --inc=*)
++    includedir=$ac_optarg ;;
++
++  -infodir | --infodir | --infodi | --infod | --info | --inf)
++    ac_prev=infodir ;;
++  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
++    infodir=$ac_optarg ;;
++
++  -libdir | --libdir | --libdi | --libd)
++    ac_prev=libdir ;;
++  -libdir=* | --libdir=* | --libdi=* | --libd=*)
++    libdir=$ac_optarg ;;
++
++  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
++  | --libexe | --libex | --libe)
++    ac_prev=libexecdir ;;
++  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
++  | --libexe=* | --libex=* | --libe=*)
++    libexecdir=$ac_optarg ;;
++
++  -localedir | --localedir | --localedi | --localed | --locale)
++    ac_prev=localedir ;;
++  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
++    localedir=$ac_optarg ;;
++
++  -localstatedir | --localstatedir | --localstatedi | --localstated \
++  | --localstate | --localstat | --localsta | --localst | --locals)
++    ac_prev=localstatedir ;;
++  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
++  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
++    localstatedir=$ac_optarg ;;
++
++  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
++    ac_prev=mandir ;;
++  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
++    mandir=$ac_optarg ;;
++
++  -nfp | --nfp | --nf)
++    # Obsolete; use --without-fp.
++    with_fp=no ;;
++
++  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
++  | --no-cr | --no-c | -n)
++    no_create=yes ;;
++
++  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
++  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
++    no_recursion=yes ;;
++
++  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
++  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
++  | --oldin | --oldi | --old | --ol | --o)
++    ac_prev=oldincludedir ;;
++  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
++  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
++  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
++    oldincludedir=$ac_optarg ;;
++
++  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
++    ac_prev=prefix ;;
++  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
++    prefix=$ac_optarg ;;
++
++  -program-prefix | --program-prefix | --program-prefi | --program-pref \
++  | --program-pre | --program-pr | --program-p)
++    ac_prev=program_prefix ;;
++  -program-prefix=* | --program-prefix=* | --program-prefi=* \
++  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
++    program_prefix=$ac_optarg ;;
++
++  -program-suffix | --program-suffix | --program-suffi | --program-suff \
++  | --program-suf | --program-su | --program-s)
++    ac_prev=program_suffix ;;
++  -program-suffix=* | --program-suffix=* | --program-suffi=* \
++  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
++    program_suffix=$ac_optarg ;;
++
++  -program-transform-name | --program-transform-name \
++  | --program-transform-nam | --program-transform-na \
++  | --program-transform-n | --program-transform- \
++  | --program-transform | --program-transfor \
++  | --program-transfo | --program-transf \
++  | --program-trans | --program-tran \
++  | --progr-tra | --program-tr | --program-t)
++    ac_prev=program_transform_name ;;
++  -program-transform-name=* | --program-transform-name=* \
++  | --program-transform-nam=* | --program-transform-na=* \
++  | --program-transform-n=* | --program-transform-=* \
++  | --program-transform=* | --program-transfor=* \
++  | --program-transfo=* | --program-transf=* \
++  | --program-trans=* | --program-tran=* \
++  | --progr-tra=* | --program-tr=* | --program-t=*)
++    program_transform_name=$ac_optarg ;;
++
++  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
++    ac_prev=pdfdir ;;
++  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
++    pdfdir=$ac_optarg ;;
++
++  -psdir | --psdir | --psdi | --psd | --ps)
++    ac_prev=psdir ;;
++  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
++    psdir=$ac_optarg ;;
++
++  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++  | -silent | --silent | --silen | --sile | --sil)
++    silent=yes ;;
++
++  -runstatedir | --runstatedir | --runstatedi | --runstated \
++  | --runstate | --runstat | --runsta | --runst | --runs \
++  | --run | --ru | --r)
++    ac_prev=runstatedir ;;
++  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
++  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
++  | --run=* | --ru=* | --r=*)
++    runstatedir=$ac_optarg ;;
++
++  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
++    ac_prev=sbindir ;;
++  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
++  | --sbi=* | --sb=*)
++    sbindir=$ac_optarg ;;
++
++  -sharedstatedir | --sharedstatedir | --sharedstatedi \
++  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
++  | --sharedst | --shareds | --shared | --share | --shar \
++  | --sha | --sh)
++    ac_prev=sharedstatedir ;;
++  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
++  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
++  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
++  | --sha=* | --sh=*)
++    sharedstatedir=$ac_optarg ;;
++
++  -site | --site | --sit)
++    ac_prev=site ;;
++  -site=* | --site=* | --sit=*)
++    site=$ac_optarg ;;
++
++  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
++    ac_prev=srcdir ;;
++  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
++    srcdir=$ac_optarg ;;
++
++  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
++  | --syscon | --sysco | --sysc | --sys | --sy)
++    ac_prev=sysconfdir ;;
++  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
++  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
++    sysconfdir=$ac_optarg ;;
++
++  -target | --target | --targe | --targ | --tar | --ta | --t)
++    ac_prev=target_alias ;;
++  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
++    target_alias=$ac_optarg ;;
++
++  -v | -verbose | --verbose | --verbos | --verbo | --verb)
++    verbose=yes ;;
++
++  -version | --version | --versio | --versi | --vers | -V)
++    ac_init_version=: ;;
++
++  -with-* | --with-*)
++    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
++    # Reject names that are not valid shell variable names.
++    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
++      as_fn_error $? "invalid package name: \`$ac_useropt'"
++    ac_useropt_orig=$ac_useropt
++    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    case $ac_user_opts in
++      *"
++"with_$ac_useropt"
++"*) ;;
++      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
++	 ac_unrecognized_sep=', ';;
++    esac
++    eval with_$ac_useropt=\$ac_optarg ;;
++
++  -without-* | --without-*)
++    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
++    # Reject names that are not valid shell variable names.
++    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
++      as_fn_error $? "invalid package name: \`$ac_useropt'"
++    ac_useropt_orig=$ac_useropt
++    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    case $ac_user_opts in
++      *"
++"with_$ac_useropt"
++"*) ;;
++      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
++	 ac_unrecognized_sep=', ';;
++    esac
++    eval with_$ac_useropt=no ;;
++
++  --x)
++    # Obsolete; use --with-x.
++    with_x=yes ;;
++
++  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
++  | --x-incl | --x-inc | --x-in | --x-i)
++    ac_prev=x_includes ;;
++  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
++  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
++    x_includes=$ac_optarg ;;
++
++  -x-libraries | --x-libraries | --x-librarie | --x-librari \
++  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
++    ac_prev=x_libraries ;;
++  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
++  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
++    x_libraries=$ac_optarg ;;
++
++  -*) as_fn_error $? "unrecognized option: \`$ac_option'
++Try \`$0 --help' for more information"
++    ;;
++
++  *=*)
++    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
++    # Reject names that are not valid shell variable names.
++    case $ac_envvar in #(
++      '' | [0-9]* | *[!_$as_cr_alnum]* )
++      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
++    esac
++    eval $ac_envvar=\$ac_optarg
++    export $ac_envvar ;;
++
++  *)
++    # FIXME: should be removed in autoconf 3.0.
++    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
++    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
++      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
++    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
++    ;;
++
++  esac
++done
++
++if test -n "$ac_prev"; then
++  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
++  as_fn_error $? "missing argument to $ac_option"
++fi
++
++if test -n "$ac_unrecognized_opts"; then
++  case $enable_option_checking in
++    no) ;;
++    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
++    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
++  esac
++fi
++
++# Check all directory arguments for consistency.
++for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
++		datadir sysconfdir sharedstatedir localstatedir includedir \
++		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
++		libdir localedir mandir runstatedir
++do
++  eval ac_val=\$$ac_var
++  # Remove trailing slashes.
++  case $ac_val in
++    */ )
++      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
++      eval $ac_var=\$ac_val;;
++  esac
++  # Be sure to have absolute directory names.
++  case $ac_val in
++    [\\/$]* | ?:[\\/]* )  continue;;
++    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
++  esac
++  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
++done
++
++# There might be people who depend on the old broken behavior: `$host'
++# used to hold the argument of --host etc.
++# FIXME: To remove some day.
++build=$build_alias
++host=$host_alias
++target=$target_alias
++
++# FIXME: To remove some day.
++if test "x$host_alias" != x; then
++  if test "x$build_alias" = x; then
++    cross_compiling=maybe
++  elif test "x$build_alias" != "x$host_alias"; then
++    cross_compiling=yes
++  fi
++fi
++
++ac_tool_prefix=
++test -n "$host_alias" && ac_tool_prefix=$host_alias-
++
++test "$silent" = yes && exec 6>/dev/null
++
++
++ac_pwd=`pwd` && test -n "$ac_pwd" &&
++ac_ls_di=`ls -di .` &&
++ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
++  as_fn_error $? "working directory cannot be determined"
++test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
++  as_fn_error $? "pwd does not report name of working directory"
++
++
++# Find the source files, if location was not specified.
++if test -z "$srcdir"; then
++  ac_srcdir_defaulted=yes
++  # Try the directory containing this script, then the parent directory.
++  ac_confdir=`$as_dirname -- "$as_myself" ||
++$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$as_myself" : 'X\(//\)[^/]' \| \
++	 X"$as_myself" : 'X\(//\)$' \| \
++	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X"$as_myself" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)[^/].*/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++  srcdir=$ac_confdir
++  if test ! -r "$srcdir/$ac_unique_file"; then
++    srcdir=..
++  fi
++else
++  ac_srcdir_defaulted=no
++fi
++if test ! -r "$srcdir/$ac_unique_file"; then
++  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
++  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
++fi
++ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
++ac_abs_confdir=`(
++	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
++	pwd)`
++# When building in place, set srcdir=.
++if test "$ac_abs_confdir" = "$ac_pwd"; then
++  srcdir=.
++fi
++# Remove unnecessary trailing slashes from srcdir.
++# Double slashes in file names in object file debugging info
++# mess up M-x gdb in Emacs.
++case $srcdir in
++*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
++esac
++for ac_var in $ac_precious_vars; do
++  eval ac_env_${ac_var}_set=\${${ac_var}+set}
++  eval ac_env_${ac_var}_value=\$${ac_var}
++  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
++  eval ac_cv_env_${ac_var}_value=\$${ac_var}
++done
++
++#
++# Report the --help message.
++#
++if test "$ac_init_help" = "long"; then
++  # Omit some internal or obsolete options to make the list less imposing.
++  # This message is too long to be a string in the A/UX 3.1 sh.
++  cat <<_ACEOF
++\`configure' configures bolt plugin for ld 0.1 to adapt to many kinds of systems.
++
++Usage: $0 [OPTION]... [VAR=VALUE]...
++
++To assign environment variables (e.g., CC, CFLAGS...), specify them as
++VAR=VALUE.  See below for descriptions of some of the useful variables.
++
++Defaults for the options are specified in brackets.
++
++Configuration:
++  -h, --help              display this help and exit
++      --help=short        display options specific to this package
++      --help=recursive    display the short help of all the included packages
++  -V, --version           display version information and exit
++  -q, --quiet, --silent   do not print \`checking ...' messages
++      --cache-file=FILE   cache test results in FILE [disabled]
++  -C, --config-cache      alias for \`--cache-file=config.cache'
++  -n, --no-create         do not create output files
++      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
++
++Installation directories:
++  --prefix=PREFIX         install architecture-independent files in PREFIX
++                          [$ac_default_prefix]
++  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
++                          [PREFIX]
++
++By default, \`make install' will install all the files in
++\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
++an installation prefix other than \`$ac_default_prefix' using \`--prefix',
++for instance \`--prefix=\$HOME'.
++
++For better control, use the options below.
++
++Fine tuning of the installation directories:
++  --bindir=DIR            user executables [EPREFIX/bin]
++  --sbindir=DIR           system admin executables [EPREFIX/sbin]
++  --libexecdir=DIR        program executables [EPREFIX/libexec]
++  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
++  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
++  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
++  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
++  --libdir=DIR            object code libraries [EPREFIX/lib]
++  --includedir=DIR        C header files [PREFIX/include]
++  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
++  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
++  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
++  --infodir=DIR           info documentation [DATAROOTDIR/info]
++  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
++  --mandir=DIR            man documentation [DATAROOTDIR/man]
++  --docdir=DIR            documentation root [DATAROOTDIR/doc/bolt-plugin]
++  --htmldir=DIR           html documentation [DOCDIR]
++  --dvidir=DIR            dvi documentation [DOCDIR]
++  --pdfdir=DIR            pdf documentation [DOCDIR]
++  --psdir=DIR             ps documentation [DOCDIR]
++_ACEOF
++
++  cat <<\_ACEOF
++
++Program names:
++  --program-prefix=PREFIX            prepend PREFIX to installed program names
++  --program-suffix=SUFFIX            append SUFFIX to installed program names
++  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
++
++System types:
++  --build=BUILD     configure for building on BUILD [guessed]
++  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
++  --target=TARGET   configure for building compilers for TARGET [HOST]
++_ACEOF
++fi
++
++if test -n "$ac_init_help"; then
++  case $ac_init_help in
++     short | recursive ) echo "Configuration of bolt plugin for ld 0.1:";;
++   esac
++  cat <<\_ACEOF
++
++Optional Features:
++  --disable-option-checking  ignore unrecognized --enable/--with options
++  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
++  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
++  --enable-silent-rules   less verbose build output (undo: "make V=1")
++  --disable-silent-rules  verbose build output (undo: "make V=0")
++  --enable-maintainer-mode
++                          enable make rules and dependencies not useful (and
++                          sometimes confusing) to the casual installer
++  --enable-dependency-tracking
++                          do not reject slow dependency extractors
++  --disable-dependency-tracking
++                          speeds up one-time build
++  --disable-largefile     omit support for large files
++  --enable-shared[=PKGS]  build shared libraries [default=yes]
++  --enable-static[=PKGS]  build static libraries [default=yes]
++  --enable-fast-install[=PKGS]
++                          optimize for fast installation [default=yes]
++  --disable-libtool-lock  avoid locking (might break parallel builds)
++
++Optional Packages:
++  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
++  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
++  --with-libiberty=PATH   specify the directory where to find libiberty
++                          [../libiberty]
++  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
++                          both]
++  --with-aix-soname=aix|svr4|both
++                          shared library versioning (aka "SONAME") variant to
++                          provide on AIX, [default=aix].
++  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
++  --with-sysroot[=DIR]    Search for dependent libraries within DIR (or the
++                          compiler's sysroot if not specified).
++
++Some influential environment variables:
++  CC          C compiler command
++  CFLAGS      C compiler flags
++  LDFLAGS     linker flags, e.g. -L if you have libraries in a
++              nonstandard directory 
++  LIBS        libraries to pass to the linker, e.g. -l
++  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I if
++              you have headers in a nonstandard directory 
++  CXX         C++ compiler command
++  CXXFLAGS    C++ compiler flags
++  LT_SYS_LIBRARY_PATH
++              User-defined run-time library search path.
++  CXXCPP      C++ preprocessor
++
++Use these variables to override the choices made by `configure' or to help
++it to find libraries and programs with nonstandard names/locations.
++
++Report bugs to the package provider.
++_ACEOF
++ac_status=$?
++fi
++
++if test "$ac_init_help" = "recursive"; then
++  # If there are subdirs, report their specific --help.
++  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
++    test -d "$ac_dir" ||
++      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
++      continue
++    ac_builddir=.
++
++case "$ac_dir" in
++.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
++*)
++  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
++  # A ".." for each directory in $ac_dir_suffix.
++  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
++  case $ac_top_builddir_sub in
++  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
++  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
++  esac ;;
++esac
++ac_abs_top_builddir=$ac_pwd
++ac_abs_builddir=$ac_pwd$ac_dir_suffix
++# for backward compatibility:
++ac_top_builddir=$ac_top_build_prefix
++
++case $srcdir in
++  .)  # We are building in place.
++    ac_srcdir=.
++    ac_top_srcdir=$ac_top_builddir_sub
++    ac_abs_top_srcdir=$ac_pwd ;;
++  [\\/]* | ?:[\\/]* )  # Absolute name.
++    ac_srcdir=$srcdir$ac_dir_suffix;
++    ac_top_srcdir=$srcdir
++    ac_abs_top_srcdir=$srcdir ;;
++  *) # Relative name.
++    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
++    ac_top_srcdir=$ac_top_build_prefix$srcdir
++    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
++esac
++ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
++
++    cd "$ac_dir" || { ac_status=$?; continue; }
++    # Check for configure.gnu first; this name is used for a wrapper for
++    # Metaconfig's "Configure" on case-insensitive file systems.
++    if test -f "$ac_srcdir/configure.gnu"; then
++      echo &&
++      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
++    elif test -f "$ac_srcdir/configure"; then
++      echo &&
++      $SHELL "$ac_srcdir/configure" --help=recursive
++    else
++      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
++    fi || ac_status=$?
++    cd "$ac_pwd" || { ac_status=$?; break; }
++  done
++fi
++
++test -n "$ac_init_help" && exit $ac_status
++if $ac_init_version; then
++  cat <<\_ACEOF
++bolt plugin for ld configure 0.1
++generated by GNU Autoconf 2.71
++
++Copyright (C) 2021 Free Software Foundation, Inc.
++This configure script is free software; the Free Software Foundation
++gives unlimited permission to copy, distribute and modify it.
++_ACEOF
++  exit
++fi
++
++## ------------------------ ##
++## Autoconf initialization. ##
++## ------------------------ ##
++
++# ac_fn_c_try_compile LINENO
++# --------------------------
++# Try to compile conftest.$ac_ext, and return whether this succeeded.
++ac_fn_c_try_compile ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  rm -f conftest.$ac_objext conftest.beam
++  if { { ac_try="$ac_compile"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_compile") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    grep -v '^ *+' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++    mv -f conftest.er1 conftest.err
++  fi
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && {
++	 test -z "$ac_c_werror_flag" ||
++	 test ! -s conftest.err
++       } && test -s conftest.$ac_objext
++then :
++  ac_retval=0
++else $as_nop
++  printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++	ac_retval=1
++fi
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_c_try_compile
++
++# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
++# -------------------------------------------------------
++# Tests whether HEADER exists and can be compiled using the include files in
++# INCLUDES, setting the cache variable VAR accordingly.
++ac_fn_c_check_header_compile ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++printf %s "checking for $2... " >&6; }
++if eval test \${$3+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$4
++#include <$2>
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  eval "$3=yes"
++else $as_nop
++  eval "$3=no"
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++eval ac_res=\$$3
++	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++printf "%s\n" "$ac_res" >&6; }
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++
++} # ac_fn_c_check_header_compile
++
++# ac_fn_cxx_try_compile LINENO
++# ----------------------------
++# Try to compile conftest.$ac_ext, and return whether this succeeded.
++ac_fn_cxx_try_compile ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  rm -f conftest.$ac_objext conftest.beam
++  if { { ac_try="$ac_compile"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_compile") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    grep -v '^ *+' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++    mv -f conftest.er1 conftest.err
++  fi
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && {
++	 test -z "$ac_cxx_werror_flag" ||
++	 test ! -s conftest.err
++       } && test -s conftest.$ac_objext
++then :
++  ac_retval=0
++else $as_nop
++  printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++	ac_retval=1
++fi
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_cxx_try_compile
++
++# ac_fn_c_try_link LINENO
++# -----------------------
++# Try to link conftest.$ac_ext, and return whether this succeeded.
++ac_fn_c_try_link ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
++  if { { ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_link") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    grep -v '^ *+' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++    mv -f conftest.er1 conftest.err
++  fi
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && {
++	 test -z "$ac_c_werror_flag" ||
++	 test ! -s conftest.err
++       } && test -s conftest$ac_exeext && {
++	 test "$cross_compiling" = yes ||
++	 test -x conftest$ac_exeext
++       }
++then :
++  ac_retval=0
++else $as_nop
++  printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++	ac_retval=1
++fi
++  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
++  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
++  # interfere with the next link command; also delete a directory that is
++  # left behind by Apple's compiler.  We do this before executing the actions.
++  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_c_try_link
++
++# ac_fn_c_check_func LINENO FUNC VAR
++# ----------------------------------
++# Tests whether FUNC exists, setting the cache variable VAR accordingly
++ac_fn_c_check_func ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++printf %s "checking for $2... " >&6; }
++if eval test \${$3+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++/* Define $2 to an innocuous variant, in case  declares $2.
++   For example, HP-UX 11i  declares gettimeofday.  */
++#define $2 innocuous_$2
++
++/* System header to define __stub macros and hopefully few prototypes,
++   which can conflict with char $2 (); below.  */
++
++#include 
++#undef $2
++
++/* Override any GCC internal prototype to avoid an error.
++   Use char because int might match the return type of a GCC
++   builtin and then its argument prototype would still apply.  */
++#ifdef __cplusplus
++extern "C"
++#endif
++char $2 ();
++/* The GNU C library defines this for functions which it implements
++    to always fail with ENOSYS.  Some functions are actually named
++    something starting with __ and the normal name is an alias.  */
++#if defined __stub_$2 || defined __stub___$2
++choke me
++#endif
++
++int
++main (void)
++{
++return $2 ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  eval "$3=yes"
++else $as_nop
++  eval "$3=no"
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++fi
++eval ac_res=\$$3
++	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++printf "%s\n" "$ac_res" >&6; }
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++
++} # ac_fn_c_check_func
++
++# ac_fn_cxx_try_cpp LINENO
++# ------------------------
++# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
++ac_fn_cxx_try_cpp ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  if { { ac_try="$ac_cpp conftest.$ac_ext"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    grep -v '^ *+' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++    mv -f conftest.er1 conftest.err
++  fi
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } > conftest.i && {
++	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
++	 test ! -s conftest.err
++       }
++then :
++  ac_retval=0
++else $as_nop
++  printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++    ac_retval=1
++fi
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_cxx_try_cpp
++
++# ac_fn_cxx_try_link LINENO
++# -------------------------
++# Try to link conftest.$ac_ext, and return whether this succeeded.
++ac_fn_cxx_try_link ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
++  if { { ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_link") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    grep -v '^ *+' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++    mv -f conftest.er1 conftest.err
++  fi
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && {
++	 test -z "$ac_cxx_werror_flag" ||
++	 test ! -s conftest.err
++       } && test -s conftest$ac_exeext && {
++	 test "$cross_compiling" = yes ||
++	 test -x conftest$ac_exeext
++       }
++then :
++  ac_retval=0
++else $as_nop
++  printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++	ac_retval=1
++fi
++  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
++  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
++  # interfere with the next link command; also delete a directory that is
++  # left behind by Apple's compiler.  We do this before executing the actions.
++  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_cxx_try_link
++
++# ac_fn_c_find_intX_t LINENO BITS VAR
++# -----------------------------------
++# Finds a signed integer type with width BITS, setting cache variable VAR
++# accordingly.
++ac_fn_c_find_intX_t ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
++printf %s "checking for int$2_t... " >&6; }
++if eval test \${$3+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  eval "$3=no"
++     # Order is important - never check a type that is potentially smaller
++     # than half of the expected target width.
++     for ac_type in int$2_t 'int' 'long int' \
++	 'long long int' 'short int' 'signed char'; do
++       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_includes_default
++	     enum { N = $2 / 2 - 1 };
++int
++main (void)
++{
++static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
++test_array [0] = 0;
++return test_array [0];
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_includes_default
++	        enum { N = $2 / 2 - 1 };
++int
++main (void)
++{
++static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
++		 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
++test_array [0] = 0;
++return test_array [0];
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++
++else $as_nop
++  case $ac_type in #(
++  int$2_t) :
++    eval "$3=yes" ;; #(
++  *) :
++    eval "$3=\$ac_type" ;;
++esac
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++       if eval test \"x\$"$3"\" = x"no"
++then :
++
++else $as_nop
++  break
++fi
++     done
++fi
++eval ac_res=\$$3
++	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++printf "%s\n" "$ac_res" >&6; }
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++
++} # ac_fn_c_find_intX_t
++
++# ac_fn_c_find_uintX_t LINENO BITS VAR
++# ------------------------------------
++# Finds an unsigned integer type with width BITS, setting cache variable VAR
++# accordingly.
++ac_fn_c_find_uintX_t ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
++printf %s "checking for uint$2_t... " >&6; }
++if eval test \${$3+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  eval "$3=no"
++     # Order is important - never check a type that is potentially smaller
++     # than half of the expected target width.
++     for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
++	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
++       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_includes_default
++int
++main (void)
++{
++static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
++test_array [0] = 0;
++return test_array [0];
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  case $ac_type in #(
++  uint$2_t) :
++    eval "$3=yes" ;; #(
++  *) :
++    eval "$3=\$ac_type" ;;
++esac
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++       if eval test \"x\$"$3"\" = x"no"
++then :
++
++else $as_nop
++  break
++fi
++     done
++fi
++eval ac_res=\$$3
++	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++printf "%s\n" "$ac_res" >&6; }
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++
++} # ac_fn_c_find_uintX_t
++ac_configure_args_raw=
++for ac_arg
++do
++  case $ac_arg in
++  *\'*)
++    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
++  esac
++  as_fn_append ac_configure_args_raw " '$ac_arg'"
++done
++
++case $ac_configure_args_raw in
++  *$as_nl*)
++    ac_safe_unquote= ;;
++  *)
++    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
++    ac_unsafe_a="$ac_unsafe_z#~"
++    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
++    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
++esac
++
++cat >config.log <<_ACEOF
++This file contains any messages produced by compilers while
++running configure, to aid debugging if configure makes a mistake.
++
++It was created by bolt plugin for ld $as_me 0.1, which was
++generated by GNU Autoconf 2.71.  Invocation command line was
++
++  $ $0$ac_configure_args_raw
++
++_ACEOF
++exec 5>>config.log
++{
++cat <<_ASUNAME
++## --------- ##
++## Platform. ##
++## --------- ##
++
++hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
++uname -m = `(uname -m) 2>/dev/null || echo unknown`
++uname -r = `(uname -r) 2>/dev/null || echo unknown`
++uname -s = `(uname -s) 2>/dev/null || echo unknown`
++uname -v = `(uname -v) 2>/dev/null || echo unknown`
++
++/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
++/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
++
++/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
++/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
++/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
++/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
++/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
++/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
++/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
++
++_ASUNAME
++
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    printf "%s\n" "PATH: $as_dir"
++  done
++IFS=$as_save_IFS
++
++} >&5
++
++cat >&5 <<_ACEOF
++
++
++## ----------- ##
++## Core tests. ##
++## ----------- ##
++
++_ACEOF
++
++
++# Keep a trace of the command line.
++# Strip out --no-create and --no-recursion so they do not pile up.
++# Strip out --silent because we don't want to record it for future runs.
++# Also quote any args containing shell meta-characters.
++# Make two passes to allow for proper duplicate-argument suppression.
++ac_configure_args=
++ac_configure_args0=
++ac_configure_args1=
++ac_must_keep_next=false
++for ac_pass in 1 2
++do
++  for ac_arg
++  do
++    case $ac_arg in
++    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
++    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++    | -silent | --silent | --silen | --sile | --sil)
++      continue ;;
++    *\'*)
++      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
++    esac
++    case $ac_pass in
++    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
++    2)
++      as_fn_append ac_configure_args1 " '$ac_arg'"
++      if test $ac_must_keep_next = true; then
++	ac_must_keep_next=false # Got value, back to normal.
++      else
++	case $ac_arg in
++	  *=* | --config-cache | -C | -disable-* | --disable-* \
++	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
++	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
++	  | -with-* | --with-* | -without-* | --without-* | --x)
++	    case "$ac_configure_args0 " in
++	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
++	    esac
++	    ;;
++	  -* ) ac_must_keep_next=true ;;
++	esac
++      fi
++      as_fn_append ac_configure_args " '$ac_arg'"
++      ;;
++    esac
++  done
++done
++{ ac_configure_args0=; unset ac_configure_args0;}
++{ ac_configure_args1=; unset ac_configure_args1;}
++
++# When interrupted or exit'd, cleanup temporary files, and complete
++# config.log.  We remove comments because anyway the quotes in there
++# would cause problems or look ugly.
++# WARNING: Use '\'' to represent an apostrophe within the trap.
++# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
++trap 'exit_status=$?
++  # Sanitize IFS.
++  IFS=" ""	$as_nl"
++  # Save into config.log some information that might help in debugging.
++  {
++    echo
++
++    printf "%s\n" "## ---------------- ##
++## Cache variables. ##
++## ---------------- ##"
++    echo
++    # The following way of writing the cache mishandles newlines in values,
++(
++  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
++    eval ac_val=\$$ac_var
++    case $ac_val in #(
++    *${as_nl}*)
++      case $ac_var in #(
++      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
++printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
++      esac
++      case $ac_var in #(
++      _ | IFS | as_nl) ;; #(
++      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
++      *) { eval $ac_var=; unset $ac_var;} ;;
++      esac ;;
++    esac
++  done
++  (set) 2>&1 |
++    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
++    *${as_nl}ac_space=\ *)
++      sed -n \
++	"s/'\''/'\''\\\\'\'''\''/g;
++	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
++      ;; #(
++    *)
++      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
++      ;;
++    esac |
++    sort
++)
++    echo
++
++    printf "%s\n" "## ----------------- ##
++## Output variables. ##
++## ----------------- ##"
++    echo
++    for ac_var in $ac_subst_vars
++    do
++      eval ac_val=\$$ac_var
++      case $ac_val in
++      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
++      esac
++      printf "%s\n" "$ac_var='\''$ac_val'\''"
++    done | sort
++    echo
++
++    if test -n "$ac_subst_files"; then
++      printf "%s\n" "## ------------------- ##
++## File substitutions. ##
++## ------------------- ##"
++      echo
++      for ac_var in $ac_subst_files
++      do
++	eval ac_val=\$$ac_var
++	case $ac_val in
++	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
++	esac
++	printf "%s\n" "$ac_var='\''$ac_val'\''"
++      done | sort
++      echo
++    fi
++
++    if test -s confdefs.h; then
++      printf "%s\n" "## ----------- ##
++## confdefs.h. ##
++## ----------- ##"
++      echo
++      cat confdefs.h
++      echo
++    fi
++    test "$ac_signal" != 0 &&
++      printf "%s\n" "$as_me: caught signal $ac_signal"
++    printf "%s\n" "$as_me: exit $exit_status"
++  } >&5
++  rm -f core *.core core.conftest.* &&
++    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
++    exit $exit_status
++' 0
++for ac_signal in 1 2 13 15; do
++  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
++done
++ac_signal=0
++
++# confdefs.h avoids OS command line length limits that DEFS can exceed.
++rm -f -r conftest* confdefs.h
++
++printf "%s\n" "/* confdefs.h */" > confdefs.h
++
++# Predefined preprocessor variables.
++
++printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
++
++printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
++
++printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
++
++printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
++
++printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
++
++printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
++
++
++# Let the site file select an alternate cache file if it wants to.
++# Prefer an explicitly selected file to automatically selected ones.
++if test -n "$CONFIG_SITE"; then
++  ac_site_files="$CONFIG_SITE"
++elif test "x$prefix" != xNONE; then
++  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
++else
++  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
++fi
++
++for ac_site_file in $ac_site_files
++do
++  case $ac_site_file in #(
++  */*) :
++     ;; #(
++  *) :
++    ac_site_file=./$ac_site_file ;;
++esac
++  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
++printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
++    sed 's/^/| /' "$ac_site_file" >&5
++    . "$ac_site_file" \
++      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "failed to load site script $ac_site_file
++See \`config.log' for more details" "$LINENO" 5; }
++  fi
++done
++
++if test -r "$cache_file"; then
++  # Some versions of bash will fail to source /dev/null (special files
++  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
++  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
++printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
++    case $cache_file in
++      [\\/]* | ?:[\\/]* ) . "$cache_file";;
++      *)                      . "./$cache_file";;
++    esac
++  fi
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
++printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
++  >$cache_file
++fi
++
++as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
++# Test code for whether the C compiler supports C89 (global declarations)
++ac_c_conftest_c89_globals='
++/* Does the compiler advertise C89 conformance?
++   Do not test the value of __STDC__, because some compilers set it to 0
++   while being otherwise adequately conformant. */
++#if !defined __STDC__
++# error "Compiler does not advertise C89 conformance"
++#endif
++
++#include 
++#include 
++struct stat;
++/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
++struct buf { int x; };
++struct buf * (*rcsopen) (struct buf *, struct stat *, int);
++static char *e (p, i)
++     char **p;
++     int i;
++{
++  return p[i];
++}
++static char *f (char * (*g) (char **, int), char **p, ...)
++{
++  char *s;
++  va_list v;
++  va_start (v,p);
++  s = g (p, va_arg (v,int));
++  va_end (v);
++  return s;
++}
++
++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
++   function prototypes and stuff, but not \xHH hex character constants.
++   These do not provoke an error unfortunately, instead are silently treated
++   as an "x".  The following induces an error, until -std is added to get
++   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
++   array size at least.  It is necessary to write \x00 == 0 to get something
++   that is true only with -std.  */
++int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
++
++/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
++   inside strings and character constants.  */
++#define FOO(x) '\''x'\''
++int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
++
++int test (int i, double x);
++struct s1 {int (*f) (int a);};
++struct s2 {int (*f) (double a);};
++int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
++               int, int);'
++
++# Test code for whether the C compiler supports C89 (body of main).
++ac_c_conftest_c89_main='
++ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
++'
++
++# Test code for whether the C compiler supports C99 (global declarations)
++ac_c_conftest_c99_globals='
++// Does the compiler advertise C99 conformance?
++#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
++# error "Compiler does not advertise C99 conformance"
++#endif
++
++#include 
++extern int puts (const char *);
++extern int printf (const char *, ...);
++extern int dprintf (int, const char *, ...);
++extern void *malloc (size_t);
++
++// Check varargs macros.  These examples are taken from C99 6.10.3.5.
++// dprintf is used instead of fprintf to avoid needing to declare
++// FILE and stderr.
++#define debug(...) dprintf (2, __VA_ARGS__)
++#define showlist(...) puts (#__VA_ARGS__)
++#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
++static void
++test_varargs_macros (void)
++{
++  int x = 1234;
++  int y = 5678;
++  debug ("Flag");
++  debug ("X = %d\n", x);
++  showlist (The first, second, and third items.);
++  report (x>y, "x is %d but y is %d", x, y);
++}
++
++// Check long long types.
++#define BIG64 18446744073709551615ull
++#define BIG32 4294967295ul
++#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
++#if !BIG_OK
++  #error "your preprocessor is broken"
++#endif
++#if BIG_OK
++#else
++  #error "your preprocessor is broken"
++#endif
++static long long int bignum = -9223372036854775807LL;
++static unsigned long long int ubignum = BIG64;
++
++struct incomplete_array
++{
++  int datasize;
++  double data[];
++};
++
++struct named_init {
++  int number;
++  const wchar_t *name;
++  double average;
++};
++
++typedef const char *ccp;
++
++static inline int
++test_restrict (ccp restrict text)
++{
++  // See if C++-style comments work.
++  // Iterate through items via the restricted pointer.
++  // Also check for declarations in for loops.
++  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
++    continue;
++  return 0;
++}
++
++// Check varargs and va_copy.
++static bool
++test_varargs (const char *format, ...)
++{
++  va_list args;
++  va_start (args, format);
++  va_list args_copy;
++  va_copy (args_copy, args);
++
++  const char *str = "";
++  int number = 0;
++  float fnumber = 0;
++
++  while (*format)
++    {
++      switch (*format++)
++	{
++	case '\''s'\'': // string
++	  str = va_arg (args_copy, const char *);
++	  break;
++	case '\''d'\'': // int
++	  number = va_arg (args_copy, int);
++	  break;
++	case '\''f'\'': // float
++	  fnumber = va_arg (args_copy, double);
++	  break;
++	default:
++	  break;
++	}
++    }
++  va_end (args_copy);
++  va_end (args);
++
++  return *str && number && fnumber;
++}
++'
++
++# Test code for whether the C compiler supports C99 (body of main).
++ac_c_conftest_c99_main='
++  // Check bool.
++  _Bool success = false;
++  success |= (argc != 0);
++
++  // Check restrict.
++  if (test_restrict ("String literal") == 0)
++    success = true;
++  char *restrict newvar = "Another string";
++
++  // Check varargs.
++  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
++  test_varargs_macros ();
++
++  // Check flexible array members.
++  struct incomplete_array *ia =
++    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
++  ia->datasize = 10;
++  for (int i = 0; i < ia->datasize; ++i)
++    ia->data[i] = i * 1.234;
++
++  // Check named initializers.
++  struct named_init ni = {
++    .number = 34,
++    .name = L"Test wide string",
++    .average = 543.34343,
++  };
++
++  ni.number = 58;
++
++  int dynamic_array[ni.number];
++  dynamic_array[0] = argv[0][0];
++  dynamic_array[ni.number - 1] = 543;
++
++  // work around unused variable warnings
++  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
++	 || dynamic_array[ni.number - 1] != 543);
++'
++
++# Test code for whether the C compiler supports C11 (global declarations)
++ac_c_conftest_c11_globals='
++// Does the compiler advertise C11 conformance?
++#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
++# error "Compiler does not advertise C11 conformance"
++#endif
++
++// Check _Alignas.
++char _Alignas (double) aligned_as_double;
++char _Alignas (0) no_special_alignment;
++extern char aligned_as_int;
++char _Alignas (0) _Alignas (int) aligned_as_int;
++
++// Check _Alignof.
++enum
++{
++  int_alignment = _Alignof (int),
++  int_array_alignment = _Alignof (int[100]),
++  char_alignment = _Alignof (char)
++};
++_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
++
++// Check _Noreturn.
++int _Noreturn does_not_return (void) { for (;;) continue; }
++
++// Check _Static_assert.
++struct test_static_assert
++{
++  int x;
++  _Static_assert (sizeof (int) <= sizeof (long int),
++                  "_Static_assert does not work in struct");
++  long int y;
++};
++
++// Check UTF-8 literals.
++#define u8 syntax error!
++char const utf8_literal[] = u8"happens to be ASCII" "another string";
++
++// Check duplicate typedefs.
++typedef long *long_ptr;
++typedef long int *long_ptr;
++typedef long_ptr long_ptr;
++
++// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
++struct anonymous
++{
++  union {
++    struct { int i; int j; };
++    struct { int k; long int l; } w;
++  };
++  int m;
++} v1;
++'
++
++# Test code for whether the C compiler supports C11 (body of main).
++ac_c_conftest_c11_main='
++  _Static_assert ((offsetof (struct anonymous, i)
++		   == offsetof (struct anonymous, w.k)),
++		  "Anonymous union alignment botch");
++  v1.i = 2;
++  v1.w.k = 5;
++  ok |= v1.i != 5;
++'
++
++# Test code for whether the C compiler supports C11 (complete).
++ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
++${ac_c_conftest_c99_globals}
++${ac_c_conftest_c11_globals}
++
++int
++main (int argc, char **argv)
++{
++  int ok = 0;
++  ${ac_c_conftest_c89_main}
++  ${ac_c_conftest_c99_main}
++  ${ac_c_conftest_c11_main}
++  return ok;
++}
++"
++
++# Test code for whether the C compiler supports C99 (complete).
++ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
++${ac_c_conftest_c99_globals}
++
++int
++main (int argc, char **argv)
++{
++  int ok = 0;
++  ${ac_c_conftest_c89_main}
++  ${ac_c_conftest_c99_main}
++  return ok;
++}
++"
++
++# Test code for whether the C compiler supports C89 (complete).
++ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
++
++int
++main (int argc, char **argv)
++{
++  int ok = 0;
++  ${ac_c_conftest_c89_main}
++  return ok;
++}
++"
++
++as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
++as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
++as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
++as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
++as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
++as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
++as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
++as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
++as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H"
++as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H"
++# Test code for whether the C++ compiler supports C++98 (global declarations)
++ac_cxx_conftest_cxx98_globals='
++// Does the compiler advertise C++98 conformance?
++#if !defined __cplusplus || __cplusplus < 199711L
++# error "Compiler does not advertise C++98 conformance"
++#endif
++
++// These inclusions are to reject old compilers that
++// lack the unsuffixed header files.
++#include 
++#include 
++
++//  and  are *not* freestanding headers in C++98.
++extern void assert (int);
++namespace std {
++  extern int strcmp (const char *, const char *);
++}
++
++// Namespaces, exceptions, and templates were all added after "C++ 2.0".
++using std::exception;
++using std::strcmp;
++
++namespace {
++
++void test_exception_syntax()
++{
++  try {
++    throw "test";
++  } catch (const char *s) {
++    // Extra parentheses suppress a warning when building autoconf itself,
++    // due to lint rules shared with more typical C programs.
++    assert (!(strcmp) (s, "test"));
++  }
++}
++
++template  struct test_template
++{
++  T const val;
++  explicit test_template(T t) : val(t) {}
++  template  T add(U u) { return static_cast(u) + val; }
++};
++
++} // anonymous namespace
++'
++
++# Test code for whether the C++ compiler supports C++98 (body of main)
++ac_cxx_conftest_cxx98_main='
++  assert (argc);
++  assert (! argv[0]);
++{
++  test_exception_syntax ();
++  test_template tt (2.0);
++  assert (tt.add (4) == 6.0);
++  assert (true && !false);
++}
++'
++
++# Test code for whether the C++ compiler supports C++11 (global declarations)
++ac_cxx_conftest_cxx11_globals='
++// Does the compiler advertise C++ 2011 conformance?
++#if !defined __cplusplus || __cplusplus < 201103L
++# error "Compiler does not advertise C++11 conformance"
++#endif
++
++namespace cxx11test
++{
++  constexpr int get_val() { return 20; }
++
++  struct testinit
++  {
++    int i;
++    double d;
++  };
++
++  class delegate
++  {
++  public:
++    delegate(int n) : n(n) {}
++    delegate(): delegate(2354) {}
++
++    virtual int getval() { return this->n; };
++  protected:
++    int n;
++  };
++
++  class overridden : public delegate
++  {
++  public:
++    overridden(int n): delegate(n) {}
++    virtual int getval() override final { return this->n * 2; }
++  };
++
++  class nocopy
++  {
++  public:
++    nocopy(int i): i(i) {}
++    nocopy() = default;
++    nocopy(const nocopy&) = delete;
++    nocopy & operator=(const nocopy&) = delete;
++  private:
++    int i;
++  };
++
++  // for testing lambda expressions
++  template  Ret eval(Fn f, Ret v)
++  {
++    return f(v);
++  }
++
++  // for testing variadic templates and trailing return types
++  template  auto sum(V first) -> V
++  {
++    return first;
++  }
++  template  auto sum(V first, Args... rest) -> V
++  {
++    return first + sum(rest...);
++  }
++}
++'
++
++# Test code for whether the C++ compiler supports C++11 (body of main)
++ac_cxx_conftest_cxx11_main='
++{
++  // Test auto and decltype
++  auto a1 = 6538;
++  auto a2 = 48573953.4;
++  auto a3 = "String literal";
++
++  int total = 0;
++  for (auto i = a3; *i; ++i) { total += *i; }
++
++  decltype(a2) a4 = 34895.034;
++}
++{
++  // Test constexpr
++  short sa[cxx11test::get_val()] = { 0 };
++}
++{
++  // Test initializer lists
++  cxx11test::testinit il = { 4323, 435234.23544 };
++}
++{
++  // Test range-based for
++  int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
++                 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
++  for (auto &x : array) { x += 23; }
++}
++{
++  // Test lambda expressions
++  using cxx11test::eval;
++  assert (eval ([](int x) { return x*2; }, 21) == 42);
++  double d = 2.0;
++  assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
++  assert (d == 5.0);
++  assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
++  assert (d == 5.0);
++}
++{
++  // Test use of variadic templates
++  using cxx11test::sum;
++  auto a = sum(1);
++  auto b = sum(1, 2);
++  auto c = sum(1.0, 2.0, 3.0);
++}
++{
++  // Test constructor delegation
++  cxx11test::delegate d1;
++  cxx11test::delegate d2();
++  cxx11test::delegate d3(45);
++}
++{
++  // Test override and final
++  cxx11test::overridden o1(55464);
++}
++{
++  // Test nullptr
++  char *c = nullptr;
++}
++{
++  // Test template brackets
++  test_template<::test_template> v(test_template(12));
++}
++{
++  // Unicode literals
++  char const *utf8 = u8"UTF-8 string \u2500";
++  char16_t const *utf16 = u"UTF-8 string \u2500";
++  char32_t const *utf32 = U"UTF-32 string \u2500";
++}
++'
++
++# Test code for whether the C compiler supports C++11 (complete).
++ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
++${ac_cxx_conftest_cxx11_globals}
++
++int
++main (int argc, char **argv)
++{
++  int ok = 0;
++  ${ac_cxx_conftest_cxx98_main}
++  ${ac_cxx_conftest_cxx11_main}
++  return ok;
++}
++"
++
++# Test code for whether the C compiler supports C++98 (complete).
++ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
++int
++main (int argc, char **argv)
++{
++  int ok = 0;
++  ${ac_cxx_conftest_cxx98_main}
++  return ok;
++}
++"
++
++
++# Auxiliary files required by this configure script.
++ac_aux_files="ltmain.sh compile missing install-sh config.guess config.sub"
++
++# Locations in which to look for auxiliary files.
++ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
++
++# Search for a directory containing all of the required auxiliary files,
++# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
++# If we don't find one directory that contains all the files we need,
++# we report the set of missing files from the *first* directory in
++# $ac_aux_dir_candidates and give up.
++ac_missing_aux_files=""
++ac_first_candidate=:
++printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++as_found=false
++for as_dir in $ac_aux_dir_candidates
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++  as_found=:
++
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}:  trying $as_dir" >&5
++  ac_aux_dir_found=yes
++  ac_install_sh=
++  for ac_aux in $ac_aux_files
++  do
++    # As a special case, if "install-sh" is required, that requirement
++    # can be satisfied by any of "install-sh", "install.sh", or "shtool",
++    # and $ac_install_sh is set appropriately for whichever one is found.
++    if test x"$ac_aux" = x"install-sh"
++    then
++      if test -f "${as_dir}install-sh"; then
++        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install-sh found" >&5
++        ac_install_sh="${as_dir}install-sh -c"
++      elif test -f "${as_dir}install.sh"; then
++        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install.sh found" >&5
++        ac_install_sh="${as_dir}install.sh -c"
++      elif test -f "${as_dir}shtool"; then
++        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}shtool found" >&5
++        ac_install_sh="${as_dir}shtool install -c"
++      else
++        ac_aux_dir_found=no
++        if $ac_first_candidate; then
++          ac_missing_aux_files="${ac_missing_aux_files} install-sh"
++        else
++          break
++        fi
++      fi
++    else
++      if test -f "${as_dir}${ac_aux}"; then
++        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}${ac_aux} found" >&5
++      else
++        ac_aux_dir_found=no
++        if $ac_first_candidate; then
++          ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
++        else
++          break
++        fi
++      fi
++    fi
++  done
++  if test "$ac_aux_dir_found" = yes; then
++    ac_aux_dir="$as_dir"
++    break
++  fi
++  ac_first_candidate=false
++
++  as_found=false
++done
++IFS=$as_save_IFS
++if $as_found
++then :
++
++else $as_nop
++  as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
++fi
++
++
++# These three variables are undocumented and unsupported,
++# and are intended to be withdrawn in a future Autoconf release.
++# They can cause serious problems if a builder's source tree is in a directory
++# whose full name contains unusual characters.
++if test -f "${ac_aux_dir}config.guess"; then
++  ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
++fi
++if test -f "${ac_aux_dir}config.sub"; then
++  ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
++fi
++if test -f "$ac_aux_dir/configure"; then
++  ac_configure="$SHELL ${ac_aux_dir}configure"
++fi
++
++# Check that the precious variables saved in the cache have kept the same
++# value.
++ac_cache_corrupted=false
++for ac_var in $ac_precious_vars; do
++  eval ac_old_set=\$ac_cv_env_${ac_var}_set
++  eval ac_new_set=\$ac_env_${ac_var}_set
++  eval ac_old_val=\$ac_cv_env_${ac_var}_value
++  eval ac_new_val=\$ac_env_${ac_var}_value
++  case $ac_old_set,$ac_new_set in
++    set,)
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
++printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
++      ac_cache_corrupted=: ;;
++    ,set)
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
++printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
++      ac_cache_corrupted=: ;;
++    ,);;
++    *)
++      if test "x$ac_old_val" != "x$ac_new_val"; then
++	# differences in whitespace do not lead to failure.
++	ac_old_val_w=`echo x $ac_old_val`
++	ac_new_val_w=`echo x $ac_new_val`
++	if test "$ac_old_val_w" != "$ac_new_val_w"; then
++	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
++printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
++	  ac_cache_corrupted=:
++	else
++	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
++printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
++	  eval $ac_var=\$ac_old_val
++	fi
++	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
++printf "%s\n" "$as_me:   former value:  \`$ac_old_val'" >&2;}
++	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
++printf "%s\n" "$as_me:   current value: \`$ac_new_val'" >&2;}
++      fi;;
++  esac
++  # Pass precious variables to config.status.
++  if test "$ac_new_set" = set; then
++    case $ac_new_val in
++    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
++    *) ac_arg=$ac_var=$ac_new_val ;;
++    esac
++    case " $ac_configure_args " in
++      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
++      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
++    esac
++  fi
++done
++if $ac_cache_corrupted; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
++printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
++  as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
++	    and start over" "$LINENO" 5
++fi
++## -------------------- ##
++## Main body of script. ##
++## -------------------- ##
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++
++
++
++  # Make sure we can run config.sub.
++$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
++  as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
++printf %s "checking build system type... " >&6; }
++if test ${ac_cv_build+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_build_alias=$build_alias
++test "x$ac_build_alias" = x &&
++  ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
++test "x$ac_build_alias" = x &&
++  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
++ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
++  as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
++printf "%s\n" "$ac_cv_build" >&6; }
++case $ac_cv_build in
++*-*-*) ;;
++*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
++esac
++build=$ac_cv_build
++ac_save_IFS=$IFS; IFS='-'
++set x $ac_cv_build
++shift
++build_cpu=$1
++build_vendor=$2
++shift; shift
++# Remember, the first character of IFS is used to create $*,
++# except with old shells:
++build_os=$*
++IFS=$ac_save_IFS
++case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
++printf %s "checking host system type... " >&6; }
++if test ${ac_cv_host+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test "x$host_alias" = x; then
++  ac_cv_host=$ac_cv_build
++else
++  ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
++    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
++printf "%s\n" "$ac_cv_host" >&6; }
++case $ac_cv_host in
++*-*-*) ;;
++*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
++esac
++host=$ac_cv_host
++ac_save_IFS=$IFS; IFS='-'
++set x $ac_cv_host
++shift
++host_cpu=$1
++host_vendor=$2
++shift; shift
++# Remember, the first character of IFS is used to create $*,
++# except with old shells:
++host_os=$*
++IFS=$ac_save_IFS
++case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
++printf %s "checking target system type... " >&6; }
++if test ${ac_cv_target+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test "x$target_alias" = x; then
++  ac_cv_target=$ac_cv_host
++else
++  ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
++    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
++printf "%s\n" "$ac_cv_target" >&6; }
++case $ac_cv_target in
++*-*-*) ;;
++*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
++esac
++target=$ac_cv_target
++ac_save_IFS=$IFS; IFS='-'
++set x $ac_cv_target
++shift
++target_cpu=$1
++target_vendor=$2
++shift; shift
++# Remember, the first character of IFS is used to create $*,
++# except with old shells:
++target_os=$*
++IFS=$ac_save_IFS
++case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
++
++
++# The aliases save the names the user supplied, while $host etc.
++# will get canonicalized.
++test -n "$target_alias" &&
++  test "$program_prefix$program_suffix$program_transform_name" = \
++    NONENONEs,x,x, &&
++  program_prefix=${target_alias}-
++GCC_TOPLEV_SUBDIRS
++am__api_version='1.16'
++
++
++  # Find a good install program.  We prefer a C program (faster),
++# so one script is as good as another.  But avoid the broken or
++# incompatible versions:
++# SysV /etc/install, /usr/sbin/install
++# SunOS /usr/etc/install
++# IRIX /sbin/install
++# AIX /bin/install
++# AmigaOS /C/install, which installs bootblocks on floppy discs
++# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
++# AFS /usr/afsws/bin/install, which mishandles nonexistent args
++# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
++# OS/2's system install, which has a completely different semantic
++# ./install, which can be erroneously created by make from ./install.sh.
++# Reject install programs that cannot install multiple files.
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
++printf %s "checking for a BSD-compatible install... " >&6; }
++if test -z "$INSTALL"; then
++if test ${ac_cv_path_install+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    # Account for fact that we put trailing slashes in our PATH walk.
++case $as_dir in #((
++  ./ | /[cC]/* | \
++  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
++  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
++  /usr/ucb/* ) ;;
++  *)
++    # OSF1 and SCO ODT 3.0 have their own names for install.
++    # Don't use installbsd from OSF since it installs stuff as root
++    # by default.
++    for ac_prog in ginstall scoinst install; do
++      for ac_exec_ext in '' $ac_executable_extensions; do
++	if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
++	  if test $ac_prog = install &&
++	    grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++	    # AIX install.  It has an incompatible calling convention.
++	    :
++	  elif test $ac_prog = install &&
++	    grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++	    # program-specific install script used by HP pwplus--don't use.
++	    :
++	  else
++	    rm -rf conftest.one conftest.two conftest.dir
++	    echo one > conftest.one
++	    echo two > conftest.two
++	    mkdir conftest.dir
++	    if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
++	      test -s conftest.one && test -s conftest.two &&
++	      test -s conftest.dir/conftest.one &&
++	      test -s conftest.dir/conftest.two
++	    then
++	      ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
++	      break 3
++	    fi
++	  fi
++	fi
++      done
++    done
++    ;;
++esac
++
++  done
++IFS=$as_save_IFS
++
++rm -rf conftest.one conftest.two conftest.dir
++
++fi
++  if test ${ac_cv_path_install+y}; then
++    INSTALL=$ac_cv_path_install
++  else
++    # As a last resort, use the slow shell script.  Don't cache a
++    # value for INSTALL within a source directory, because that will
++    # break other packages using the cache if that directory is
++    # removed, or if the value is a relative name.
++    INSTALL=$ac_install_sh
++  fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
++printf "%s\n" "$INSTALL" >&6; }
++
++# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
++# It thinks the first close brace ends the variable substitution.
++test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
++
++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
++
++test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
++printf %s "checking whether build environment is sane... " >&6; }
++# Reject unsafe characters in $srcdir or the absolute working directory
++# name.  Accept space and tab only in the latter.
++am_lf='
++'
++case `pwd` in
++  *[\\\"\#\$\&\'\`$am_lf]*)
++    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
++esac
++case $srcdir in
++  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
++    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
++esac
++
++# Do 'set' in a subshell so we don't clobber the current shell's
++# arguments.  Must try -L first in case configure is actually a
++# symlink; some systems play weird games with the mod time of symlinks
++# (eg FreeBSD returns the mod time of the symlink's containing
++# directory).
++if (
++   am_has_slept=no
++   for am_try in 1 2; do
++     echo "timestamp, slept: $am_has_slept" > conftest.file
++     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
++     if test "$*" = "X"; then
++	# -L didn't work.
++	set X `ls -t "$srcdir/configure" conftest.file`
++     fi
++     if test "$*" != "X $srcdir/configure conftest.file" \
++	&& test "$*" != "X conftest.file $srcdir/configure"; then
++
++	# If neither matched, then we have a broken ls.  This can happen
++	# if, for instance, CONFIG_SHELL is bash and it inherits a
++	# broken ls alias from the environment.  This has actually
++	# happened.  Such a system could not be considered "sane".
++	as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
++  alias in your environment" "$LINENO" 5
++     fi
++     if test "$2" = conftest.file || test $am_try -eq 2; then
++       break
++     fi
++     # Just in case.
++     sleep 1
++     am_has_slept=yes
++   done
++   test "$2" = conftest.file
++   )
++then
++   # Ok.
++   :
++else
++   as_fn_error $? "newly created file is older than distributed files!
++Check your system clock" "$LINENO" 5
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++# If we didn't sleep, we still need to ensure time stamps of config.status and
++# generated files are strictly newer.
++am_sleep_pid=
++if grep 'slept: no' conftest.file >/dev/null 2>&1; then
++  ( sleep 1 ) &
++  am_sleep_pid=$!
++fi
++
++rm -f conftest.file
++
++test "$program_prefix" != NONE &&
++  program_transform_name="s&^&$program_prefix&;$program_transform_name"
++# Use a double $ so make ignores it.
++test "$program_suffix" != NONE &&
++  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
++# Double any \ or $.
++# By default was `s,x,x', remove it if useless.
++ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
++program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"`
++
++
++# Expand $ac_aux_dir to an absolute path.
++am_aux_dir=`cd "$ac_aux_dir" && pwd`
++
++
++  if test x"${MISSING+set}" != xset; then
++  MISSING="\${SHELL} '$am_aux_dir/missing'"
++fi
++# Use eval to expand $SHELL
++if eval "$MISSING --is-lightweight"; then
++  am_missing_run="$MISSING "
++else
++  am_missing_run=
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
++printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
++fi
++
++if test x"${install_sh+set}" != xset; then
++  case $am_aux_dir in
++  *\ * | *\	*)
++    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
++  *)
++    install_sh="\${SHELL} $am_aux_dir/install-sh"
++  esac
++fi
++
++# Installed binaries are usually stripped using 'strip' when the user
++# run "make install-strip".  However 'strip' might not be the right
++# tool to use in cross-compilation environments, therefore Automake
++# will honor the 'STRIP' environment variable to overrule this program.
++if test "$cross_compiling" != no; then
++  if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
++set dummy ${ac_tool_prefix}strip; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_STRIP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$STRIP"; then
++  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++STRIP=$ac_cv_prog_STRIP
++if test -n "$STRIP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
++printf "%s\n" "$STRIP" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_STRIP"; then
++  ac_ct_STRIP=$STRIP
++  # Extract the first word of "strip", so it can be a program name with args.
++set dummy strip; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_STRIP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_STRIP"; then
++  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_STRIP="strip"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
++if test -n "$ac_ct_STRIP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
++printf "%s\n" "$ac_ct_STRIP" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_STRIP" = x; then
++    STRIP=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    STRIP=$ac_ct_STRIP
++  fi
++else
++  STRIP="$ac_cv_prog_STRIP"
++fi
++
++fi
++INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
++printf %s "checking for a race-free mkdir -p... " >&6; }
++if test -z "$MKDIR_P"; then
++  if test ${ac_cv_path_mkdir+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_prog in mkdir gmkdir; do
++	 for ac_exec_ext in '' $ac_executable_extensions; do
++	   as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue
++	   case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #(
++	     'mkdir ('*'coreutils) '* | \
++	     'BusyBox '* | \
++	     'mkdir (fileutils) '4.1*)
++	       ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext
++	       break 3;;
++	   esac
++	 done
++       done
++  done
++IFS=$as_save_IFS
++
++fi
++
++  test -d ./--version && rmdir ./--version
++  if test ${ac_cv_path_mkdir+y}; then
++    MKDIR_P="$ac_cv_path_mkdir -p"
++  else
++    # As a last resort, use the slow shell script.  Don't cache a
++    # value for MKDIR_P within a source directory, because that will
++    # break other packages using the cache if that directory is
++    # removed, or if the value is a relative name.
++    MKDIR_P="$ac_install_sh -d"
++  fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
++printf "%s\n" "$MKDIR_P" >&6; }
++
++for ac_prog in gawk mawk nawk awk
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_AWK+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$AWK"; then
++  ac_cv_prog_AWK="$AWK" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_AWK="$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++AWK=$ac_cv_prog_AWK
++if test -n "$AWK"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
++printf "%s\n" "$AWK" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  test -n "$AWK" && break
++done
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
++printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
++set x ${MAKE-make}
++ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
++if eval test \${ac_cv_prog_make_${ac_make}_set+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat >conftest.make <<\_ACEOF
++SHELL = /bin/sh
++all:
++	@echo '@@@%%%=$(MAKE)=@@@%%%'
++_ACEOF
++# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
++case `${MAKE-make} -f conftest.make 2>/dev/null` in
++  *@@@%%%=?*=@@@%%%*)
++    eval ac_cv_prog_make_${ac_make}_set=yes;;
++  *)
++    eval ac_cv_prog_make_${ac_make}_set=no;;
++esac
++rm -f conftest.make
++fi
++if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++  SET_MAKE=
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++  SET_MAKE="MAKE=${MAKE-make}"
++fi
++
++rm -rf .tst 2>/dev/null
++mkdir .tst 2>/dev/null
++if test -d .tst; then
++  am__leading_dot=.
++else
++  am__leading_dot=_
++fi
++rmdir .tst 2>/dev/null
++
++# Check whether --enable-silent-rules was given.
++if test ${enable_silent_rules+y}
++then :
++  enableval=$enable_silent_rules;
++fi
++
++case $enable_silent_rules in # (((
++  yes) AM_DEFAULT_VERBOSITY=0;;
++   no) AM_DEFAULT_VERBOSITY=1;;
++    *) AM_DEFAULT_VERBOSITY=1;;
++esac
++am_make=${MAKE-make}
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
++printf %s "checking whether $am_make supports nested variables... " >&6; }
++if test ${am_cv_make_support_nested_variables+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if printf "%s\n" 'TRUE=$(BAR$(V))
++BAR0=false
++BAR1=true
++V=1
++am__doit:
++	@$(TRUE)
++.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
++  am_cv_make_support_nested_variables=yes
++else
++  am_cv_make_support_nested_variables=no
++fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
++printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
++if test $am_cv_make_support_nested_variables = yes; then
++    AM_V='$(V)'
++  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
++else
++  AM_V=$AM_DEFAULT_VERBOSITY
++  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
++fi
++AM_BACKSLASH='\'
++
++if test "`cd $srcdir && pwd`" != "`pwd`"; then
++  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
++  # is not polluted with repeated "-I."
++  am__isrc=' -I$(srcdir)'
++  # test to see if srcdir already configured
++  if test -f $srcdir/config.status; then
++    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
++  fi
++fi
++
++# test whether we have cygpath
++if test -z "$CYGPATH_W"; then
++  if (cygpath --version) >/dev/null 2>/dev/null; then
++    CYGPATH_W='cygpath -w'
++  else
++    CYGPATH_W=echo
++  fi
++fi
++
++
++# Define the identity of the package.
++ PACKAGE='bolt-plugin'
++ VERSION='0.1'
++
++
++printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
++
++
++printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h
++
++# Some tools Automake needs.
++
++ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
++
++
++AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
++
++
++AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
++
++
++AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
++
++
++MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
++
++# For better backward compatibility.  To be removed once Automake 1.9.x
++# dies out for good.  For more background, see:
++# 
++# 
++mkdir_p='$(MKDIR_P)'
++
++# We need awk for the "check" target (and possibly the TAP driver).  The
++# system "awk" is bad on some platforms.
++# Always define AMTAR for backward compatibility.  Yes, it's still used
++# in the wild :-(  We should find a proper way to deprecate it ...
++AMTAR='$${TAR-tar}'
++
++
++# We'll loop over all known methods to create a tar archive until one works.
++_am_tools='gnutar  pax cpio none'
++
++am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
++
++
++
++
++
++# Variables for tags utilities; see am/tags.am
++if test -z "$CTAGS"; then
++  CTAGS=ctags
++fi
++
++if test -z "$ETAGS"; then
++  ETAGS=etags
++fi
++
++if test -z "$CSCOPE"; then
++  CSCOPE=cscope
++fi
++
++
++
++# POSIX will say in a future version that running "rm -f" with no argument
++# is OK; and we want to be able to make that assumption in our Makefile
++# recipes.  So use an aggressive probe to check that the usage we want is
++# actually supported "in the wild" to an acceptable degree.
++# See automake bug#10828.
++# To make any issue more visible, cause the running configure to be aborted
++# by default if the 'rm' program in use doesn't match our expectations; the
++# user can still override this though.
++if rm -f && rm -fr && rm -rf; then : OK; else
++  cat >&2 <<'END'
++Oops!
++
++Your 'rm' program seems unable to run without file operands specified
++on the command line, even when the '-f' option is present.  This is contrary
++to the behaviour of most rm programs out there, and not conforming with
++the upcoming POSIX standard: 
++
++Please tell bug-automake@gnu.org about your system, including the value
++of your $PATH and any error possibly output before this message.  This
++can help us improve future automake versions.
++
++END
++  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
++    echo 'Configuration will proceed anyway, since you have set the' >&2
++    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
++    echo >&2
++  else
++    cat >&2 <<'END'
++Aborting the configuration process, to ensure you take notice of the issue.
++
++You can download and install GNU coreutils to get an 'rm' implementation
++that behaves properly: .
++
++If you want to complete the configuration process using your problematic
++'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
++to "yes", and re-run configure.
++
++END
++    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
++  fi
++fi
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
++printf %s "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
++    # Check whether --enable-maintainer-mode was given.
++if test ${enable_maintainer_mode+y}
++then :
++  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
++else $as_nop
++  USE_MAINTAINER_MODE=no
++fi
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
++printf "%s\n" "$USE_MAINTAINER_MODE" >&6; }
++   if test $USE_MAINTAINER_MODE = yes; then
++  MAINTAINER_MODE_TRUE=
++  MAINTAINER_MODE_FALSE='#'
++else
++  MAINTAINER_MODE_TRUE='#'
++  MAINTAINER_MODE_FALSE=
++fi
++
++  MAINT=$MAINTAINER_MODE_TRUE
++
++
++
++# Check whether --with-libiberty was given.
++if test ${with_libiberty+y}
++then :
++  withval=$with_libiberty;
++else $as_nop
++  with_libiberty=../libiberty
++fi
++
++
++
++
++
++
++
++
++
++
++
++DEPDIR="${am__leading_dot}deps"
++
++ac_config_commands="$ac_config_commands depfiles"
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
++printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; }
++cat > confinc.mk << 'END'
++am__doit:
++	@echo this is the am__doit target >confinc.out
++.PHONY: am__doit
++END
++am__include="#"
++am__quote=
++# BSD make does it like this.
++echo '.include "confinc.mk" # ignored' > confmf.BSD
++# Other make implementations (GNU, Solaris 10, AIX) do it like this.
++echo 'include confinc.mk # ignored' > confmf.GNU
++_am_result=no
++for s in GNU BSD; do
++  { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
++   (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
++   ac_status=$?
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   (exit $ac_status); }
++  case $?:`cat confinc.out 2>/dev/null` in #(
++  '0:this is the am__doit target') :
++    case $s in #(
++  BSD) :
++    am__include='.include' am__quote='"' ;; #(
++  *) :
++    am__include='include' am__quote='' ;;
++esac ;; #(
++  *) :
++     ;;
++esac
++  if test "$am__include" != "#"; then
++    _am_result="yes ($s style)"
++    break
++  fi
++done
++rm -f confinc.* confmf.*
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
++printf "%s\n" "${_am_result}" >&6; }
++
++# Check whether --enable-dependency-tracking was given.
++if test ${enable_dependency_tracking+y}
++then :
++  enableval=$enable_dependency_tracking;
++fi
++
++if test "x$enable_dependency_tracking" != xno; then
++  am_depcomp="$ac_aux_dir/depcomp"
++  AMDEPBACKSLASH='\'
++  am__nodep='_no'
++fi
++ if test "x$enable_dependency_tracking" != xno; then
++  AMDEP_TRUE=
++  AMDEP_FALSE='#'
++else
++  AMDEP_TRUE='#'
++  AMDEP_FALSE=
++fi
++
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
++set dummy ${ac_tool_prefix}gcc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="${ac_tool_prefix}gcc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_CC"; then
++  ac_ct_CC=$CC
++  # Extract the first word of "gcc", so it can be a program name with args.
++set dummy gcc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CC"; then
++  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="gcc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++printf "%s\n" "$ac_ct_CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CC=$ac_ct_CC
++  fi
++else
++  CC="$ac_cv_prog_CC"
++fi
++
++if test -z "$CC"; then
++          if test -n "$ac_tool_prefix"; then
++    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
++set dummy ${ac_tool_prefix}cc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="${ac_tool_prefix}cc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  fi
++fi
++if test -z "$CC"; then
++  # Extract the first word of "cc", so it can be a program name with args.
++set dummy cc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++  ac_prog_rejected=no
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
++       ac_prog_rejected=yes
++       continue
++     fi
++    ac_cv_prog_CC="cc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++if test $ac_prog_rejected = yes; then
++  # We found a bogon in the path, so make sure we never use it.
++  set dummy $ac_cv_prog_CC
++  shift
++  if test $# != 0; then
++    # We chose a different compiler from the bogus one.
++    # However, it has the same basename, so the bogon will be chosen
++    # first if we set CC to just the basename; use the full file name.
++    shift
++    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
++  fi
++fi
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$CC"; then
++  if test -n "$ac_tool_prefix"; then
++  for ac_prog in cl.exe
++  do
++    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
++set dummy $ac_tool_prefix$ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++    test -n "$CC" && break
++  done
++fi
++if test -z "$CC"; then
++  ac_ct_CC=$CC
++  for ac_prog in cl.exe
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CC"; then
++  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++printf "%s\n" "$ac_ct_CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  test -n "$ac_ct_CC" && break
++done
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CC=$ac_ct_CC
++  fi
++fi
++
++fi
++if test -z "$CC"; then
++  if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
++set dummy ${ac_tool_prefix}clang; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="${ac_tool_prefix}clang"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_CC"; then
++  ac_ct_CC=$CC
++  # Extract the first word of "clang", so it can be a program name with args.
++set dummy clang; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CC"; then
++  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="clang"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++printf "%s\n" "$ac_ct_CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CC=$ac_ct_CC
++  fi
++else
++  CC="$ac_cv_prog_CC"
++fi
++
++fi
++
++
++test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "no acceptable C compiler found in \$PATH
++See \`config.log' for more details" "$LINENO" 5; }
++
++# Provide some information about the compiler.
++printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
++set X $ac_compile
++ac_compiler=$2
++for ac_option in --version -v -V -qversion -version; do
++  { { ac_try="$ac_compiler $ac_option >&5"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    sed '10a\
++... rest of stderr output deleted ...
++         10q' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++  fi
++  rm -f conftest.er1 conftest.err
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++done
++
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++ac_clean_files_save=$ac_clean_files
++ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
++# Try to create an executable without -o first, disregard a.out.
++# It will help us diagnose broken compilers, and finding out an intuition
++# of exeext.
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
++printf %s "checking whether the C compiler works... " >&6; }
++ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
++
++# The possible output files:
++ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
++
++ac_rmfiles=
++for ac_file in $ac_files
++do
++  case $ac_file in
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
++    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
++  esac
++done
++rm -f $ac_rmfiles
++
++if { { ac_try="$ac_link_default"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_link_default") 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++then :
++  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
++# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
++# in a Makefile.  We should not override ac_cv_exeext if it was cached,
++# so that the user can short-circuit this test for compilers unknown to
++# Autoconf.
++for ac_file in $ac_files ''
++do
++  test -f "$ac_file" || continue
++  case $ac_file in
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
++	;;
++    [ab].out )
++	# We found the default executable, but exeext='' is most
++	# certainly right.
++	break;;
++    *.* )
++	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
++	then :; else
++	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
++	fi
++	# We set ac_cv_exeext here because the later test for it is not
++	# safe: cross compilers may not add the suffix if given an `-o'
++	# argument, so we may need to know it at that point already.
++	# Even if this section looks crufty: it has the advantage of
++	# actually working.
++	break;;
++    * )
++	break;;
++  esac
++done
++test "$ac_cv_exeext" = no && ac_cv_exeext=
++
++else $as_nop
++  ac_file=''
++fi
++if test -z "$ac_file"
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error 77 "C compiler cannot create executables
++See \`config.log' for more details" "$LINENO" 5; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
++printf %s "checking for C compiler default output file name... " >&6; }
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
++printf "%s\n" "$ac_file" >&6; }
++ac_exeext=$ac_cv_exeext
++
++rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
++ac_clean_files=$ac_clean_files_save
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
++printf %s "checking for suffix of executables... " >&6; }
++if { { ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_link") 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++then :
++  # If both `conftest.exe' and `conftest' are `present' (well, observable)
++# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
++# work properly (i.e., refer to `conftest.exe'), while it won't with
++# `rm'.
++for ac_file in conftest.exe conftest conftest.*; do
++  test -f "$ac_file" || continue
++  case $ac_file in
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
++    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
++	  break;;
++    * ) break;;
++  esac
++done
++else $as_nop
++  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "cannot compute suffix of executables: cannot compile and link
++See \`config.log' for more details" "$LINENO" 5; }
++fi
++rm -f conftest conftest$ac_cv_exeext
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
++printf "%s\n" "$ac_cv_exeext" >&6; }
++
++rm -f conftest.$ac_ext
++EXEEXT=$ac_cv_exeext
++ac_exeext=$EXEEXT
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++int
++main (void)
++{
++FILE *f = fopen ("conftest.out", "w");
++ return ferror (f) || fclose (f) != 0;
++
++  ;
++  return 0;
++}
++_ACEOF
++ac_clean_files="$ac_clean_files conftest.out"
++# Check that the compiler produces executables we can run.  If not, either
++# the compiler is broken, or we cross compile.
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
++printf %s "checking whether we are cross compiling... " >&6; }
++if test "$cross_compiling" != yes; then
++  { { ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_link") 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++  if { ac_try='./conftest$ac_cv_exeext'
++  { { case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_try") 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; }; then
++    cross_compiling=no
++  else
++    if test "$cross_compiling" = maybe; then
++	cross_compiling=yes
++    else
++	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error 77 "cannot run C compiled programs.
++If you meant to cross compile, use \`--host'.
++See \`config.log' for more details" "$LINENO" 5; }
++    fi
++  fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
++printf "%s\n" "$cross_compiling" >&6; }
++
++rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
++ac_clean_files=$ac_clean_files_save
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
++printf %s "checking for suffix of object files... " >&6; }
++if test ${ac_cv_objext+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++rm -f conftest.o conftest.obj
++if { { ac_try="$ac_compile"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_compile") 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++then :
++  for ac_file in conftest.o conftest.obj conftest.*; do
++  test -f "$ac_file" || continue;
++  case $ac_file in
++    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
++    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
++       break;;
++  esac
++done
++else $as_nop
++  printf "%s\n" "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "cannot compute suffix of object files: cannot compile
++See \`config.log' for more details" "$LINENO" 5; }
++fi
++rm -f conftest.$ac_cv_objext conftest.$ac_ext
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
++printf "%s\n" "$ac_cv_objext" >&6; }
++OBJEXT=$ac_cv_objext
++ac_objext=$OBJEXT
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
++printf %s "checking whether the compiler supports GNU C... " >&6; }
++if test ${ac_cv_c_compiler_gnu+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++#ifndef __GNUC__
++       choke me
++#endif
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_compiler_gnu=yes
++else $as_nop
++  ac_compiler_gnu=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++ac_cv_c_compiler_gnu=$ac_compiler_gnu
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
++printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++if test $ac_compiler_gnu = yes; then
++  GCC=yes
++else
++  GCC=
++fi
++ac_test_CFLAGS=${CFLAGS+y}
++ac_save_CFLAGS=$CFLAGS
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
++printf %s "checking whether $CC accepts -g... " >&6; }
++if test ${ac_cv_prog_cc_g+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_save_c_werror_flag=$ac_c_werror_flag
++   ac_c_werror_flag=yes
++   ac_cv_prog_cc_g=no
++   CFLAGS="-g"
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_g=yes
++else $as_nop
++  CFLAGS=""
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++
++else $as_nop
++  ac_c_werror_flag=$ac_save_c_werror_flag
++	 CFLAGS="-g"
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_g=yes
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++   ac_c_werror_flag=$ac_save_c_werror_flag
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
++printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
++if test $ac_test_CFLAGS; then
++  CFLAGS=$ac_save_CFLAGS
++elif test $ac_cv_prog_cc_g = yes; then
++  if test "$GCC" = yes; then
++    CFLAGS="-g -O2"
++  else
++    CFLAGS="-g"
++  fi
++else
++  if test "$GCC" = yes; then
++    CFLAGS="-O2"
++  else
++    CFLAGS=
++  fi
++fi
++ac_prog_cc_stdc=no
++if test x$ac_prog_cc_stdc = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
++printf %s "checking for $CC option to enable C11 features... " >&6; }
++if test ${ac_cv_prog_cc_c11+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cc_c11=no
++ac_save_CC=$CC
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_c_conftest_c11_program
++_ACEOF
++for ac_arg in '' -std=gnu11
++do
++  CC="$ac_save_CC $ac_arg"
++  if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_c11=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cc_c11" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++fi
++
++if test "x$ac_cv_prog_cc_c11" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cc_c11" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
++printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
++     CC="$CC $ac_cv_prog_cc_c11"
++fi
++  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
++  ac_prog_cc_stdc=c11
++fi
++fi
++if test x$ac_prog_cc_stdc = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
++printf %s "checking for $CC option to enable C99 features... " >&6; }
++if test ${ac_cv_prog_cc_c99+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cc_c99=no
++ac_save_CC=$CC
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_c_conftest_c99_program
++_ACEOF
++for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
++do
++  CC="$ac_save_CC $ac_arg"
++  if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_c99=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cc_c99" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++fi
++
++if test "x$ac_cv_prog_cc_c99" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cc_c99" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
++printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
++     CC="$CC $ac_cv_prog_cc_c99"
++fi
++  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
++  ac_prog_cc_stdc=c99
++fi
++fi
++if test x$ac_prog_cc_stdc = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
++printf %s "checking for $CC option to enable C89 features... " >&6; }
++if test ${ac_cv_prog_cc_c89+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cc_c89=no
++ac_save_CC=$CC
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_c_conftest_c89_program
++_ACEOF
++for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
++do
++  CC="$ac_save_CC $ac_arg"
++  if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_c89=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cc_c89" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++fi
++
++if test "x$ac_cv_prog_cc_c89" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cc_c89" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
++printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
++     CC="$CC $ac_cv_prog_cc_c89"
++fi
++  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
++  ac_prog_cc_stdc=c89
++fi
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++  ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
++printf %s "checking whether $CC understands -c and -o together... " >&6; }
++if test ${am_cv_prog_cc_c_o+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++  # Make sure it works both with $CC and with simple cc.
++  # Following AC_PROG_CC_C_O, we do the test twice because some
++  # compilers refuse to overwrite an existing .o file with -o,
++  # though they will create one.
++  am_cv_prog_cc_c_o=yes
++  for am_i in 1 2; do
++    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
++   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
++   ac_status=$?
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   (exit $ac_status); } \
++         && test -f conftest2.$ac_objext; then
++      : OK
++    else
++      am_cv_prog_cc_c_o=no
++      break
++    fi
++  done
++  rm -f core conftest*
++  unset am_i
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
++printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
++if test "$am_cv_prog_cc_c_o" != yes; then
++   # Losing compiler, so override with the script.
++   # FIXME: It is wrong to rewrite CC.
++   # But if we don't then we get into trouble of one sort or another.
++   # A longer-term fix would be to have automake use am__CC in this case,
++   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
++   CC="$am_aux_dir/compile $CC"
++fi
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++depcc="$CC"   am_compiler_list=
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
++printf %s "checking dependency style of $depcc... " >&6; }
++if test ${am_cv_CC_dependencies_compiler_type+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
++  # We make a subdir and do the tests there.  Otherwise we can end up
++  # making bogus files that we don't know about and never remove.  For
++  # instance it was reported that on HP-UX the gcc test will end up
++  # making a dummy file named 'D' -- because '-MD' means "put the output
++  # in D".
++  rm -rf conftest.dir
++  mkdir conftest.dir
++  # Copy depcomp to subdir because otherwise we won't find it if we're
++  # using a relative directory.
++  cp "$am_depcomp" conftest.dir
++  cd conftest.dir
++  # We will build objects and dependencies in a subdirectory because
++  # it helps to detect inapplicable dependency modes.  For instance
++  # both Tru64's cc and ICC support -MD to output dependencies as a
++  # side effect of compilation, but ICC will put the dependencies in
++  # the current directory while Tru64 will put them in the object
++  # directory.
++  mkdir sub
++
++  am_cv_CC_dependencies_compiler_type=none
++  if test "$am_compiler_list" = ""; then
++     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
++  fi
++  am__universal=false
++  case " $depcc " in #(
++     *\ -arch\ *\ -arch\ *) am__universal=true ;;
++     esac
++
++  for depmode in $am_compiler_list; do
++    # Setup a source with many dependencies, because some compilers
++    # like to wrap large dependency lists on column 80 (with \), and
++    # we should not choose a depcomp mode which is confused by this.
++    #
++    # We need to recreate these files for each test, as the compiler may
++    # overwrite some of them when testing with obscure command lines.
++    # This happens at least with the AIX C compiler.
++    : > sub/conftest.c
++    for i in 1 2 3 4 5 6; do
++      echo '#include "conftst'$i'.h"' >> sub/conftest.c
++      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
++      # Solaris 10 /bin/sh.
++      echo '/* dummy */' > sub/conftst$i.h
++    done
++    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
++
++    # We check with '-c' and '-o' for the sake of the "dashmstdout"
++    # mode.  It turns out that the SunPro C++ compiler does not properly
++    # handle '-M -o', and we need to detect this.  Also, some Intel
++    # versions had trouble with output in subdirs.
++    am__obj=sub/conftest.${OBJEXT-o}
++    am__minus_obj="-o $am__obj"
++    case $depmode in
++    gcc)
++      # This depmode causes a compiler race in universal mode.
++      test "$am__universal" = false || continue
++      ;;
++    nosideeffect)
++      # After this tag, mechanisms are not by side-effect, so they'll
++      # only be used when explicitly requested.
++      if test "x$enable_dependency_tracking" = xyes; then
++	continue
++      else
++	break
++      fi
++      ;;
++    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
++      # This compiler won't grok '-c -o', but also, the minuso test has
++      # not run yet.  These depmodes are late enough in the game, and
++      # so weak that their functioning should not be impacted.
++      am__obj=conftest.${OBJEXT-o}
++      am__minus_obj=
++      ;;
++    none) break ;;
++    esac
++    if depmode=$depmode \
++       source=sub/conftest.c object=$am__obj \
++       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
++       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
++         >/dev/null 2>conftest.err &&
++       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
++       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
++      # icc doesn't choke on unknown options, it will just issue warnings
++      # or remarks (even with -Werror).  So we grep stderr for any message
++      # that says an option was ignored or not supported.
++      # When given -MP, icc 7.0 and 7.1 complain thusly:
++      #   icc: Command line warning: ignoring option '-M'; no argument required
++      # The diagnosis changed in icc 8.0:
++      #   icc: Command line remark: option '-MP' not supported
++      if (grep 'ignoring option' conftest.err ||
++          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
++        am_cv_CC_dependencies_compiler_type=$depmode
++        break
++      fi
++    fi
++  done
++
++  cd ..
++  rm -rf conftest.dir
++else
++  am_cv_CC_dependencies_compiler_type=none
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
++printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
++CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
++
++ if
++  test "x$enable_dependency_tracking" != xno \
++  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
++  am__fastdepCC_TRUE=
++  am__fastdepCC_FALSE='#'
++else
++  am__fastdepCC_TRUE='#'
++  am__fastdepCC_FALSE=
++fi
++
++
++
++ac_header= ac_cache=
++for ac_item in $ac_header_c_list
++do
++  if test $ac_cache; then
++    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
++    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
++      printf "%s\n" "#define $ac_item 1" >> confdefs.h
++    fi
++    ac_header= ac_cache=
++  elif test $ac_header; then
++    ac_cache=$ac_item
++  else
++    ac_header=$ac_item
++  fi
++done
++
++
++
++
++
++
++
++
++if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
++then :
++
++printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
++
++fi
++
++
++
++
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
++printf %s "checking whether it is safe to define __EXTENSIONS__... " >&6; }
++if test ${ac_cv_safe_to_define___extensions__+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++#         define __EXTENSIONS__ 1
++          $ac_includes_default
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_safe_to_define___extensions__=yes
++else $as_nop
++  ac_cv_safe_to_define___extensions__=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
++printf "%s\n" "$ac_cv_safe_to_define___extensions__" >&6; }
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _XOPEN_SOURCE should be defined" >&5
++printf %s "checking whether _XOPEN_SOURCE should be defined... " >&6; }
++if test ${ac_cv_should_define__xopen_source+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_should_define__xopen_source=no
++    if test $ac_cv_header_wchar_h = yes
++then :
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++          #include 
++          mbstate_t x;
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++            #define _XOPEN_SOURCE 500
++            #include 
++            mbstate_t x;
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_should_define__xopen_source=yes
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_should_define__xopen_source" >&5
++printf "%s\n" "$ac_cv_should_define__xopen_source" >&6; }
++
++  printf "%s\n" "#define _ALL_SOURCE 1" >>confdefs.h
++
++  printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h
++
++  printf "%s\n" "#define _GNU_SOURCE 1" >>confdefs.h
++
++  printf "%s\n" "#define _HPUX_ALT_XOPEN_SOCKET_API 1" >>confdefs.h
++
++  printf "%s\n" "#define _NETBSD_SOURCE 1" >>confdefs.h
++
++  printf "%s\n" "#define _OPENBSD_SOURCE 1" >>confdefs.h
++
++  printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_IEC_60559_BFP_EXT__ 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_IEC_60559_DFP_EXT__ 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_LIB_EXT2__ 1" >>confdefs.h
++
++  printf "%s\n" "#define __STDC_WANT_MATH_SPEC_FUNCS__ 1" >>confdefs.h
++
++  printf "%s\n" "#define _TANDEM_SOURCE 1" >>confdefs.h
++
++  if test $ac_cv_header_minix_config_h = yes
++then :
++  MINIX=yes
++    printf "%s\n" "#define _MINIX 1" >>confdefs.h
++
++    printf "%s\n" "#define _POSIX_SOURCE 1" >>confdefs.h
++
++    printf "%s\n" "#define _POSIX_1_SOURCE 2" >>confdefs.h
++
++else $as_nop
++  MINIX=
++fi
++  if test $ac_cv_safe_to_define___extensions__ = yes
++then :
++  printf "%s\n" "#define __EXTENSIONS__ 1" >>confdefs.h
++
++fi
++  if test $ac_cv_should_define__xopen_source = yes
++then :
++  printf "%s\n" "#define _XOPEN_SOURCE 500" >>confdefs.h
++
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
++set dummy ${ac_tool_prefix}gcc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="${ac_tool_prefix}gcc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_CC"; then
++  ac_ct_CC=$CC
++  # Extract the first word of "gcc", so it can be a program name with args.
++set dummy gcc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CC"; then
++  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="gcc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++printf "%s\n" "$ac_ct_CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CC=$ac_ct_CC
++  fi
++else
++  CC="$ac_cv_prog_CC"
++fi
++
++if test -z "$CC"; then
++          if test -n "$ac_tool_prefix"; then
++    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
++set dummy ${ac_tool_prefix}cc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="${ac_tool_prefix}cc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  fi
++fi
++if test -z "$CC"; then
++  # Extract the first word of "cc", so it can be a program name with args.
++set dummy cc; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++  ac_prog_rejected=no
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
++       ac_prog_rejected=yes
++       continue
++     fi
++    ac_cv_prog_CC="cc"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++if test $ac_prog_rejected = yes; then
++  # We found a bogon in the path, so make sure we never use it.
++  set dummy $ac_cv_prog_CC
++  shift
++  if test $# != 0; then
++    # We chose a different compiler from the bogus one.
++    # However, it has the same basename, so the bogon will be chosen
++    # first if we set CC to just the basename; use the full file name.
++    shift
++    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
++  fi
++fi
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$CC"; then
++  if test -n "$ac_tool_prefix"; then
++  for ac_prog in cl.exe
++  do
++    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
++set dummy $ac_tool_prefix$ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++    test -n "$CC" && break
++  done
++fi
++if test -z "$CC"; then
++  ac_ct_CC=$CC
++  for ac_prog in cl.exe
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CC"; then
++  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++printf "%s\n" "$ac_ct_CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  test -n "$ac_ct_CC" && break
++done
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CC=$ac_ct_CC
++  fi
++fi
++
++fi
++if test -z "$CC"; then
++  if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
++set dummy ${ac_tool_prefix}clang; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CC"; then
++  ac_cv_prog_CC="$CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CC="${ac_tool_prefix}clang"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CC=$ac_cv_prog_CC
++if test -n "$CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++printf "%s\n" "$CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_CC"; then
++  ac_ct_CC=$CC
++  # Extract the first word of "clang", so it can be a program name with args.
++set dummy clang; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CC"; then
++  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="clang"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CC=$ac_cv_prog_ac_ct_CC
++if test -n "$ac_ct_CC"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++printf "%s\n" "$ac_ct_CC" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_CC" = x; then
++    CC=""
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CC=$ac_ct_CC
++  fi
++else
++  CC="$ac_cv_prog_CC"
++fi
++
++fi
++
++
++test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "no acceptable C compiler found in \$PATH
++See \`config.log' for more details" "$LINENO" 5; }
++
++# Provide some information about the compiler.
++printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
++set X $ac_compile
++ac_compiler=$2
++for ac_option in --version -v -V -qversion -version; do
++  { { ac_try="$ac_compiler $ac_option >&5"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    sed '10a\
++... rest of stderr output deleted ...
++         10q' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++  fi
++  rm -f conftest.er1 conftest.err
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++done
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
++printf %s "checking whether the compiler supports GNU C... " >&6; }
++if test ${ac_cv_c_compiler_gnu+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++#ifndef __GNUC__
++       choke me
++#endif
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_compiler_gnu=yes
++else $as_nop
++  ac_compiler_gnu=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++ac_cv_c_compiler_gnu=$ac_compiler_gnu
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
++printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++if test $ac_compiler_gnu = yes; then
++  GCC=yes
++else
++  GCC=
++fi
++ac_test_CFLAGS=${CFLAGS+y}
++ac_save_CFLAGS=$CFLAGS
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
++printf %s "checking whether $CC accepts -g... " >&6; }
++if test ${ac_cv_prog_cc_g+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_save_c_werror_flag=$ac_c_werror_flag
++   ac_c_werror_flag=yes
++   ac_cv_prog_cc_g=no
++   CFLAGS="-g"
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_g=yes
++else $as_nop
++  CFLAGS=""
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++
++else $as_nop
++  ac_c_werror_flag=$ac_save_c_werror_flag
++	 CFLAGS="-g"
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_g=yes
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++   ac_c_werror_flag=$ac_save_c_werror_flag
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
++printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
++if test $ac_test_CFLAGS; then
++  CFLAGS=$ac_save_CFLAGS
++elif test $ac_cv_prog_cc_g = yes; then
++  if test "$GCC" = yes; then
++    CFLAGS="-g -O2"
++  else
++    CFLAGS="-g"
++  fi
++else
++  if test "$GCC" = yes; then
++    CFLAGS="-O2"
++  else
++    CFLAGS=
++  fi
++fi
++ac_prog_cc_stdc=no
++if test x$ac_prog_cc_stdc = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
++printf %s "checking for $CC option to enable C11 features... " >&6; }
++if test ${ac_cv_prog_cc_c11+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cc_c11=no
++ac_save_CC=$CC
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_c_conftest_c11_program
++_ACEOF
++for ac_arg in '' -std=gnu11
++do
++  CC="$ac_save_CC $ac_arg"
++  if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_c11=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cc_c11" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++fi
++
++if test "x$ac_cv_prog_cc_c11" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cc_c11" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
++printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
++     CC="$CC $ac_cv_prog_cc_c11"
++fi
++  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
++  ac_prog_cc_stdc=c11
++fi
++fi
++if test x$ac_prog_cc_stdc = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
++printf %s "checking for $CC option to enable C99 features... " >&6; }
++if test ${ac_cv_prog_cc_c99+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cc_c99=no
++ac_save_CC=$CC
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_c_conftest_c99_program
++_ACEOF
++for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
++do
++  CC="$ac_save_CC $ac_arg"
++  if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_c99=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cc_c99" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++fi
++
++if test "x$ac_cv_prog_cc_c99" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cc_c99" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
++printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
++     CC="$CC $ac_cv_prog_cc_c99"
++fi
++  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
++  ac_prog_cc_stdc=c99
++fi
++fi
++if test x$ac_prog_cc_stdc = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
++printf %s "checking for $CC option to enable C89 features... " >&6; }
++if test ${ac_cv_prog_cc_c89+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cc_c89=no
++ac_save_CC=$CC
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_c_conftest_c89_program
++_ACEOF
++for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
++do
++  CC="$ac_save_CC $ac_arg"
++  if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_prog_cc_c89=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cc_c89" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CC=$ac_save_CC
++fi
++
++if test "x$ac_cv_prog_cc_c89" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cc_c89" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
++printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
++     CC="$CC $ac_cv_prog_cc_c89"
++fi
++  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
++  ac_prog_cc_stdc=c89
++fi
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++  ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
++printf %s "checking whether $CC understands -c and -o together... " >&6; }
++if test ${am_cv_prog_cc_c_o+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++  # Make sure it works both with $CC and with simple cc.
++  # Following AC_PROG_CC_C_O, we do the test twice because some
++  # compilers refuse to overwrite an existing .o file with -o,
++  # though they will create one.
++  am_cv_prog_cc_c_o=yes
++  for am_i in 1 2; do
++    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
++   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
++   ac_status=$?
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   (exit $ac_status); } \
++         && test -f conftest2.$ac_objext; then
++      : OK
++    else
++      am_cv_prog_cc_c_o=no
++      break
++    fi
++  done
++  rm -f core conftest*
++  unset am_i
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
++printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
++if test "$am_cv_prog_cc_c_o" != yes; then
++   # Losing compiler, so override with the script.
++   # FIXME: It is wrong to rewrite CC.
++   # But if we don't then we get into trouble of one sort or another.
++   # A longer-term fix would be to have automake use am__CC in this case,
++   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
++   CC="$am_aux_dir/compile $CC"
++fi
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++depcc="$CC"   am_compiler_list=
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
++printf %s "checking dependency style of $depcc... " >&6; }
++if test ${am_cv_CC_dependencies_compiler_type+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
++  # We make a subdir and do the tests there.  Otherwise we can end up
++  # making bogus files that we don't know about and never remove.  For
++  # instance it was reported that on HP-UX the gcc test will end up
++  # making a dummy file named 'D' -- because '-MD' means "put the output
++  # in D".
++  rm -rf conftest.dir
++  mkdir conftest.dir
++  # Copy depcomp to subdir because otherwise we won't find it if we're
++  # using a relative directory.
++  cp "$am_depcomp" conftest.dir
++  cd conftest.dir
++  # We will build objects and dependencies in a subdirectory because
++  # it helps to detect inapplicable dependency modes.  For instance
++  # both Tru64's cc and ICC support -MD to output dependencies as a
++  # side effect of compilation, but ICC will put the dependencies in
++  # the current directory while Tru64 will put them in the object
++  # directory.
++  mkdir sub
++
++  am_cv_CC_dependencies_compiler_type=none
++  if test "$am_compiler_list" = ""; then
++     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
++  fi
++  am__universal=false
++  case " $depcc " in #(
++     *\ -arch\ *\ -arch\ *) am__universal=true ;;
++     esac
++
++  for depmode in $am_compiler_list; do
++    # Setup a source with many dependencies, because some compilers
++    # like to wrap large dependency lists on column 80 (with \), and
++    # we should not choose a depcomp mode which is confused by this.
++    #
++    # We need to recreate these files for each test, as the compiler may
++    # overwrite some of them when testing with obscure command lines.
++    # This happens at least with the AIX C compiler.
++    : > sub/conftest.c
++    for i in 1 2 3 4 5 6; do
++      echo '#include "conftst'$i'.h"' >> sub/conftest.c
++      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
++      # Solaris 10 /bin/sh.
++      echo '/* dummy */' > sub/conftst$i.h
++    done
++    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
++
++    # We check with '-c' and '-o' for the sake of the "dashmstdout"
++    # mode.  It turns out that the SunPro C++ compiler does not properly
++    # handle '-M -o', and we need to detect this.  Also, some Intel
++    # versions had trouble with output in subdirs.
++    am__obj=sub/conftest.${OBJEXT-o}
++    am__minus_obj="-o $am__obj"
++    case $depmode in
++    gcc)
++      # This depmode causes a compiler race in universal mode.
++      test "$am__universal" = false || continue
++      ;;
++    nosideeffect)
++      # After this tag, mechanisms are not by side-effect, so they'll
++      # only be used when explicitly requested.
++      if test "x$enable_dependency_tracking" = xyes; then
++	continue
++      else
++	break
++      fi
++      ;;
++    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
++      # This compiler won't grok '-c -o', but also, the minuso test has
++      # not run yet.  These depmodes are late enough in the game, and
++      # so weak that their functioning should not be impacted.
++      am__obj=conftest.${OBJEXT-o}
++      am__minus_obj=
++      ;;
++    none) break ;;
++    esac
++    if depmode=$depmode \
++       source=sub/conftest.c object=$am__obj \
++       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
++       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
++         >/dev/null 2>conftest.err &&
++       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
++       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
++      # icc doesn't choke on unknown options, it will just issue warnings
++      # or remarks (even with -Werror).  So we grep stderr for any message
++      # that says an option was ignored or not supported.
++      # When given -MP, icc 7.0 and 7.1 complain thusly:
++      #   icc: Command line warning: ignoring option '-M'; no argument required
++      # The diagnosis changed in icc 8.0:
++      #   icc: Command line remark: option '-MP' not supported
++      if (grep 'ignoring option' conftest.err ||
++          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
++        am_cv_CC_dependencies_compiler_type=$depmode
++        break
++      fi
++    fi
++  done
++
++  cd ..
++  rm -rf conftest.dir
++else
++  am_cv_CC_dependencies_compiler_type=none
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
++printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
++CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
++
++ if
++  test "x$enable_dependency_tracking" != xno \
++  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
++  am__fastdepCC_TRUE=
++  am__fastdepCC_FALSE='#'
++else
++  am__fastdepCC_TRUE='#'
++  am__fastdepCC_FALSE=
++fi
++
++
++
++
++
++
++
++
++ac_ext=cpp
++ac_cpp='$CXXCPP $CPPFLAGS'
++ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
++if test -z "$CXX"; then
++  if test -n "$CCC"; then
++    CXX=$CCC
++  else
++    if test -n "$ac_tool_prefix"; then
++  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
++  do
++    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
++set dummy $ac_tool_prefix$ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$CXX"; then
++  ac_cv_prog_CXX="$CXX" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++CXX=$ac_cv_prog_CXX
++if test -n "$CXX"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
++printf "%s\n" "$CXX" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++    test -n "$CXX" && break
++  done
++fi
++if test -z "$CXX"; then
++  ac_ct_CXX=$CXX
++  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_CXX"; then
++  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CXX="$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
++if test -n "$ac_ct_CXX"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
++printf "%s\n" "$ac_ct_CXX" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  test -n "$ac_ct_CXX" && break
++done
++
++  if test "x$ac_ct_CXX" = x; then
++    CXX="g++"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    CXX=$ac_ct_CXX
++  fi
++fi
++
++  fi
++fi
++# Provide some information about the compiler.
++printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
++set X $ac_compile
++ac_compiler=$2
++for ac_option in --version -v -V -qversion; do
++  { { ac_try="$ac_compiler $ac_option >&5"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++printf "%s\n" "$ac_try_echo"; } >&5
++  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    sed '10a\
++... rest of stderr output deleted ...
++         10q' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++  fi
++  rm -f conftest.er1 conftest.err
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++done
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
++printf %s "checking whether the compiler supports GNU C++... " >&6; }
++if test ${ac_cv_cxx_compiler_gnu+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++#ifndef __GNUC__
++       choke me
++#endif
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"
++then :
++  ac_compiler_gnu=yes
++else $as_nop
++  ac_compiler_gnu=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
++printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
++ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
++
++if test $ac_compiler_gnu = yes; then
++  GXX=yes
++else
++  GXX=
++fi
++ac_test_CXXFLAGS=${CXXFLAGS+y}
++ac_save_CXXFLAGS=$CXXFLAGS
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
++printf %s "checking whether $CXX accepts -g... " >&6; }
++if test ${ac_cv_prog_cxx_g+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
++   ac_cxx_werror_flag=yes
++   ac_cv_prog_cxx_g=no
++   CXXFLAGS="-g"
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"
++then :
++  ac_cv_prog_cxx_g=yes
++else $as_nop
++  CXXFLAGS=""
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"
++then :
++
++else $as_nop
++  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
++	 CXXFLAGS="-g"
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_compile "$LINENO"
++then :
++  ac_cv_prog_cxx_g=yes
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
++printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
++if test $ac_test_CXXFLAGS; then
++  CXXFLAGS=$ac_save_CXXFLAGS
++elif test $ac_cv_prog_cxx_g = yes; then
++  if test "$GXX" = yes; then
++    CXXFLAGS="-g -O2"
++  else
++    CXXFLAGS="-g"
++  fi
++else
++  if test "$GXX" = yes; then
++    CXXFLAGS="-O2"
++  else
++    CXXFLAGS=
++  fi
++fi
++ac_prog_cxx_stdcxx=no
++if test x$ac_prog_cxx_stdcxx = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
++printf %s "checking for $CXX option to enable C++11 features... " >&6; }
++if test ${ac_cv_prog_cxx_cxx11+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cxx_cxx11=no
++ac_save_CXX=$CXX
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_cxx_conftest_cxx11_program
++_ACEOF
++for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
++do
++  CXX="$ac_save_CXX $ac_arg"
++  if ac_fn_cxx_try_compile "$LINENO"
++then :
++  ac_cv_prog_cxx_cxx11=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CXX=$ac_save_CXX
++fi
++
++if test "x$ac_cv_prog_cxx_cxx11" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cxx_cxx11" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
++printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
++     CXX="$CXX $ac_cv_prog_cxx_cxx11"
++fi
++  ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
++  ac_prog_cxx_stdcxx=cxx11
++fi
++fi
++if test x$ac_prog_cxx_stdcxx = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
++printf %s "checking for $CXX option to enable C++98 features... " >&6; }
++if test ${ac_cv_prog_cxx_cxx98+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_prog_cxx_cxx98=no
++ac_save_CXX=$CXX
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$ac_cxx_conftest_cxx98_program
++_ACEOF
++for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
++do
++  CXX="$ac_save_CXX $ac_arg"
++  if ac_fn_cxx_try_compile "$LINENO"
++then :
++  ac_cv_prog_cxx_cxx98=$ac_arg
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++  test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
++done
++rm -f conftest.$ac_ext
++CXX=$ac_save_CXX
++fi
++
++if test "x$ac_cv_prog_cxx_cxx98" = xno
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++printf "%s\n" "unsupported" >&6; }
++else $as_nop
++  if test "x$ac_cv_prog_cxx_cxx98" = x
++then :
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++printf "%s\n" "none needed" >&6; }
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
++printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
++     CXX="$CXX $ac_cv_prog_cxx_cxx98"
++fi
++  ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
++  ac_prog_cxx_stdcxx=cxx98
++fi
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++depcc="$CXX"  am_compiler_list=
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
++printf %s "checking dependency style of $depcc... " >&6; }
++if test ${am_cv_CXX_dependencies_compiler_type+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
++  # We make a subdir and do the tests there.  Otherwise we can end up
++  # making bogus files that we don't know about and never remove.  For
++  # instance it was reported that on HP-UX the gcc test will end up
++  # making a dummy file named 'D' -- because '-MD' means "put the output
++  # in D".
++  rm -rf conftest.dir
++  mkdir conftest.dir
++  # Copy depcomp to subdir because otherwise we won't find it if we're
++  # using a relative directory.
++  cp "$am_depcomp" conftest.dir
++  cd conftest.dir
++  # We will build objects and dependencies in a subdirectory because
++  # it helps to detect inapplicable dependency modes.  For instance
++  # both Tru64's cc and ICC support -MD to output dependencies as a
++  # side effect of compilation, but ICC will put the dependencies in
++  # the current directory while Tru64 will put them in the object
++  # directory.
++  mkdir sub
++
++  am_cv_CXX_dependencies_compiler_type=none
++  if test "$am_compiler_list" = ""; then
++     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
++  fi
++  am__universal=false
++  case " $depcc " in #(
++     *\ -arch\ *\ -arch\ *) am__universal=true ;;
++     esac
++
++  for depmode in $am_compiler_list; do
++    # Setup a source with many dependencies, because some compilers
++    # like to wrap large dependency lists on column 80 (with \), and
++    # we should not choose a depcomp mode which is confused by this.
++    #
++    # We need to recreate these files for each test, as the compiler may
++    # overwrite some of them when testing with obscure command lines.
++    # This happens at least with the AIX C compiler.
++    : > sub/conftest.c
++    for i in 1 2 3 4 5 6; do
++      echo '#include "conftst'$i'.h"' >> sub/conftest.c
++      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
++      # Solaris 10 /bin/sh.
++      echo '/* dummy */' > sub/conftst$i.h
++    done
++    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
++
++    # We check with '-c' and '-o' for the sake of the "dashmstdout"
++    # mode.  It turns out that the SunPro C++ compiler does not properly
++    # handle '-M -o', and we need to detect this.  Also, some Intel
++    # versions had trouble with output in subdirs.
++    am__obj=sub/conftest.${OBJEXT-o}
++    am__minus_obj="-o $am__obj"
++    case $depmode in
++    gcc)
++      # This depmode causes a compiler race in universal mode.
++      test "$am__universal" = false || continue
++      ;;
++    nosideeffect)
++      # After this tag, mechanisms are not by side-effect, so they'll
++      # only be used when explicitly requested.
++      if test "x$enable_dependency_tracking" = xyes; then
++	continue
++      else
++	break
++      fi
++      ;;
++    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
++      # This compiler won't grok '-c -o', but also, the minuso test has
++      # not run yet.  These depmodes are late enough in the game, and
++      # so weak that their functioning should not be impacted.
++      am__obj=conftest.${OBJEXT-o}
++      am__minus_obj=
++      ;;
++    none) break ;;
++    esac
++    if depmode=$depmode \
++       source=sub/conftest.c object=$am__obj \
++       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
++       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
++         >/dev/null 2>conftest.err &&
++       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
++       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
++       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
++      # icc doesn't choke on unknown options, it will just issue warnings
++      # or remarks (even with -Werror).  So we grep stderr for any message
++      # that says an option was ignored or not supported.
++      # When given -MP, icc 7.0 and 7.1 complain thusly:
++      #   icc: Command line warning: ignoring option '-M'; no argument required
++      # The diagnosis changed in icc 8.0:
++      #   icc: Command line remark: option '-MP' not supported
++      if (grep 'ignoring option' conftest.err ||
++          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
++        am_cv_CXX_dependencies_compiler_type=$depmode
++        break
++      fi
++    fi
++  done
++
++  cd ..
++  rm -rf conftest.dir
++else
++  am_cv_CXX_dependencies_compiler_type=none
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
++printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; }
++CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
++
++ if
++  test "x$enable_dependency_tracking" != xno \
++  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
++  am__fastdepCXX_TRUE=
++  am__fastdepCXX_FALSE='#'
++else
++  am__fastdepCXX_TRUE='#'
++  am__fastdepCXX_FALSE=
++fi
++
++
++# Check whether --enable-largefile was given.
++if test ${enable_largefile+y}
++then :
++  enableval=$enable_largefile;
++fi
++
++if test "$enable_largefile" != no; then
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
++printf %s "checking for special C compiler options needed for large files... " >&6; }
++if test ${ac_cv_sys_largefile_CC+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_cv_sys_largefile_CC=no
++     if test "$GCC" != yes; then
++       ac_save_CC=$CC
++       while :; do
++	 # IRIX 6.2 and later do not support large files by default,
++	 # so use the C compiler's -n32 option if that helps.
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++ /* Check that off_t can represent 2**63 - 1 correctly.
++    We can't simply define LARGE_OFF_T to be 9223372036854775807,
++    since some C++ compilers masquerading as C compilers
++    incorrectly reject 9223372036854775807.  */
++#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
++		       && LARGE_OFF_T % 2147483647 == 1)
++		      ? 1 : -1];
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++	 if ac_fn_c_try_compile "$LINENO"
++then :
++  break
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++	 CC="$CC -n32"
++	 if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_sys_largefile_CC=' -n32'; break
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam
++	 break
++       done
++       CC=$ac_save_CC
++       rm -f conftest.$ac_ext
++    fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
++printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; }
++  if test "$ac_cv_sys_largefile_CC" != no; then
++    CC=$CC$ac_cv_sys_largefile_CC
++  fi
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
++printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
++if test ${ac_cv_sys_file_offset_bits+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  while :; do
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++ /* Check that off_t can represent 2**63 - 1 correctly.
++    We can't simply define LARGE_OFF_T to be 9223372036854775807,
++    since some C++ compilers masquerading as C compilers
++    incorrectly reject 9223372036854775807.  */
++#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
++		       && LARGE_OFF_T % 2147483647 == 1)
++		      ? 1 : -1];
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_sys_file_offset_bits=no; break
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#define _FILE_OFFSET_BITS 64
++#include 
++ /* Check that off_t can represent 2**63 - 1 correctly.
++    We can't simply define LARGE_OFF_T to be 9223372036854775807,
++    since some C++ compilers masquerading as C compilers
++    incorrectly reject 9223372036854775807.  */
++#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
++		       && LARGE_OFF_T % 2147483647 == 1)
++		      ? 1 : -1];
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_sys_file_offset_bits=64; break
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++  ac_cv_sys_file_offset_bits=unknown
++  break
++done
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
++printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; }
++case $ac_cv_sys_file_offset_bits in #(
++  no | unknown) ;;
++  *)
++printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h
++;;
++esac
++rm -rf conftest*
++  if test $ac_cv_sys_file_offset_bits = unknown; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
++printf %s "checking for _LARGE_FILES value needed for large files... " >&6; }
++if test ${ac_cv_sys_large_files+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  while :; do
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++ /* Check that off_t can represent 2**63 - 1 correctly.
++    We can't simply define LARGE_OFF_T to be 9223372036854775807,
++    since some C++ compilers masquerading as C compilers
++    incorrectly reject 9223372036854775807.  */
++#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
++		       && LARGE_OFF_T % 2147483647 == 1)
++		      ? 1 : -1];
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_sys_large_files=no; break
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#define _LARGE_FILES 1
++#include 
++ /* Check that off_t can represent 2**63 - 1 correctly.
++    We can't simply define LARGE_OFF_T to be 9223372036854775807,
++    since some C++ compilers masquerading as C compilers
++    incorrectly reject 9223372036854775807.  */
++#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
++		       && LARGE_OFF_T % 2147483647 == 1)
++		      ? 1 : -1];
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_sys_large_files=1; break
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++  ac_cv_sys_large_files=unknown
++  break
++done
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
++printf "%s\n" "$ac_cv_sys_large_files" >&6; }
++case $ac_cv_sys_large_files in #(
++  no | unknown) ;;
++  *)
++printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h
++;;
++esac
++rm -rf conftest*
++  fi
++fi
++
++
++# Check whether -static-libgcc is supported.
++saved_LDFLAGS="$LDFLAGS"
++LDFLAGS="$LDFLAGS -static-libgcc"
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -static-libgcc" >&5
++printf %s "checking for -static-libgcc... " >&6; }
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++  int main() {}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  have_static_libgcc=yes
++else $as_nop
++  have_static_libgcc=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_static_libgcc" >&5
++printf "%s\n" "$have_static_libgcc" >&6; };
++LDFLAGS="$saved_LDFLAGS"
++# Need -Wc to get it through libtool.
++if test "x$have_static_libgcc" = xyes; then
++   ac_bolt_plugin_ldflags="-Wc,-static-libgcc"
++fi
++
++
++if test x"$host_subdir" = x.; then
++   gcc_build_dir=../gcc
++else
++   gcc_build_dir=../../$host_subdir/gcc
++fi
++
++
++# Used for constructing correct paths for offload compilers.
++accel_dir_suffix=
++real_target_noncanonical=${target_noncanonical}
++if test x"$enable_as_accelerator_for" != x; then
++  accel_dir_suffix=/accel/${target_noncanonical}
++  real_target_noncanonical=${enable_as_accelerator_for}
++fi
++
++
++
++# Determine what GCC version number to use in filesystem paths.
++GCC_BASE_VER
++
++case `pwd` in
++  *\ * | *\	*)
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
++printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
++esac
++
++
++
++macro_version='2.4.7'
++macro_revision='2.4.7'
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++ltmain=$ac_aux_dir/ltmain.sh
++
++# Backslashify metacharacters that are still active within
++# double-quoted strings.
++sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
++
++# Same as above, but do not quote variable references.
++double_quote_subst='s/\(["`\\]\)/\\\1/g'
++
++# Sed substitution to delay expansion of an escaped shell variable in a
++# double_quote_subst'ed string.
++delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
++
++# Sed substitution to delay expansion of an escaped single quote.
++delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
++
++# Sed substitution to avoid accidental globbing in evaled expressions
++no_glob_subst='s/\*/\\\*/g'
++
++ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
++ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
++printf %s "checking how to print strings... " >&6; }
++# Test print first, because it will be a builtin if present.
++if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
++   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
++  ECHO='print -r --'
++elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
++  ECHO='printf %s\n'
++else
++  # Use this function as a fallback that always works.
++  func_fallback_echo ()
++  {
++    eval 'cat <<_LTECHO_EOF
++$1
++_LTECHO_EOF'
++  }
++  ECHO='func_fallback_echo'
++fi
++
++# func_echo_all arg...
++# Invoke $ECHO with all args, space-separated.
++func_echo_all ()
++{
++    $ECHO ""
++}
++
++case $ECHO in
++  printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5
++printf "%s\n" "printf" >&6; } ;;
++  print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
++printf "%s\n" "print -r" >&6; } ;;
++  *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5
++printf "%s\n" "cat" >&6; } ;;
++esac
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
++printf %s "checking for a sed that does not truncate output... " >&6; }
++if test ${ac_cv_path_SED+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
++     for ac_i in 1 2 3 4 5 6 7; do
++       ac_script="$ac_script$as_nl$ac_script"
++     done
++     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
++     { ac_script=; unset ac_script;}
++     if test -z "$SED"; then
++  ac_path_SED_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_prog in sed gsed
++   do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_SED="$as_dir$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_SED" || continue
++# Check for GNU ac_path_SED and select it if it is found.
++  # Check for GNU $ac_path_SED
++case `"$ac_path_SED" --version 2>&1` in
++*GNU*)
++  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
++*)
++  ac_count=0
++  printf %s 0123456789 >"conftest.in"
++  while :
++  do
++    cat "conftest.in" "conftest.in" >"conftest.tmp"
++    mv "conftest.tmp" "conftest.in"
++    cp "conftest.in" "conftest.nl"
++    printf "%s\n" '' >> "conftest.nl"
++    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
++    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++    as_fn_arith $ac_count + 1 && ac_count=$as_val
++    if test $ac_count -gt ${ac_path_SED_max-0}; then
++      # Best one so far, save it but keep looking for a better one
++      ac_cv_path_SED="$ac_path_SED"
++      ac_path_SED_max=$ac_count
++    fi
++    # 10*(2^10) chars as input seems more than enough
++    test $ac_count -gt 10 && break
++  done
++  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++      $ac_path_SED_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_SED"; then
++    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
++  fi
++else
++  ac_cv_path_SED=$SED
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
++printf "%s\n" "$ac_cv_path_SED" >&6; }
++ SED="$ac_cv_path_SED"
++  rm -f conftest.sed
++
++test -z "$SED" && SED=sed
++Xsed="$SED -e 1s/^X//"
++
++
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
++printf %s "checking for grep that handles long lines and -e... " >&6; }
++if test ${ac_cv_path_GREP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -z "$GREP"; then
++  ac_path_GREP_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_prog in grep ggrep
++   do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_GREP" || continue
++# Check for GNU ac_path_GREP and select it if it is found.
++  # Check for GNU $ac_path_GREP
++case `"$ac_path_GREP" --version 2>&1` in
++*GNU*)
++  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
++*)
++  ac_count=0
++  printf %s 0123456789 >"conftest.in"
++  while :
++  do
++    cat "conftest.in" "conftest.in" >"conftest.tmp"
++    mv "conftest.tmp" "conftest.in"
++    cp "conftest.in" "conftest.nl"
++    printf "%s\n" 'GREP' >> "conftest.nl"
++    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++    as_fn_arith $ac_count + 1 && ac_count=$as_val
++    if test $ac_count -gt ${ac_path_GREP_max-0}; then
++      # Best one so far, save it but keep looking for a better one
++      ac_cv_path_GREP="$ac_path_GREP"
++      ac_path_GREP_max=$ac_count
++    fi
++    # 10*(2^10) chars as input seems more than enough
++    test $ac_count -gt 10 && break
++  done
++  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++      $ac_path_GREP_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_GREP"; then
++    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++  fi
++else
++  ac_cv_path_GREP=$GREP
++fi
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
++printf "%s\n" "$ac_cv_path_GREP" >&6; }
++ GREP="$ac_cv_path_GREP"
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
++printf %s "checking for egrep... " >&6; }
++if test ${ac_cv_path_EGREP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
++   then ac_cv_path_EGREP="$GREP -E"
++   else
++     if test -z "$EGREP"; then
++  ac_path_EGREP_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_prog in egrep
++   do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_EGREP" || continue
++# Check for GNU ac_path_EGREP and select it if it is found.
++  # Check for GNU $ac_path_EGREP
++case `"$ac_path_EGREP" --version 2>&1` in
++*GNU*)
++  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
++*)
++  ac_count=0
++  printf %s 0123456789 >"conftest.in"
++  while :
++  do
++    cat "conftest.in" "conftest.in" >"conftest.tmp"
++    mv "conftest.tmp" "conftest.in"
++    cp "conftest.in" "conftest.nl"
++    printf "%s\n" 'EGREP' >> "conftest.nl"
++    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++    as_fn_arith $ac_count + 1 && ac_count=$as_val
++    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
++      # Best one so far, save it but keep looking for a better one
++      ac_cv_path_EGREP="$ac_path_EGREP"
++      ac_path_EGREP_max=$ac_count
++    fi
++    # 10*(2^10) chars as input seems more than enough
++    test $ac_count -gt 10 && break
++  done
++  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++      $ac_path_EGREP_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_EGREP"; then
++    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++  fi
++else
++  ac_cv_path_EGREP=$EGREP
++fi
++
++   fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
++printf "%s\n" "$ac_cv_path_EGREP" >&6; }
++ EGREP="$ac_cv_path_EGREP"
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
++printf %s "checking for fgrep... " >&6; }
++if test ${ac_cv_path_FGREP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
++   then ac_cv_path_FGREP="$GREP -F"
++   else
++     if test -z "$FGREP"; then
++  ac_path_FGREP_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_prog in fgrep
++   do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_FGREP" || continue
++# Check for GNU ac_path_FGREP and select it if it is found.
++  # Check for GNU $ac_path_FGREP
++case `"$ac_path_FGREP" --version 2>&1` in
++*GNU*)
++  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
++*)
++  ac_count=0
++  printf %s 0123456789 >"conftest.in"
++  while :
++  do
++    cat "conftest.in" "conftest.in" >"conftest.tmp"
++    mv "conftest.tmp" "conftest.in"
++    cp "conftest.in" "conftest.nl"
++    printf "%s\n" 'FGREP' >> "conftest.nl"
++    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
++    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++    as_fn_arith $ac_count + 1 && ac_count=$as_val
++    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
++      # Best one so far, save it but keep looking for a better one
++      ac_cv_path_FGREP="$ac_path_FGREP"
++      ac_path_FGREP_max=$ac_count
++    fi
++    # 10*(2^10) chars as input seems more than enough
++    test $ac_count -gt 10 && break
++  done
++  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++      $ac_path_FGREP_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_FGREP"; then
++    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++  fi
++else
++  ac_cv_path_FGREP=$FGREP
++fi
++
++   fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
++printf "%s\n" "$ac_cv_path_FGREP" >&6; }
++ FGREP="$ac_cv_path_FGREP"
++
++
++test -z "$GREP" && GREP=grep
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# Check whether --with-gnu-ld was given.
++if test ${with_gnu_ld+y}
++then :
++  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
++else $as_nop
++  with_gnu_ld=no
++fi
++
++ac_prog=ld
++if test yes = "$GCC"; then
++  # Check if gcc -print-prog-name=ld gives a path.
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
++printf %s "checking for ld used by $CC... " >&6; }
++  case $host in
++  *-*-mingw*)
++    # gcc leaves a trailing carriage return, which upsets mingw
++    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
++  *)
++    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
++  esac
++  case $ac_prog in
++    # Accept absolute paths.
++    [\\/]* | ?:[\\/]*)
++      re_direlt='/[^/][^/]*/\.\./'
++      # Canonicalize the pathname of ld
++      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
++      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
++	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
++      done
++      test -z "$LD" && LD=$ac_prog
++      ;;
++  "")
++    # If it fails, then pretend we aren't using GCC.
++    ac_prog=ld
++    ;;
++  *)
++    # If it is relative, then search for the first ld in PATH.
++    with_gnu_ld=unknown
++    ;;
++  esac
++elif test yes = "$with_gnu_ld"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
++printf %s "checking for GNU ld... " >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
++printf %s "checking for non-GNU ld... " >&6; }
++fi
++if test ${lt_cv_path_LD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -z "$LD"; then
++  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  for ac_dir in $PATH; do
++    IFS=$lt_save_ifs
++    test -z "$ac_dir" && ac_dir=.
++    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
++      lt_cv_path_LD=$ac_dir/$ac_prog
++      # Check to see if the program is GNU ld.  I'd rather use --version,
++      # but apparently some variants of GNU ld only accept -v.
++      # Break only if it was the GNU/non-GNU ld that we prefer.
++      case `"$lt_cv_path_LD" -v 2>&1 &5
++printf "%s\n" "$LD" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
++printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
++if test ${lt_cv_prog_gnu_ld+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  # I'd rather use --version here, but apparently some GNU lds only accept -v.
++case `$LD -v 2>&1 &5
++printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
++printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
++if test ${lt_cv_path_NM+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$NM"; then
++  # Let the user override the test.
++  lt_cv_path_NM=$NM
++else
++  lt_nm_to_check=${ac_tool_prefix}nm
++  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
++    lt_nm_to_check="$lt_nm_to_check nm"
++  fi
++  for lt_tmp_nm in $lt_nm_to_check; do
++    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
++      IFS=$lt_save_ifs
++      test -z "$ac_dir" && ac_dir=.
++      tmp_nm=$ac_dir/$lt_tmp_nm
++      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
++	# Check to see if the nm accepts a BSD-compat flag.
++	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
++	#   nm: unknown option "B" ignored
++	# Tru64's nm complains that /dev/null is an invalid object file
++	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
++	case $build_os in
++	mingw*) lt_bad_file=conftest.nm/nofile ;;
++	*) lt_bad_file=/dev/null ;;
++	esac
++	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
++	*$lt_bad_file* | *'Invalid file or object type'*)
++	  lt_cv_path_NM="$tmp_nm -B"
++	  break 2
++	  ;;
++	*)
++	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
++	  */dev/null*)
++	    lt_cv_path_NM="$tmp_nm -p"
++	    break 2
++	    ;;
++	  *)
++	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
++	    continue # so that we can try to find one that supports BSD flags
++	    ;;
++	  esac
++	  ;;
++	esac
++      fi
++    done
++    IFS=$lt_save_ifs
++  done
++  : ${lt_cv_path_NM=no}
++fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
++printf "%s\n" "$lt_cv_path_NM" >&6; }
++if test no != "$lt_cv_path_NM"; then
++  NM=$lt_cv_path_NM
++else
++  # Didn't find any BSD compatible name lister, look for dumpbin.
++  if test -n "$DUMPBIN"; then :
++    # Let the user override the test.
++  else
++    if test -n "$ac_tool_prefix"; then
++  for ac_prog in dumpbin "link -dump"
++  do
++    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
++set dummy $ac_tool_prefix$ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_DUMPBIN+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$DUMPBIN"; then
++  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++DUMPBIN=$ac_cv_prog_DUMPBIN
++if test -n "$DUMPBIN"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
++printf "%s\n" "$DUMPBIN" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++    test -n "$DUMPBIN" && break
++  done
++fi
++if test -z "$DUMPBIN"; then
++  ac_ct_DUMPBIN=$DUMPBIN
++  for ac_prog in dumpbin "link -dump"
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_DUMPBIN+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_DUMPBIN"; then
++  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
++if test -n "$ac_ct_DUMPBIN"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
++printf "%s\n" "$ac_ct_DUMPBIN" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  test -n "$ac_ct_DUMPBIN" && break
++done
++
++  if test "x$ac_ct_DUMPBIN" = x; then
++    DUMPBIN=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    DUMPBIN=$ac_ct_DUMPBIN
++  fi
++fi
++
++    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
++    *COFF*)
++      DUMPBIN="$DUMPBIN -symbols -headers"
++      ;;
++    *)
++      DUMPBIN=:
++      ;;
++    esac
++  fi
++
++  if test : != "$DUMPBIN"; then
++    NM=$DUMPBIN
++  fi
++fi
++test -z "$NM" && NM=nm
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
++printf %s "checking the name lister ($NM) interface... " >&6; }
++if test ${lt_cv_nm_interface+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_nm_interface="BSD nm"
++  echo "int some_variable = 0;" > conftest.$ac_ext
++  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
++  (eval "$ac_compile" 2>conftest.err)
++  cat conftest.err >&5
++  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
++  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
++  cat conftest.err >&5
++  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
++  cat conftest.out >&5
++  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
++    lt_cv_nm_interface="MS dumpbin"
++  fi
++  rm -f conftest*
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
++printf "%s\n" "$lt_cv_nm_interface" >&6; }
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
++printf %s "checking whether ln -s works... " >&6; }
++LN_S=$as_ln_s
++if test "$LN_S" = "ln -s"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
++printf "%s\n" "no, using $LN_S" >&6; }
++fi
++
++# find the maximum length of command line arguments
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
++printf %s "checking the maximum length of command line arguments... " >&6; }
++if test ${lt_cv_sys_max_cmd_len+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++    i=0
++  teststring=ABCD
++
++  case $build_os in
++  msdosdjgpp*)
++    # On DJGPP, this test can blow up pretty badly due to problems in libc
++    # (any single argument exceeding 2000 bytes causes a buffer overrun
++    # during glob expansion).  Even if it were fixed, the result of this
++    # check would be larger than it should be.
++    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
++    ;;
++
++  gnu*)
++    # Under GNU Hurd, this test is not required because there is
++    # no limit to the length of command line arguments.
++    # Libtool will interpret -1 as no limit whatsoever
++    lt_cv_sys_max_cmd_len=-1;
++    ;;
++
++  cygwin* | mingw* | cegcc*)
++    # On Win9x/ME, this test blows up -- it succeeds, but takes
++    # about 5 minutes as the teststring grows exponentially.
++    # Worse, since 9x/ME are not pre-emptively multitasking,
++    # you end up with a "frozen" computer, even though with patience
++    # the test eventually succeeds (with a max line length of 256k).
++    # Instead, let's just punt: use the minimum linelength reported by
++    # all of the supported platforms: 8192 (on NT/2K/XP).
++    lt_cv_sys_max_cmd_len=8192;
++    ;;
++
++  mint*)
++    # On MiNT this can take a long time and run out of memory.
++    lt_cv_sys_max_cmd_len=8192;
++    ;;
++
++  amigaos*)
++    # On AmigaOS with pdksh, this test takes hours, literally.
++    # So we just punt and use a minimum line length of 8192.
++    lt_cv_sys_max_cmd_len=8192;
++    ;;
++
++  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
++    # This has been around since 386BSD, at least.  Likely further.
++    if test -x /sbin/sysctl; then
++      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
++    elif test -x /usr/sbin/sysctl; then
++      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
++    else
++      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
++    fi
++    # And add a safety zone
++    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
++    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
++    ;;
++
++  interix*)
++    # We know the value 262144 and hardcode it with a safety zone (like BSD)
++    lt_cv_sys_max_cmd_len=196608
++    ;;
++
++  os2*)
++    # The test takes a long time on OS/2.
++    lt_cv_sys_max_cmd_len=8192
++    ;;
++
++  osf*)
++    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
++    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
++    # nice to cause kernel panics so lets avoid the loop below.
++    # First set a reasonable default.
++    lt_cv_sys_max_cmd_len=16384
++    #
++    if test -x /sbin/sysconfig; then
++      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
++        *1*) lt_cv_sys_max_cmd_len=-1 ;;
++      esac
++    fi
++    ;;
++  sco3.2v5*)
++    lt_cv_sys_max_cmd_len=102400
++    ;;
++  sysv5* | sco5v6* | sysv4.2uw2*)
++    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
++    if test -n "$kargmax"; then
++      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[	 ]//'`
++    else
++      lt_cv_sys_max_cmd_len=32768
++    fi
++    ;;
++  *)
++    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
++    if test -n "$lt_cv_sys_max_cmd_len" && \
++       test undefined != "$lt_cv_sys_max_cmd_len"; then
++      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
++      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
++    else
++      # Make teststring a little bigger before we do anything with it.
++      # a 1K string should be a reasonable start.
++      for i in 1 2 3 4 5 6 7 8; do
++        teststring=$teststring$teststring
++      done
++      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
++      # If test is not a shell built-in, we'll probably end up computing a
++      # maximum length that is only half of the actual maximum length, but
++      # we can't tell.
++      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
++	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
++	      test 17 != "$i" # 1/2 MB should be enough
++      do
++        i=`expr $i + 1`
++        teststring=$teststring$teststring
++      done
++      # Only check the string length outside the loop.
++      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
++      teststring=
++      # Add a significant safety factor because C++ compilers can tack on
++      # massive amounts of additional arguments before passing them to the
++      # linker.  It appears as though 1/2 is a usable value.
++      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
++    fi
++    ;;
++  esac
++
++fi
++
++if test -n "$lt_cv_sys_max_cmd_len"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
++printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
++printf "%s\n" "none" >&6; }
++fi
++max_cmd_len=$lt_cv_sys_max_cmd_len
++
++
++
++
++
++
++: ${CP="cp -f"}
++: ${MV="mv -f"}
++: ${RM="rm -f"}
++
++if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
++  lt_unset=unset
++else
++  lt_unset=false
++fi
++
++
++
++
++
++# test EBCDIC or ASCII
++case `echo X|tr X '\101'` in
++ A) # ASCII based system
++    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
++  lt_SP2NL='tr \040 \012'
++  lt_NL2SP='tr \015\012 \040\040'
++  ;;
++ *) # EBCDIC based system
++  lt_SP2NL='tr \100 \n'
++  lt_NL2SP='tr \r\n \100\100'
++  ;;
++esac
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
++printf %s "checking how to convert $build file names to $host format... " >&6; }
++if test ${lt_cv_to_host_file_cmd+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  case $host in
++  *-*-mingw* )
++    case $build in
++      *-*-mingw* ) # actually msys
++        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
++        ;;
++      *-*-cygwin* )
++        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
++        ;;
++      * ) # otherwise, assume *nix
++        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
++        ;;
++    esac
++    ;;
++  *-*-cygwin* )
++    case $build in
++      *-*-mingw* ) # actually msys
++        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
++        ;;
++      *-*-cygwin* )
++        lt_cv_to_host_file_cmd=func_convert_file_noop
++        ;;
++      * ) # otherwise, assume *nix
++        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
++        ;;
++    esac
++    ;;
++  * ) # unhandled hosts (and "normal" native builds)
++    lt_cv_to_host_file_cmd=func_convert_file_noop
++    ;;
++esac
++
++fi
++
++to_host_file_cmd=$lt_cv_to_host_file_cmd
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
++printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; }
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
++printf %s "checking how to convert $build file names to toolchain format... " >&6; }
++if test ${lt_cv_to_tool_file_cmd+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  #assume ordinary cross tools, or native build.
++lt_cv_to_tool_file_cmd=func_convert_file_noop
++case $host in
++  *-*-mingw* )
++    case $build in
++      *-*-mingw* ) # actually msys
++        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
++        ;;
++    esac
++    ;;
++esac
++
++fi
++
++to_tool_file_cmd=$lt_cv_to_tool_file_cmd
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
++printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; }
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
++printf %s "checking for $LD option to reload object files... " >&6; }
++if test ${lt_cv_ld_reload_flag+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_ld_reload_flag='-r'
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
++printf "%s\n" "$lt_cv_ld_reload_flag" >&6; }
++reload_flag=$lt_cv_ld_reload_flag
++case $reload_flag in
++"" | " "*) ;;
++*) reload_flag=" $reload_flag" ;;
++esac
++reload_cmds='$LD$reload_flag -o $output$reload_objs'
++case $host_os in
++  cygwin* | mingw* | pw32* | cegcc*)
++    if test yes != "$GCC"; then
++      reload_cmds=false
++    fi
++    ;;
++  darwin*)
++    if test yes = "$GCC"; then
++      reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
++    else
++      reload_cmds='$LD$reload_flag -o $output$reload_objs'
++    fi
++    ;;
++esac
++
++
++
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args.
++set dummy ${ac_tool_prefix}file; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_FILECMD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$FILECMD"; then
++  ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_FILECMD="${ac_tool_prefix}file"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++FILECMD=$ac_cv_prog_FILECMD
++if test -n "$FILECMD"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
++printf "%s\n" "$FILECMD" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_FILECMD"; then
++  ac_ct_FILECMD=$FILECMD
++  # Extract the first word of "file", so it can be a program name with args.
++set dummy file; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_FILECMD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_FILECMD"; then
++  ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_FILECMD="file"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD
++if test -n "$ac_ct_FILECMD"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5
++printf "%s\n" "$ac_ct_FILECMD" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_FILECMD" = x; then
++    FILECMD=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    FILECMD=$ac_ct_FILECMD
++  fi
++else
++  FILECMD="$ac_cv_prog_FILECMD"
++fi
++
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
++set dummy ${ac_tool_prefix}objdump; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_OBJDUMP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$OBJDUMP"; then
++  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++OBJDUMP=$ac_cv_prog_OBJDUMP
++if test -n "$OBJDUMP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
++printf "%s\n" "$OBJDUMP" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_OBJDUMP"; then
++  ac_ct_OBJDUMP=$OBJDUMP
++  # Extract the first word of "objdump", so it can be a program name with args.
++set dummy objdump; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_OBJDUMP"; then
++  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_OBJDUMP="objdump"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
++if test -n "$ac_ct_OBJDUMP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
++printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_OBJDUMP" = x; then
++    OBJDUMP="false"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    OBJDUMP=$ac_ct_OBJDUMP
++  fi
++else
++  OBJDUMP="$ac_cv_prog_OBJDUMP"
++fi
++
++test -z "$OBJDUMP" && OBJDUMP=objdump
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
++printf %s "checking how to recognize dependent libraries... " >&6; }
++if test ${lt_cv_deplibs_check_method+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_file_magic_cmd='$MAGIC_CMD'
++lt_cv_file_magic_test_file=
++lt_cv_deplibs_check_method='unknown'
++# Need to set the preceding variable on all platforms that support
++# interlibrary dependencies.
++# 'none' -- dependencies not supported.
++# 'unknown' -- same as none, but documents that we really don't know.
++# 'pass_all' -- all dependencies passed with no checks.
++# 'test_compile' -- check by making test program.
++# 'file_magic [[regex]]' -- check by looking for files in library path
++# that responds to the $file_magic_cmd with a given extended regex.
++# If you have 'file' or equivalent on your system and you're not sure
++# whether 'pass_all' will *always* work, you probably want this one.
++
++case $host_os in
++aix[4-9]*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++beos*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++bsdi[45]*)
++  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
++  lt_cv_file_magic_cmd='$FILECMD -L'
++  lt_cv_file_magic_test_file=/shlib/libc.so
++  ;;
++
++cygwin*)
++  # func_win32_libid is a shell function defined in ltmain.sh
++  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++  lt_cv_file_magic_cmd='func_win32_libid'
++  ;;
++
++mingw* | pw32*)
++  # Base MSYS/MinGW do not provide the 'file' command needed by
++  # func_win32_libid shell function, so use a weaker test based on 'objdump',
++  # unless we find 'file', for example because we are cross-compiling.
++  if ( file / ) >/dev/null 2>&1; then
++    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
++    lt_cv_file_magic_cmd='func_win32_libid'
++  else
++    # Keep this pattern in sync with the one in func_win32_libid.
++    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
++    lt_cv_file_magic_cmd='$OBJDUMP -f'
++  fi
++  ;;
++
++cegcc*)
++  # use the weaker test based on 'objdump'. See mingw*.
++  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
++  lt_cv_file_magic_cmd='$OBJDUMP -f'
++  ;;
++
++darwin* | rhapsody*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
++    case $host_cpu in
++    i*86 )
++      # Not sure whether the presence of OpenBSD here was a mistake.
++      # Let's accept both of them until this is cleared up.
++      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
++      lt_cv_file_magic_cmd=$FILECMD
++      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
++      ;;
++    esac
++  else
++    lt_cv_deplibs_check_method=pass_all
++  fi
++  ;;
++
++haiku*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++hpux10.20* | hpux11*)
++  lt_cv_file_magic_cmd=$FILECMD
++  case $host_cpu in
++  ia64*)
++    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
++    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
++    ;;
++  hppa*64*)
++    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
++    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
++    ;;
++  *)
++    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
++    lt_cv_file_magic_test_file=/usr/lib/libc.sl
++    ;;
++  esac
++  ;;
++
++interix[3-9]*)
++  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
++  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
++  ;;
++
++irix5* | irix6* | nonstopux*)
++  case $LD in
++  *-32|*"-32 ") libmagic=32-bit;;
++  *-n32|*"-n32 ") libmagic=N32;;
++  *-64|*"-64 ") libmagic=64-bit;;
++  *) libmagic=never-match;;
++  esac
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++netbsd*)
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
++    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
++  else
++    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
++  fi
++  ;;
++
++newos6*)
++  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
++  lt_cv_file_magic_cmd=$FILECMD
++  lt_cv_file_magic_test_file=/usr/lib/libnls.so
++  ;;
++
++*nto* | *qnx*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++openbsd* | bitrig*)
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
++  else
++    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
++  fi
++  ;;
++
++osf3* | osf4* | osf5*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++rdos*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++solaris*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
++sysv4 | sysv4.3*)
++  case $host_vendor in
++  motorola)
++    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
++    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
++    ;;
++  ncr)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  sequent)
++    lt_cv_file_magic_cmd='/bin/file'
++    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++    ;;
++  sni)
++    lt_cv_file_magic_cmd='/bin/file'
++    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
++    lt_cv_file_magic_test_file=/lib/libc.so
++    ;;
++  siemens)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  pc)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  esac
++  ;;
++
++tpf*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++os2*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++esac
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
++printf "%s\n" "$lt_cv_deplibs_check_method" >&6; }
++
++file_magic_glob=
++want_nocaseglob=no
++if test "$build" = "$host"; then
++  case $host_os in
++  mingw* | pw32*)
++    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
++      want_nocaseglob=yes
++    else
++      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
++    fi
++    ;;
++  esac
++fi
++
++file_magic_cmd=$lt_cv_file_magic_cmd
++deplibs_check_method=$lt_cv_deplibs_check_method
++test -z "$deplibs_check_method" && deplibs_check_method=unknown
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
++set dummy ${ac_tool_prefix}dlltool; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_DLLTOOL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$DLLTOOL"; then
++  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++DLLTOOL=$ac_cv_prog_DLLTOOL
++if test -n "$DLLTOOL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
++printf "%s\n" "$DLLTOOL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_DLLTOOL"; then
++  ac_ct_DLLTOOL=$DLLTOOL
++  # Extract the first word of "dlltool", so it can be a program name with args.
++set dummy dlltool; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_DLLTOOL"; then
++  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
++if test -n "$ac_ct_DLLTOOL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
++printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_DLLTOOL" = x; then
++    DLLTOOL="false"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    DLLTOOL=$ac_ct_DLLTOOL
++  fi
++else
++  DLLTOOL="$ac_cv_prog_DLLTOOL"
++fi
++
++test -z "$DLLTOOL" && DLLTOOL=dlltool
++
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
++printf %s "checking how to associate runtime and link libraries... " >&6; }
++if test ${lt_cv_sharedlib_from_linklib_cmd+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_sharedlib_from_linklib_cmd='unknown'
++
++case $host_os in
++cygwin* | mingw* | pw32* | cegcc*)
++  # two different shell functions defined in ltmain.sh;
++  # decide which one to use based on capabilities of $DLLTOOL
++  case `$DLLTOOL --help 2>&1` in
++  *--identify-strict*)
++    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
++    ;;
++  *)
++    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
++    ;;
++  esac
++  ;;
++*)
++  # fallback: assume linklib IS sharedlib
++  lt_cv_sharedlib_from_linklib_cmd=$ECHO
++  ;;
++esac
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
++printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
++sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
++test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
++
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  for ac_prog in ar
++  do
++    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
++set dummy $ac_tool_prefix$ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_AR+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$AR"; then
++  ac_cv_prog_AR="$AR" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++AR=$ac_cv_prog_AR
++if test -n "$AR"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
++printf "%s\n" "$AR" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++    test -n "$AR" && break
++  done
++fi
++if test -z "$AR"; then
++  ac_ct_AR=$AR
++  for ac_prog in ar
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_AR+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_AR"; then
++  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_AR="$ac_prog"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_AR=$ac_cv_prog_ac_ct_AR
++if test -n "$ac_ct_AR"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
++printf "%s\n" "$ac_ct_AR" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  test -n "$ac_ct_AR" && break
++done
++
++  if test "x$ac_ct_AR" = x; then
++    AR="false"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    AR=$ac_ct_AR
++  fi
++fi
++
++: ${AR=ar}
++
++
++
++
++
++
++# Use ARFLAGS variable as AR's operation code to sync the variable naming with
++# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
++# higher priority because thats what people were doing historically (setting
++# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
++# variable obsoleted/removed.
++
++test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
++lt_ar_flags=$AR_FLAGS
++
++
++
++
++
++
++# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
++# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
++printf %s "checking for archiver @FILE support... " >&6; }
++if test ${lt_cv_ar_at_file+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_ar_at_file=no
++   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  echo conftest.$ac_objext > conftest.lst
++      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
++      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
++  (eval $lt_ar_try) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++      if test 0 -eq "$ac_status"; then
++	# Ensure the archiver fails upon bogus file names.
++	rm -f conftest.$ac_objext libconftest.a
++	{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
++  (eval $lt_ar_try) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++	if test 0 -ne "$ac_status"; then
++          lt_cv_ar_at_file=@
++        fi
++      fi
++      rm -f conftest.* libconftest.a
++
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
++printf "%s\n" "$lt_cv_ar_at_file" >&6; }
++
++if test no = "$lt_cv_ar_at_file"; then
++  archiver_list_spec=
++else
++  archiver_list_spec=$lt_cv_ar_at_file
++fi
++
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
++set dummy ${ac_tool_prefix}strip; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_STRIP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$STRIP"; then
++  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++STRIP=$ac_cv_prog_STRIP
++if test -n "$STRIP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
++printf "%s\n" "$STRIP" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_STRIP"; then
++  ac_ct_STRIP=$STRIP
++  # Extract the first word of "strip", so it can be a program name with args.
++set dummy strip; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_STRIP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_STRIP"; then
++  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_STRIP="strip"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
++if test -n "$ac_ct_STRIP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
++printf "%s\n" "$ac_ct_STRIP" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_STRIP" = x; then
++    STRIP=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    STRIP=$ac_ct_STRIP
++  fi
++else
++  STRIP="$ac_cv_prog_STRIP"
++fi
++
++test -z "$STRIP" && STRIP=:
++
++
++
++
++
++
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
++set dummy ${ac_tool_prefix}ranlib; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_RANLIB+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$RANLIB"; then
++  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++RANLIB=$ac_cv_prog_RANLIB
++if test -n "$RANLIB"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
++printf "%s\n" "$RANLIB" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_RANLIB"; then
++  ac_ct_RANLIB=$RANLIB
++  # Extract the first word of "ranlib", so it can be a program name with args.
++set dummy ranlib; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_RANLIB+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_RANLIB"; then
++  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_RANLIB="ranlib"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
++if test -n "$ac_ct_RANLIB"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
++printf "%s\n" "$ac_ct_RANLIB" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_RANLIB" = x; then
++    RANLIB=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    RANLIB=$ac_ct_RANLIB
++  fi
++else
++  RANLIB="$ac_cv_prog_RANLIB"
++fi
++
++test -z "$RANLIB" && RANLIB=:
++
++
++
++
++
++
++# Determine commands to create old-style static archives.
++old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
++old_postinstall_cmds='chmod 644 $oldlib'
++old_postuninstall_cmds=
++
++if test -n "$RANLIB"; then
++  case $host_os in
++  bitrig* | openbsd*)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
++    ;;
++  *)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
++    ;;
++  esac
++  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
++fi
++
++case $host_os in
++  darwin*)
++    lock_old_archive_extraction=yes ;;
++  *)
++    lock_old_archive_extraction=no ;;
++esac
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++# If no C compiler was specified, use CC.
++LTCC=${LTCC-"$CC"}
++
++# If no C compiler flags were specified, use CFLAGS.
++LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
++
++# Allow CC to be a program name with arguments.
++compiler=$CC
++
++
++# Check for command to grab the raw symbol name followed by C symbol from nm.
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
++printf %s "checking command to parse $NM output from $compiler object... " >&6; }
++if test ${lt_cv_sys_global_symbol_pipe+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++
++# These are sane defaults that work on at least a few old systems.
++# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
++
++# Character class describing NM global symbol codes.
++symcode='[BCDEGRST]'
++
++# Regexp to match symbols that can be accessed directly from C.
++sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
++
++# Define system-specific variables.
++case $host_os in
++aix*)
++  symcode='[BCDT]'
++  ;;
++cygwin* | mingw* | pw32* | cegcc*)
++  symcode='[ABCDGISTW]'
++  ;;
++hpux*)
++  if test ia64 = "$host_cpu"; then
++    symcode='[ABCDEGRST]'
++  fi
++  ;;
++irix* | nonstopux*)
++  symcode='[BCDEGRST]'
++  ;;
++osf*)
++  symcode='[BCDEGQRST]'
++  ;;
++solaris*)
++  symcode='[BDRT]'
++  ;;
++sco3.2v5*)
++  symcode='[DT]'
++  ;;
++sysv4.2uw2*)
++  symcode='[DT]'
++  ;;
++sysv5* | sco5v6* | unixware* | OpenUNIX*)
++  symcode='[ABDT]'
++  ;;
++sysv4)
++  symcode='[DFNSTU]'
++  ;;
++esac
++
++# If we're using GNU nm, then use its standard symbol codes.
++case `$NM -V 2>&1` in
++*GNU* | *'with BFD'*)
++  symcode='[ABCDGIRSTW]' ;;
++esac
++
++if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++  # Gets list of data symbols to import.
++  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
++  # Adjust the below global symbol transforms to fixup imported variables.
++  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
++  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
++  lt_c_name_lib_hook="\
++  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
++  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
++else
++  # Disable hooks by default.
++  lt_cv_sys_global_symbol_to_import=
++  lt_cdecl_hook=
++  lt_c_name_hook=
++  lt_c_name_lib_hook=
++fi
++
++# Transform an extracted symbol line into a proper C declaration.
++# Some systems (esp. on ia64) link data and code symbols differently,
++# so use this general approach.
++lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
++$lt_cdecl_hook\
++" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
++
++# Transform an extracted symbol line into symbol name and symbol address
++lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
++$lt_c_name_hook\
++" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
++
++# Transform an extracted symbol line into symbol name with lib prefix and
++# symbol address.
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
++$lt_c_name_lib_hook\
++" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
++" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
++" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
++
++# Handle CRLF in mingw tool chain
++opt_cr=
++case $build_os in
++mingw*)
++  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
++  ;;
++esac
++
++# Try without a prefix underscore, then with it.
++for ac_symprfx in "" "_"; do
++
++  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
++  symxfrm="\\1 $ac_symprfx\\2 \\2"
++
++  # Write the raw and C identifiers.
++  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++    # Fake it for dumpbin and say T for any non-static function,
++    # D for any global variable and I for any imported variable.
++    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
++    # which start with @ or ?.
++    lt_cv_sys_global_symbol_pipe="$AWK '"\
++"     {last_section=section; section=\$ 3};"\
++"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
++"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
++"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
++"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
++"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
++"     \$ 0!~/External *\|/{next};"\
++"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
++"     {if(hide[section]) next};"\
++"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
++"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
++"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
++"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
++"     ' prfx=^$ac_symprfx"
++  else
++    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
++  fi
++  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
++
++  # Check to see that the pipe works correctly.
++  pipe_works=no
++
++  rm -f conftest*
++  cat > conftest.$ac_ext <<_LT_EOF
++#ifdef __cplusplus
++extern "C" {
++#endif
++char nm_test_var;
++void nm_test_func(void);
++void nm_test_func(void){}
++#ifdef __cplusplus
++}
++#endif
++int main(){nm_test_var='a';nm_test_func();return(0);}
++_LT_EOF
++
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    # Now try to grab the symbols.
++    nlist=conftest.nm
++    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
++  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s "$nlist"; then
++      # Try sorting and uniquifying the output.
++      if sort "$nlist" | uniq > "$nlist"T; then
++	mv -f "$nlist"T "$nlist"
++      else
++	rm -f "$nlist"T
++      fi
++
++      # Make sure that we snagged all the symbols we need.
++      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
++	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
++	  cat <<_LT_EOF > conftest.$ac_ext
++/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
++#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
++/* DATA imports from DLLs on WIN32 can't be const, because runtime
++   relocations are performed -- see ld's documentation on pseudo-relocs.  */
++# define LT_DLSYM_CONST
++#elif defined __osf__
++/* This system does not cope well with relocations in const data.  */
++# define LT_DLSYM_CONST
++#else
++# define LT_DLSYM_CONST const
++#endif
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++_LT_EOF
++	  # Now generate the symbol file.
++	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
++
++	  cat <<_LT_EOF >> conftest.$ac_ext
++
++/* The mapping between symbol names and symbols.  */
++LT_DLSYM_CONST struct {
++  const char *name;
++  void       *address;
++}
++lt__PROGRAM__LTX_preloaded_symbols[] =
++{
++  { "@PROGRAM@", (void *) 0 },
++_LT_EOF
++	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
++	  cat <<\_LT_EOF >> conftest.$ac_ext
++  {0, (void *) 0}
++};
++
++/* This works around a problem in FreeBSD linker */
++#ifdef FREEBSD_WORKAROUND
++static const void *lt_preloaded_setup() {
++  return lt__PROGRAM__LTX_preloaded_symbols;
++}
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++_LT_EOF
++	  # Now try linking the two files.
++	  mv conftest.$ac_objext conftstm.$ac_objext
++	  lt_globsym_save_LIBS=$LIBS
++	  lt_globsym_save_CFLAGS=$CFLAGS
++	  LIBS=conftstm.$ac_objext
++	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
++	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
++  (eval $ac_link) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s conftest$ac_exeext; then
++	    pipe_works=yes
++	  fi
++	  LIBS=$lt_globsym_save_LIBS
++	  CFLAGS=$lt_globsym_save_CFLAGS
++	else
++	  echo "cannot find nm_test_func in $nlist" >&5
++	fi
++      else
++	echo "cannot find nm_test_var in $nlist" >&5
++      fi
++    else
++      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
++    fi
++  else
++    echo "$progname: failed program was:" >&5
++    cat conftest.$ac_ext >&5
++  fi
++  rm -rf conftest* conftst*
++
++  # Do not use the global_symbol_pipe unless it works.
++  if test yes = "$pipe_works"; then
++    break
++  else
++    lt_cv_sys_global_symbol_pipe=
++  fi
++done
++
++fi
++
++if test -z "$lt_cv_sys_global_symbol_pipe"; then
++  lt_cv_sys_global_symbol_to_cdecl=
++fi
++if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
++printf "%s\n" "failed" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5
++printf "%s\n" "ok" >&6; }
++fi
++
++# Response file support.
++if test "$lt_cv_nm_interface" = "MS dumpbin"; then
++  nm_file_list_spec='@'
++elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
++  nm_file_list_spec='@'
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
++printf %s "checking for sysroot... " >&6; }
++
++# Check whether --with-sysroot was given.
++if test ${with_sysroot+y}
++then :
++  withval=$with_sysroot;
++else $as_nop
++  with_sysroot=no
++fi
++
++
++lt_sysroot=
++case $with_sysroot in #(
++ yes)
++   if test yes = "$GCC"; then
++     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
++   fi
++   ;; #(
++ /*)
++   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
++   ;; #(
++ no|'')
++   ;; #(
++ *)
++   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
++printf "%s\n" "$with_sysroot" >&6; }
++   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
++   ;;
++esac
++
++ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
++printf "%s\n" "${lt_sysroot:-no}" >&6; }
++
++
++
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
++printf %s "checking for a working dd... " >&6; }
++if test ${ac_cv_path_lt_DD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  printf 0123456789abcdef0123456789abcdef >conftest.i
++cat conftest.i conftest.i >conftest2.i
++: ${lt_DD:=$DD}
++if test -z "$lt_DD"; then
++  ac_path_lt_DD_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_prog in dd
++   do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_lt_DD" || continue
++if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
++  cmp -s conftest.i conftest.out \
++  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
++fi
++      $ac_path_lt_DD_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_lt_DD"; then
++    :
++  fi
++else
++  ac_cv_path_lt_DD=$lt_DD
++fi
++
++rm -f conftest.i conftest2.i conftest.out
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
++printf "%s\n" "$ac_cv_path_lt_DD" >&6; }
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
++printf %s "checking how to truncate binary pipes... " >&6; }
++if test ${lt_cv_truncate_bin+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  printf 0123456789abcdef0123456789abcdef >conftest.i
++cat conftest.i conftest.i >conftest2.i
++lt_cv_truncate_bin=
++if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
++  cmp -s conftest.i conftest.out \
++  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
++fi
++rm -f conftest.i conftest2.i conftest.out
++test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
++printf "%s\n" "$lt_cv_truncate_bin" >&6; }
++
++
++
++
++
++
++
++# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
++func_cc_basename ()
++{
++    for cc_temp in $*""; do
++      case $cc_temp in
++        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
++        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
++        \-*) ;;
++        *) break;;
++      esac
++    done
++    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
++}
++
++# Check whether --enable-libtool-lock was given.
++if test ${enable_libtool_lock+y}
++then :
++  enableval=$enable_libtool_lock;
++fi
++
++test no = "$enable_libtool_lock" || enable_libtool_lock=yes
++
++# Some flags need to be propagated to the compiler or linker for good
++# libtool support.
++case $host in
++ia64-*-hpux*)
++  # Find out what ABI is being produced by ac_compile, and set mode
++  # options accordingly.
++  echo 'int i;' > conftest.$ac_ext
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    case `$FILECMD conftest.$ac_objext` in
++      *ELF-32*)
++	HPUX_IA64_MODE=32
++	;;
++      *ELF-64*)
++	HPUX_IA64_MODE=64
++	;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++*-*-irix6*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.
++  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    if test yes = "$lt_cv_prog_gnu_ld"; then
++      case `$FILECMD conftest.$ac_objext` in
++	*32-bit*)
++	  LD="${LD-ld} -melf32bsmip"
++	  ;;
++	*N32*)
++	  LD="${LD-ld} -melf32bmipn32"
++	  ;;
++	*64-bit*)
++	  LD="${LD-ld} -melf64bmip"
++	;;
++      esac
++    else
++      case `$FILECMD conftest.$ac_objext` in
++	*32-bit*)
++	  LD="${LD-ld} -32"
++	  ;;
++	*N32*)
++	  LD="${LD-ld} -n32"
++	  ;;
++	*64-bit*)
++	  LD="${LD-ld} -64"
++	  ;;
++      esac
++    fi
++  fi
++  rm -rf conftest*
++  ;;
++
++mips64*-*linux*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.
++  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    emul=elf
++    case `$FILECMD conftest.$ac_objext` in
++      *32-bit*)
++	emul="${emul}32"
++	;;
++      *64-bit*)
++	emul="${emul}64"
++	;;
++    esac
++    case `$FILECMD conftest.$ac_objext` in
++      *MSB*)
++	emul="${emul}btsmip"
++	;;
++      *LSB*)
++	emul="${emul}ltsmip"
++	;;
++    esac
++    case `$FILECMD conftest.$ac_objext` in
++      *N32*)
++	emul="${emul}n32"
++	;;
++    esac
++    LD="${LD-ld} -m $emul"
++  fi
++  rm -rf conftest*
++  ;;
++
++x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
++s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.  Note that the listed cases only cover the
++  # situations where additional linker options are needed (such as when
++  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
++  # vice versa); the common cases where no linker options are needed do
++  # not appear in the list.
++  echo 'int i;' > conftest.$ac_ext
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    case `$FILECMD conftest.o` in
++      *32-bit*)
++	case $host in
++	  x86_64-*kfreebsd*-gnu)
++	    LD="${LD-ld} -m elf_i386_fbsd"
++	    ;;
++	  x86_64-*linux*)
++	    case `$FILECMD conftest.o` in
++	      *x86-64*)
++		LD="${LD-ld} -m elf32_x86_64"
++		;;
++	      *)
++		LD="${LD-ld} -m elf_i386"
++		;;
++	    esac
++	    ;;
++	  powerpc64le-*linux*)
++	    LD="${LD-ld} -m elf32lppclinux"
++	    ;;
++	  powerpc64-*linux*)
++	    LD="${LD-ld} -m elf32ppclinux"
++	    ;;
++	  s390x-*linux*)
++	    LD="${LD-ld} -m elf_s390"
++	    ;;
++	  sparc64-*linux*)
++	    LD="${LD-ld} -m elf32_sparc"
++	    ;;
++	esac
++	;;
++      *64-bit*)
++	case $host in
++	  x86_64-*kfreebsd*-gnu)
++	    LD="${LD-ld} -m elf_x86_64_fbsd"
++	    ;;
++	  x86_64-*linux*)
++	    LD="${LD-ld} -m elf_x86_64"
++	    ;;
++	  powerpcle-*linux*)
++	    LD="${LD-ld} -m elf64lppc"
++	    ;;
++	  powerpc-*linux*)
++	    LD="${LD-ld} -m elf64ppc"
++	    ;;
++	  s390*-*linux*|s390*-*tpf*)
++	    LD="${LD-ld} -m elf64_s390"
++	    ;;
++	  sparc*-*linux*)
++	    LD="${LD-ld} -m elf64_sparc"
++	    ;;
++	esac
++	;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++
++*-*-sco3.2v5*)
++  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
++  SAVE_CFLAGS=$CFLAGS
++  CFLAGS="$CFLAGS -belf"
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
++printf %s "checking whether the C compiler needs -belf... " >&6; }
++if test ${lt_cv_cc_needs_belf+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  lt_cv_cc_needs_belf=yes
++else $as_nop
++  lt_cv_cc_needs_belf=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++     ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
++printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
++  if test yes != "$lt_cv_cc_needs_belf"; then
++    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
++    CFLAGS=$SAVE_CFLAGS
++  fi
++  ;;
++*-*solaris*)
++  # Find out what ABI is being produced by ac_compile, and set linker
++  # options accordingly.
++  echo 'int i;' > conftest.$ac_ext
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++    case `$FILECMD conftest.o` in
++    *64-bit*)
++      case $lt_cv_prog_gnu_ld in
++      yes*)
++        case $host in
++        i?86-*-solaris*|x86_64-*-solaris*)
++          LD="${LD-ld} -m elf_x86_64"
++          ;;
++        sparc*-*-solaris*)
++          LD="${LD-ld} -m elf64_sparc"
++          ;;
++        esac
++        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
++        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
++          LD=${LD-ld}_sol2
++        fi
++        ;;
++      *)
++	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
++	  LD="${LD-ld} -64"
++	fi
++	;;
++      esac
++      ;;
++    esac
++  fi
++  rm -rf conftest*
++  ;;
++esac
++
++need_locks=$enable_libtool_lock
++
++if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
++set dummy ${ac_tool_prefix}mt; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_MANIFEST_TOOL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$MANIFEST_TOOL"; then
++  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
++if test -n "$MANIFEST_TOOL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
++printf "%s\n" "$MANIFEST_TOOL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
++  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
++  # Extract the first word of "mt", so it can be a program name with args.
++set dummy mt; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_MANIFEST_TOOL"; then
++  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
++if test -n "$ac_ct_MANIFEST_TOOL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
++printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_MANIFEST_TOOL" = x; then
++    MANIFEST_TOOL=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
++  fi
++else
++  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
++fi
++
++test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
++printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
++if test ${lt_cv_path_mainfest_tool+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_path_mainfest_tool=no
++  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
++  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
++  cat conftest.err >&5
++  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
++    lt_cv_path_mainfest_tool=yes
++  fi
++  rm -f conftest*
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
++printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; }
++if test yes != "$lt_cv_path_mainfest_tool"; then
++  MANIFEST_TOOL=:
++fi
++
++
++
++
++
++
++  case $host_os in
++    rhapsody* | darwin*)
++    if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
++set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_DSYMUTIL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$DSYMUTIL"; then
++  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++DSYMUTIL=$ac_cv_prog_DSYMUTIL
++if test -n "$DSYMUTIL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
++printf "%s\n" "$DSYMUTIL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_DSYMUTIL"; then
++  ac_ct_DSYMUTIL=$DSYMUTIL
++  # Extract the first word of "dsymutil", so it can be a program name with args.
++set dummy dsymutil; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_DSYMUTIL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_DSYMUTIL"; then
++  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
++if test -n "$ac_ct_DSYMUTIL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
++printf "%s\n" "$ac_ct_DSYMUTIL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_DSYMUTIL" = x; then
++    DSYMUTIL=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    DSYMUTIL=$ac_ct_DSYMUTIL
++  fi
++else
++  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
++fi
++
++    if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
++set dummy ${ac_tool_prefix}nmedit; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_NMEDIT+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$NMEDIT"; then
++  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++NMEDIT=$ac_cv_prog_NMEDIT
++if test -n "$NMEDIT"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
++printf "%s\n" "$NMEDIT" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_NMEDIT"; then
++  ac_ct_NMEDIT=$NMEDIT
++  # Extract the first word of "nmedit", so it can be a program name with args.
++set dummy nmedit; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_NMEDIT+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_NMEDIT"; then
++  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_NMEDIT="nmedit"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
++if test -n "$ac_ct_NMEDIT"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
++printf "%s\n" "$ac_ct_NMEDIT" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_NMEDIT" = x; then
++    NMEDIT=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    NMEDIT=$ac_ct_NMEDIT
++  fi
++else
++  NMEDIT="$ac_cv_prog_NMEDIT"
++fi
++
++    if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
++set dummy ${ac_tool_prefix}lipo; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_LIPO+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$LIPO"; then
++  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++LIPO=$ac_cv_prog_LIPO
++if test -n "$LIPO"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
++printf "%s\n" "$LIPO" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_LIPO"; then
++  ac_ct_LIPO=$LIPO
++  # Extract the first word of "lipo", so it can be a program name with args.
++set dummy lipo; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_LIPO+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_LIPO"; then
++  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_LIPO="lipo"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
++if test -n "$ac_ct_LIPO"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
++printf "%s\n" "$ac_ct_LIPO" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_LIPO" = x; then
++    LIPO=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    LIPO=$ac_ct_LIPO
++  fi
++else
++  LIPO="$ac_cv_prog_LIPO"
++fi
++
++    if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
++set dummy ${ac_tool_prefix}otool; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_OTOOL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$OTOOL"; then
++  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++OTOOL=$ac_cv_prog_OTOOL
++if test -n "$OTOOL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
++printf "%s\n" "$OTOOL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_OTOOL"; then
++  ac_ct_OTOOL=$OTOOL
++  # Extract the first word of "otool", so it can be a program name with args.
++set dummy otool; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_OTOOL+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_OTOOL"; then
++  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_OTOOL="otool"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
++if test -n "$ac_ct_OTOOL"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
++printf "%s\n" "$ac_ct_OTOOL" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_OTOOL" = x; then
++    OTOOL=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    OTOOL=$ac_ct_OTOOL
++  fi
++else
++  OTOOL="$ac_cv_prog_OTOOL"
++fi
++
++    if test -n "$ac_tool_prefix"; then
++  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
++set dummy ${ac_tool_prefix}otool64; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_OTOOL64+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$OTOOL64"; then
++  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++OTOOL64=$ac_cv_prog_OTOOL64
++if test -n "$OTOOL64"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
++printf "%s\n" "$OTOOL64" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++fi
++if test -z "$ac_cv_prog_OTOOL64"; then
++  ac_ct_OTOOL64=$OTOOL64
++  # Extract the first word of "otool64", so it can be a program name with args.
++set dummy otool64; ac_word=$2
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++printf %s "checking for $ac_word... " >&6; }
++if test ${ac_cv_prog_ac_ct_OTOOL64+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -n "$ac_ct_OTOOL64"; then
++  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_OTOOL64="otool64"
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
++if test -n "$ac_ct_OTOOL64"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
++printf "%s\n" "$ac_ct_OTOOL64" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++  if test "x$ac_ct_OTOOL64" = x; then
++    OTOOL64=":"
++  else
++    case $cross_compiling:$ac_tool_warned in
++yes:)
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++ac_tool_warned=yes ;;
++esac
++    OTOOL64=$ac_ct_OTOOL64
++  fi
++else
++  OTOOL64="$ac_cv_prog_OTOOL64"
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
++printf %s "checking for -single_module linker flag... " >&6; }
++if test ${lt_cv_apple_cc_single_mod+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_apple_cc_single_mod=no
++      if test -z "$LT_MULTI_MODULE"; then
++	# By default we will add the -single_module flag. You can override
++	# by either setting the environment variable LT_MULTI_MODULE
++	# non-empty at configure time, or by adding -multi_module to the
++	# link flags.
++	rm -rf libconftest.dylib*
++	echo "int foo(void){return 1;}" > conftest.c
++	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
++-dynamiclib -Wl,-single_module conftest.c" >&5
++	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
++	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
++        _lt_result=$?
++	# If there is a non-empty error log, and "single_module"
++	# appears in it, assume the flag caused a linker warning
++        if test -s conftest.err && $GREP single_module conftest.err; then
++	  cat conftest.err >&5
++	# Otherwise, if the output was created with a 0 exit code from
++	# the compiler, it worked.
++	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
++	  lt_cv_apple_cc_single_mod=yes
++	else
++	  cat conftest.err >&5
++	fi
++	rm -rf libconftest.dylib*
++	rm -f conftest.*
++      fi
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
++printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; }
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
++printf %s "checking for -exported_symbols_list linker flag... " >&6; }
++if test ${lt_cv_ld_exported_symbols_list+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_ld_exported_symbols_list=no
++      save_LDFLAGS=$LDFLAGS
++      echo "_main" > conftest.sym
++      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
++      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  lt_cv_ld_exported_symbols_list=yes
++else $as_nop
++  lt_cv_ld_exported_symbols_list=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++	LDFLAGS=$save_LDFLAGS
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
++printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; }
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
++printf %s "checking for -force_load linker flag... " >&6; }
++if test ${lt_cv_ld_force_load+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_ld_force_load=no
++      cat > conftest.c << _LT_EOF
++int forced_loaded() { return 2;}
++_LT_EOF
++      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
++      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
++      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
++      $AR $AR_FLAGS libconftest.a conftest.o 2>&5
++      echo "$RANLIB libconftest.a" >&5
++      $RANLIB libconftest.a 2>&5
++      cat > conftest.c << _LT_EOF
++int main() { return 0;}
++_LT_EOF
++      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
++      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
++      _lt_result=$?
++      if test -s conftest.err && $GREP force_load conftest.err; then
++	cat conftest.err >&5
++      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
++	lt_cv_ld_force_load=yes
++      else
++	cat conftest.err >&5
++      fi
++        rm -f conftest.err libconftest.a conftest conftest.c
++        rm -rf conftest.dSYM
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
++printf "%s\n" "$lt_cv_ld_force_load" >&6; }
++    case $host_os in
++    rhapsody* | darwin1.[012])
++      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
++    darwin1.*)
++      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
++    darwin*)
++      case $MACOSX_DEPLOYMENT_TARGET,$host in
++        10.[012],*|,*powerpc*-darwin[5-8]*)
++          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
++        *)
++          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
++      esac
++    ;;
++  esac
++    if test yes = "$lt_cv_apple_cc_single_mod"; then
++      _lt_dar_single_mod='$single_module'
++    fi
++    if test yes = "$lt_cv_ld_exported_symbols_list"; then
++      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
++    else
++      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
++    fi
++    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
++      _lt_dsymutil='~$DSYMUTIL $lib || :'
++    else
++      _lt_dsymutil=
++    fi
++    ;;
++  esac
++
++# func_munge_path_list VARIABLE PATH
++# -----------------------------------
++# VARIABLE is name of variable containing _space_ separated list of
++# directories to be munged by the contents of PATH, which is string
++# having a format:
++# "DIR[:DIR]:"
++#       string "DIR[ DIR]" will be prepended to VARIABLE
++# ":DIR[:DIR]"
++#       string "DIR[ DIR]" will be appended to VARIABLE
++# "DIRP[:DIRP]::[DIRA:]DIRA"
++#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
++#       "DIRA[ DIRA]" will be appended to VARIABLE
++# "DIR[:DIR]"
++#       VARIABLE will be replaced by "DIR[ DIR]"
++func_munge_path_list ()
++{
++    case x$2 in
++    x)
++        ;;
++    *:)
++        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
++        ;;
++    x:*)
++        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
++        ;;
++    *::*)
++        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
++        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
++        ;;
++    *)
++        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
++        ;;
++    esac
++}
++
++ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
++"
++if test "x$ac_cv_header_dlfcn_h" = xyes
++then :
++  printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
++
++fi
++
++
++
++
++func_stripname_cnf ()
++{
++  case $2 in
++  .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;;
++  *)  func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;;
++  esac
++} # func_stripname_cnf
++
++
++
++
++
++# Set options
++
++
++
++        enable_dlopen=no
++
++
++  enable_win32_dll=no
++
++
++            # Check whether --enable-shared was given.
++if test ${enable_shared+y}
++then :
++  enableval=$enable_shared; p=${PACKAGE-default}
++    case $enableval in
++    yes) enable_shared=yes ;;
++    no) enable_shared=no ;;
++    *)
++      enable_shared=no
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for pkg in $enableval; do
++	IFS=$lt_save_ifs
++	if test "X$pkg" = "X$p"; then
++	  enable_shared=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac
++else $as_nop
++  enable_shared=yes
++fi
++
++
++
++
++
++
++
++
++
++  # Check whether --enable-static was given.
++if test ${enable_static+y}
++then :
++  enableval=$enable_static; p=${PACKAGE-default}
++    case $enableval in
++    yes) enable_static=yes ;;
++    no) enable_static=no ;;
++    *)
++     enable_static=no
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for pkg in $enableval; do
++	IFS=$lt_save_ifs
++	if test "X$pkg" = "X$p"; then
++	  enable_static=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac
++else $as_nop
++  enable_static=yes
++fi
++
++
++
++
++
++
++
++
++
++
++# Check whether --with-pic was given.
++if test ${with_pic+y}
++then :
++  withval=$with_pic; lt_p=${PACKAGE-default}
++    case $withval in
++    yes|no) pic_mode=$withval ;;
++    *)
++      pic_mode=default
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for lt_pkg in $withval; do
++	IFS=$lt_save_ifs
++	if test "X$lt_pkg" = "X$lt_p"; then
++	  pic_mode=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac
++else $as_nop
++  pic_mode=default
++fi
++
++
++
++
++
++
++
++
++  # Check whether --enable-fast-install was given.
++if test ${enable_fast_install+y}
++then :
++  enableval=$enable_fast_install; p=${PACKAGE-default}
++    case $enableval in
++    yes) enable_fast_install=yes ;;
++    no) enable_fast_install=no ;;
++    *)
++      enable_fast_install=no
++      # Look at the argument we got.  We use all the common list separators.
++      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      for pkg in $enableval; do
++	IFS=$lt_save_ifs
++	if test "X$pkg" = "X$p"; then
++	  enable_fast_install=yes
++	fi
++      done
++      IFS=$lt_save_ifs
++      ;;
++    esac
++else $as_nop
++  enable_fast_install=yes
++fi
++
++
++
++
++
++
++
++
++  shared_archive_member_spec=
++case $host,$enable_shared in
++power*-*-aix[5-9]*,yes)
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
++printf %s "checking which variant of shared library versioning to provide... " >&6; }
++
++# Check whether --with-aix-soname was given.
++if test ${with_aix_soname+y}
++then :
++  withval=$with_aix_soname; case $withval in
++    aix|svr4|both)
++      ;;
++    *)
++      as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
++      ;;
++    esac
++    lt_cv_with_aix_soname=$with_aix_soname
++else $as_nop
++  if test ${lt_cv_with_aix_soname+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_with_aix_soname=aix
++fi
++
++    with_aix_soname=$lt_cv_with_aix_soname
++fi
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
++printf "%s\n" "$with_aix_soname" >&6; }
++  if test aix != "$with_aix_soname"; then
++    # For the AIX way of multilib, we name the shared archive member
++    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
++    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
++    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
++    # the AIX toolchain works better with OBJECT_MODE set (default 32).
++    if test 64 = "${OBJECT_MODE-32}"; then
++      shared_archive_member_spec=shr_64
++    else
++      shared_archive_member_spec=shr
++    fi
++  fi
++  ;;
++*)
++  with_aix_soname=aix
++  ;;
++esac
++
++
++
++
++
++
++
++
++
++
++# This can be used to rebuild libtool when needed
++LIBTOOL_DEPS=$ltmain
++
++# Always use our own libtool.
++LIBTOOL='$(SHELL) $(top_builddir)/libtool'
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++test -z "$LN_S" && LN_S="ln -s"
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++if test -n "${ZSH_VERSION+set}"; then
++   setopt NO_GLOB_SUBST
++fi
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
++printf %s "checking for objdir... " >&6; }
++if test ${lt_cv_objdir+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  rm -f .libs 2>/dev/null
++mkdir .libs 2>/dev/null
++if test -d .libs; then
++  lt_cv_objdir=.libs
++else
++  # MS-DOS does not allow filenames that begin with a dot.
++  lt_cv_objdir=_libs
++fi
++rmdir .libs 2>/dev/null
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
++printf "%s\n" "$lt_cv_objdir" >&6; }
++objdir=$lt_cv_objdir
++
++
++
++
++
++printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h
++
++
++
++
++case $host_os in
++aix3*)
++  # AIX sometimes has problems with the GCC collect2 program.  For some
++  # reason, if we set the COLLECT_NAMES environment variable, the problems
++  # vanish in a puff of smoke.
++  if test set != "${COLLECT_NAMES+set}"; then
++    COLLECT_NAMES=
++    export COLLECT_NAMES
++  fi
++  ;;
++esac
++
++# Global variables:
++ofile=libtool
++can_build_shared=yes
++
++# All known linkers require a '.a' archive for static linking (except MSVC and
++# ICC, which need '.lib').
++libext=a
++
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++old_CC=$CC
++old_CFLAGS=$CFLAGS
++
++# Set sane defaults for various variables
++test -z "$CC" && CC=cc
++test -z "$LTCC" && LTCC=$CC
++test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
++test -z "$LD" && LD=ld
++test -z "$ac_objext" && ac_objext=o
++
++func_cc_basename $compiler
++cc_basename=$func_cc_basename_result
++
++
++# Only perform the check for file, if the check method requires it
++test -z "$MAGIC_CMD" && MAGIC_CMD=file
++case $deplibs_check_method in
++file_magic*)
++  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
++printf %s "checking for ${ac_tool_prefix}file... " >&6; }
++if test ${lt_cv_path_MAGIC_CMD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  case $MAGIC_CMD in
++[\\/*] |  ?:[\\/]*)
++  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
++  ;;
++*)
++  lt_save_MAGIC_CMD=$MAGIC_CMD
++  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
++  for ac_dir in $ac_dummy; do
++    IFS=$lt_save_ifs
++    test -z "$ac_dir" && ac_dir=.
++    if test -f "$ac_dir/${ac_tool_prefix}file"; then
++      lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
++      if test -n "$file_magic_test_file"; then
++	case $deplibs_check_method in
++	"file_magic "*)
++	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
++	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
++	    $EGREP "$file_magic_regex" > /dev/null; then
++	    :
++	  else
++	    cat <<_LT_EOF 1>&2
++
++*** Warning: the command libtool uses to detect shared libraries,
++*** $file_magic_cmd, produces output that libtool cannot recognize.
++*** The result is that libtool may fail to recognize shared libraries
++*** as such.  This will affect the creation of libtool libraries that
++*** depend on shared libraries, but programs linked with such libtool
++*** libraries will work regardless of this problem.  Nevertheless, you
++*** may want to report the problem to your system manager and/or to
++*** bug-libtool@gnu.org
++
++_LT_EOF
++	  fi ;;
++	esac
++      fi
++      break
++    fi
++  done
++  IFS=$lt_save_ifs
++  MAGIC_CMD=$lt_save_MAGIC_CMD
++  ;;
++esac
++fi
++
++MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++if test -n "$MAGIC_CMD"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
++printf "%s\n" "$MAGIC_CMD" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++
++
++
++if test -z "$lt_cv_path_MAGIC_CMD"; then
++  if test -n "$ac_tool_prefix"; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5
++printf %s "checking for file... " >&6; }
++if test ${lt_cv_path_MAGIC_CMD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  case $MAGIC_CMD in
++[\\/*] |  ?:[\\/]*)
++  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
++  ;;
++*)
++  lt_save_MAGIC_CMD=$MAGIC_CMD
++  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
++  for ac_dir in $ac_dummy; do
++    IFS=$lt_save_ifs
++    test -z "$ac_dir" && ac_dir=.
++    if test -f "$ac_dir/file"; then
++      lt_cv_path_MAGIC_CMD=$ac_dir/"file"
++      if test -n "$file_magic_test_file"; then
++	case $deplibs_check_method in
++	"file_magic "*)
++	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
++	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
++	    $EGREP "$file_magic_regex" > /dev/null; then
++	    :
++	  else
++	    cat <<_LT_EOF 1>&2
++
++*** Warning: the command libtool uses to detect shared libraries,
++*** $file_magic_cmd, produces output that libtool cannot recognize.
++*** The result is that libtool may fail to recognize shared libraries
++*** as such.  This will affect the creation of libtool libraries that
++*** depend on shared libraries, but programs linked with such libtool
++*** libraries will work regardless of this problem.  Nevertheless, you
++*** may want to report the problem to your system manager and/or to
++*** bug-libtool@gnu.org
++
++_LT_EOF
++	  fi ;;
++	esac
++      fi
++      break
++    fi
++  done
++  IFS=$lt_save_ifs
++  MAGIC_CMD=$lt_save_MAGIC_CMD
++  ;;
++esac
++fi
++
++MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++if test -n "$MAGIC_CMD"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
++printf "%s\n" "$MAGIC_CMD" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++
++
++  else
++    MAGIC_CMD=:
++  fi
++fi
++
++  fi
++  ;;
++esac
++
++# Use C for the default configuration in the libtool script
++
++lt_save_CC=$CC
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++# Source file extension for C test sources.
++ac_ext=c
++
++# Object file extension for compiled C test sources.
++objext=o
++objext=$objext
++
++# Code to be used in simple compile tests
++lt_simple_compile_test_code="int some_variable = 0;"
++
++# Code to be used in simple link tests
++lt_simple_link_test_code='int main(){return(0);}'
++
++
++
++
++
++
++
++# If no C compiler was specified, use CC.
++LTCC=${LTCC-"$CC"}
++
++# If no C compiler flags were specified, use CFLAGS.
++LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
++
++# Allow CC to be a program name with arguments.
++compiler=$CC
++
++# Save the default compiler, since it gets overwritten when the other
++# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
++compiler_DEFAULT=$CC
++
++# save warnings/boilerplate of simple test code
++ac_outfile=conftest.$ac_objext
++echo "$lt_simple_compile_test_code" >conftest.$ac_ext
++eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_compiler_boilerplate=`cat conftest.err`
++$RM conftest*
++
++ac_outfile=conftest.$ac_objext
++echo "$lt_simple_link_test_code" >conftest.$ac_ext
++eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_linker_boilerplate=`cat conftest.err`
++$RM -r conftest*
++
++
++if test -n "$compiler"; then
++
++lt_prog_compiler_no_builtin_flag=
++
++if test yes = "$GCC"; then
++  case $cc_basename in
++  nvcc*)
++    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
++  *)
++    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
++  esac
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
++printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
++if test ${lt_cv_prog_compiler_rtti_exceptions+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_rtti_exceptions=no
++   ac_outfile=conftest.$ac_objext
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++   lt_compiler_flag="-fno-rtti -fno-exceptions"  ## exclude from sc_useless_quotes_in_assignment
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   # The option is referenced via a variable to avoid confusing sed.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>conftest.err)
++   ac_status=$?
++   cat conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s "$ac_outfile"; then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings other than the usual output.
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
++     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_rtti_exceptions=yes
++     fi
++   fi
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
++printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
++
++if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
++    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
++else
++    :
++fi
++
++fi
++
++
++
++
++
++
++  lt_prog_compiler_wl=
++lt_prog_compiler_pic=
++lt_prog_compiler_static=
++
++
++  if test yes = "$GCC"; then
++    lt_prog_compiler_wl='-Wl,'
++    lt_prog_compiler_static='-static'
++
++    case $host_os in
++      aix*)
++      # All AIX code is PIC.
++      if test ia64 = "$host_cpu"; then
++	# AIX 5 now supports IA64 processor
++	lt_prog_compiler_static='-Bstatic'
++      fi
++      lt_prog_compiler_pic='-fPIC'
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            lt_prog_compiler_pic='-fPIC'
++        ;;
++      m68k)
++            # FIXME: we need at least 68020 code to build shared libraries, but
++            # adding the '-m68020' flag to GCC prevents building anything better,
++            # like '-m68040'.
++            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
++        ;;
++      esac
++      ;;
++
++    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++      # PIC is the default for these OSes.
++      ;;
++
++    mingw* | cygwin* | pw32* | os2* | cegcc*)
++      # This hack is so that the source file can tell whether it is being
++      # built for inclusion in a dll (and should export symbols for example).
++      # Although the cygwin gcc ignores -fPIC, still need this for old-style
++      # (--disable-auto-import) libraries
++      lt_prog_compiler_pic='-DDLL_EXPORT'
++      case $host_os in
++      os2*)
++	lt_prog_compiler_static='$wl-static'
++	;;
++      esac
++      ;;
++
++    darwin* | rhapsody*)
++      # PIC is the default on this platform
++      # Common symbols not allowed in MH_DYLIB files
++      lt_prog_compiler_pic='-fno-common'
++      ;;
++
++    haiku*)
++      # PIC is the default for Haiku.
++      # The "-static" flag exists, but is broken.
++      lt_prog_compiler_static=
++      ;;
++
++    hpux*)
++      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
++      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
++      # sets the default TLS model and affects inlining.
++      case $host_cpu in
++      hppa*64*)
++	# +Z the default
++	;;
++      *)
++	lt_prog_compiler_pic='-fPIC'
++	;;
++      esac
++      ;;
++
++    interix[3-9]*)
++      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
++      # Instead, we relocate shared libraries at runtime.
++      ;;
++
++    msdosdjgpp*)
++      # Just because we use GCC doesn't mean we suddenly get shared libraries
++      # on systems that don't support them.
++      lt_prog_compiler_can_build_shared=no
++      enable_shared=no
++      ;;
++
++    *nto* | *qnx*)
++      # QNX uses GNU C++, but need to define -shared option too, otherwise
++      # it will coredump.
++      lt_prog_compiler_pic='-fPIC -shared'
++      ;;
++
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	lt_prog_compiler_pic=-Kconform_pic
++      fi
++      ;;
++
++    *)
++      lt_prog_compiler_pic='-fPIC'
++      ;;
++    esac
++
++    case $cc_basename in
++    nvcc*) # Cuda Compiler Driver 2.2
++      lt_prog_compiler_wl='-Xlinker '
++      if test -n "$lt_prog_compiler_pic"; then
++        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
++      fi
++      ;;
++    esac
++  else
++    # PORTME Check for flag to pass linker flags through the system compiler.
++    case $host_os in
++    aix*)
++      lt_prog_compiler_wl='-Wl,'
++      if test ia64 = "$host_cpu"; then
++	# AIX 5 now supports IA64 processor
++	lt_prog_compiler_static='-Bstatic'
++      else
++	lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
++      fi
++      ;;
++
++    darwin* | rhapsody*)
++      # PIC is the default on this platform
++      # Common symbols not allowed in MH_DYLIB files
++      lt_prog_compiler_pic='-fno-common'
++      case $cc_basename in
++      nagfor*)
++        # NAG Fortran compiler
++        lt_prog_compiler_wl='-Wl,-Wl,,'
++        lt_prog_compiler_pic='-PIC'
++        lt_prog_compiler_static='-Bstatic'
++        ;;
++      esac
++      ;;
++
++    mingw* | cygwin* | pw32* | os2* | cegcc*)
++      # This hack is so that the source file can tell whether it is being
++      # built for inclusion in a dll (and should export symbols for example).
++      lt_prog_compiler_pic='-DDLL_EXPORT'
++      case $host_os in
++      os2*)
++	lt_prog_compiler_static='$wl-static'
++	;;
++      esac
++      ;;
++
++    hpux9* | hpux10* | hpux11*)
++      lt_prog_compiler_wl='-Wl,'
++      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
++      # not for PA HP-UX.
++      case $host_cpu in
++      hppa*64*|ia64*)
++	# +Z the default
++	;;
++      *)
++	lt_prog_compiler_pic='+Z'
++	;;
++      esac
++      # Is there a better lt_prog_compiler_static that works with the bundled CC?
++      lt_prog_compiler_static='$wl-a ${wl}archive'
++      ;;
++
++    irix5* | irix6* | nonstopux*)
++      lt_prog_compiler_wl='-Wl,'
++      # PIC (with -KPIC) is the default.
++      lt_prog_compiler_static='-non_shared'
++      ;;
++
++    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++      case $cc_basename in
++      # old Intel for x86_64, which still supported -KPIC.
++      ecc*)
++	lt_prog_compiler_wl='-Wl,'
++	lt_prog_compiler_pic='-KPIC'
++	lt_prog_compiler_static='-static'
++        ;;
++      # icc used to be incompatible with GCC.
++      # ICC 10 doesn't accept -KPIC any more.
++      icc* | ifort*)
++	lt_prog_compiler_wl='-Wl,'
++	lt_prog_compiler_pic='-fPIC'
++	lt_prog_compiler_static='-static'
++        ;;
++      # Lahey Fortran 8.1.
++      lf95*)
++	lt_prog_compiler_wl='-Wl,'
++	lt_prog_compiler_pic='--shared'
++	lt_prog_compiler_static='--static'
++	;;
++      nagfor*)
++	# NAG Fortran compiler
++	lt_prog_compiler_wl='-Wl,-Wl,,'
++	lt_prog_compiler_pic='-PIC'
++	lt_prog_compiler_static='-Bstatic'
++	;;
++      tcc*)
++	# Fabrice Bellard et al's Tiny C Compiler
++	lt_prog_compiler_wl='-Wl,'
++	lt_prog_compiler_pic='-fPIC'
++	lt_prog_compiler_static='-static'
++	;;
++      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
++        # Portland Group compilers (*not* the Pentium gcc compiler,
++	# which looks to be a dead project)
++	lt_prog_compiler_wl='-Wl,'
++	lt_prog_compiler_pic='-fpic'
++	lt_prog_compiler_static='-Bstatic'
++        ;;
++      ccc*)
++        lt_prog_compiler_wl='-Wl,'
++        # All Alpha code is PIC.
++        lt_prog_compiler_static='-non_shared'
++        ;;
++      xl* | bgxl* | bgf* | mpixl*)
++	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
++	lt_prog_compiler_wl='-Wl,'
++	lt_prog_compiler_pic='-qpic'
++	lt_prog_compiler_static='-qstaticlink'
++	;;
++      *)
++	case `$CC -V 2>&1 | $SED 5q` in
++	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
++	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
++	  lt_prog_compiler_pic='-KPIC'
++	  lt_prog_compiler_static='-Bstatic'
++	  lt_prog_compiler_wl=''
++	  ;;
++	*Sun\ F* | *Sun*Fortran*)
++	  lt_prog_compiler_pic='-KPIC'
++	  lt_prog_compiler_static='-Bstatic'
++	  lt_prog_compiler_wl='-Qoption ld '
++	  ;;
++	*Sun\ C*)
++	  # Sun C 5.9
++	  lt_prog_compiler_pic='-KPIC'
++	  lt_prog_compiler_static='-Bstatic'
++	  lt_prog_compiler_wl='-Wl,'
++	  ;;
++        *Intel*\ [CF]*Compiler*)
++	  lt_prog_compiler_wl='-Wl,'
++	  lt_prog_compiler_pic='-fPIC'
++	  lt_prog_compiler_static='-static'
++	  ;;
++	*Portland\ Group*)
++	  lt_prog_compiler_wl='-Wl,'
++	  lt_prog_compiler_pic='-fpic'
++	  lt_prog_compiler_static='-Bstatic'
++	  ;;
++	esac
++	;;
++      esac
++      ;;
++
++    newsos6)
++      lt_prog_compiler_pic='-KPIC'
++      lt_prog_compiler_static='-Bstatic'
++      ;;
++
++    *nto* | *qnx*)
++      # QNX uses GNU C++, but need to define -shared option too, otherwise
++      # it will coredump.
++      lt_prog_compiler_pic='-fPIC -shared'
++      ;;
++
++    osf3* | osf4* | osf5*)
++      lt_prog_compiler_wl='-Wl,'
++      # All OSF/1 code is PIC.
++      lt_prog_compiler_static='-non_shared'
++      ;;
++
++    rdos*)
++      lt_prog_compiler_static='-non_shared'
++      ;;
++
++    solaris*)
++      lt_prog_compiler_pic='-KPIC'
++      lt_prog_compiler_static='-Bstatic'
++      case $cc_basename in
++      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
++	lt_prog_compiler_wl='-Qoption ld ';;
++      *)
++	lt_prog_compiler_wl='-Wl,';;
++      esac
++      ;;
++
++    sunos4*)
++      lt_prog_compiler_wl='-Qoption ld '
++      lt_prog_compiler_pic='-PIC'
++      lt_prog_compiler_static='-Bstatic'
++      ;;
++
++    sysv4 | sysv4.2uw2* | sysv4.3*)
++      lt_prog_compiler_wl='-Wl,'
++      lt_prog_compiler_pic='-KPIC'
++      lt_prog_compiler_static='-Bstatic'
++      ;;
++
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	lt_prog_compiler_pic='-Kconform_pic'
++	lt_prog_compiler_static='-Bstatic'
++      fi
++      ;;
++
++    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
++      lt_prog_compiler_wl='-Wl,'
++      lt_prog_compiler_pic='-KPIC'
++      lt_prog_compiler_static='-Bstatic'
++      ;;
++
++    unicos*)
++      lt_prog_compiler_wl='-Wl,'
++      lt_prog_compiler_can_build_shared=no
++      ;;
++
++    uts4*)
++      lt_prog_compiler_pic='-pic'
++      lt_prog_compiler_static='-Bstatic'
++      ;;
++
++    *)
++      lt_prog_compiler_can_build_shared=no
++      ;;
++    esac
++  fi
++
++case $host_os in
++  # For platforms that do not support PIC, -DPIC is meaningless:
++  *djgpp*)
++    lt_prog_compiler_pic=
++    ;;
++  *)
++    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
++    ;;
++esac
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
++printf %s "checking for $compiler option to produce PIC... " >&6; }
++if test ${lt_cv_prog_compiler_pic+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
++printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
++lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
++
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$lt_prog_compiler_pic"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
++printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
++if test ${lt_cv_prog_compiler_pic_works+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_pic_works=no
++   ac_outfile=conftest.$ac_objext
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"  ## exclude from sc_useless_quotes_in_assignment
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   # The option is referenced via a variable to avoid confusing sed.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>conftest.err)
++   ac_status=$?
++   cat conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s "$ac_outfile"; then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings other than the usual output.
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
++     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_pic_works=yes
++     fi
++   fi
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
++printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
++
++if test yes = "$lt_cv_prog_compiler_pic_works"; then
++    case $lt_prog_compiler_pic in
++     "" | " "*) ;;
++     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
++     esac
++else
++    lt_prog_compiler_pic=
++     lt_prog_compiler_can_build_shared=no
++fi
++
++fi
++
++
++
++
++
++
++
++
++
++
++
++#
++# Check to make sure the static flag actually works.
++#
++wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
++printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
++if test ${lt_cv_prog_compiler_static_works+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_static_works=no
++   save_LDFLAGS=$LDFLAGS
++   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
++   echo "$lt_simple_link_test_code" > conftest.$ac_ext
++   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
++     # The linker can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     if test -s conftest.err; then
++       # Append any errors to the config.log.
++       cat conftest.err 1>&5
++       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
++       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++       if diff conftest.exp conftest.er2 >/dev/null; then
++         lt_cv_prog_compiler_static_works=yes
++       fi
++     else
++       lt_cv_prog_compiler_static_works=yes
++     fi
++   fi
++   $RM -r conftest*
++   LDFLAGS=$save_LDFLAGS
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
++printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
++
++if test yes = "$lt_cv_prog_compiler_static_works"; then
++    :
++else
++    lt_prog_compiler_static=
++fi
++
++
++
++
++
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if test ${lt_cv_prog_compiler_c_o+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_c_o=no
++   $RM -r conftest 2>/dev/null
++   mkdir conftest
++   cd conftest
++   mkdir out
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++   lt_compiler_flag="-o out/conftest2.$ac_objext"
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>out/conftest.err)
++   ac_status=$?
++   cat out/conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s out/conftest2.$ac_objext
++   then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
++     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
++     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_c_o=yes
++     fi
++   fi
++   chmod u+w . 2>&5
++   $RM conftest*
++   # SGI C++ compiler will create directory out/ii_files/ for
++   # template instantiation
++   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
++   $RM out/* && rmdir out
++   cd ..
++   $RM -r conftest
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
++printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
++
++
++
++
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if test ${lt_cv_prog_compiler_c_o+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_c_o=no
++   $RM -r conftest 2>/dev/null
++   mkdir conftest
++   cd conftest
++   mkdir out
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++   lt_compiler_flag="-o out/conftest2.$ac_objext"
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>out/conftest.err)
++   ac_status=$?
++   cat out/conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s out/conftest2.$ac_objext
++   then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
++     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
++     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_c_o=yes
++     fi
++   fi
++   chmod u+w . 2>&5
++   $RM conftest*
++   # SGI C++ compiler will create directory out/ii_files/ for
++   # template instantiation
++   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
++   $RM out/* && rmdir out
++   cd ..
++   $RM -r conftest
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
++printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
++
++
++
++
++hard_links=nottested
++if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
++  # do not overwrite the value of need_locks provided by the user
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
++printf %s "checking if we can lock with hard links... " >&6; }
++  hard_links=yes
++  $RM conftest*
++  ln conftest.a conftest.b 2>/dev/null && hard_links=no
++  touch conftest.a
++  ln conftest.a conftest.b 2>&5 || hard_links=no
++  ln conftest.a conftest.b 2>/dev/null && hard_links=no
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
++printf "%s\n" "$hard_links" >&6; }
++  if test no = "$hard_links"; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
++printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
++    need_locks=warn
++  fi
++else
++  need_locks=no
++fi
++
++
++
++
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
++printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
++
++  runpath_var=
++  allow_undefined_flag=
++  always_export_symbols=no
++  archive_cmds=
++  archive_expsym_cmds=
++  compiler_needs_object=no
++  enable_shared_with_static_runtimes=no
++  export_dynamic_flag_spec=
++  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++  hardcode_automatic=no
++  hardcode_direct=no
++  hardcode_direct_absolute=no
++  hardcode_libdir_flag_spec=
++  hardcode_libdir_separator=
++  hardcode_minus_L=no
++  hardcode_shlibpath_var=unsupported
++  inherit_rpath=no
++  link_all_deplibs=unknown
++  module_cmds=
++  module_expsym_cmds=
++  old_archive_from_new_cmds=
++  old_archive_from_expsyms_cmds=
++  thread_safe_flag_spec=
++  whole_archive_flag_spec=
++  # include_expsyms should be a list of space-separated symbols to be *always*
++  # included in the symbol list
++  include_expsyms=
++  # exclude_expsyms can be an extended regexp of symbols to exclude
++  # it will be wrapped by ' (' and ')$', so one must not match beginning or
++  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
++  # as well as any symbol that contains 'd'.
++  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
++  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
++  # platforms (ab)use it in PIC code, but their linkers get confused if
++  # the symbol is explicitly referenced.  Since portable code cannot
++  # rely on this symbol name, it's probably fine to never include it in
++  # preloaded symbol tables.
++  # Exclude shared library initialization/finalization symbols.
++  extract_expsyms_cmds=
++
++  case $host_os in
++  cygwin* | mingw* | pw32* | cegcc*)
++    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
++    # When not using gcc, we currently assume that we are using
++    # Microsoft Visual C++ or Intel C++ Compiler.
++    if test yes != "$GCC"; then
++      with_gnu_ld=no
++    fi
++    ;;
++  interix*)
++    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
++    with_gnu_ld=yes
++    ;;
++  openbsd* | bitrig*)
++    with_gnu_ld=no
++    ;;
++  esac
++
++  ld_shlibs=yes
++
++  # On some targets, GNU ld is compatible enough with the native linker
++  # that we're better off using the native interface for both.
++  lt_use_gnu_ld_interface=no
++  if test yes = "$with_gnu_ld"; then
++    case $host_os in
++      aix*)
++	# The AIX port of GNU ld has always aspired to compatibility
++	# with the native linker.  However, as the warning in the GNU ld
++	# block says, versions before 2.19.5* couldn't really create working
++	# shared libraries, regardless of the interface used.
++	case `$LD -v 2>&1` in
++	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
++	  *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
++	  *\ \(GNU\ Binutils\)\ [3-9]*) ;;
++	  *)
++	    lt_use_gnu_ld_interface=yes
++	    ;;
++	esac
++	;;
++      *)
++	lt_use_gnu_ld_interface=yes
++	;;
++    esac
++  fi
++
++  if test yes = "$lt_use_gnu_ld_interface"; then
++    # If archive_cmds runs LD, not CC, wlarc should be empty
++    wlarc='$wl'
++
++    # Set some defaults for GNU ld with shared library support. These
++    # are reset later if shared libraries are not supported. Putting them
++    # here allows them to be overridden if necessary.
++    runpath_var=LD_RUN_PATH
++    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++    export_dynamic_flag_spec='$wl--export-dynamic'
++    # ancient GNU ld didn't support --whole-archive et. al.
++    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
++      whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++    else
++      whole_archive_flag_spec=
++    fi
++    supports_anon_versioning=no
++    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
++      *GNU\ gold*) supports_anon_versioning=yes ;;
++      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
++      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
++      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
++      *\ 2.11.*) ;; # other 2.11 versions
++      *) supports_anon_versioning=yes ;;
++    esac
++
++    # See if GNU ld supports shared libraries.
++    case $host_os in
++    aix[3-9]*)
++      # On AIX/PPC, the GNU linker is very broken
++      if test ia64 != "$host_cpu"; then
++	ld_shlibs=no
++	cat <<_LT_EOF 1>&2
++
++*** Warning: the GNU linker, at least up to release 2.19, is reported
++*** to be unable to reliably create shared libraries on AIX.
++*** Therefore, libtool is disabling shared libraries support.  If you
++*** really care for shared libraries, you may want to install binutils
++*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
++*** You will then need to restart the configuration process.
++
++_LT_EOF
++      fi
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++            archive_expsym_cmds=''
++        ;;
++      m68k)
++            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++            hardcode_libdir_flag_spec='-L$libdir'
++            hardcode_minus_L=yes
++        ;;
++      esac
++      ;;
++
++    beos*)
++      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	allow_undefined_flag=unsupported
++	# Joseph Beckenbach  says some releases of gcc
++	# support --undefined.  This deserves some investigation.  FIXME
++	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++      else
++	ld_shlibs=no
++      fi
++      ;;
++
++    cygwin* | mingw* | pw32* | cegcc*)
++      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
++      # as there is no search path for DLLs.
++      hardcode_libdir_flag_spec='-L$libdir'
++      export_dynamic_flag_spec='$wl--export-all-symbols'
++      allow_undefined_flag=unsupported
++      always_export_symbols=no
++      enable_shared_with_static_runtimes=yes
++      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
++      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
++
++      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	# If the export-symbols file already is a .def file, use it as
++	# is; otherwise, prepend EXPORTS...
++	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
++          cp $export_symbols $output_objdir/$soname.def;
++        else
++          echo EXPORTS > $output_objdir/$soname.def;
++          cat $export_symbols >> $output_objdir/$soname.def;
++        fi~
++        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++      else
++	ld_shlibs=no
++      fi
++      ;;
++
++    haiku*)
++      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++      link_all_deplibs=yes
++      ;;
++
++    os2*)
++      hardcode_libdir_flag_spec='-L$libdir'
++      hardcode_minus_L=yes
++      allow_undefined_flag=unsupported
++      shrext_cmds=.dll
++      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	prefix_cmds="$SED"~
++	if test EXPORTS = "`$SED 1q $export_symbols`"; then
++	  prefix_cmds="$prefix_cmds -e 1d";
++	fi~
++	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++      enable_shared_with_static_runtimes=yes
++      file_list_spec='@'
++      ;;
++
++    interix[3-9]*)
++      hardcode_direct=no
++      hardcode_shlibpath_var=no
++      hardcode_libdir_flag_spec='$wl-rpath,$libdir'
++      export_dynamic_flag_spec='$wl-E'
++      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
++      # Instead, shared libraries are loaded at an image base (0x10000000 by
++      # default) and relocated if they conflict, which is a slow very memory
++      # consuming and fragmenting process.  To avoid this, we pick a random,
++      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
++      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
++      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++      archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++      ;;
++
++    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
++      tmp_diet=no
++      if test linux-dietlibc = "$host_os"; then
++	case $cc_basename in
++	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
++	esac
++      fi
++      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
++	 && test no = "$tmp_diet"
++      then
++	tmp_addflag=' $pic_flag'
++	tmp_sharedflag='-shared'
++	case $cc_basename,$host_cpu in
++        pgcc*)				# Portland Group C compiler
++	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  tmp_addflag=' $pic_flag'
++	  ;;
++	pgf77* | pgf90* | pgf95* | pgfortran*)
++					# Portland Group f77 and f90 compilers
++	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  tmp_addflag=' $pic_flag -Mnomain' ;;
++	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
++	  tmp_addflag=' -i_dynamic' ;;
++	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
++	  tmp_addflag=' -i_dynamic -nofor_main' ;;
++	ifc* | ifort*)			# Intel Fortran compiler
++	  tmp_addflag=' -nofor_main' ;;
++	lf95*)				# Lahey Fortran 8.1
++	  whole_archive_flag_spec=
++	  tmp_sharedflag='--shared' ;;
++        nagfor*)                        # NAGFOR 5.3
++          tmp_sharedflag='-Wl,-shared' ;;
++	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
++	  tmp_sharedflag='-qmkshrobj'
++	  tmp_addflag= ;;
++	nvcc*)	# Cuda Compiler Driver 2.2
++	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  compiler_needs_object=yes
++	  ;;
++	esac
++	case `$CC -V 2>&1 | $SED 5q` in
++	*Sun\ C*)			# Sun C 5.9
++	  whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  compiler_needs_object=yes
++	  tmp_sharedflag='-G' ;;
++	*Sun\ F*)			# Sun Fortran 8.3
++	  tmp_sharedflag='-G' ;;
++	esac
++	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++
++        if test yes = "$supports_anon_versioning"; then
++          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
++            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++            echo "local: *; };" >> $output_objdir/$libname.ver~
++            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++        fi
++
++	case $cc_basename in
++	tcc*)
++	  export_dynamic_flag_spec='-rdynamic'
++	  ;;
++	xlf* | bgf* | bgxlf* | mpixlf*)
++	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
++	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
++	  hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
++	  if test yes = "$supports_anon_versioning"; then
++	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
++              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++              echo "local: *; };" >> $output_objdir/$libname.ver~
++              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
++	  fi
++	  ;;
++	esac
++      else
++        ld_shlibs=no
++      fi
++      ;;
++
++    netbsd*)
++      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
++	wlarc=
++      else
++	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      fi
++      ;;
++
++    solaris*)
++      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
++	ld_shlibs=no
++	cat <<_LT_EOF 1>&2
++
++*** Warning: The releases 2.8.* of the GNU linker cannot reliably
++*** create shared libraries on Solaris systems.  Therefore, libtool
++*** is disabling shared libraries support.  We urge you to upgrade GNU
++*** binutils to release 2.9.1 or newer.  Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
++
++_LT_EOF
++      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      else
++	ld_shlibs=no
++      fi
++      ;;
++
++    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
++      case `$LD -v 2>&1` in
++        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
++	ld_shlibs=no
++	cat <<_LT_EOF 1>&2
++
++*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
++*** reliably create shared libraries on SCO systems.  Therefore, libtool
++*** is disabling shared libraries support.  We urge you to upgrade GNU
++*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
++*** your PATH or compiler configuration so that the native linker is
++*** used, and then restart.
++
++_LT_EOF
++	;;
++	*)
++	  # For security reasons, it is highly recommended that you always
++	  # use absolute paths for naming shared libraries, and exclude the
++	  # DT_RUNPATH tag from executables and libraries.  But doing so
++	  # requires that you compile everything twice, which is a pain.
++	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	  else
++	    ld_shlibs=no
++	  fi
++	;;
++      esac
++      ;;
++
++    sunos4*)
++      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++      wlarc=
++      hardcode_direct=yes
++      hardcode_shlibpath_var=no
++      ;;
++
++    *)
++      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      else
++	ld_shlibs=no
++      fi
++      ;;
++    esac
++
++    if test no = "$ld_shlibs"; then
++      runpath_var=
++      hardcode_libdir_flag_spec=
++      export_dynamic_flag_spec=
++      whole_archive_flag_spec=
++    fi
++  else
++    # PORTME fill in a description of your system's linker (not GNU ld)
++    case $host_os in
++    aix3*)
++      allow_undefined_flag=unsupported
++      always_export_symbols=yes
++      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
++      # Note: this linker hardcodes the directories in LIBPATH if there
++      # are no directories specified by -L.
++      hardcode_minus_L=yes
++      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
++	# Neither direct hardcoding nor static linking is supported with a
++	# broken collect2.
++	hardcode_direct=unsupported
++      fi
++      ;;
++
++    aix[4-9]*)
++      if test ia64 = "$host_cpu"; then
++	# On IA64, the linker does run time linking by default, so we don't
++	# have to do anything special.
++	aix_use_runtimelinking=no
++	exp_sym_flag='-Bexport'
++	no_entry_flag=
++      else
++	# If we're using GNU nm, then we don't want the "-C" option.
++	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
++	# Without the "-l" option, or with the "-B" option, AIX nm treats
++	# weak defined symbols like other global defined symbols, whereas
++	# GNU nm marks them as "W".
++	# While the 'weak' keyword is ignored in the Export File, we need
++	# it in the Import File for the 'aix-soname' feature, so we have
++	# to replace the "-B" option with "-P" for AIX nm.
++	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
++	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++	else
++	  export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++	fi
++	aix_use_runtimelinking=no
++
++	# Test if we are trying to use run time linking or normal
++	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
++	# have runtime linking enabled, and use it for executables.
++	# For shared libraries, we enable/disable runtime linking
++	# depending on the kind of the shared library created -
++	# when "with_aix_soname,aix_use_runtimelinking" is:
++	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
++	# "aix,yes"  lib.so          shared, rtl:yes, for executables
++	#            lib.a           static archive
++	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
++	#            lib.a(lib.so.V) shared, rtl:no,  for executables
++	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
++	#            lib.a(lib.so.V) shared, rtl:no
++	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
++	#            lib.a           static archive
++	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
++	  for ld_flag in $LDFLAGS; do
++	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
++	    aix_use_runtimelinking=yes
++	    break
++	  fi
++	  done
++	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
++	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
++	    # so we don't have lib.a shared libs to link our executables.
++	    # We have to force runtime linking in this case.
++	    aix_use_runtimelinking=yes
++	    LDFLAGS="$LDFLAGS -Wl,-brtl"
++	  fi
++	  ;;
++	esac
++
++	exp_sym_flag='-bexport'
++	no_entry_flag='-bnoentry'
++      fi
++
++      # When large executables or shared objects are built, AIX ld can
++      # have problems creating the table of contents.  If linking a library
++      # or program results in "error TOC overflow" add -mminimal-toc to
++      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
++      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++      archive_cmds=''
++      hardcode_direct=yes
++      hardcode_direct_absolute=yes
++      hardcode_libdir_separator=':'
++      link_all_deplibs=yes
++      file_list_spec='$wl-f,'
++      case $with_aix_soname,$aix_use_runtimelinking in
++      aix,*) ;; # traditional, no import file
++      svr4,* | *,yes) # use import file
++	# The Import File defines what to hardcode.
++	hardcode_direct=no
++	hardcode_direct_absolute=no
++	;;
++      esac
++
++      if test yes = "$GCC"; then
++	case $host_os in aix4.[012]|aix4.[012].*)
++	# We only want to do this on AIX 4.2 and lower, the check
++	# below for broken collect2 doesn't work under 4.3+
++	  collect2name=`$CC -print-prog-name=collect2`
++	  if test -f "$collect2name" &&
++	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
++	  then
++	  # We have reworked collect2
++	  :
++	  else
++	  # We have old collect2
++	  hardcode_direct=unsupported
++	  # It fails to find uninstalled libraries when the uninstalled
++	  # path is not listed in the libpath.  Setting hardcode_minus_L
++	  # to unsupported forces relinking
++	  hardcode_minus_L=yes
++	  hardcode_libdir_flag_spec='-L$libdir'
++	  hardcode_libdir_separator=
++	  fi
++	  ;;
++	esac
++	shared_flag='-shared'
++	if test yes = "$aix_use_runtimelinking"; then
++	  shared_flag="$shared_flag "'$wl-G'
++	fi
++	# Need to ensure runtime linking is disabled for the traditional
++	# shared library, or the linker may eventually find shared libraries
++	# /with/ Import File - we do not want to mix them.
++	shared_flag_aix='-shared'
++	shared_flag_svr4='-shared $wl-G'
++      else
++	# not using gcc
++	if test ia64 = "$host_cpu"; then
++	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++	# chokes on -Wl,-G. The following line is correct:
++	  shared_flag='-G'
++	else
++	  if test yes = "$aix_use_runtimelinking"; then
++	    shared_flag='$wl-G'
++	  else
++	    shared_flag='$wl-bM:SRE'
++	  fi
++	  shared_flag_aix='$wl-bM:SRE'
++	  shared_flag_svr4='$wl-G'
++	fi
++      fi
++
++      export_dynamic_flag_spec='$wl-bexpall'
++      # It seems that -bexpall does not export symbols beginning with
++      # underscore (_), so it is better to generate a list of symbols to export.
++      always_export_symbols=yes
++      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++	# Warning - without using the other runtime loading flags (-brtl),
++	# -berok will link without error, but may produce a broken library.
++	allow_undefined_flag='-berok'
++        # Determine the default libpath from the value encoded in an
++        # empty executable.
++        if test set = "${lt_cv_aix_libpath+set}"; then
++  aix_libpath=$lt_cv_aix_libpath
++else
++  if test ${lt_cv_aix_libpath_+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++
++  lt_aix_libpath_sed='
++      /Import File Strings/,/^$/ {
++	  /^0/ {
++	      s/^0  *\([^ ]*\) *$/\1/
++	      p
++	  }
++      }'
++  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  # Check for a 64-bit object if we didn't find anything.
++  if test -z "$lt_cv_aix_libpath_"; then
++    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++  if test -z "$lt_cv_aix_libpath_"; then
++    lt_cv_aix_libpath_=/usr/lib:/lib
++  fi
++
++fi
++
++  aix_libpath=$lt_cv_aix_libpath_
++fi
++
++        hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
++        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++      else
++	if test ia64 = "$host_cpu"; then
++	  hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
++	  allow_undefined_flag="-z nodefs"
++	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++	else
++	 # Determine the default libpath from the value encoded in an
++	 # empty executable.
++	 if test set = "${lt_cv_aix_libpath+set}"; then
++  aix_libpath=$lt_cv_aix_libpath
++else
++  if test ${lt_cv_aix_libpath_+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++
++  lt_aix_libpath_sed='
++      /Import File Strings/,/^$/ {
++	  /^0/ {
++	      s/^0  *\([^ ]*\) *$/\1/
++	      p
++	  }
++      }'
++  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  # Check for a 64-bit object if we didn't find anything.
++  if test -z "$lt_cv_aix_libpath_"; then
++    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++  if test -z "$lt_cv_aix_libpath_"; then
++    lt_cv_aix_libpath_=/usr/lib:/lib
++  fi
++
++fi
++
++  aix_libpath=$lt_cv_aix_libpath_
++fi
++
++	 hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
++	  # Warning - without using the other run time loading flags,
++	  # -berok will link without error, but may produce a broken library.
++	  no_undefined_flag=' $wl-bernotok'
++	  allow_undefined_flag=' $wl-berok'
++	  if test yes = "$with_gnu_ld"; then
++	    # We only use this code for GNU lds that support --whole-archive.
++	    whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
++	  else
++	    # Exported symbols can be pulled into shared objects from archives
++	    whole_archive_flag_spec='$convenience'
++	  fi
++	  archive_cmds_need_lc=yes
++	  archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
++	  # -brtl affects multiple linker settings, -berok does not and is overridden later
++	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
++	  if test svr4 != "$with_aix_soname"; then
++	    # This is similar to how AIX traditionally builds its shared libraries.
++	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
++	  fi
++	  if test aix != "$with_aix_soname"; then
++	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
++	  else
++	    # used by -dlpreopen to get the symbols
++	    archive_expsym_cmds="$archive_expsym_cmds"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
++	  fi
++	  archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
++	fi
++      fi
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++            archive_expsym_cmds=''
++        ;;
++      m68k)
++            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
++            hardcode_libdir_flag_spec='-L$libdir'
++            hardcode_minus_L=yes
++        ;;
++      esac
++      ;;
++
++    bsdi[45]*)
++      export_dynamic_flag_spec=-rdynamic
++      ;;
++
++    cygwin* | mingw* | pw32* | cegcc*)
++      # When not using gcc, we currently assume that we are using
++      # Microsoft Visual C++ or Intel C++ Compiler.
++      # hardcode_libdir_flag_spec is actually meaningless, as there is
++      # no search path for DLLs.
++      case $cc_basename in
++      cl* | icl*)
++	# Native MSVC or ICC
++	hardcode_libdir_flag_spec=' '
++	allow_undefined_flag=unsupported
++	always_export_symbols=yes
++	file_list_spec='@'
++	# Tell ltmain to make .lib files, not .a files.
++	libext=lib
++	# Tell ltmain to make .dll files, not .so files.
++	shrext_cmds=.dll
++	# FIXME: Setting linknames here is a bad hack.
++	archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
++	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
++            cp "$export_symbols" "$output_objdir/$soname.def";
++            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
++          else
++            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
++          fi~
++          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
++          linknames='
++	# The linker will not automatically build a static lib if we build a DLL.
++	# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
++	enable_shared_with_static_runtimes=yes
++	exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
++	export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
++	# Don't use ranlib
++	old_postinstall_cmds='chmod 644 $oldlib'
++	postlink_cmds='lt_outputfile="@OUTPUT@"~
++          lt_tool_outputfile="@TOOL_OUTPUT@"~
++          case $lt_outputfile in
++            *.exe|*.EXE) ;;
++            *)
++              lt_outputfile=$lt_outputfile.exe
++              lt_tool_outputfile=$lt_tool_outputfile.exe
++              ;;
++          esac~
++          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
++            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
++            $RM "$lt_outputfile.manifest";
++          fi'
++	;;
++      *)
++	# Assume MSVC and ICC wrapper
++	hardcode_libdir_flag_spec=' '
++	allow_undefined_flag=unsupported
++	# Tell ltmain to make .lib files, not .a files.
++	libext=lib
++	# Tell ltmain to make .dll files, not .so files.
++	shrext_cmds=.dll
++	# FIXME: Setting linknames here is a bad hack.
++	archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
++	# The linker will automatically build a .lib file if we build a DLL.
++	old_archive_from_new_cmds='true'
++	# FIXME: Should let the user specify the lib program.
++	old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
++	enable_shared_with_static_runtimes=yes
++	;;
++      esac
++      ;;
++
++    darwin* | rhapsody*)
++
++
++  archive_cmds_need_lc=no
++  hardcode_direct=no
++  hardcode_automatic=yes
++  hardcode_shlibpath_var=unsupported
++  if test yes = "$lt_cv_ld_force_load"; then
++    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
++
++  else
++    whole_archive_flag_spec=''
++  fi
++  link_all_deplibs=yes
++  allow_undefined_flag=$_lt_dar_allow_undefined
++  case $cc_basename in
++     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
++     *) _lt_dar_can_shared=$GCC ;;
++  esac
++  if test yes = "$_lt_dar_can_shared"; then
++    output_verbose_link_cmd=func_echo_all
++    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
++    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
++    archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
++    module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
++
++  else
++  ld_shlibs=no
++  fi
++
++      ;;
++
++    dgux*)
++      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      hardcode_libdir_flag_spec='-L$libdir'
++      hardcode_shlibpath_var=no
++      ;;
++
++    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
++    # support.  Future versions do this automatically, but an explicit c++rt0.o
++    # does not break anything, and helps significantly (at the cost of a little
++    # extra space).
++    freebsd2.2*)
++      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
++      hardcode_libdir_flag_spec='-R$libdir'
++      hardcode_direct=yes
++      hardcode_shlibpath_var=no
++      ;;
++
++    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
++    freebsd2.*)
++      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++      hardcode_direct=yes
++      hardcode_minus_L=yes
++      hardcode_shlibpath_var=no
++      ;;
++
++    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
++    freebsd* | dragonfly* | midnightbsd*)
++      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++      hardcode_libdir_flag_spec='-R$libdir'
++      hardcode_direct=yes
++      hardcode_shlibpath_var=no
++      ;;
++
++    hpux9*)
++      if test yes = "$GCC"; then
++	archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++      else
++	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++      fi
++      hardcode_libdir_flag_spec='$wl+b $wl$libdir'
++      hardcode_libdir_separator=:
++      hardcode_direct=yes
++
++      # hardcode_minus_L: Not really in the search PATH,
++      # but as the default location of the library.
++      hardcode_minus_L=yes
++      export_dynamic_flag_spec='$wl-E'
++      ;;
++
++    hpux10*)
++      if test yes,no = "$GCC,$with_gnu_ld"; then
++	archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
++      fi
++      if test no = "$with_gnu_ld"; then
++	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
++	hardcode_libdir_separator=:
++	hardcode_direct=yes
++	hardcode_direct_absolute=yes
++	export_dynamic_flag_spec='$wl-E'
++	# hardcode_minus_L: Not really in the search PATH,
++	# but as the default location of the library.
++	hardcode_minus_L=yes
++      fi
++      ;;
++
++    hpux11*)
++      if test yes,no = "$GCC,$with_gnu_ld"; then
++	case $host_cpu in
++	hppa*64*)
++	  archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	ia64*)
++	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	*)
++	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	esac
++      else
++	case $host_cpu in
++	hppa*64*)
++	  archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	ia64*)
++	  archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	*)
++
++	  # Older versions of the 11.00 compiler do not understand -b yet
++	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
++	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
++printf %s "checking if $CC understands -b... " >&6; }
++if test ${lt_cv_prog_compiler__b+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler__b=no
++   save_LDFLAGS=$LDFLAGS
++   LDFLAGS="$LDFLAGS -b"
++   echo "$lt_simple_link_test_code" > conftest.$ac_ext
++   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
++     # The linker can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     if test -s conftest.err; then
++       # Append any errors to the config.log.
++       cat conftest.err 1>&5
++       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
++       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++       if diff conftest.exp conftest.er2 >/dev/null; then
++         lt_cv_prog_compiler__b=yes
++       fi
++     else
++       lt_cv_prog_compiler__b=yes
++     fi
++   fi
++   $RM -r conftest*
++   LDFLAGS=$save_LDFLAGS
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
++printf "%s\n" "$lt_cv_prog_compiler__b" >&6; }
++
++if test yes = "$lt_cv_prog_compiler__b"; then
++    archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++else
++    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
++fi
++
++	  ;;
++	esac
++      fi
++      if test no = "$with_gnu_ld"; then
++	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
++	hardcode_libdir_separator=:
++
++	case $host_cpu in
++	hppa*64*|ia64*)
++	  hardcode_direct=no
++	  hardcode_shlibpath_var=no
++	  ;;
++	*)
++	  hardcode_direct=yes
++	  hardcode_direct_absolute=yes
++	  export_dynamic_flag_spec='$wl-E'
++
++	  # hardcode_minus_L: Not really in the search PATH,
++	  # but as the default location of the library.
++	  hardcode_minus_L=yes
++	  ;;
++	esac
++      fi
++      ;;
++
++    irix5* | irix6* | nonstopux*)
++      if test yes = "$GCC"; then
++	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	# Try to use the -exported_symbol ld option, if it does not
++	# work, assume that -exports_file does not work either and
++	# implicitly export all symbols.
++	# This should be the same for all languages, so no per-tag cache variable.
++	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
++printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
++if test ${lt_cv_irix_exported_symbol+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  save_LDFLAGS=$LDFLAGS
++	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
++	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++int foo (void) { return 0; }
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  lt_cv_irix_exported_symbol=yes
++else $as_nop
++  lt_cv_irix_exported_symbol=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++           LDFLAGS=$save_LDFLAGS
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
++printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
++	if test yes = "$lt_cv_irix_exported_symbol"; then
++          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
++	fi
++      else
++	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
++      fi
++      archive_cmds_need_lc='no'
++      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      hardcode_libdir_separator=:
++      inherit_rpath=yes
++      link_all_deplibs=yes
++      ;;
++
++    linux*)
++      case $cc_basename in
++      tcc*)
++	# Fabrice Bellard et al's Tiny C Compiler
++	ld_shlibs=yes
++	archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	;;
++      esac
++      ;;
++
++    netbsd*)
++      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
++      else
++	archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
++      fi
++      hardcode_libdir_flag_spec='-R$libdir'
++      hardcode_direct=yes
++      hardcode_shlibpath_var=no
++      ;;
++
++    newsos6)
++      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      hardcode_direct=yes
++      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      hardcode_libdir_separator=:
++      hardcode_shlibpath_var=no
++      ;;
++
++    *nto* | *qnx*)
++      ;;
++
++    openbsd* | bitrig*)
++      if test -f /usr/libexec/ld.so; then
++	hardcode_direct=yes
++	hardcode_shlibpath_var=no
++	hardcode_direct_absolute=yes
++	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
++	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
++	  export_dynamic_flag_spec='$wl-E'
++	else
++	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
++	fi
++      else
++	ld_shlibs=no
++      fi
++      ;;
++
++    os2*)
++      hardcode_libdir_flag_spec='-L$libdir'
++      hardcode_minus_L=yes
++      allow_undefined_flag=unsupported
++      shrext_cmds=.dll
++      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	$ECHO EXPORTS >> $output_objdir/$libname.def~
++	prefix_cmds="$SED"~
++	if test EXPORTS = "`$SED 1q $export_symbols`"; then
++	  prefix_cmds="$prefix_cmds -e 1d";
++	fi~
++	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	emximp -o $lib $output_objdir/$libname.def'
++      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++      enable_shared_with_static_runtimes=yes
++      file_list_spec='@'
++      ;;
++
++    osf3*)
++      if test yes = "$GCC"; then
++	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
++	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++      else
++	allow_undefined_flag=' -expect_unresolved \*'
++	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++      fi
++      archive_cmds_need_lc='no'
++      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      hardcode_libdir_separator=:
++      ;;
++
++    osf4* | osf5*)	# as osf3* with the addition of -msym flag
++      if test yes = "$GCC"; then
++	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
++	archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      else
++	allow_undefined_flag=' -expect_unresolved \*'
++	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
++          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
++
++	# Both c and cxx compiler support -rpath directly
++	hardcode_libdir_flag_spec='-rpath $libdir'
++      fi
++      archive_cmds_need_lc='no'
++      hardcode_libdir_separator=:
++      ;;
++
++    solaris*)
++      no_undefined_flag=' -z defs'
++      if test yes = "$GCC"; then
++	wlarc='$wl'
++	archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++      else
++	case `$CC -V 2>&1` in
++	*"Compilers 5.0"*)
++	  wlarc=''
++	  archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
++	  ;;
++	*)
++	  wlarc='$wl'
++	  archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++	  ;;
++	esac
++      fi
++      hardcode_libdir_flag_spec='-R$libdir'
++      hardcode_shlibpath_var=no
++      case $host_os in
++      solaris2.[0-5] | solaris2.[0-5].*) ;;
++      *)
++	# The compiler driver will combine and reorder linker options,
++	# but understands '-z linker_flag'.  GCC discards it without '$wl',
++	# but is careful enough not to reorder.
++	# Supported since Solaris 2.6 (maybe 2.5.1?)
++	if test yes = "$GCC"; then
++	  whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++	else
++	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
++	fi
++	;;
++      esac
++      link_all_deplibs=yes
++      ;;
++
++    sunos4*)
++      if test sequent = "$host_vendor"; then
++	# Use $CC to link under sequent, because it throws in some extra .o
++	# files that make .init and .fini sections work.
++	archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
++      fi
++      hardcode_libdir_flag_spec='-L$libdir'
++      hardcode_direct=yes
++      hardcode_minus_L=yes
++      hardcode_shlibpath_var=no
++      ;;
++
++    sysv4)
++      case $host_vendor in
++	sni)
++	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  hardcode_direct=yes # is this really true???
++	;;
++	siemens)
++	  ## LD is ld it makes a PLAMLIB
++	  ## CC just makes a GrossModule.
++	  archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
++	  reload_cmds='$CC -r -o $output$reload_objs'
++	  hardcode_direct=no
++        ;;
++	motorola)
++	  archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  hardcode_direct=no #Motorola manual says yes, but my tests say they lie
++	;;
++      esac
++      runpath_var='LD_RUN_PATH'
++      hardcode_shlibpath_var=no
++      ;;
++
++    sysv4.3*)
++      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      hardcode_shlibpath_var=no
++      export_dynamic_flag_spec='-Bexport'
++      ;;
++
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	hardcode_shlibpath_var=no
++	runpath_var=LD_RUN_PATH
++	hardcode_runpath_var=yes
++	ld_shlibs=yes
++      fi
++      ;;
++
++    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
++      no_undefined_flag='$wl-z,text'
++      archive_cmds_need_lc=no
++      hardcode_shlibpath_var=no
++      runpath_var='LD_RUN_PATH'
++
++      if test yes = "$GCC"; then
++	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      fi
++      ;;
++
++    sysv5* | sco3.2v5* | sco5v6*)
++      # Note: We CANNOT use -z defs as we might desire, because we do not
++      # link with -lc, and that would cause any symbols used from libc to
++      # always be unresolved, which means just about no library would
++      # ever link correctly.  If we're not using GNU ld we use -z text
++      # though, which does catch some bad symbols but isn't as heavy-handed
++      # as -z defs.
++      no_undefined_flag='$wl-z,text'
++      allow_undefined_flag='$wl-z,nodefs'
++      archive_cmds_need_lc=no
++      hardcode_shlibpath_var=no
++      hardcode_libdir_flag_spec='$wl-R,$libdir'
++      hardcode_libdir_separator=':'
++      link_all_deplibs=yes
++      export_dynamic_flag_spec='$wl-Bexport'
++      runpath_var='LD_RUN_PATH'
++
++      if test yes = "$GCC"; then
++	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      else
++	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      fi
++      ;;
++
++    uts4*)
++      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
++      hardcode_libdir_flag_spec='-L$libdir'
++      hardcode_shlibpath_var=no
++      ;;
++
++    *)
++      ld_shlibs=no
++      ;;
++    esac
++
++    if test sni = "$host_vendor"; then
++      case $host in
++      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
++	export_dynamic_flag_spec='$wl-Blargedynsym'
++	;;
++      esac
++    fi
++  fi
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
++printf "%s\n" "$ld_shlibs" >&6; }
++test no = "$ld_shlibs" && can_build_shared=no
++
++with_gnu_ld=$with_gnu_ld
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++#
++# Do we need to explicitly link libc?
++#
++case "x$archive_cmds_need_lc" in
++x|xyes)
++  # Assume -lc should be added
++  archive_cmds_need_lc=yes
++
++  if test yes,yes = "$GCC,$enable_shared"; then
++    case $archive_cmds in
++    *'~'*)
++      # FIXME: we may have to deal with multi-command sequences.
++      ;;
++    '$CC '*)
++      # Test whether the compiler implicitly links with -lc since on some
++      # systems, -lgcc has to come before -lc. If gcc already passes -lc
++      # to ld, don't add -lc before -lgcc.
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
++printf %s "checking whether -lc should be explicitly linked in... " >&6; }
++if test ${lt_cv_archive_cmds_need_lc+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  $RM conftest*
++	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } 2>conftest.err; then
++	  soname=conftest
++	  lib=conftest
++	  libobjs=conftest.$ac_objext
++	  deplibs=
++	  wl=$lt_prog_compiler_wl
++	  pic_flag=$lt_prog_compiler_pic
++	  compiler_flags=-v
++	  linker_flags=-v
++	  verstring=
++	  output_objdir=.
++	  libname=conftest
++	  lt_save_allow_undefined_flag=$allow_undefined_flag
++	  allow_undefined_flag=
++	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
++  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++	  then
++	    lt_cv_archive_cmds_need_lc=no
++	  else
++	    lt_cv_archive_cmds_need_lc=yes
++	  fi
++	  allow_undefined_flag=$lt_save_allow_undefined_flag
++	else
++	  cat conftest.err 1>&5
++	fi
++	$RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
++printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; }
++      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
++      ;;
++    esac
++  fi
++  ;;
++esac
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
++printf %s "checking dynamic linker characteristics... " >&6; }
++
++if test yes = "$GCC"; then
++  case $host_os in
++    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
++    *) lt_awk_arg='/^libraries:/' ;;
++  esac
++  case $host_os in
++    mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
++    *) lt_sed_strip_eq='s|=/|/|g' ;;
++  esac
++  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
++  case $lt_search_path_spec in
++  *\;*)
++    # if the path contains ";" then we assume it to be the separator
++    # otherwise default to the standard path separator (i.e. ":") - it is
++    # assumed that no part of a normal pathname contains ";" but that should
++    # okay in the real world where ";" in dirpaths is itself problematic.
++    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
++    ;;
++  *)
++    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
++    ;;
++  esac
++  # Ok, now we have the path, separated by spaces, we can step through it
++  # and add multilib dir if necessary...
++  lt_tmp_lt_search_path_spec=
++  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
++  # ...but if some path component already ends with the multilib dir we assume
++  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
++  case "$lt_multi_os_dir; $lt_search_path_spec " in
++  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
++    lt_multi_os_dir=
++    ;;
++  esac
++  for lt_sys_path in $lt_search_path_spec; do
++    if test -d "$lt_sys_path$lt_multi_os_dir"; then
++      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
++    elif test -n "$lt_multi_os_dir"; then
++      test -d "$lt_sys_path" && \
++	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
++    fi
++  done
++  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
++BEGIN {RS = " "; FS = "/|\n";} {
++  lt_foo = "";
++  lt_count = 0;
++  for (lt_i = NF; lt_i > 0; lt_i--) {
++    if ($lt_i != "" && $lt_i != ".") {
++      if ($lt_i == "..") {
++        lt_count++;
++      } else {
++        if (lt_count == 0) {
++          lt_foo = "/" $lt_i lt_foo;
++        } else {
++          lt_count--;
++        }
++      }
++    }
++  }
++  if (lt_foo != "") { lt_freq[lt_foo]++; }
++  if (lt_freq[lt_foo] == 1) { print lt_foo; }
++}'`
++  # AWK program above erroneously prepends '/' to C:/dos/paths
++  # for these hosts.
++  case $host_os in
++    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
++      $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
++  esac
++  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
++else
++  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++fi
++library_names_spec=
++libname_spec='lib$name'
++soname_spec=
++shrext_cmds=.so
++postinstall_cmds=
++postuninstall_cmds=
++finish_cmds=
++finish_eval=
++shlibpath_var=
++shlibpath_overrides_runpath=unknown
++version_type=none
++dynamic_linker="$host_os ld.so"
++sys_lib_dlsearch_path_spec="/lib /usr/lib"
++need_lib_prefix=unknown
++hardcode_into_libs=no
++
++# when you set need_version to no, make sure it does not cause -set_version
++# flags to be left without arguments
++need_version=unknown
++
++
++
++case $host_os in
++aix3*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
++  shlibpath_var=LIBPATH
++
++  # AIX 3 has no versioning support, so we append a major version to the name.
++  soname_spec='$libname$release$shared_ext$major'
++  ;;
++
++aix[4-9]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  hardcode_into_libs=yes
++  if test ia64 = "$host_cpu"; then
++    # AIX 5 supports IA64
++    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
++    shlibpath_var=LD_LIBRARY_PATH
++  else
++    # With GCC up to 2.95.x, collect2 would create an import file
++    # for dependence libraries.  The import file would start with
++    # the line '#! .'.  This would cause the generated library to
++    # depend on '.', always an invalid library.  This was fixed in
++    # development snapshots of GCC prior to 3.0.
++    case $host_os in
++      aix4 | aix4.[01] | aix4.[01].*)
++      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++	   echo ' yes '
++	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
++	:
++      else
++	can_build_shared=no
++      fi
++      ;;
++    esac
++    # Using Import Files as archive members, it is possible to support
++    # filename-based versioning of shared library archives on AIX. While
++    # this would work for both with and without runtime linking, it will
++    # prevent static linking of such archives. So we do filename-based
++    # shared library versioning with .so extension only, which is used
++    # when both runtime linking and shared linking is enabled.
++    # Unfortunately, runtime linking may impact performance, so we do
++    # not want this to be the default eventually. Also, we use the
++    # versioned .so libs for executables only if there is the -brtl
++    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
++    # To allow for filename-based versioning support, we need to create
++    # libNAME.so.V as an archive file, containing:
++    # *) an Import File, referring to the versioned filename of the
++    #    archive as well as the shared archive member, telling the
++    #    bitwidth (32 or 64) of that shared object, and providing the
++    #    list of exported symbols of that shared object, eventually
++    #    decorated with the 'weak' keyword
++    # *) the shared object with the F_LOADONLY flag set, to really avoid
++    #    it being seen by the linker.
++    # At run time we better use the real file rather than another symlink,
++    # but for link time we create the symlink libNAME.so -> libNAME.so.V
++
++    case $with_aix_soname,$aix_use_runtimelinking in
++    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
++    # soname into executable. Probably we can add versioning support to
++    # collect2, so additional links can be useful in future.
++    aix,yes) # traditional libtool
++      dynamic_linker='AIX unversionable lib.so'
++      # If using run time linking (on AIX 4.2 or later) use lib.so
++      # instead of lib.a to let people know that these are not
++      # typical AIX shared libraries.
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++      ;;
++    aix,no) # traditional AIX only
++      dynamic_linker='AIX lib.a(lib.so.V)'
++      # We preserve .a as extension for shared libraries through AIX4.2
++      # and later when we are not doing run time linking.
++      library_names_spec='$libname$release.a $libname.a'
++      soname_spec='$libname$release$shared_ext$major'
++      ;;
++    svr4,*) # full svr4 only
++      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
++      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++      # We do not specify a path in Import Files, so LIBPATH fires.
++      shlibpath_overrides_runpath=yes
++      ;;
++    *,yes) # both, prefer svr4
++      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
++      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++      # unpreferred sharedlib libNAME.a needs extra handling
++      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
++      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
++      # We do not specify a path in Import Files, so LIBPATH fires.
++      shlibpath_overrides_runpath=yes
++      ;;
++    *,no) # both, prefer aix
++      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
++      library_names_spec='$libname$release.a $libname.a'
++      soname_spec='$libname$release$shared_ext$major'
++      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
++      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
++      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
++      ;;
++    esac
++    shlibpath_var=LIBPATH
++  fi
++  ;;
++
++amigaos*)
++  case $host_cpu in
++  powerpc)
++    # Since July 2007 AmigaOS4 officially supports .so libraries.
++    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    ;;
++  m68k)
++    library_names_spec='$libname.ixlibrary $libname.a'
++    # Create ${libname}_ixlibrary.a entries in /sys/libs.
++    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++    ;;
++  esac
++  ;;
++
++beos*)
++  library_names_spec='$libname$shared_ext'
++  dynamic_linker="$host_os ld.so"
++  shlibpath_var=LIBRARY_PATH
++  ;;
++
++bsdi[45]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
++  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
++  # the default ld.so.conf also contains /usr/contrib/lib and
++  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
++  # libtool to hard-code these into programs
++  ;;
++
++cygwin* | mingw* | pw32* | cegcc*)
++  version_type=windows
++  shrext_cmds=.dll
++  need_version=no
++  need_lib_prefix=no
++
++  case $GCC,$cc_basename in
++  yes,*)
++    # gcc
++    library_names_spec='$libname.dll.a'
++    # DLL is installed to $(libdir)/../bin by postinstall_cmds
++    postinstall_cmds='base_file=`basename \$file`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++      dldir=$destdir/`dirname \$dlpath`~
++      test -d \$dldir || mkdir -p \$dldir~
++      $install_prog $dir/$dlname \$dldir/$dlname~
++      chmod a+x \$dldir/$dlname~
++      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++      fi'
++    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++      dlpath=$dir/\$dldll~
++       $RM \$dlpath'
++    shlibpath_overrides_runpath=yes
++
++    case $host_os in
++    cygwin*)
++      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
++      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++
++      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
++      ;;
++    mingw* | cegcc*)
++      # MinGW DLLs use traditional 'lib' prefix
++      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      ;;
++    pw32*)
++      # pw32 DLLs use 'pw' prefix rather than 'lib'
++      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      ;;
++    esac
++    dynamic_linker='Win32 ld.exe'
++    ;;
++
++  *,cl* | *,icl*)
++    # Native MSVC or ICC
++    libname_spec='$name'
++    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++    library_names_spec='$libname.dll.lib'
++
++    case $build_os in
++    mingw*)
++      sys_lib_search_path_spec=
++      lt_save_ifs=$IFS
++      IFS=';'
++      for lt_path in $LIB
++      do
++        IFS=$lt_save_ifs
++        # Let DOS variable expansion print the short 8.3 style file name.
++        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
++        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
++      done
++      IFS=$lt_save_ifs
++      # Convert to MSYS style.
++      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
++      ;;
++    cygwin*)
++      # Convert to unix form, then to dos form, then back to unix form
++      # but this time dos style (no spaces!) so that the unix form looks
++      # like /cygdrive/c/PROGRA~1:/cygdr...
++      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
++      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
++      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++      ;;
++    *)
++      sys_lib_search_path_spec=$LIB
++      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
++        # It is most probably a Windows format PATH.
++        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
++      else
++        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++      fi
++      # FIXME: find the short name or the path components, as spaces are
++      # common. (e.g. "Program Files" -> "PROGRA~1")
++      ;;
++    esac
++
++    # DLL is installed to $(libdir)/../bin by postinstall_cmds
++    postinstall_cmds='base_file=`basename \$file`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++      dldir=$destdir/`dirname \$dlpath`~
++      test -d \$dldir || mkdir -p \$dldir~
++      $install_prog $dir/$dlname \$dldir/$dlname'
++    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++      dlpath=$dir/\$dldll~
++       $RM \$dlpath'
++    shlibpath_overrides_runpath=yes
++    dynamic_linker='Win32 link.exe'
++    ;;
++
++  *)
++    # Assume MSVC and ICC wrapper
++    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
++    dynamic_linker='Win32 ld.exe'
++    ;;
++  esac
++  # FIXME: first we should search . and the directory the executable is in
++  shlibpath_var=PATH
++  ;;
++
++darwin* | rhapsody*)
++  dynamic_linker="$host_os dyld"
++  version_type=darwin
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
++  soname_spec='$libname$release$major$shared_ext'
++  shlibpath_overrides_runpath=yes
++  shlibpath_var=DYLD_LIBRARY_PATH
++  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
++
++  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
++  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
++  ;;
++
++dgux*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++  # DragonFly does not have aout.  When/if they implement a new
++  # versioning mechanism, adjust this.
++  if test -x /usr/bin/objformat; then
++    objformat=`/usr/bin/objformat`
++  else
++    case $host_os in
++    freebsd[23].*) objformat=aout ;;
++    *) objformat=elf ;;
++    esac
++  fi
++  version_type=freebsd-$objformat
++  case $version_type in
++    freebsd-elf*)
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++      soname_spec='$libname$release$shared_ext$major'
++      need_version=no
++      need_lib_prefix=no
++      ;;
++    freebsd-*)
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++      need_version=yes
++      ;;
++  esac
++  shlibpath_var=LD_LIBRARY_PATH
++  case $host_os in
++  freebsd2.*)
++    shlibpath_overrides_runpath=yes
++    ;;
++  freebsd3.[01]* | freebsdelf3.[01]*)
++    shlibpath_overrides_runpath=yes
++    hardcode_into_libs=yes
++    ;;
++  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
++  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
++    shlibpath_overrides_runpath=no
++    hardcode_into_libs=yes
++    ;;
++  *) # from 4.6 on, and DragonFly
++    shlibpath_overrides_runpath=yes
++    hardcode_into_libs=yes
++    ;;
++  esac
++  ;;
++
++haiku*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  dynamic_linker="$host_os runtime_loader"
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
++  hardcode_into_libs=yes
++  ;;
++
++hpux9* | hpux10* | hpux11*)
++  # Give a soname corresponding to the major version so that dld.sl refuses to
++  # link against other versions.
++  version_type=sunos
++  need_lib_prefix=no
++  need_version=no
++  case $host_cpu in
++  ia64*)
++    shrext_cmds='.so'
++    hardcode_into_libs=yes
++    dynamic_linker="$host_os dld.so"
++    shlibpath_var=LD_LIBRARY_PATH
++    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    if test 32 = "$HPUX_IA64_MODE"; then
++      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
++    else
++      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
++    fi
++    ;;
++  hppa*64*)
++    shrext_cmds='.sl'
++    hardcode_into_libs=yes
++    dynamic_linker="$host_os dld.sl"
++    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
++    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++    ;;
++  *)
++    shrext_cmds='.sl'
++    dynamic_linker="$host_os dld.sl"
++    shlibpath_var=SHLIB_PATH
++    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    ;;
++  esac
++  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
++  postinstall_cmds='chmod 555 $lib'
++  # or fails outright, so override atomically:
++  install_override_mode=555
++  ;;
++
++interix[3-9]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  ;;
++
++irix5* | irix6* | nonstopux*)
++  case $host_os in
++    nonstopux*) version_type=nonstopux ;;
++    *)
++	if test yes = "$lt_cv_prog_gnu_ld"; then
++		version_type=linux # correct to gnu/linux during the next big refactor
++	else
++		version_type=irix
++	fi ;;
++  esac
++  need_lib_prefix=no
++  need_version=no
++  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
++  case $host_os in
++  irix5* | nonstopux*)
++    libsuff= shlibsuff=
++    ;;
++  *)
++    case $LD in # libtool.m4 will add one of these switches to LD
++    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
++      libsuff= shlibsuff= libmagic=32-bit;;
++    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
++      libsuff=32 shlibsuff=N32 libmagic=N32;;
++    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
++      libsuff=64 shlibsuff=64 libmagic=64-bit;;
++    *) libsuff= shlibsuff= libmagic=never-match;;
++    esac
++    ;;
++  esac
++  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
++  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
++  hardcode_into_libs=yes
++  ;;
++
++# No shared lib support for Linux oldld, aout, or coff.
++linux*oldld* | linux*aout* | linux*coff*)
++  dynamic_linker=no
++  ;;
++
++linux*android*)
++  version_type=none # Android doesn't support versioned libraries.
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext'
++  soname_spec='$libname$release$shared_ext'
++  finish_cmds=
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  hardcode_into_libs=yes
++
++  dynamic_linker='Android linker'
++  # Don't embed -rpath directories since the linker doesn't support them.
++  hardcode_libdir_flag_spec='-L$libdir'
++  ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++
++  # Some binutils ld are patched to set DT_RUNPATH
++  if test ${lt_cv_shlibpath_overrides_runpath+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_shlibpath_overrides_runpath=no
++    save_LDFLAGS=$LDFLAGS
++    save_libdir=$libdir
++    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
++	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
++    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
++then :
++  lt_cv_shlibpath_overrides_runpath=yes
++fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++    LDFLAGS=$save_LDFLAGS
++    libdir=$save_libdir
++
++fi
++
++  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
++
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  hardcode_into_libs=yes
++
++  # Add ABI-specific directories to the system library path.
++  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
++
++  # Ideally, we could use ldconfig to report *all* directores which are
++  # searched for libraries, however this is still not possible.  Aside from not
++  # being certain /sbin/ldconfig is available, command
++  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
++  # even though it is searched at run-time.  Try to do the best guess by
++  # appending ld.so.conf contents (and includes) to the search path.
++  if test -f /etc/ld.so.conf; then
++    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
++    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
++  fi
++
++  # We used to test for /lib/ld.so.1 and disable shared libraries on
++  # powerpc, because MkLinux only supported shared libraries with the
++  # GNU dynamic linker.  Since this was broken with cross compilers,
++  # most powerpc-linux boxes support dynamic linking these days and
++  # people can always --disable-shared, the test was removed, and we
++  # assume the GNU/Linux dynamic linker is in use.
++  dynamic_linker='GNU/Linux ld.so'
++  ;;
++
++netbsd*)
++  version_type=sunos
++  need_lib_prefix=no
++  need_version=no
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++    dynamic_linker='NetBSD (a.out) ld.so'
++  else
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    dynamic_linker='NetBSD ld.elf_so'
++  fi
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  ;;
++
++newsos6)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  ;;
++
++*nto* | *qnx*)
++  version_type=qnx
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  dynamic_linker='ldqnx.so'
++  ;;
++
++openbsd* | bitrig*)
++  version_type=sunos
++  sys_lib_dlsearch_path_spec=/usr/lib
++  need_lib_prefix=no
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++    need_version=no
++  else
++    need_version=yes
++  fi
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  ;;
++
++os2*)
++  libname_spec='$name'
++  version_type=windows
++  shrext_cmds=.dll
++  need_version=no
++  need_lib_prefix=no
++  # OS/2 can only load a DLL with a base name of 8 characters or less.
++  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
++    v=$($ECHO $release$versuffix | tr -d .-);
++    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
++    $ECHO $n$v`$shared_ext'
++  library_names_spec='${libname}_dll.$libext'
++  dynamic_linker='OS/2 ld.exe'
++  shlibpath_var=BEGINLIBPATH
++  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  postinstall_cmds='base_file=`basename \$file`~
++    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
++    dldir=$destdir/`dirname \$dlpath`~
++    test -d \$dldir || mkdir -p \$dldir~
++    $install_prog $dir/$dlname \$dldir/$dlname~
++    chmod a+x \$dldir/$dlname~
++    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++    fi'
++  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
++    dlpath=$dir/\$dldll~
++    $RM \$dlpath'
++  ;;
++
++osf3* | osf4* | osf5*)
++  version_type=osf
++  need_lib_prefix=no
++  need_version=no
++  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
++  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  ;;
++
++rdos*)
++  dynamic_linker=no
++  ;;
++
++solaris*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  # ldd complains unless libraries are executable
++  postinstall_cmds='chmod +x $lib'
++  ;;
++
++sunos4*)
++  version_type=sunos
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  if test yes = "$with_gnu_ld"; then
++    need_lib_prefix=no
++  fi
++  need_version=yes
++  ;;
++
++sysv4 | sysv4.3*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  case $host_vendor in
++    sni)
++      shlibpath_overrides_runpath=no
++      need_lib_prefix=no
++      runpath_var=LD_RUN_PATH
++      ;;
++    siemens)
++      need_lib_prefix=no
++      ;;
++    motorola)
++      need_lib_prefix=no
++      need_version=no
++      shlibpath_overrides_runpath=no
++      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
++      ;;
++  esac
++  ;;
++
++sysv4*MP*)
++  if test -d /usr/nec; then
++    version_type=linux # correct to gnu/linux during the next big refactor
++    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
++    soname_spec='$libname$shared_ext.$major'
++    shlibpath_var=LD_LIBRARY_PATH
++  fi
++  ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++  version_type=sco
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  if test yes = "$with_gnu_ld"; then
++    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
++  else
++    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
++    case $host_os in
++      sco3.2v5*)
++        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
++	;;
++    esac
++  fi
++  sys_lib_dlsearch_path_spec='/usr/lib'
++  ;;
++
++tpf*)
++  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  ;;
++
++uts4*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  ;;
++
++*)
++  dynamic_linker=no
++  ;;
++esac
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
++printf "%s\n" "$dynamic_linker" >&6; }
++test no = "$dynamic_linker" && can_build_shared=no
++
++variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
++if test yes = "$GCC"; then
++  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
++
++if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
++  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
++fi
++
++if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
++  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
++fi
++
++# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
++configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
++
++# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
++func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
++
++# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
++configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
++printf %s "checking how to hardcode library paths into programs... " >&6; }
++hardcode_action=
++if test -n "$hardcode_libdir_flag_spec" ||
++   test -n "$runpath_var" ||
++   test yes = "$hardcode_automatic"; then
++
++  # We can hardcode non-existent directories.
++  if test no != "$hardcode_direct" &&
++     # If the only mechanism to avoid hardcoding is shlibpath_var, we
++     # have to relink, otherwise we might link with an installed library
++     # when we should be linking with a yet-to-be-installed one
++     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
++     test no != "$hardcode_minus_L"; then
++    # Linking always hardcodes the temporary library directory.
++    hardcode_action=relink
++  else
++    # We can link without hardcoding, and we can hardcode nonexisting dirs.
++    hardcode_action=immediate
++  fi
++else
++  # We cannot hardcode anything, or else we can only hardcode existing
++  # directories.
++  hardcode_action=unsupported
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
++printf "%s\n" "$hardcode_action" >&6; }
++
++if test relink = "$hardcode_action" ||
++   test yes = "$inherit_rpath"; then
++  # Fast installation is not supported
++  enable_fast_install=no
++elif test yes = "$shlibpath_overrides_runpath" ||
++     test no = "$enable_shared"; then
++  # Fast installation is not necessary
++  enable_fast_install=needless
++fi
++
++
++
++
++
++
++  if test yes != "$enable_dlopen"; then
++  enable_dlopen=unknown
++  enable_dlopen_self=unknown
++  enable_dlopen_self_static=unknown
++else
++  lt_cv_dlopen=no
++  lt_cv_dlopen_libs=
++
++  case $host_os in
++  beos*)
++    lt_cv_dlopen=load_add_on
++    lt_cv_dlopen_libs=
++    lt_cv_dlopen_self=yes
++    ;;
++
++  mingw* | pw32* | cegcc*)
++    lt_cv_dlopen=LoadLibrary
++    lt_cv_dlopen_libs=
++    ;;
++
++  cygwin*)
++    lt_cv_dlopen=dlopen
++    lt_cv_dlopen_libs=
++    ;;
++
++  darwin*)
++    # if libdl is installed we need to link against it
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
++printf %s "checking for dlopen in -ldl... " >&6; }
++if test ${ac_cv_lib_dl_dlopen+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_check_lib_save_LIBS=$LIBS
++LIBS="-ldl  $LIBS"
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++/* Override any GCC internal prototype to avoid an error.
++   Use char because int might match the return type of a GCC
++   builtin and then its argument prototype would still apply.  */
++char dlopen ();
++int
++main (void)
++{
++return dlopen ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  ac_cv_lib_dl_dlopen=yes
++else $as_nop
++  ac_cv_lib_dl_dlopen=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
++printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
++if test "x$ac_cv_lib_dl_dlopen" = xyes
++then :
++  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
++else $as_nop
++
++    lt_cv_dlopen=dyld
++    lt_cv_dlopen_libs=
++    lt_cv_dlopen_self=yes
++
++fi
++
++    ;;
++
++  tpf*)
++    # Don't try to run any link tests for TPF.  We know it's impossible
++    # because TPF is a cross-compiler, and we know how we open DSOs.
++    lt_cv_dlopen=dlopen
++    lt_cv_dlopen_libs=
++    lt_cv_dlopen_self=no
++    ;;
++
++  *)
++    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
++if test "x$ac_cv_func_shl_load" = xyes
++then :
++  lt_cv_dlopen=shl_load
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
++printf %s "checking for shl_load in -ldld... " >&6; }
++if test ${ac_cv_lib_dld_shl_load+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_check_lib_save_LIBS=$LIBS
++LIBS="-ldld  $LIBS"
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++/* Override any GCC internal prototype to avoid an error.
++   Use char because int might match the return type of a GCC
++   builtin and then its argument prototype would still apply.  */
++char shl_load ();
++int
++main (void)
++{
++return shl_load ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  ac_cv_lib_dld_shl_load=yes
++else $as_nop
++  ac_cv_lib_dld_shl_load=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
++printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
++if test "x$ac_cv_lib_dld_shl_load" = xyes
++then :
++  lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
++else $as_nop
++  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
++if test "x$ac_cv_func_dlopen" = xyes
++then :
++  lt_cv_dlopen=dlopen
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
++printf %s "checking for dlopen in -ldl... " >&6; }
++if test ${ac_cv_lib_dl_dlopen+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_check_lib_save_LIBS=$LIBS
++LIBS="-ldl  $LIBS"
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++/* Override any GCC internal prototype to avoid an error.
++   Use char because int might match the return type of a GCC
++   builtin and then its argument prototype would still apply.  */
++char dlopen ();
++int
++main (void)
++{
++return dlopen ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  ac_cv_lib_dl_dlopen=yes
++else $as_nop
++  ac_cv_lib_dl_dlopen=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
++printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
++if test "x$ac_cv_lib_dl_dlopen" = xyes
++then :
++  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
++printf %s "checking for dlopen in -lsvld... " >&6; }
++if test ${ac_cv_lib_svld_dlopen+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_check_lib_save_LIBS=$LIBS
++LIBS="-lsvld  $LIBS"
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++/* Override any GCC internal prototype to avoid an error.
++   Use char because int might match the return type of a GCC
++   builtin and then its argument prototype would still apply.  */
++char dlopen ();
++int
++main (void)
++{
++return dlopen ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  ac_cv_lib_svld_dlopen=yes
++else $as_nop
++  ac_cv_lib_svld_dlopen=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
++printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; }
++if test "x$ac_cv_lib_svld_dlopen" = xyes
++then :
++  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
++else $as_nop
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
++printf %s "checking for dld_link in -ldld... " >&6; }
++if test ${ac_cv_lib_dld_dld_link+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  ac_check_lib_save_LIBS=$LIBS
++LIBS="-ldld  $LIBS"
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++/* Override any GCC internal prototype to avoid an error.
++   Use char because int might match the return type of a GCC
++   builtin and then its argument prototype would still apply.  */
++char dld_link ();
++int
++main (void)
++{
++return dld_link ();
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_link "$LINENO"
++then :
++  ac_cv_lib_dld_dld_link=yes
++else $as_nop
++  ac_cv_lib_dld_dld_link=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++LIBS=$ac_check_lib_save_LIBS
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
++printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; }
++if test "x$ac_cv_lib_dld_dld_link" = xyes
++then :
++  lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
++fi
++
++
++fi
++
++
++fi
++
++
++fi
++
++
++fi
++
++
++fi
++
++    ;;
++  esac
++
++  if test no = "$lt_cv_dlopen"; then
++    enable_dlopen=no
++  else
++    enable_dlopen=yes
++  fi
++
++  case $lt_cv_dlopen in
++  dlopen)
++    save_CPPFLAGS=$CPPFLAGS
++    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
++
++    save_LDFLAGS=$LDFLAGS
++    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
++
++    save_LIBS=$LIBS
++    LIBS="$lt_cv_dlopen_libs $LIBS"
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
++printf %s "checking whether a program can dlopen itself... " >&6; }
++if test ${lt_cv_dlopen_self+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  	  if test yes = "$cross_compiling"; then :
++  lt_cv_dlopen_self=cross
++else
++  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
++  lt_status=$lt_dlunknown
++  cat > conftest.$ac_ext <<_LT_EOF
++#line $LINENO "configure"
++#include "confdefs.h"
++
++#if HAVE_DLFCN_H
++#include 
++#endif
++
++#include 
++
++#ifdef RTLD_GLOBAL
++#  define LT_DLGLOBAL		RTLD_GLOBAL
++#else
++#  ifdef DL_GLOBAL
++#    define LT_DLGLOBAL		DL_GLOBAL
++#  else
++#    define LT_DLGLOBAL		0
++#  endif
++#endif
++
++/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
++   find out it does not work in some platform. */
++#ifndef LT_DLLAZY_OR_NOW
++#  ifdef RTLD_LAZY
++#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
++#  else
++#    ifdef DL_LAZY
++#      define LT_DLLAZY_OR_NOW		DL_LAZY
++#    else
++#      ifdef RTLD_NOW
++#        define LT_DLLAZY_OR_NOW	RTLD_NOW
++#      else
++#        ifdef DL_NOW
++#          define LT_DLLAZY_OR_NOW	DL_NOW
++#        else
++#          define LT_DLLAZY_OR_NOW	0
++#        endif
++#      endif
++#    endif
++#  endif
++#endif
++
++/* When -fvisibility=hidden is used, assume the code has been annotated
++   correspondingly for the symbols needed.  */
++#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
++int fnord () __attribute__((visibility("default")));
++#endif
++
++int fnord () { return 42; }
++int main ()
++{
++  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
++  int status = $lt_dlunknown;
++
++  if (self)
++    {
++      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
++      else
++        {
++	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
++          else puts (dlerror ());
++	}
++      /* dlclose (self); */
++    }
++  else
++    puts (dlerror ());
++
++  return status;
++}
++_LT_EOF
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
++  (eval $ac_link) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
++    (./conftest; exit; ) >&5 2>/dev/null
++    lt_status=$?
++    case x$lt_status in
++      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
++      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
++      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
++    esac
++  else :
++    # compilation failed
++    lt_cv_dlopen_self=no
++  fi
++fi
++rm -fr conftest*
++
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
++printf "%s\n" "$lt_cv_dlopen_self" >&6; }
++
++    if test yes = "$lt_cv_dlopen_self"; then
++      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
++printf %s "checking whether a statically linked program can dlopen itself... " >&6; }
++if test ${lt_cv_dlopen_self_static+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  	  if test yes = "$cross_compiling"; then :
++  lt_cv_dlopen_self_static=cross
++else
++  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
++  lt_status=$lt_dlunknown
++  cat > conftest.$ac_ext <<_LT_EOF
++#line $LINENO "configure"
++#include "confdefs.h"
++
++#if HAVE_DLFCN_H
++#include 
++#endif
++
++#include 
++
++#ifdef RTLD_GLOBAL
++#  define LT_DLGLOBAL		RTLD_GLOBAL
++#else
++#  ifdef DL_GLOBAL
++#    define LT_DLGLOBAL		DL_GLOBAL
++#  else
++#    define LT_DLGLOBAL		0
++#  endif
++#endif
++
++/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
++   find out it does not work in some platform. */
++#ifndef LT_DLLAZY_OR_NOW
++#  ifdef RTLD_LAZY
++#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
++#  else
++#    ifdef DL_LAZY
++#      define LT_DLLAZY_OR_NOW		DL_LAZY
++#    else
++#      ifdef RTLD_NOW
++#        define LT_DLLAZY_OR_NOW	RTLD_NOW
++#      else
++#        ifdef DL_NOW
++#          define LT_DLLAZY_OR_NOW	DL_NOW
++#        else
++#          define LT_DLLAZY_OR_NOW	0
++#        endif
++#      endif
++#    endif
++#  endif
++#endif
++
++/* When -fvisibility=hidden is used, assume the code has been annotated
++   correspondingly for the symbols needed.  */
++#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
++int fnord () __attribute__((visibility("default")));
++#endif
++
++int fnord () { return 42; }
++int main ()
++{
++  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
++  int status = $lt_dlunknown;
++
++  if (self)
++    {
++      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
++      else
++        {
++	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
++          else puts (dlerror ());
++	}
++      /* dlclose (self); */
++    }
++  else
++    puts (dlerror ());
++
++  return status;
++}
++_LT_EOF
++  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
++  (eval $ac_link) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
++    (./conftest; exit; ) >&5 2>/dev/null
++    lt_status=$?
++    case x$lt_status in
++      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
++      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
++      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
++    esac
++  else :
++    # compilation failed
++    lt_cv_dlopen_self_static=no
++  fi
++fi
++rm -fr conftest*
++
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
++printf "%s\n" "$lt_cv_dlopen_self_static" >&6; }
++    fi
++
++    CPPFLAGS=$save_CPPFLAGS
++    LDFLAGS=$save_LDFLAGS
++    LIBS=$save_LIBS
++    ;;
++  esac
++
++  case $lt_cv_dlopen_self in
++  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
++  *) enable_dlopen_self=unknown ;;
++  esac
++
++  case $lt_cv_dlopen_self_static in
++  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
++  *) enable_dlopen_self_static=unknown ;;
++  esac
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++striplib=
++old_striplib=
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
++printf %s "checking whether stripping libraries is possible... " >&6; }
++if test -z "$STRIP"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++else
++  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
++    old_striplib="$STRIP --strip-debug"
++    striplib="$STRIP --strip-unneeded"
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++  else
++    case $host_os in
++    darwin*)
++      # FIXME - insert some real tests, host_os isn't really good enough
++      striplib="$STRIP -x"
++      old_striplib="$STRIP -S"
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++      ;;
++    freebsd*)
++      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
++        old_striplib="$STRIP --strip-debug"
++        striplib="$STRIP --strip-unneeded"
++        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++printf "%s\n" "yes" >&6; }
++      else
++        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++      fi
++      ;;
++    *)
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++      ;;
++    esac
++  fi
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++  # Report what library types will actually be built
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
++printf %s "checking if libtool supports shared libraries... " >&6; }
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
++printf "%s\n" "$can_build_shared" >&6; }
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
++printf %s "checking whether to build shared libraries... " >&6; }
++  test no = "$can_build_shared" && enable_shared=no
++
++  # On AIX, shared libraries and static libraries use the same namespace, and
++  # are all built from PIC.
++  case $host_os in
++  aix3*)
++    test yes = "$enable_shared" && enable_static=no
++    if test -n "$RANLIB"; then
++      archive_cmds="$archive_cmds~\$RANLIB \$lib"
++      postinstall_cmds='$RANLIB $lib'
++    fi
++    ;;
++
++  aix[4-9]*)
++    if test ia64 != "$host_cpu"; then
++      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
++      yes,aix,yes) ;;			# shared object as lib.so file only
++      yes,svr4,*) ;;			# shared object as lib.so archive member only
++      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
++      esac
++    fi
++    ;;
++  esac
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
++printf "%s\n" "$enable_shared" >&6; }
++
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
++printf %s "checking whether to build static libraries... " >&6; }
++  # Make sure either enable_shared or enable_static is yes.
++  test yes = "$enable_shared" || enable_static=yes
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
++printf "%s\n" "$enable_static" >&6; }
++
++
++
++
++fi
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++CC=$lt_save_CC
++
++      if test -n "$CXX" && ( test no != "$CXX" &&
++    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
++    (test g++ != "$CXX"))); then
++  ac_ext=cpp
++ac_cpp='$CXXCPP $CPPFLAGS'
++ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
++printf %s "checking how to run the C++ preprocessor... " >&6; }
++if test -z "$CXXCPP"; then
++  if test ${ac_cv_prog_CXXCPP+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++      # Double quotes because $CXX needs to be expanded
++    for CXXCPP in "$CXX -E" cpp /lib/cpp
++    do
++      ac_preproc_ok=false
++for ac_cxx_preproc_warn_flag in '' yes
++do
++  # Use a header file that comes with gcc, so configuring glibc
++  # with a fresh cross-compiler works.
++  # On the NeXT, cc -E runs the code through the compiler's parser,
++  # not just through cpp. "Syntax error" is here to catch this case.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++		     Syntax error
++_ACEOF
++if ac_fn_cxx_try_cpp "$LINENO"
++then :
++
++else $as_nop
++  # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++  # OK, works on sane cases.  Now check whether nonexistent headers
++  # can be detected and how.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++_ACEOF
++if ac_fn_cxx_try_cpp "$LINENO"
++then :
++  # Broken: success on invalid input.
++continue
++else $as_nop
++  # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.i conftest.err conftest.$ac_ext
++if $ac_preproc_ok
++then :
++  break
++fi
++
++    done
++    ac_cv_prog_CXXCPP=$CXXCPP
++
++fi
++  CXXCPP=$ac_cv_prog_CXXCPP
++else
++  ac_cv_prog_CXXCPP=$CXXCPP
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
++printf "%s\n" "$CXXCPP" >&6; }
++ac_preproc_ok=false
++for ac_cxx_preproc_warn_flag in '' yes
++do
++  # Use a header file that comes with gcc, so configuring glibc
++  # with a fresh cross-compiler works.
++  # On the NeXT, cc -E runs the code through the compiler's parser,
++  # not just through cpp. "Syntax error" is here to catch this case.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++		     Syntax error
++_ACEOF
++if ac_fn_cxx_try_cpp "$LINENO"
++then :
++
++else $as_nop
++  # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++  # OK, works on sane cases.  Now check whether nonexistent headers
++  # can be detected and how.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++_ACEOF
++if ac_fn_cxx_try_cpp "$LINENO"
++then :
++  # Broken: success on invalid input.
++continue
++else $as_nop
++  # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.i conftest.err conftest.$ac_ext
++if $ac_preproc_ok
++then :
++
++else $as_nop
++  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
++See \`config.log' for more details" "$LINENO" 5; }
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++else
++  _lt_caught_CXX_error=yes
++fi
++
++ac_ext=cpp
++ac_cpp='$CXXCPP $CPPFLAGS'
++ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
++
++archive_cmds_need_lc_CXX=no
++allow_undefined_flag_CXX=
++always_export_symbols_CXX=no
++archive_expsym_cmds_CXX=
++compiler_needs_object_CXX=no
++export_dynamic_flag_spec_CXX=
++hardcode_direct_CXX=no
++hardcode_direct_absolute_CXX=no
++hardcode_libdir_flag_spec_CXX=
++hardcode_libdir_separator_CXX=
++hardcode_minus_L_CXX=no
++hardcode_shlibpath_var_CXX=unsupported
++hardcode_automatic_CXX=no
++inherit_rpath_CXX=no
++module_cmds_CXX=
++module_expsym_cmds_CXX=
++link_all_deplibs_CXX=unknown
++old_archive_cmds_CXX=$old_archive_cmds
++reload_flag_CXX=$reload_flag
++reload_cmds_CXX=$reload_cmds
++no_undefined_flag_CXX=
++whole_archive_flag_spec_CXX=
++enable_shared_with_static_runtimes_CXX=no
++
++# Source file extension for C++ test sources.
++ac_ext=cpp
++
++# Object file extension for compiled C++ test sources.
++objext=o
++objext_CXX=$objext
++
++# No sense in running all these tests if we already determined that
++# the CXX compiler isn't working.  Some variables (like enable_shared)
++# are currently assumed to apply to all compilers on this platform,
++# and will be corrupted by setting them based on a non-working compiler.
++if test yes != "$_lt_caught_CXX_error"; then
++  # Code to be used in simple compile tests
++  lt_simple_compile_test_code="int some_variable = 0;"
++
++  # Code to be used in simple link tests
++  lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
++
++  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
++
++
++
++
++
++
++# If no C compiler was specified, use CC.
++LTCC=${LTCC-"$CC"}
++
++# If no C compiler flags were specified, use CFLAGS.
++LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
++
++# Allow CC to be a program name with arguments.
++compiler=$CC
++
++
++  # save warnings/boilerplate of simple test code
++  ac_outfile=conftest.$ac_objext
++echo "$lt_simple_compile_test_code" >conftest.$ac_ext
++eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_compiler_boilerplate=`cat conftest.err`
++$RM conftest*
++
++  ac_outfile=conftest.$ac_objext
++echo "$lt_simple_link_test_code" >conftest.$ac_ext
++eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
++_lt_linker_boilerplate=`cat conftest.err`
++$RM -r conftest*
++
++
++  # Allow CC to be a program name with arguments.
++  lt_save_CC=$CC
++  lt_save_CFLAGS=$CFLAGS
++  lt_save_LD=$LD
++  lt_save_GCC=$GCC
++  GCC=$GXX
++  lt_save_with_gnu_ld=$with_gnu_ld
++  lt_save_path_LD=$lt_cv_path_LD
++  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
++    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
++  else
++    $as_unset lt_cv_prog_gnu_ld
++  fi
++  if test -n "${lt_cv_path_LDCXX+set}"; then
++    lt_cv_path_LD=$lt_cv_path_LDCXX
++  else
++    $as_unset lt_cv_path_LD
++  fi
++  test -z "${LDCXX+set}" || LD=$LDCXX
++  CC=${CXX-"c++"}
++  CFLAGS=$CXXFLAGS
++  compiler=$CC
++  compiler_CXX=$CC
++  func_cc_basename $compiler
++cc_basename=$func_cc_basename_result
++
++
++  if test -n "$compiler"; then
++    # We don't want -fno-exception when compiling C++ code, so set the
++    # no_builtin_flag separately
++    if test yes = "$GXX"; then
++      lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
++    else
++      lt_prog_compiler_no_builtin_flag_CXX=
++    fi
++
++    if test yes = "$GXX"; then
++      # Set up default GNU C++ configuration
++
++
++
++# Check whether --with-gnu-ld was given.
++if test ${with_gnu_ld+y}
++then :
++  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
++else $as_nop
++  with_gnu_ld=no
++fi
++
++ac_prog=ld
++if test yes = "$GCC"; then
++  # Check if gcc -print-prog-name=ld gives a path.
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
++printf %s "checking for ld used by $CC... " >&6; }
++  case $host in
++  *-*-mingw*)
++    # gcc leaves a trailing carriage return, which upsets mingw
++    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
++  *)
++    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
++  esac
++  case $ac_prog in
++    # Accept absolute paths.
++    [\\/]* | ?:[\\/]*)
++      re_direlt='/[^/][^/]*/\.\./'
++      # Canonicalize the pathname of ld
++      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
++      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
++	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
++      done
++      test -z "$LD" && LD=$ac_prog
++      ;;
++  "")
++    # If it fails, then pretend we aren't using GCC.
++    ac_prog=ld
++    ;;
++  *)
++    # If it is relative, then search for the first ld in PATH.
++    with_gnu_ld=unknown
++    ;;
++  esac
++elif test yes = "$with_gnu_ld"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
++printf %s "checking for GNU ld... " >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
++printf %s "checking for non-GNU ld... " >&6; }
++fi
++if test ${lt_cv_path_LD+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  if test -z "$LD"; then
++  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  for ac_dir in $PATH; do
++    IFS=$lt_save_ifs
++    test -z "$ac_dir" && ac_dir=.
++    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
++      lt_cv_path_LD=$ac_dir/$ac_prog
++      # Check to see if the program is GNU ld.  I'd rather use --version,
++      # but apparently some variants of GNU ld only accept -v.
++      # Break only if it was the GNU/non-GNU ld that we prefer.
++      case `"$lt_cv_path_LD" -v 2>&1 &5
++printf "%s\n" "$LD" >&6; }
++else
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
++printf "%s\n" "no" >&6; }
++fi
++test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
++printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
++if test ${lt_cv_prog_gnu_ld+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  # I'd rather use --version here, but apparently some GNU lds only accept -v.
++case `$LD -v 2>&1 &5
++printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
++with_gnu_ld=$lt_cv_prog_gnu_ld
++
++
++
++
++
++
++
++      # Check if GNU C++ uses GNU ld as the underlying linker, since the
++      # archiving commands below assume that GNU ld is being used.
++      if test yes = "$with_gnu_ld"; then
++        archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++        archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++
++        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++        export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++
++        # If archive_cmds runs LD, not CC, wlarc should be empty
++        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
++        #     investigate it a little bit more. (MM)
++        wlarc='$wl'
++
++        # ancient GNU ld didn't support --whole-archive et. al.
++        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
++	  $GREP 'no-whole-archive' > /dev/null; then
++          whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++        else
++          whole_archive_flag_spec_CXX=
++        fi
++      else
++        with_gnu_ld=no
++        wlarc=
++
++        # A generic and very simple default shared library creation
++        # command for GNU C++ for the case where it uses the native
++        # linker, instead of GNU ld.  If possible, this setting should
++        # overridden to take advantage of the native linker features on
++        # the platform it is being used on.
++        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++      fi
++
++      # Commands to make compiler produce verbose output that lists
++      # what "hidden" libraries, object files and flags are used when
++      # linking a shared library.
++      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++
++    else
++      GXX=no
++      with_gnu_ld=no
++      wlarc=
++    fi
++
++    # PORTME: fill in a description of your system's C++ link characteristics
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
++printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
++    ld_shlibs_CXX=yes
++    case $host_os in
++      aix3*)
++        # FIXME: insert proper C++ library support
++        ld_shlibs_CXX=no
++        ;;
++      aix[4-9]*)
++        if test ia64 = "$host_cpu"; then
++          # On IA64, the linker does run time linking by default, so we don't
++          # have to do anything special.
++          aix_use_runtimelinking=no
++          exp_sym_flag='-Bexport'
++          no_entry_flag=
++        else
++          aix_use_runtimelinking=no
++
++          # Test if we are trying to use run time linking or normal
++          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
++          # have runtime linking enabled, and use it for executables.
++          # For shared libraries, we enable/disable runtime linking
++          # depending on the kind of the shared library created -
++          # when "with_aix_soname,aix_use_runtimelinking" is:
++          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
++          # "aix,yes"  lib.so          shared, rtl:yes, for executables
++          #            lib.a           static archive
++          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
++          #            lib.a(lib.so.V) shared, rtl:no,  for executables
++          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
++          #            lib.a(lib.so.V) shared, rtl:no
++          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
++          #            lib.a           static archive
++          case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
++	    for ld_flag in $LDFLAGS; do
++	      case $ld_flag in
++	      *-brtl*)
++	        aix_use_runtimelinking=yes
++	        break
++	        ;;
++	      esac
++	    done
++	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
++	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
++	      # so we don't have lib.a shared libs to link our executables.
++	      # We have to force runtime linking in this case.
++	      aix_use_runtimelinking=yes
++	      LDFLAGS="$LDFLAGS -Wl,-brtl"
++	    fi
++	    ;;
++          esac
++
++          exp_sym_flag='-bexport'
++          no_entry_flag='-bnoentry'
++        fi
++
++        # When large executables or shared objects are built, AIX ld can
++        # have problems creating the table of contents.  If linking a library
++        # or program results in "error TOC overflow" add -mminimal-toc to
++        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
++        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
++
++        archive_cmds_CXX=''
++        hardcode_direct_CXX=yes
++        hardcode_direct_absolute_CXX=yes
++        hardcode_libdir_separator_CXX=':'
++        link_all_deplibs_CXX=yes
++        file_list_spec_CXX='$wl-f,'
++        case $with_aix_soname,$aix_use_runtimelinking in
++        aix,*) ;;	# no import file
++        svr4,* | *,yes) # use import file
++          # The Import File defines what to hardcode.
++          hardcode_direct_CXX=no
++          hardcode_direct_absolute_CXX=no
++          ;;
++        esac
++
++        if test yes = "$GXX"; then
++          case $host_os in aix4.[012]|aix4.[012].*)
++          # We only want to do this on AIX 4.2 and lower, the check
++          # below for broken collect2 doesn't work under 4.3+
++	  collect2name=`$CC -print-prog-name=collect2`
++	  if test -f "$collect2name" &&
++	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
++	  then
++	    # We have reworked collect2
++	    :
++	  else
++	    # We have old collect2
++	    hardcode_direct_CXX=unsupported
++	    # It fails to find uninstalled libraries when the uninstalled
++	    # path is not listed in the libpath.  Setting hardcode_minus_L
++	    # to unsupported forces relinking
++	    hardcode_minus_L_CXX=yes
++	    hardcode_libdir_flag_spec_CXX='-L$libdir'
++	    hardcode_libdir_separator_CXX=
++	  fi
++          esac
++          shared_flag='-shared'
++	  if test yes = "$aix_use_runtimelinking"; then
++	    shared_flag=$shared_flag' $wl-G'
++	  fi
++	  # Need to ensure runtime linking is disabled for the traditional
++	  # shared library, or the linker may eventually find shared libraries
++	  # /with/ Import File - we do not want to mix them.
++	  shared_flag_aix='-shared'
++	  shared_flag_svr4='-shared $wl-G'
++        else
++          # not using gcc
++          if test ia64 = "$host_cpu"; then
++	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
++	  # chokes on -Wl,-G. The following line is correct:
++	  shared_flag='-G'
++          else
++	    if test yes = "$aix_use_runtimelinking"; then
++	      shared_flag='$wl-G'
++	    else
++	      shared_flag='$wl-bM:SRE'
++	    fi
++	    shared_flag_aix='$wl-bM:SRE'
++	    shared_flag_svr4='$wl-G'
++          fi
++        fi
++
++        export_dynamic_flag_spec_CXX='$wl-bexpall'
++        # It seems that -bexpall does not export symbols beginning with
++        # underscore (_), so it is better to generate a list of symbols to
++	# export.
++        always_export_symbols_CXX=yes
++	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++          # Warning - without using the other runtime loading flags (-brtl),
++          # -berok will link without error, but may produce a broken library.
++          # The "-G" linker flag allows undefined symbols.
++          no_undefined_flag_CXX='-bernotok'
++          # Determine the default libpath from the value encoded in an empty
++          # executable.
++          if test set = "${lt_cv_aix_libpath+set}"; then
++  aix_libpath=$lt_cv_aix_libpath
++else
++  if test ${lt_cv_aix_libpath__CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_link "$LINENO"
++then :
++
++  lt_aix_libpath_sed='
++      /Import File Strings/,/^$/ {
++	  /^0/ {
++	      s/^0  *\([^ ]*\) *$/\1/
++	      p
++	  }
++      }'
++  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  # Check for a 64-bit object if we didn't find anything.
++  if test -z "$lt_cv_aix_libpath__CXX"; then
++    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++  if test -z "$lt_cv_aix_libpath__CXX"; then
++    lt_cv_aix_libpath__CXX=/usr/lib:/lib
++  fi
++
++fi
++
++  aix_libpath=$lt_cv_aix_libpath__CXX
++fi
++
++          hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
++
++          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++        else
++          if test ia64 = "$host_cpu"; then
++	    hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib'
++	    allow_undefined_flag_CXX="-z nodefs"
++	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++          else
++	    # Determine the default libpath from the value encoded in an
++	    # empty executable.
++	    if test set = "${lt_cv_aix_libpath+set}"; then
++  aix_libpath=$lt_cv_aix_libpath
++else
++  if test ${lt_cv_aix_libpath__CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_link "$LINENO"
++then :
++
++  lt_aix_libpath_sed='
++      /Import File Strings/,/^$/ {
++	  /^0/ {
++	      s/^0  *\([^ ]*\) *$/\1/
++	      p
++	  }
++      }'
++  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  # Check for a 64-bit object if we didn't find anything.
++  if test -z "$lt_cv_aix_libpath__CXX"; then
++    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++  fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++  if test -z "$lt_cv_aix_libpath__CXX"; then
++    lt_cv_aix_libpath__CXX=/usr/lib:/lib
++  fi
++
++fi
++
++  aix_libpath=$lt_cv_aix_libpath__CXX
++fi
++
++	    hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
++	    # Warning - without using the other run time loading flags,
++	    # -berok will link without error, but may produce a broken library.
++	    no_undefined_flag_CXX=' $wl-bernotok'
++	    allow_undefined_flag_CXX=' $wl-berok'
++	    if test yes = "$with_gnu_ld"; then
++	      # We only use this code for GNU lds that support --whole-archive.
++	      whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
++	    else
++	      # Exported symbols can be pulled into shared objects from archives
++	      whole_archive_flag_spec_CXX='$convenience'
++	    fi
++	    archive_cmds_need_lc_CXX=yes
++	    archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
++	    # -brtl affects multiple linker settings, -berok does not and is overridden later
++	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
++	    if test svr4 != "$with_aix_soname"; then
++	      # This is similar to how AIX traditionally builds its shared
++	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
++	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
++	    fi
++	    if test aix != "$with_aix_soname"; then
++	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
++	    else
++	      # used by -dlpreopen to get the symbols
++	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
++	    fi
++	    archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d'
++          fi
++        fi
++        ;;
++
++      beos*)
++	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
++	  allow_undefined_flag_CXX=unsupported
++	  # Joseph Beckenbach  says some releases of gcc
++	  # support --undefined.  This deserves some investigation.  FIXME
++	  archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	else
++	  ld_shlibs_CXX=no
++	fi
++	;;
++
++      chorus*)
++        case $cc_basename in
++          *)
++	  # FIXME: insert proper C++ library support
++	  ld_shlibs_CXX=no
++	  ;;
++        esac
++        ;;
++
++      cygwin* | mingw* | pw32* | cegcc*)
++	case $GXX,$cc_basename in
++	,cl* | no,cl* | ,icl* | no,icl*)
++	  # Native MSVC or ICC
++	  # hardcode_libdir_flag_spec is actually meaningless, as there is
++	  # no search path for DLLs.
++	  hardcode_libdir_flag_spec_CXX=' '
++	  allow_undefined_flag_CXX=unsupported
++	  always_export_symbols_CXX=yes
++	  file_list_spec_CXX='@'
++	  # Tell ltmain to make .lib files, not .a files.
++	  libext=lib
++	  # Tell ltmain to make .dll files, not .so files.
++	  shrext_cmds=.dll
++	  # FIXME: Setting linknames here is a bad hack.
++	  archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
++	  archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
++              cp "$export_symbols" "$output_objdir/$soname.def";
++              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
++            else
++              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
++            fi~
++            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
++            linknames='
++	  # The linker will not automatically build a static lib if we build a DLL.
++	  # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true'
++	  enable_shared_with_static_runtimes_CXX=yes
++	  # Don't use ranlib
++	  old_postinstall_cmds_CXX='chmod 644 $oldlib'
++	  postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~
++            lt_tool_outputfile="@TOOL_OUTPUT@"~
++            case $lt_outputfile in
++              *.exe|*.EXE) ;;
++              *)
++                lt_outputfile=$lt_outputfile.exe
++                lt_tool_outputfile=$lt_tool_outputfile.exe
++                ;;
++            esac~
++            func_to_tool_file "$lt_outputfile"~
++            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
++              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
++              $RM "$lt_outputfile.manifest";
++            fi'
++	  ;;
++	*)
++	  # g++
++	  # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
++	  # as there is no search path for DLLs.
++	  hardcode_libdir_flag_spec_CXX='-L$libdir'
++	  export_dynamic_flag_spec_CXX='$wl--export-all-symbols'
++	  allow_undefined_flag_CXX=unsupported
++	  always_export_symbols_CXX=no
++	  enable_shared_with_static_runtimes_CXX=yes
++
++	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++	    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	    # If the export-symbols file already is a .def file, use it as
++	    # is; otherwise, prepend EXPORTS...
++	    archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
++              cp $export_symbols $output_objdir/$soname.def;
++            else
++              echo EXPORTS > $output_objdir/$soname.def;
++              cat $export_symbols >> $output_objdir/$soname.def;
++            fi~
++            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	  else
++	    ld_shlibs_CXX=no
++	  fi
++	  ;;
++	esac
++	;;
++      darwin* | rhapsody*)
++
++
++  archive_cmds_need_lc_CXX=no
++  hardcode_direct_CXX=no
++  hardcode_automatic_CXX=yes
++  hardcode_shlibpath_var_CXX=unsupported
++  if test yes = "$lt_cv_ld_force_load"; then
++    whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
++
++  else
++    whole_archive_flag_spec_CXX=''
++  fi
++  link_all_deplibs_CXX=yes
++  allow_undefined_flag_CXX=$_lt_dar_allow_undefined
++  case $cc_basename in
++     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
++     *) _lt_dar_can_shared=$GCC ;;
++  esac
++  if test yes = "$_lt_dar_can_shared"; then
++    output_verbose_link_cmd=func_echo_all
++    archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
++    module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
++    archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
++    module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
++       if test yes != "$lt_cv_apple_cc_single_mod"; then
++      archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
++      archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
++    fi
++
++  else
++  ld_shlibs_CXX=no
++  fi
++
++	;;
++
++      os2*)
++	hardcode_libdir_flag_spec_CXX='-L$libdir'
++	hardcode_minus_L_CXX=yes
++	allow_undefined_flag_CXX=unsupported
++	shrext_cmds=.dll
++	archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	  $ECHO EXPORTS >> $output_objdir/$libname.def~
++	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
++	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	  emximp -o $lib $output_objdir/$libname.def'
++	archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
++	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
++	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
++	  $ECHO EXPORTS >> $output_objdir/$libname.def~
++	  prefix_cmds="$SED"~
++	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
++	    prefix_cmds="$prefix_cmds -e 1d";
++	  fi~
++	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
++	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
++	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
++	  emximp -o $lib $output_objdir/$libname.def'
++	old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
++	enable_shared_with_static_runtimes_CXX=yes
++	file_list_spec_CXX='@'
++	;;
++
++      dgux*)
++        case $cc_basename in
++          ec++*)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          ghcx*)
++	    # Green Hills C++ Compiler
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          *)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++        esac
++        ;;
++
++      freebsd2.*)
++        # C++ shared libraries reported to be fairly broken before
++	# switch to ELF
++        ld_shlibs_CXX=no
++        ;;
++
++      freebsd-elf*)
++        archive_cmds_need_lc_CXX=no
++        ;;
++
++      freebsd* | dragonfly* | midnightbsd*)
++        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
++        # conventions
++        ld_shlibs_CXX=yes
++        ;;
++
++      haiku*)
++        archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++        link_all_deplibs_CXX=yes
++        ;;
++
++      hpux9*)
++        hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
++        hardcode_libdir_separator_CXX=:
++        export_dynamic_flag_spec_CXX='$wl-E'
++        hardcode_direct_CXX=yes
++        hardcode_minus_L_CXX=yes # Not in the search PATH,
++				             # but as the default
++				             # location of the library.
++
++        case $cc_basename in
++          CC*)
++            # FIXME: insert proper C++ library support
++            ld_shlibs_CXX=no
++            ;;
++          aCC*)
++            archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++            # Commands to make compiler produce verbose output that lists
++            # what "hidden" libraries, object files and flags are used when
++            # linking a shared library.
++            #
++            # There doesn't appear to be a way to prevent this compiler from
++            # explicitly linking system object files so we need to strip them
++            # from the output so that they don't get included in the library
++            # dependencies.
++            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++            ;;
++          *)
++            if test yes = "$GXX"; then
++              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++            else
++              # FIXME: insert proper C++ library support
++              ld_shlibs_CXX=no
++            fi
++            ;;
++        esac
++        ;;
++
++      hpux10*|hpux11*)
++        if test no = "$with_gnu_ld"; then
++	  hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
++	  hardcode_libdir_separator_CXX=:
++
++          case $host_cpu in
++            hppa*64*|ia64*)
++              ;;
++            *)
++	      export_dynamic_flag_spec_CXX='$wl-E'
++              ;;
++          esac
++        fi
++        case $host_cpu in
++          hppa*64*|ia64*)
++            hardcode_direct_CXX=no
++            hardcode_shlibpath_var_CXX=no
++            ;;
++          *)
++            hardcode_direct_CXX=yes
++            hardcode_direct_absolute_CXX=yes
++            hardcode_minus_L_CXX=yes # Not in the search PATH,
++					         # but as the default
++					         # location of the library.
++            ;;
++        esac
++
++        case $cc_basename in
++          CC*)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          aCC*)
++	    case $host_cpu in
++	      hppa*64*)
++	        archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        ;;
++	      ia64*)
++	        archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        ;;
++	      *)
++	        archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        ;;
++	    esac
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    ;;
++          *)
++	    if test yes = "$GXX"; then
++	      if test no = "$with_gnu_ld"; then
++	        case $host_cpu in
++	          hppa*64*)
++	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            ;;
++	          ia64*)
++	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            ;;
++	          *)
++	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            ;;
++	        esac
++	      fi
++	    else
++	      # FIXME: insert proper C++ library support
++	      ld_shlibs_CXX=no
++	    fi
++	    ;;
++        esac
++        ;;
++
++      interix[3-9]*)
++	hardcode_direct_CXX=no
++	hardcode_shlibpath_var_CXX=no
++	hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
++	export_dynamic_flag_spec_CXX='$wl-E'
++	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
++	# Instead, shared libraries are loaded at an image base (0x10000000 by
++	# default) and relocated if they conflict, which is a slow very memory
++	# consuming and fragmenting process.  To avoid this, we pick a random,
++	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
++	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
++	archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++	archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++	;;
++      irix5* | irix6*)
++        case $cc_basename in
++          CC*)
++	    # SGI C++
++	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++
++	    # Archives containing C++ object files must be created using
++	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
++	    # necessary to make sure instantiated templates are included
++	    # in the archive.
++	    old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
++	    ;;
++          *)
++	    if test yes = "$GXX"; then
++	      if test no = "$with_gnu_ld"; then
++	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	      else
++	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
++	      fi
++	    fi
++	    link_all_deplibs_CXX=yes
++	    ;;
++        esac
++        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++        hardcode_libdir_separator_CXX=:
++        inherit_rpath_CXX=yes
++        ;;
++
++      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++        case $cc_basename in
++          KCC*)
++	    # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++	    # KCC will only create a shared library if the output file
++	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
++	    # to its proper name (with version) after linking.
++	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++	    archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++
++	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
++	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++
++	    # Archives containing C++ object files must be created using
++	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
++	    old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
++	    ;;
++	  icpc* | ecpc* )
++	    # Intel C++
++	    with_gnu_ld=yes
++	    # version 8.0 and above of icpc choke on multiply defined symbols
++	    # if we add $predep_objects and $postdep_objects, however 7.1 and
++	    # earlier do not add the objects themselves.
++	    case `$CC -V 2>&1` in
++	      *"Version 7."*)
++	        archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++		archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++		;;
++	      *)  # Version 8.0 or newer
++	        tmp_idyn=
++	        case $host_cpu in
++		  ia64*) tmp_idyn=' -i_dynamic';;
++		esac
++	        archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++		archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++		;;
++	    esac
++	    archive_cmds_need_lc_CXX=no
++	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
++	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++	    whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
++	    ;;
++          pgCC* | pgcpp*)
++            # Portland Group C++ compiler
++	    case `$CC -V` in
++	    *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
++	      prelink_cmds_CXX='tpldir=Template.dir~
++               rm -rf $tpldir~
++               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
++               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
++	      old_archive_cmds_CXX='tpldir=Template.dir~
++                rm -rf $tpldir~
++                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
++                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
++                $RANLIB $oldlib'
++	      archive_cmds_CXX='tpldir=Template.dir~
++                rm -rf $tpldir~
++                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++	      archive_expsym_cmds_CXX='tpldir=Template.dir~
++                rm -rf $tpldir~
++                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	      ;;
++	    *) # Version 6 and above use weak symbols
++	      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++	      archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	      ;;
++	    esac
++
++	    hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir'
++	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++	    whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++            ;;
++	  cxx*)
++	    # Compaq C++
++	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++	    archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
++
++	    runpath_var=LD_RUN_PATH
++	    hardcode_libdir_flag_spec_CXX='-rpath $libdir'
++	    hardcode_libdir_separator_CXX=:
++
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
++	    ;;
++	  xl* | mpixl* | bgxl*)
++	    # IBM XL 8.0 on PPC, with GNU ld
++	    hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++	    archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	    if test yes = "$supports_anon_versioning"; then
++	      archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
++                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++                echo "local: *; };" >> $output_objdir/$libname.ver~
++                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++	    fi
++	    ;;
++	  *)
++	    case `$CC -V 2>&1 | $SED 5q` in
++	    *Sun\ C*)
++	      # Sun C++ 5.9
++	      no_undefined_flag_CXX=' -zdefs'
++	      archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	      archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
++	      hardcode_libdir_flag_spec_CXX='-R$libdir'
++	      whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	      compiler_needs_object_CXX=yes
++
++	      # Not sure whether something based on
++	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
++	      # would be better.
++	      output_verbose_link_cmd='func_echo_all'
++
++	      # Archives containing C++ object files must be created using
++	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
++	      # necessary to make sure instantiated templates are included
++	      # in the archive.
++	      old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
++	      ;;
++	    esac
++	    ;;
++	esac
++	;;
++
++      lynxos*)
++        # FIXME: insert proper C++ library support
++	ld_shlibs_CXX=no
++	;;
++
++      m88k*)
++        # FIXME: insert proper C++ library support
++        ld_shlibs_CXX=no
++	;;
++
++      mvs*)
++        case $cc_basename in
++          cxx*)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++	  *)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++	esac
++	;;
++
++      netbsd*)
++        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++	  archive_cmds_CXX='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
++	  wlarc=
++	  hardcode_libdir_flag_spec_CXX='-R$libdir'
++	  hardcode_direct_CXX=yes
++	  hardcode_shlibpath_var_CXX=no
++	fi
++	# Workaround some broken pre-1.5 toolchains
++	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
++	;;
++
++      *nto* | *qnx*)
++        ld_shlibs_CXX=yes
++	;;
++
++      openbsd* | bitrig*)
++	if test -f /usr/libexec/ld.so; then
++	  hardcode_direct_CXX=yes
++	  hardcode_shlibpath_var_CXX=no
++	  hardcode_direct_absolute_CXX=yes
++	  archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
++	  hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
++	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
++	    archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
++	    export_dynamic_flag_spec_CXX='$wl-E'
++	    whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++	  fi
++	  output_verbose_link_cmd=func_echo_all
++	else
++	  ld_shlibs_CXX=no
++	fi
++	;;
++
++      osf3* | osf4* | osf5*)
++        case $cc_basename in
++          KCC*)
++	    # Kuck and Associates, Inc. (KAI) C++ Compiler
++
++	    # KCC will only create a shared library if the output file
++	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
++	    # to its proper name (with version) after linking.
++	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++
++	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
++	    hardcode_libdir_separator_CXX=:
++
++	    # Archives containing C++ object files must be created using
++	    # the KAI C++ compiler.
++	    case $host in
++	      osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;;
++	      *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;;
++	    esac
++	    ;;
++          RCC*)
++	    # Rational C++ 2.4.1
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          cxx*)
++	    case $host in
++	      osf3*)
++	        allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
++	        archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++		;;
++	      *)
++	        allow_undefined_flag_CXX=' -expect_unresolved \*'
++	        archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	        archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
++                  echo "-hidden">> $lib.exp~
++                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
++                  $RM $lib.exp'
++	        hardcode_libdir_flag_spec_CXX='-rpath $libdir'
++		;;
++	    esac
++
++	    hardcode_libdir_separator_CXX=:
++
++	    # Commands to make compiler produce verbose output that lists
++	    # what "hidden" libraries, object files and flags are used when
++	    # linking a shared library.
++	    #
++	    # There doesn't appear to be a way to prevent this compiler from
++	    # explicitly linking system object files so we need to strip them
++	    # from the output so that they don't get included in the library
++	    # dependencies.
++	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    ;;
++	  *)
++	    if test yes,no = "$GXX,$with_gnu_ld"; then
++	      allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
++	      case $host in
++	        osf3*)
++	          archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++		  ;;
++	        *)
++	          archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++		  ;;
++	      esac
++
++	      hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++	      hardcode_libdir_separator_CXX=:
++
++	      # Commands to make compiler produce verbose output that lists
++	      # what "hidden" libraries, object files and flags are used when
++	      # linking a shared library.
++	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++
++	    else
++	      # FIXME: insert proper C++ library support
++	      ld_shlibs_CXX=no
++	    fi
++	    ;;
++        esac
++        ;;
++
++      psos*)
++        # FIXME: insert proper C++ library support
++        ld_shlibs_CXX=no
++        ;;
++
++      sunos4*)
++        case $cc_basename in
++          CC*)
++	    # Sun C++ 4.x
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          lcc*)
++	    # Lucid
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          *)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++        esac
++        ;;
++
++      solaris*)
++        case $cc_basename in
++          CC* | sunCC*)
++	    # Sun C++ 4.2, 5.x and Centerline C++
++            archive_cmds_need_lc_CXX=yes
++	    no_undefined_flag_CXX=' -zdefs'
++	    archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	    archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++	    hardcode_libdir_flag_spec_CXX='-R$libdir'
++	    hardcode_shlibpath_var_CXX=no
++	    case $host_os in
++	      solaris2.[0-5] | solaris2.[0-5].*) ;;
++	      *)
++		# The compiler driver will combine and reorder linker options,
++		# but understands '-z linker_flag'.
++	        # Supported since Solaris 2.6 (maybe 2.5.1?)
++		whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
++	        ;;
++	    esac
++	    link_all_deplibs_CXX=yes
++
++	    output_verbose_link_cmd='func_echo_all'
++
++	    # Archives containing C++ object files must be created using
++	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
++	    # necessary to make sure instantiated templates are included
++	    # in the archive.
++	    old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
++	    ;;
++          gcx*)
++	    # Green Hills C++ Compiler
++	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++
++	    # The C++ compiler must be used to create the archive.
++	    old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
++	    ;;
++          *)
++	    # GNU C++ compiler with Solaris linker
++	    if test yes,no = "$GXX,$with_gnu_ld"; then
++	      no_undefined_flag_CXX=' $wl-z ${wl}defs'
++	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
++	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++	        # Commands to make compiler produce verbose output that lists
++	        # what "hidden" libraries, object files and flags are used when
++	        # linking a shared library.
++	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++	      else
++	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
++	        # platform.
++	        archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
++                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++
++	        # Commands to make compiler produce verbose output that lists
++	        # what "hidden" libraries, object files and flags are used when
++	        # linking a shared library.
++	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
++	      fi
++
++	      hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir'
++	      case $host_os in
++		solaris2.[0-5] | solaris2.[0-5].*) ;;
++		*)
++		  whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++		  ;;
++	      esac
++	    fi
++	    ;;
++        esac
++        ;;
++
++    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
++      no_undefined_flag_CXX='$wl-z,text'
++      archive_cmds_need_lc_CXX=no
++      hardcode_shlibpath_var_CXX=no
++      runpath_var='LD_RUN_PATH'
++
++      case $cc_basename in
++        CC*)
++	  archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++	*)
++	  archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  ;;
++      esac
++      ;;
++
++      sysv5* | sco3.2v5* | sco5v6*)
++	# Note: We CANNOT use -z defs as we might desire, because we do not
++	# link with -lc, and that would cause any symbols used from libc to
++	# always be unresolved, which means just about no library would
++	# ever link correctly.  If we're not using GNU ld we use -z text
++	# though, which does catch some bad symbols but isn't as heavy-handed
++	# as -z defs.
++	no_undefined_flag_CXX='$wl-z,text'
++	allow_undefined_flag_CXX='$wl-z,nodefs'
++	archive_cmds_need_lc_CXX=no
++	hardcode_shlibpath_var_CXX=no
++	hardcode_libdir_flag_spec_CXX='$wl-R,$libdir'
++	hardcode_libdir_separator_CXX=':'
++	link_all_deplibs_CXX=yes
++	export_dynamic_flag_spec_CXX='$wl-Bexport'
++	runpath_var='LD_RUN_PATH'
++
++	case $cc_basename in
++          CC*)
++	    archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
++              '"$old_archive_cmds_CXX"
++	    reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
++              '"$reload_cmds_CXX"
++	    ;;
++	  *)
++	    archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    ;;
++	esac
++      ;;
++
++      tandem*)
++        case $cc_basename in
++          NCC*)
++	    # NonStop-UX NCC 3.20
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++          *)
++	    # FIXME: insert proper C++ library support
++	    ld_shlibs_CXX=no
++	    ;;
++        esac
++        ;;
++
++      vxworks*)
++        # FIXME: insert proper C++ library support
++        ld_shlibs_CXX=no
++        ;;
++
++      *)
++        # FIXME: insert proper C++ library support
++        ld_shlibs_CXX=no
++        ;;
++    esac
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
++printf "%s\n" "$ld_shlibs_CXX" >&6; }
++    test no = "$ld_shlibs_CXX" && can_build_shared=no
++
++    GCC_CXX=$GXX
++    LD_CXX=$LD
++
++    ## CAVEAT EMPTOR:
++    ## There is no encapsulation within the following macros, do not change
++    ## the running order or otherwise move them around unless you know exactly
++    ## what you are doing...
++    # Dependencies to place before and after the object being linked:
++predep_objects_CXX=
++postdep_objects_CXX=
++predeps_CXX=
++postdeps_CXX=
++compiler_lib_search_path_CXX=
++
++cat > conftest.$ac_ext <<_LT_EOF
++class Foo
++{
++public:
++  Foo (void) { a = 0; }
++private:
++  int a;
++};
++_LT_EOF
++
++
++_lt_libdeps_save_CFLAGS=$CFLAGS
++case "$CC $CFLAGS " in #(
++*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
++*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
++*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
++esac
++
++if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then
++  # Parse the compiler output and extract the necessary
++  # objects, libraries and library flags.
++
++  # Sentinel used to keep track of whether or not we are before
++  # the conftest object file.
++  pre_test_object_deps_done=no
++
++  for p in `eval "$output_verbose_link_cmd"`; do
++    case $prev$p in
++
++    -L* | -R* | -l*)
++       # Some compilers place space between "-{L,R}" and the path.
++       # Remove the space.
++       if test x-L = "$p" ||
++          test x-R = "$p"; then
++	 prev=$p
++	 continue
++       fi
++
++       # Expand the sysroot to ease extracting the directories later.
++       if test -z "$prev"; then
++         case $p in
++         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
++         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
++         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
++         esac
++       fi
++       case $p in
++       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
++       esac
++       if test no = "$pre_test_object_deps_done"; then
++	 case $prev in
++	 -L | -R)
++	   # Internal compiler library paths should come after those
++	   # provided the user.  The postdeps already come after the
++	   # user supplied libs so there is no need to process them.
++	   if test -z "$compiler_lib_search_path_CXX"; then
++	     compiler_lib_search_path_CXX=$prev$p
++	   else
++	     compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p"
++	   fi
++	   ;;
++	 # The "-l" case would never come before the object being
++	 # linked, so don't bother handling this case.
++	 esac
++       else
++	 if test -z "$postdeps_CXX"; then
++	   postdeps_CXX=$prev$p
++	 else
++	   postdeps_CXX="${postdeps_CXX} $prev$p"
++	 fi
++       fi
++       prev=
++       ;;
++
++    *.lto.$objext) ;; # Ignore GCC LTO objects
++    *.$objext)
++       # This assumes that the test object file only shows up
++       # once in the compiler output.
++       if test "$p" = "conftest.$objext"; then
++	 pre_test_object_deps_done=yes
++	 continue
++       fi
++
++       if test no = "$pre_test_object_deps_done"; then
++	 if test -z "$predep_objects_CXX"; then
++	   predep_objects_CXX=$p
++	 else
++	   predep_objects_CXX="$predep_objects_CXX $p"
++	 fi
++       else
++	 if test -z "$postdep_objects_CXX"; then
++	   postdep_objects_CXX=$p
++	 else
++	   postdep_objects_CXX="$postdep_objects_CXX $p"
++	 fi
++       fi
++       ;;
++
++    *) ;; # Ignore the rest.
++
++    esac
++  done
++
++  # Clean up.
++  rm -f a.out a.exe
++else
++  echo "libtool.m4: error: problem compiling CXX test program"
++fi
++
++$RM -f confest.$objext
++CFLAGS=$_lt_libdeps_save_CFLAGS
++
++# PORTME: override above test on systems where it is broken
++case $host_os in
++interix[3-9]*)
++  # Interix 3.5 installs completely hosed .la files for C++, so rather than
++  # hack all around it, let's just trust "g++" to DTRT.
++  predep_objects_CXX=
++  postdep_objects_CXX=
++  postdeps_CXX=
++  ;;
++esac
++
++
++case " $postdeps_CXX " in
++*" -lc "*) archive_cmds_need_lc_CXX=no ;;
++esac
++ compiler_lib_search_dirs_CXX=
++if test -n "${compiler_lib_search_path_CXX}"; then
++ compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'`
++fi
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    lt_prog_compiler_wl_CXX=
++lt_prog_compiler_pic_CXX=
++lt_prog_compiler_static_CXX=
++
++
++  # C++ specific cases for pic, static, wl, etc.
++  if test yes = "$GXX"; then
++    lt_prog_compiler_wl_CXX='-Wl,'
++    lt_prog_compiler_static_CXX='-static'
++
++    case $host_os in
++    aix*)
++      # All AIX code is PIC.
++      if test ia64 = "$host_cpu"; then
++	# AIX 5 now supports IA64 processor
++	lt_prog_compiler_static_CXX='-Bstatic'
++      fi
++      lt_prog_compiler_pic_CXX='-fPIC'
++      ;;
++
++    amigaos*)
++      case $host_cpu in
++      powerpc)
++            # see comment about AmigaOS4 .so support
++            lt_prog_compiler_pic_CXX='-fPIC'
++        ;;
++      m68k)
++            # FIXME: we need at least 68020 code to build shared libraries, but
++            # adding the '-m68020' flag to GCC prevents building anything better,
++            # like '-m68040'.
++            lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
++        ;;
++      esac
++      ;;
++
++    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
++      # PIC is the default for these OSes.
++      ;;
++    mingw* | cygwin* | os2* | pw32* | cegcc*)
++      # This hack is so that the source file can tell whether it is being
++      # built for inclusion in a dll (and should export symbols for example).
++      # Although the cygwin gcc ignores -fPIC, still need this for old-style
++      # (--disable-auto-import) libraries
++      lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
++      case $host_os in
++      os2*)
++	lt_prog_compiler_static_CXX='$wl-static'
++	;;
++      esac
++      ;;
++    darwin* | rhapsody*)
++      # PIC is the default on this platform
++      # Common symbols not allowed in MH_DYLIB files
++      lt_prog_compiler_pic_CXX='-fno-common'
++      ;;
++    *djgpp*)
++      # DJGPP does not support shared libraries at all
++      lt_prog_compiler_pic_CXX=
++      ;;
++    haiku*)
++      # PIC is the default for Haiku.
++      # The "-static" flag exists, but is broken.
++      lt_prog_compiler_static_CXX=
++      ;;
++    interix[3-9]*)
++      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
++      # Instead, we relocate shared libraries at runtime.
++      ;;
++    sysv4*MP*)
++      if test -d /usr/nec; then
++	lt_prog_compiler_pic_CXX=-Kconform_pic
++      fi
++      ;;
++    hpux*)
++      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
++      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
++      # sets the default TLS model and affects inlining.
++      case $host_cpu in
++      hppa*64*)
++	;;
++      *)
++	lt_prog_compiler_pic_CXX='-fPIC'
++	;;
++      esac
++      ;;
++    *qnx* | *nto*)
++      # QNX uses GNU C++, but need to define -shared option too, otherwise
++      # it will coredump.
++      lt_prog_compiler_pic_CXX='-fPIC -shared'
++      ;;
++    *)
++      lt_prog_compiler_pic_CXX='-fPIC'
++      ;;
++    esac
++  else
++    case $host_os in
++      aix[4-9]*)
++	# All AIX code is PIC.
++	if test ia64 = "$host_cpu"; then
++	  # AIX 5 now supports IA64 processor
++	  lt_prog_compiler_static_CXX='-Bstatic'
++	else
++	  lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
++	fi
++	;;
++      chorus*)
++	case $cc_basename in
++	cxch68*)
++	  # Green Hills C++ Compiler
++	  # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
++	  ;;
++	esac
++	;;
++      mingw* | cygwin* | os2* | pw32* | cegcc*)
++	# This hack is so that the source file can tell whether it is being
++	# built for inclusion in a dll (and should export symbols for example).
++	lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
++	;;
++      dgux*)
++	case $cc_basename in
++	  ec++*)
++	    lt_prog_compiler_pic_CXX='-KPIC'
++	    ;;
++	  ghcx*)
++	    # Green Hills C++ Compiler
++	    lt_prog_compiler_pic_CXX='-pic'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      freebsd* | dragonfly* | midnightbsd*)
++	# FreeBSD uses GNU C++
++	;;
++      hpux9* | hpux10* | hpux11*)
++	case $cc_basename in
++	  CC*)
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
++	    if test ia64 != "$host_cpu"; then
++	      lt_prog_compiler_pic_CXX='+Z'
++	    fi
++	    ;;
++	  aCC*)
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
++	    case $host_cpu in
++	    hppa*64*|ia64*)
++	      # +Z the default
++	      ;;
++	    *)
++	      lt_prog_compiler_pic_CXX='+Z'
++	      ;;
++	    esac
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      interix*)
++	# This is c89, which is MS Visual C++ (no shared libs)
++	# Anyone wants to do a port?
++	;;
++      irix5* | irix6* | nonstopux*)
++	case $cc_basename in
++	  CC*)
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_static_CXX='-non_shared'
++	    # CC pic flag -KPIC is the default.
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++	case $cc_basename in
++	  KCC*)
++	    # KAI C++ Compiler
++	    lt_prog_compiler_wl_CXX='--backend -Wl,'
++	    lt_prog_compiler_pic_CXX='-fPIC'
++	    ;;
++	  ecpc* )
++	    # old Intel C++ for x86_64, which still supported -KPIC.
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_pic_CXX='-KPIC'
++	    lt_prog_compiler_static_CXX='-static'
++	    ;;
++	  icpc* )
++	    # Intel C++, used to be incompatible with GCC.
++	    # ICC 10 doesn't accept -KPIC any more.
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_pic_CXX='-fPIC'
++	    lt_prog_compiler_static_CXX='-static'
++	    ;;
++	  pgCC* | pgcpp*)
++	    # Portland Group C++ compiler
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_pic_CXX='-fpic'
++	    lt_prog_compiler_static_CXX='-Bstatic'
++	    ;;
++	  cxx*)
++	    # Compaq C++
++	    # Make sure the PIC flag is empty.  It appears that all Alpha
++	    # Linux and Compaq Tru64 Unix objects are PIC.
++	    lt_prog_compiler_pic_CXX=
++	    lt_prog_compiler_static_CXX='-non_shared'
++	    ;;
++	  xlc* | xlC* | bgxl[cC]* | mpixl[cC]*)
++	    # IBM XL 8.0, 9.0 on PPC and BlueGene
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_pic_CXX='-qpic'
++	    lt_prog_compiler_static_CXX='-qstaticlink'
++	    ;;
++	  *)
++	    case `$CC -V 2>&1 | $SED 5q` in
++	    *Sun\ C*)
++	      # Sun C++ 5.9
++	      lt_prog_compiler_pic_CXX='-KPIC'
++	      lt_prog_compiler_static_CXX='-Bstatic'
++	      lt_prog_compiler_wl_CXX='-Qoption ld '
++	      ;;
++	    esac
++	    ;;
++	esac
++	;;
++      lynxos*)
++	;;
++      m88k*)
++	;;
++      mvs*)
++	case $cc_basename in
++	  cxx*)
++	    lt_prog_compiler_pic_CXX='-W c,exportall'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      netbsd*)
++	;;
++      *qnx* | *nto*)
++        # QNX uses GNU C++, but need to define -shared option too, otherwise
++        # it will coredump.
++        lt_prog_compiler_pic_CXX='-fPIC -shared'
++        ;;
++      osf3* | osf4* | osf5*)
++	case $cc_basename in
++	  KCC*)
++	    lt_prog_compiler_wl_CXX='--backend -Wl,'
++	    ;;
++	  RCC*)
++	    # Rational C++ 2.4.1
++	    lt_prog_compiler_pic_CXX='-pic'
++	    ;;
++	  cxx*)
++	    # Digital/Compaq C++
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    # Make sure the PIC flag is empty.  It appears that all Alpha
++	    # Linux and Compaq Tru64 Unix objects are PIC.
++	    lt_prog_compiler_pic_CXX=
++	    lt_prog_compiler_static_CXX='-non_shared'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      psos*)
++	;;
++      solaris*)
++	case $cc_basename in
++	  CC* | sunCC*)
++	    # Sun C++ 4.2, 5.x and Centerline C++
++	    lt_prog_compiler_pic_CXX='-KPIC'
++	    lt_prog_compiler_static_CXX='-Bstatic'
++	    lt_prog_compiler_wl_CXX='-Qoption ld '
++	    ;;
++	  gcx*)
++	    # Green Hills C++ Compiler
++	    lt_prog_compiler_pic_CXX='-PIC'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      sunos4*)
++	case $cc_basename in
++	  CC*)
++	    # Sun C++ 4.x
++	    lt_prog_compiler_pic_CXX='-pic'
++	    lt_prog_compiler_static_CXX='-Bstatic'
++	    ;;
++	  lcc*)
++	    # Lucid
++	    lt_prog_compiler_pic_CXX='-pic'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
++	case $cc_basename in
++	  CC*)
++	    lt_prog_compiler_wl_CXX='-Wl,'
++	    lt_prog_compiler_pic_CXX='-KPIC'
++	    lt_prog_compiler_static_CXX='-Bstatic'
++	    ;;
++	esac
++	;;
++      tandem*)
++	case $cc_basename in
++	  NCC*)
++	    # NonStop-UX NCC 3.20
++	    lt_prog_compiler_pic_CXX='-KPIC'
++	    ;;
++	  *)
++	    ;;
++	esac
++	;;
++      vxworks*)
++	;;
++      *)
++	lt_prog_compiler_can_build_shared_CXX=no
++	;;
++    esac
++  fi
++
++case $host_os in
++  # For platforms that do not support PIC, -DPIC is meaningless:
++  *djgpp*)
++    lt_prog_compiler_pic_CXX=
++    ;;
++  *)
++    lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
++    ;;
++esac
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
++printf %s "checking for $compiler option to produce PIC... " >&6; }
++if test ${lt_cv_prog_compiler_pic_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5
++printf "%s\n" "$lt_cv_prog_compiler_pic_CXX" >&6; }
++lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX
++
++#
++# Check to make sure the PIC flag actually works.
++#
++if test -n "$lt_prog_compiler_pic_CXX"; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
++printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
++if test ${lt_cv_prog_compiler_pic_works_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_pic_works_CXX=no
++   ac_outfile=conftest.$ac_objext
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"  ## exclude from sc_useless_quotes_in_assignment
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   # The option is referenced via a variable to avoid confusing sed.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>conftest.err)
++   ac_status=$?
++   cat conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s "$ac_outfile"; then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings other than the usual output.
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
++     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_pic_works_CXX=yes
++     fi
++   fi
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
++printf "%s\n" "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
++
++if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then
++    case $lt_prog_compiler_pic_CXX in
++     "" | " "*) ;;
++     *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
++     esac
++else
++    lt_prog_compiler_pic_CXX=
++     lt_prog_compiler_can_build_shared_CXX=no
++fi
++
++fi
++
++
++
++
++
++#
++# Check to make sure the static flag actually works.
++#
++wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
++printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
++if test ${lt_cv_prog_compiler_static_works_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_static_works_CXX=no
++   save_LDFLAGS=$LDFLAGS
++   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
++   echo "$lt_simple_link_test_code" > conftest.$ac_ext
++   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
++     # The linker can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     if test -s conftest.err; then
++       # Append any errors to the config.log.
++       cat conftest.err 1>&5
++       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
++       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
++       if diff conftest.exp conftest.er2 >/dev/null; then
++         lt_cv_prog_compiler_static_works_CXX=yes
++       fi
++     else
++       lt_cv_prog_compiler_static_works_CXX=yes
++     fi
++   fi
++   $RM -r conftest*
++   LDFLAGS=$save_LDFLAGS
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
++printf "%s\n" "$lt_cv_prog_compiler_static_works_CXX" >&6; }
++
++if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then
++    :
++else
++    lt_prog_compiler_static_CXX=
++fi
++
++
++
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if test ${lt_cv_prog_compiler_c_o_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_c_o_CXX=no
++   $RM -r conftest 2>/dev/null
++   mkdir conftest
++   cd conftest
++   mkdir out
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++   lt_compiler_flag="-o out/conftest2.$ac_objext"
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>out/conftest.err)
++   ac_status=$?
++   cat out/conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s out/conftest2.$ac_objext
++   then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
++     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
++     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_c_o_CXX=yes
++     fi
++   fi
++   chmod u+w . 2>&5
++   $RM conftest*
++   # SGI C++ compiler will create directory out/ii_files/ for
++   # template instantiation
++   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
++   $RM out/* && rmdir out
++   cd ..
++   $RM -r conftest
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
++printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; }
++
++
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if test ${lt_cv_prog_compiler_c_o_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_prog_compiler_c_o_CXX=no
++   $RM -r conftest 2>/dev/null
++   mkdir conftest
++   cd conftest
++   mkdir out
++   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++   lt_compiler_flag="-o out/conftest2.$ac_objext"
++   # Insert the option either (1) after the last *FLAGS variable, or
++   # (2) before a word containing "conftest.", or (3) at the end.
++   # Note that $ac_compile itself does not contain backslashes and begins
++   # with a dollar sign (not a hyphen), so the echo should work correctly.
++   lt_compile=`echo "$ac_compile" | $SED \
++   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
++   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
++   -e 's:$: $lt_compiler_flag:'`
++   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
++   (eval "$lt_compile" 2>out/conftest.err)
++   ac_status=$?
++   cat out/conftest.err >&5
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   if (exit $ac_status) && test -s out/conftest2.$ac_objext
++   then
++     # The compiler can only warn and ignore the option if not recognized
++     # So say no if there are warnings
++     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
++     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
++     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
++       lt_cv_prog_compiler_c_o_CXX=yes
++     fi
++   fi
++   chmod u+w . 2>&5
++   $RM conftest*
++   # SGI C++ compiler will create directory out/ii_files/ for
++   # template instantiation
++   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
++   $RM out/* && rmdir out
++   cd ..
++   $RM -r conftest
++   $RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
++printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; }
++
++
++
++
++hard_links=nottested
++if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then
++  # do not overwrite the value of need_locks provided by the user
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
++printf %s "checking if we can lock with hard links... " >&6; }
++  hard_links=yes
++  $RM conftest*
++  ln conftest.a conftest.b 2>/dev/null && hard_links=no
++  touch conftest.a
++  ln conftest.a conftest.b 2>&5 || hard_links=no
++  ln conftest.a conftest.b 2>/dev/null && hard_links=no
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
++printf "%s\n" "$hard_links" >&6; }
++  if test no = "$hard_links"; then
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
++printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
++    need_locks=warn
++  fi
++else
++  need_locks=no
++fi
++
++
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
++printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
++
++  export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
++  case $host_os in
++  aix[4-9]*)
++    # If we're using GNU nm, then we don't want the "-C" option.
++    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
++    # Without the "-l" option, or with the "-B" option, AIX nm treats
++    # weak defined symbols like other global defined symbols, whereas
++    # GNU nm marks them as "W".
++    # While the 'weak' keyword is ignored in the Export File, we need
++    # it in the Import File for the 'aix-soname' feature, so we have
++    # to replace the "-B" option with "-P" for AIX nm.
++    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
++      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++    else
++      export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++    fi
++    ;;
++  pw32*)
++    export_symbols_cmds_CXX=$ltdll_cmds
++    ;;
++  cygwin* | mingw* | cegcc*)
++    case $cc_basename in
++    cl* | icl*)
++      exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
++      ;;
++    *)
++      export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
++      exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
++      ;;
++    esac
++    ;;
++  *)
++    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
++    ;;
++  esac
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
++printf "%s\n" "$ld_shlibs_CXX" >&6; }
++test no = "$ld_shlibs_CXX" && can_build_shared=no
++
++with_gnu_ld_CXX=$with_gnu_ld
++
++
++
++
++
++
++#
++# Do we need to explicitly link libc?
++#
++case "x$archive_cmds_need_lc_CXX" in
++x|xyes)
++  # Assume -lc should be added
++  archive_cmds_need_lc_CXX=yes
++
++  if test yes,yes = "$GCC,$enable_shared"; then
++    case $archive_cmds_CXX in
++    *'~'*)
++      # FIXME: we may have to deal with multi-command sequences.
++      ;;
++    '$CC '*)
++      # Test whether the compiler implicitly links with -lc since on some
++      # systems, -lgcc has to come before -lc. If gcc already passes -lc
++      # to ld, don't add -lc before -lgcc.
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
++printf %s "checking whether -lc should be explicitly linked in... " >&6; }
++if test ${lt_cv_archive_cmds_need_lc_CXX+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  $RM conftest*
++	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
++
++	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
++  (eval $ac_compile) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } 2>conftest.err; then
++	  soname=conftest
++	  lib=conftest
++	  libobjs=conftest.$ac_objext
++	  deplibs=
++	  wl=$lt_prog_compiler_wl_CXX
++	  pic_flag=$lt_prog_compiler_pic_CXX
++	  compiler_flags=-v
++	  linker_flags=-v
++	  verstring=
++	  output_objdir=.
++	  libname=conftest
++	  lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
++	  allow_undefined_flag_CXX=
++	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
++  (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
++  ac_status=$?
++  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }
++	  then
++	    lt_cv_archive_cmds_need_lc_CXX=no
++	  else
++	    lt_cv_archive_cmds_need_lc_CXX=yes
++	  fi
++	  allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
++	else
++	  cat conftest.err 1>&5
++	fi
++	$RM conftest*
++
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
++printf "%s\n" "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
++      archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
++      ;;
++    esac
++  fi
++  ;;
++esac
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
++printf %s "checking dynamic linker characteristics... " >&6; }
++
++library_names_spec=
++libname_spec='lib$name'
++soname_spec=
++shrext_cmds=.so
++postinstall_cmds=
++postuninstall_cmds=
++finish_cmds=
++finish_eval=
++shlibpath_var=
++shlibpath_overrides_runpath=unknown
++version_type=none
++dynamic_linker="$host_os ld.so"
++sys_lib_dlsearch_path_spec="/lib /usr/lib"
++need_lib_prefix=unknown
++hardcode_into_libs=no
++
++# when you set need_version to no, make sure it does not cause -set_version
++# flags to be left without arguments
++need_version=unknown
++
++
++
++case $host_os in
++aix3*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
++  shlibpath_var=LIBPATH
++
++  # AIX 3 has no versioning support, so we append a major version to the name.
++  soname_spec='$libname$release$shared_ext$major'
++  ;;
++
++aix[4-9]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  hardcode_into_libs=yes
++  if test ia64 = "$host_cpu"; then
++    # AIX 5 supports IA64
++    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
++    shlibpath_var=LD_LIBRARY_PATH
++  else
++    # With GCC up to 2.95.x, collect2 would create an import file
++    # for dependence libraries.  The import file would start with
++    # the line '#! .'.  This would cause the generated library to
++    # depend on '.', always an invalid library.  This was fixed in
++    # development snapshots of GCC prior to 3.0.
++    case $host_os in
++      aix4 | aix4.[01] | aix4.[01].*)
++      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
++	   echo ' yes '
++	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
++	:
++      else
++	can_build_shared=no
++      fi
++      ;;
++    esac
++    # Using Import Files as archive members, it is possible to support
++    # filename-based versioning of shared library archives on AIX. While
++    # this would work for both with and without runtime linking, it will
++    # prevent static linking of such archives. So we do filename-based
++    # shared library versioning with .so extension only, which is used
++    # when both runtime linking and shared linking is enabled.
++    # Unfortunately, runtime linking may impact performance, so we do
++    # not want this to be the default eventually. Also, we use the
++    # versioned .so libs for executables only if there is the -brtl
++    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
++    # To allow for filename-based versioning support, we need to create
++    # libNAME.so.V as an archive file, containing:
++    # *) an Import File, referring to the versioned filename of the
++    #    archive as well as the shared archive member, telling the
++    #    bitwidth (32 or 64) of that shared object, and providing the
++    #    list of exported symbols of that shared object, eventually
++    #    decorated with the 'weak' keyword
++    # *) the shared object with the F_LOADONLY flag set, to really avoid
++    #    it being seen by the linker.
++    # At run time we better use the real file rather than another symlink,
++    # but for link time we create the symlink libNAME.so -> libNAME.so.V
++
++    case $with_aix_soname,$aix_use_runtimelinking in
++    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
++    # soname into executable. Probably we can add versioning support to
++    # collect2, so additional links can be useful in future.
++    aix,yes) # traditional libtool
++      dynamic_linker='AIX unversionable lib.so'
++      # If using run time linking (on AIX 4.2 or later) use lib.so
++      # instead of lib.a to let people know that these are not
++      # typical AIX shared libraries.
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++      ;;
++    aix,no) # traditional AIX only
++      dynamic_linker='AIX lib.a(lib.so.V)'
++      # We preserve .a as extension for shared libraries through AIX4.2
++      # and later when we are not doing run time linking.
++      library_names_spec='$libname$release.a $libname.a'
++      soname_spec='$libname$release$shared_ext$major'
++      ;;
++    svr4,*) # full svr4 only
++      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
++      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++      # We do not specify a path in Import Files, so LIBPATH fires.
++      shlibpath_overrides_runpath=yes
++      ;;
++    *,yes) # both, prefer svr4
++      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
++      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
++      # unpreferred sharedlib libNAME.a needs extra handling
++      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
++      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
++      # We do not specify a path in Import Files, so LIBPATH fires.
++      shlibpath_overrides_runpath=yes
++      ;;
++    *,no) # both, prefer aix
++      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
++      library_names_spec='$libname$release.a $libname.a'
++      soname_spec='$libname$release$shared_ext$major'
++      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
++      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
++      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
++      ;;
++    esac
++    shlibpath_var=LIBPATH
++  fi
++  ;;
++
++amigaos*)
++  case $host_cpu in
++  powerpc)
++    # Since July 2007 AmigaOS4 officially supports .so libraries.
++    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    ;;
++  m68k)
++    library_names_spec='$libname.ixlibrary $libname.a'
++    # Create ${libname}_ixlibrary.a entries in /sys/libs.
++    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++    ;;
++  esac
++  ;;
++
++beos*)
++  library_names_spec='$libname$shared_ext'
++  dynamic_linker="$host_os ld.so"
++  shlibpath_var=LIBRARY_PATH
++  ;;
++
++bsdi[45]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
++  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
++  # the default ld.so.conf also contains /usr/contrib/lib and
++  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
++  # libtool to hard-code these into programs
++  ;;
++
++cygwin* | mingw* | pw32* | cegcc*)
++  version_type=windows
++  shrext_cmds=.dll
++  need_version=no
++  need_lib_prefix=no
++
++  case $GCC,$cc_basename in
++  yes,*)
++    # gcc
++    library_names_spec='$libname.dll.a'
++    # DLL is installed to $(libdir)/../bin by postinstall_cmds
++    postinstall_cmds='base_file=`basename \$file`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++      dldir=$destdir/`dirname \$dlpath`~
++      test -d \$dldir || mkdir -p \$dldir~
++      $install_prog $dir/$dlname \$dldir/$dlname~
++      chmod a+x \$dldir/$dlname~
++      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++      fi'
++    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++      dlpath=$dir/\$dldll~
++       $RM \$dlpath'
++    shlibpath_overrides_runpath=yes
++
++    case $host_os in
++    cygwin*)
++      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
++      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++
++      ;;
++    mingw* | cegcc*)
++      # MinGW DLLs use traditional 'lib' prefix
++      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      ;;
++    pw32*)
++      # pw32 DLLs use 'pw' prefix rather than 'lib'
++      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      ;;
++    esac
++    dynamic_linker='Win32 ld.exe'
++    ;;
++
++  *,cl* | *,icl*)
++    # Native MSVC or ICC
++    libname_spec='$name'
++    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++    library_names_spec='$libname.dll.lib'
++
++    case $build_os in
++    mingw*)
++      sys_lib_search_path_spec=
++      lt_save_ifs=$IFS
++      IFS=';'
++      for lt_path in $LIB
++      do
++        IFS=$lt_save_ifs
++        # Let DOS variable expansion print the short 8.3 style file name.
++        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
++        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
++      done
++      IFS=$lt_save_ifs
++      # Convert to MSYS style.
++      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
++      ;;
++    cygwin*)
++      # Convert to unix form, then to dos form, then back to unix form
++      # but this time dos style (no spaces!) so that the unix form looks
++      # like /cygdrive/c/PROGRA~1:/cygdr...
++      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
++      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
++      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++      ;;
++    *)
++      sys_lib_search_path_spec=$LIB
++      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
++        # It is most probably a Windows format PATH.
++        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
++      else
++        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
++      fi
++      # FIXME: find the short name or the path components, as spaces are
++      # common. (e.g. "Program Files" -> "PROGRA~1")
++      ;;
++    esac
++
++    # DLL is installed to $(libdir)/../bin by postinstall_cmds
++    postinstall_cmds='base_file=`basename \$file`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++      dldir=$destdir/`dirname \$dlpath`~
++      test -d \$dldir || mkdir -p \$dldir~
++      $install_prog $dir/$dlname \$dldir/$dlname'
++    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
++      dlpath=$dir/\$dldll~
++       $RM \$dlpath'
++    shlibpath_overrides_runpath=yes
++    dynamic_linker='Win32 link.exe'
++    ;;
++
++  *)
++    # Assume MSVC and ICC wrapper
++    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
++    dynamic_linker='Win32 ld.exe'
++    ;;
++  esac
++  # FIXME: first we should search . and the directory the executable is in
++  shlibpath_var=PATH
++  ;;
++
++darwin* | rhapsody*)
++  dynamic_linker="$host_os dyld"
++  version_type=darwin
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
++  soname_spec='$libname$release$major$shared_ext'
++  shlibpath_overrides_runpath=yes
++  shlibpath_var=DYLD_LIBRARY_PATH
++  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
++
++  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
++  ;;
++
++dgux*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  ;;
++
++freebsd* | dragonfly* | midnightbsd*)
++  # DragonFly does not have aout.  When/if they implement a new
++  # versioning mechanism, adjust this.
++  if test -x /usr/bin/objformat; then
++    objformat=`/usr/bin/objformat`
++  else
++    case $host_os in
++    freebsd[23].*) objformat=aout ;;
++    *) objformat=elf ;;
++    esac
++  fi
++  version_type=freebsd-$objformat
++  case $version_type in
++    freebsd-elf*)
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++      soname_spec='$libname$release$shared_ext$major'
++      need_version=no
++      need_lib_prefix=no
++      ;;
++    freebsd-*)
++      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++      need_version=yes
++      ;;
++  esac
++  shlibpath_var=LD_LIBRARY_PATH
++  case $host_os in
++  freebsd2.*)
++    shlibpath_overrides_runpath=yes
++    ;;
++  freebsd3.[01]* | freebsdelf3.[01]*)
++    shlibpath_overrides_runpath=yes
++    hardcode_into_libs=yes
++    ;;
++  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
++  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
++    shlibpath_overrides_runpath=no
++    hardcode_into_libs=yes
++    ;;
++  *) # from 4.6 on, and DragonFly
++    shlibpath_overrides_runpath=yes
++    hardcode_into_libs=yes
++    ;;
++  esac
++  ;;
++
++haiku*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  dynamic_linker="$host_os runtime_loader"
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
++  hardcode_into_libs=yes
++  ;;
++
++hpux9* | hpux10* | hpux11*)
++  # Give a soname corresponding to the major version so that dld.sl refuses to
++  # link against other versions.
++  version_type=sunos
++  need_lib_prefix=no
++  need_version=no
++  case $host_cpu in
++  ia64*)
++    shrext_cmds='.so'
++    hardcode_into_libs=yes
++    dynamic_linker="$host_os dld.so"
++    shlibpath_var=LD_LIBRARY_PATH
++    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    if test 32 = "$HPUX_IA64_MODE"; then
++      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
++      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
++    else
++      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
++      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
++    fi
++    ;;
++  hppa*64*)
++    shrext_cmds='.sl'
++    hardcode_into_libs=yes
++    dynamic_linker="$host_os dld.sl"
++    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
++    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++    ;;
++  *)
++    shrext_cmds='.sl'
++    dynamic_linker="$host_os dld.sl"
++    shlibpath_var=SHLIB_PATH
++    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    ;;
++  esac
++  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
++  postinstall_cmds='chmod 555 $lib'
++  # or fails outright, so override atomically:
++  install_override_mode=555
++  ;;
++
++interix[3-9]*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  ;;
++
++irix5* | irix6* | nonstopux*)
++  case $host_os in
++    nonstopux*) version_type=nonstopux ;;
++    *)
++	if test yes = "$lt_cv_prog_gnu_ld"; then
++		version_type=linux # correct to gnu/linux during the next big refactor
++	else
++		version_type=irix
++	fi ;;
++  esac
++  need_lib_prefix=no
++  need_version=no
++  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
++  case $host_os in
++  irix5* | nonstopux*)
++    libsuff= shlibsuff=
++    ;;
++  *)
++    case $LD in # libtool.m4 will add one of these switches to LD
++    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
++      libsuff= shlibsuff= libmagic=32-bit;;
++    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
++      libsuff=32 shlibsuff=N32 libmagic=N32;;
++    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
++      libsuff=64 shlibsuff=64 libmagic=64-bit;;
++    *) libsuff= shlibsuff= libmagic=never-match;;
++    esac
++    ;;
++  esac
++  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
++  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
++  hardcode_into_libs=yes
++  ;;
++
++# No shared lib support for Linux oldld, aout, or coff.
++linux*oldld* | linux*aout* | linux*coff*)
++  dynamic_linker=no
++  ;;
++
++linux*android*)
++  version_type=none # Android doesn't support versioned libraries.
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext'
++  soname_spec='$libname$release$shared_ext'
++  finish_cmds=
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  hardcode_into_libs=yes
++
++  dynamic_linker='Android linker'
++  # Don't embed -rpath directories since the linker doesn't support them.
++  hardcode_libdir_flag_spec_CXX='-L$libdir'
++  ;;
++
++# This must be glibc/ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++
++  # Some binutils ld are patched to set DT_RUNPATH
++  if test ${lt_cv_shlibpath_overrides_runpath+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  lt_cv_shlibpath_overrides_runpath=no
++    save_LDFLAGS=$LDFLAGS
++    save_libdir=$libdir
++    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
++	 LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
++    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main (void)
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_cxx_try_link "$LINENO"
++then :
++  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
++then :
++  lt_cv_shlibpath_overrides_runpath=yes
++fi
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam \
++    conftest$ac_exeext conftest.$ac_ext
++    LDFLAGS=$save_LDFLAGS
++    libdir=$save_libdir
++
++fi
++
++  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
++
++  # This implies no fast_install, which is unacceptable.
++  # Some rework will be needed to allow for fast_install
++  # before this can be enabled.
++  hardcode_into_libs=yes
++
++  # Add ABI-specific directories to the system library path.
++  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
++
++  # Ideally, we could use ldconfig to report *all* directores which are
++  # searched for libraries, however this is still not possible.  Aside from not
++  # being certain /sbin/ldconfig is available, command
++  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
++  # even though it is searched at run-time.  Try to do the best guess by
++  # appending ld.so.conf contents (and includes) to the search path.
++  if test -f /etc/ld.so.conf; then
++    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
++    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
++  fi
++
++  # We used to test for /lib/ld.so.1 and disable shared libraries on
++  # powerpc, because MkLinux only supported shared libraries with the
++  # GNU dynamic linker.  Since this was broken with cross compilers,
++  # most powerpc-linux boxes support dynamic linking these days and
++  # people can always --disable-shared, the test was removed, and we
++  # assume the GNU/Linux dynamic linker is in use.
++  dynamic_linker='GNU/Linux ld.so'
++  ;;
++
++netbsd*)
++  version_type=sunos
++  need_lib_prefix=no
++  need_version=no
++  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++    dynamic_linker='NetBSD (a.out) ld.so'
++  else
++    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    soname_spec='$libname$release$shared_ext$major'
++    dynamic_linker='NetBSD ld.elf_so'
++  fi
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  ;;
++
++newsos6)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  ;;
++
++*nto* | *qnx*)
++  version_type=qnx
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  dynamic_linker='ldqnx.so'
++  ;;
++
++openbsd* | bitrig*)
++  version_type=sunos
++  sys_lib_dlsearch_path_spec=/usr/lib
++  need_lib_prefix=no
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++    need_version=no
++  else
++    need_version=yes
++  fi
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  ;;
++
++os2*)
++  libname_spec='$name'
++  version_type=windows
++  shrext_cmds=.dll
++  need_version=no
++  need_lib_prefix=no
++  # OS/2 can only load a DLL with a base name of 8 characters or less.
++  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
++    v=$($ECHO $release$versuffix | tr -d .-);
++    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
++    $ECHO $n$v`$shared_ext'
++  library_names_spec='${libname}_dll.$libext'
++  dynamic_linker='OS/2 ld.exe'
++  shlibpath_var=BEGINLIBPATH
++  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
++  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  postinstall_cmds='base_file=`basename \$file`~
++    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
++    dldir=$destdir/`dirname \$dlpath`~
++    test -d \$dldir || mkdir -p \$dldir~
++    $install_prog $dir/$dlname \$dldir/$dlname~
++    chmod a+x \$dldir/$dlname~
++    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
++      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
++    fi'
++  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
++    dlpath=$dir/\$dldll~
++    $RM \$dlpath'
++  ;;
++
++osf3* | osf4* | osf5*)
++  version_type=osf
++  need_lib_prefix=no
++  need_version=no
++  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
++  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  ;;
++
++rdos*)
++  dynamic_linker=no
++  ;;
++
++solaris*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  # ldd complains unless libraries are executable
++  postinstall_cmds='chmod +x $lib'
++  ;;
++
++sunos4*)
++  version_type=sunos
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  if test yes = "$with_gnu_ld"; then
++    need_lib_prefix=no
++  fi
++  need_version=yes
++  ;;
++
++sysv4 | sysv4.3*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  case $host_vendor in
++    sni)
++      shlibpath_overrides_runpath=no
++      need_lib_prefix=no
++      runpath_var=LD_RUN_PATH
++      ;;
++    siemens)
++      need_lib_prefix=no
++      ;;
++    motorola)
++      need_lib_prefix=no
++      need_version=no
++      shlibpath_overrides_runpath=no
++      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
++      ;;
++  esac
++  ;;
++
++sysv4*MP*)
++  if test -d /usr/nec; then
++    version_type=linux # correct to gnu/linux during the next big refactor
++    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
++    soname_spec='$libname$shared_ext.$major'
++    shlibpath_var=LD_LIBRARY_PATH
++  fi
++  ;;
++
++sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
++  version_type=sco
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=yes
++  hardcode_into_libs=yes
++  if test yes = "$with_gnu_ld"; then
++    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
++  else
++    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
++    case $host_os in
++      sco3.2v5*)
++        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
++	;;
++    esac
++  fi
++  sys_lib_dlsearch_path_spec='/usr/lib'
++  ;;
++
++tpf*)
++  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
++  version_type=linux # correct to gnu/linux during the next big refactor
++  need_lib_prefix=no
++  need_version=no
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  shlibpath_var=LD_LIBRARY_PATH
++  shlibpath_overrides_runpath=no
++  hardcode_into_libs=yes
++  ;;
++
++uts4*)
++  version_type=linux # correct to gnu/linux during the next big refactor
++  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='$libname$release$shared_ext$major'
++  shlibpath_var=LD_LIBRARY_PATH
++  ;;
++
++*)
++  dynamic_linker=no
++  ;;
++esac
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
++printf "%s\n" "$dynamic_linker" >&6; }
++test no = "$dynamic_linker" && can_build_shared=no
++
++variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
++if test yes = "$GCC"; then
++  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
++fi
++
++if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
++  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
++fi
++
++if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
++  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
++fi
++
++# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
++configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
++
++# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
++func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
++
++# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
++configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
++printf %s "checking how to hardcode library paths into programs... " >&6; }
++hardcode_action_CXX=
++if test -n "$hardcode_libdir_flag_spec_CXX" ||
++   test -n "$runpath_var_CXX" ||
++   test yes = "$hardcode_automatic_CXX"; then
++
++  # We can hardcode non-existent directories.
++  if test no != "$hardcode_direct_CXX" &&
++     # If the only mechanism to avoid hardcoding is shlibpath_var, we
++     # have to relink, otherwise we might link with an installed library
++     # when we should be linking with a yet-to-be-installed one
++     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" &&
++     test no != "$hardcode_minus_L_CXX"; then
++    # Linking always hardcodes the temporary library directory.
++    hardcode_action_CXX=relink
++  else
++    # We can link without hardcoding, and we can hardcode nonexisting dirs.
++    hardcode_action_CXX=immediate
++  fi
++else
++  # We cannot hardcode anything, or else we can only hardcode existing
++  # directories.
++  hardcode_action_CXX=unsupported
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
++printf "%s\n" "$hardcode_action_CXX" >&6; }
++
++if test relink = "$hardcode_action_CXX" ||
++   test yes = "$inherit_rpath_CXX"; then
++  # Fast installation is not supported
++  enable_fast_install=no
++elif test yes = "$shlibpath_overrides_runpath" ||
++     test no = "$enable_shared"; then
++  # Fast installation is not necessary
++  enable_fast_install=needless
++fi
++
++
++
++
++
++
++
++  fi # test -n "$compiler"
++
++  CC=$lt_save_CC
++  CFLAGS=$lt_save_CFLAGS
++  LDCXX=$LD
++  LD=$lt_save_LD
++  GCC=$lt_save_GCC
++  with_gnu_ld=$lt_save_with_gnu_ld
++  lt_cv_path_LDCXX=$lt_cv_path_LD
++  lt_cv_path_LD=$lt_save_path_LD
++  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
++  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
++fi # test yes != "$_lt_caught_CXX_error"
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++        ac_config_commands="$ac_config_commands libtool"
++
++
++
++
++# Only expand once:
++
++
++ACX_LT_HOST_FLAGS
++
++ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
++case $ac_cv_c_int64_t in #(
++  no|yes) ;; #(
++  *)
++
++printf "%s\n" "#define int64_t $ac_cv_c_int64_t" >>confdefs.h
++;;
++esac
++
++ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
++case $ac_cv_c_uint64_t in #(
++  no|yes) ;; #(
++  *)
++
++printf "%s\n" "#define _UINT64_T 1" >>confdefs.h
++
++
++printf "%s\n" "#define uint64_t $ac_cv_c_uint64_t" >>confdefs.h
++;;
++  esac
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
++printf %s "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
++if test ${ac_cv_header_sys_wait_h+y}
++then :
++  printf %s "(cached) " >&6
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++#include 
++#ifndef WEXITSTATUS
++# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
++#endif
++#ifndef WIFEXITED
++# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
++#endif
++
++int
++main (void)
++{
++  int s;
++  wait (&s);
++  s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"
++then :
++  ac_cv_header_sys_wait_h=yes
++else $as_nop
++  ac_cv_header_sys_wait_h=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++fi
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
++printf "%s\n" "$ac_cv_header_sys_wait_h" >&6; }
++if test $ac_cv_header_sys_wait_h = yes; then
++
++printf "%s\n" "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
++
++fi
++
++ac_config_files="$ac_config_files Makefile"
++
++ac_config_headers="$ac_config_headers config.h"
++
++cat >confcache <<\_ACEOF
++# This file is a shell script that caches the results of configure
++# tests run on this system so they can be shared between configure
++# scripts and configure runs, see configure's option --config-cache.
++# It is not useful on other systems.  If it contains results you don't
++# want to keep, you may remove or edit it.
++#
++# config.status only pays attention to the cache file if you give it
++# the --recheck option to rerun configure.
++#
++# `ac_cv_env_foo' variables (set or unset) will be overridden when
++# loading this file, other *unset* `ac_cv_foo' will be assigned the
++# following values.
++
++_ACEOF
++
++# The following way of writing the cache mishandles newlines in values,
++# but we know of no workaround that is simple, portable, and efficient.
++# So, we kill variables containing newlines.
++# Ultrix sh set writes to stderr and can't be redirected directly,
++# and sets the high bit in the cache file unless we assign to the vars.
++(
++  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
++    eval ac_val=\$$ac_var
++    case $ac_val in #(
++    *${as_nl}*)
++      case $ac_var in #(
++      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
++printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
++      esac
++      case $ac_var in #(
++      _ | IFS | as_nl) ;; #(
++      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
++      *) { eval $ac_var=; unset $ac_var;} ;;
++      esac ;;
++    esac
++  done
++
++  (set) 2>&1 |
++    case $as_nl`(ac_space=' '; set) 2>&1` in #(
++    *${as_nl}ac_space=\ *)
++      # `set' does not quote correctly, so add quotes: double-quote
++      # substitution turns \\\\ into \\, and sed turns \\ into \.
++      sed -n \
++	"s/'/'\\\\''/g;
++	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
++      ;; #(
++    *)
++      # `set' quotes correctly as required by POSIX, so do not add quotes.
++      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
++      ;;
++    esac |
++    sort
++) |
++  sed '
++     /^ac_cv_env_/b end
++     t clear
++     :clear
++     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
++     t end
++     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
++     :end' >>confcache
++if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
++  if test -w "$cache_file"; then
++    if test "x$cache_file" != "x/dev/null"; then
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
++printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
++      if test ! -f "$cache_file" || test -h "$cache_file"; then
++	cat confcache >"$cache_file"
++      else
++        case $cache_file in #(
++        */* | ?:*)
++	  mv -f confcache "$cache_file"$$ &&
++	  mv -f "$cache_file"$$ "$cache_file" ;; #(
++        *)
++	  mv -f confcache "$cache_file" ;;
++	esac
++      fi
++    fi
++  else
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
++printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
++  fi
++fi
++rm -f confcache
++
++test "x$prefix" = xNONE && prefix=$ac_default_prefix
++# Let make expand exec_prefix.
++test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
++
++DEFS=-DHAVE_CONFIG_H
++
++ac_libobjs=
++ac_ltlibobjs=
++U=
++for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
++  # 1. Remove the extension, and $U if already installed.
++  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
++  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
++  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
++  #    will be set to the directory where LIBOBJS objects are built.
++  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
++  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
++done
++LIBOBJS=$ac_libobjs
++
++LTLIBOBJS=$ac_ltlibobjs
++
++
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
++printf %s "checking that generated files are newer than configure... " >&6; }
++   if test -n "$am_sleep_pid"; then
++     # Hide warnings about reused PIDs.
++     wait $am_sleep_pid 2>/dev/null
++   fi
++   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5
++printf "%s\n" "done" >&6; }
++ if test -n "$EXEEXT"; then
++  am__EXEEXT_TRUE=
++  am__EXEEXT_FALSE='#'
++else
++  am__EXEEXT_TRUE='#'
++  am__EXEEXT_FALSE=
++fi
++
++if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
++  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
++if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
++  as_fn_error $? "conditional \"AMDEP\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
++if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
++  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
++if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
++  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
++if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
++  as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
++
++: "${CONFIG_STATUS=./config.status}"
++ac_write_fail=0
++ac_clean_files_save=$ac_clean_files
++ac_clean_files="$ac_clean_files $CONFIG_STATUS"
++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
++printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
++as_write_fail=0
++cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
++#! $SHELL
++# Generated by $as_me.
++# Run this file to recreate the current configuration.
++# Compiler output produced by configure, useful for debugging
++# configure, is in config.log if it exists.
++
++debug=false
++ac_cs_recheck=false
++ac_cs_silent=false
++
++SHELL=\${CONFIG_SHELL-$SHELL}
++export SHELL
++_ASEOF
++cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
++## -------------------- ##
++## M4sh Initialization. ##
++## -------------------- ##
++
++# Be more Bourne compatible
++DUALCASE=1; export DUALCASE # for MKS sh
++as_nop=:
++if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
++then :
++  emulate sh
++  NULLCMD=:
++  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
++  # is contrary to our usage.  Disable this feature.
++  alias -g '${1+"$@"}'='"$@"'
++  setopt NO_GLOB_SUBST
++else $as_nop
++  case `(set -o) 2>/dev/null` in #(
++  *posix*) :
++    set -o posix ;; #(
++  *) :
++     ;;
++esac
++fi
++
++
++
++# Reset variables that may have inherited troublesome values from
++# the environment.
++
++# IFS needs to be set, to space, tab, and newline, in precisely that order.
++# (If _AS_PATH_WALK were called with IFS unset, it would have the
++# side effect of setting IFS to empty, thus disabling word splitting.)
++# Quoting is to prevent editors from complaining about space-tab.
++as_nl='
++'
++export as_nl
++IFS=" ""	$as_nl"
++
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# Ensure predictable behavior from utilities with locale-dependent output.
++LC_ALL=C
++export LC_ALL
++LANGUAGE=C
++export LANGUAGE
++
++# We cannot yet rely on "unset" to work, but we need these variables
++# to be unset--not just set to an empty or harmless value--now, to
++# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
++# also avoids known problems related to "unset" and subshell syntax
++# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
++for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
++do eval test \${$as_var+y} \
++  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
++done
++
++# Ensure that fds 0, 1, and 2 are open.
++if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
++if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
++
++# The user is always right.
++if ${PATH_SEPARATOR+false} :; then
++  PATH_SEPARATOR=:
++  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
++    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
++      PATH_SEPARATOR=';'
++  }
++fi
++
++
++# Find who we are.  Look in the path if we contain no directory separator.
++as_myself=
++case $0 in #((
++  *[\\/]* ) as_myself=$0 ;;
++  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  case $as_dir in #(((
++    '') as_dir=./ ;;
++    */) ;;
++    *) as_dir=$as_dir/ ;;
++  esac
++    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
++  done
++IFS=$as_save_IFS
++
++     ;;
++esac
++# We did not find ourselves, most probably we were run as `sh COMMAND'
++# in which case we are not to be found in the path.
++if test "x$as_myself" = x; then
++  as_myself=$0
++fi
++if test ! -f "$as_myself"; then
++  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
++  exit 1
++fi
++
++
++
++# as_fn_error STATUS ERROR [LINENO LOG_FD]
++# ----------------------------------------
++# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
++# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
++# script with STATUS, using 1 if that was 0.
++as_fn_error ()
++{
++  as_status=$1; test $as_status -eq 0 && as_status=1
++  if test "$4"; then
++    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
++  fi
++  printf "%s\n" "$as_me: error: $2" >&2
++  as_fn_exit $as_status
++} # as_fn_error
++
++
++
++# as_fn_set_status STATUS
++# -----------------------
++# Set $? to STATUS, without forking.
++as_fn_set_status ()
++{
++  return $1
++} # as_fn_set_status
++
++# as_fn_exit STATUS
++# -----------------
++# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
++as_fn_exit ()
++{
++  set +e
++  as_fn_set_status $1
++  exit $1
++} # as_fn_exit
++
++# as_fn_unset VAR
++# ---------------
++# Portably unset VAR.
++as_fn_unset ()
++{
++  { eval $1=; unset $1;}
++}
++as_unset=as_fn_unset
++
++# as_fn_append VAR VALUE
++# ----------------------
++# Append the text in VALUE to the end of the definition contained in VAR. Take
++# advantage of any shell optimizations that allow amortized linear growth over
++# repeated appends, instead of the typical quadratic growth present in naive
++# implementations.
++if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
++then :
++  eval 'as_fn_append ()
++  {
++    eval $1+=\$2
++  }'
++else $as_nop
++  as_fn_append ()
++  {
++    eval $1=\$$1\$2
++  }
++fi # as_fn_append
++
++# as_fn_arith ARG...
++# ------------------
++# Perform arithmetic evaluation on the ARGs, and store the result in the
++# global $as_val. Take advantage of shells that can avoid forks. The arguments
++# must be portable across $(()) and expr.
++if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
++then :
++  eval 'as_fn_arith ()
++  {
++    as_val=$(( $* ))
++  }'
++else $as_nop
++  as_fn_arith ()
++  {
++    as_val=`expr "$@" || test $? -eq 1`
++  }
++fi # as_fn_arith
++
++
++if expr a : '\(a\)' >/dev/null 2>&1 &&
++   test "X`expr 00001 : '.*\(...\)'`" = X001; then
++  as_expr=expr
++else
++  as_expr=false
++fi
++
++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
++  as_basename=basename
++else
++  as_basename=false
++fi
++
++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
++  as_dirname=dirname
++else
++  as_dirname=false
++fi
++
++as_me=`$as_basename -- "$0" ||
++$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
++	 X"$0" : 'X\(//\)$' \| \
++	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X/"$0" |
++    sed '/^.*\/\([^/][^/]*\)\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\/\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\/\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++
++# Avoid depending upon Character Ranges.
++as_cr_letters='abcdefghijklmnopqrstuvwxyz'
++as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
++as_cr_Letters=$as_cr_letters$as_cr_LETTERS
++as_cr_digits='0123456789'
++as_cr_alnum=$as_cr_Letters$as_cr_digits
++
++
++# Determine whether it's possible to make 'echo' print without a newline.
++# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
++# for compatibility with existing Makefiles.
++ECHO_C= ECHO_N= ECHO_T=
++case `echo -n x` in #(((((
++-n*)
++  case `echo 'xy\c'` in
++  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
++  xy)  ECHO_C='\c';;
++  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
++       ECHO_T='	';;
++  esac;;
++*)
++  ECHO_N='-n';;
++esac
++
++# For backward compatibility with old third-party macros, we provide
++# the shell variables $as_echo and $as_echo_n.  New code should use
++# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
++as_echo='printf %s\n'
++as_echo_n='printf %s'
++
++rm -f conf$$ conf$$.exe conf$$.file
++if test -d conf$$.dir; then
++  rm -f conf$$.dir/conf$$.file
++else
++  rm -f conf$$.dir
++  mkdir conf$$.dir 2>/dev/null
++fi
++if (echo >conf$$.file) 2>/dev/null; then
++  if ln -s conf$$.file conf$$ 2>/dev/null; then
++    as_ln_s='ln -s'
++    # ... but there are two gotchas:
++    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
++    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
++    # In both cases, we have to default to `cp -pR'.
++    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
++      as_ln_s='cp -pR'
++  elif ln conf$$.file conf$$ 2>/dev/null; then
++    as_ln_s=ln
++  else
++    as_ln_s='cp -pR'
++  fi
++else
++  as_ln_s='cp -pR'
++fi
++rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
++rmdir conf$$.dir 2>/dev/null
++
++
++# as_fn_mkdir_p
++# -------------
++# Create "$as_dir" as a directory, including parents if necessary.
++as_fn_mkdir_p ()
++{
++
++  case $as_dir in #(
++  -*) as_dir=./$as_dir;;
++  esac
++  test -d "$as_dir" || eval $as_mkdir_p || {
++    as_dirs=
++    while :; do
++      case $as_dir in #(
++      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
++      *) as_qdir=$as_dir;;
++      esac
++      as_dirs="'$as_qdir' $as_dirs"
++      as_dir=`$as_dirname -- "$as_dir" ||
++$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$as_dir" : 'X\(//\)[^/]' \| \
++	 X"$as_dir" : 'X\(//\)$' \| \
++	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X"$as_dir" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)[^/].*/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++      test -d "$as_dir" && break
++    done
++    test -z "$as_dirs" || eval "mkdir $as_dirs"
++  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
++
++
++} # as_fn_mkdir_p
++if mkdir -p . 2>/dev/null; then
++  as_mkdir_p='mkdir -p "$as_dir"'
++else
++  test -d ./-p && rmdir ./-p
++  as_mkdir_p=false
++fi
++
++
++# as_fn_executable_p FILE
++# -----------------------
++# Test if FILE is an executable regular file.
++as_fn_executable_p ()
++{
++  test -f "$1" && test -x "$1"
++} # as_fn_executable_p
++as_test_x='test -x'
++as_executable_p=as_fn_executable_p
++
++# Sed expression to map a string onto a valid CPP name.
++as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
++
++# Sed expression to map a string onto a valid variable name.
++as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
++
++
++exec 6>&1
++## ----------------------------------- ##
++## Main body of $CONFIG_STATUS script. ##
++## ----------------------------------- ##
++_ASEOF
++test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
++
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++# Save the log message, to keep $0 and so on meaningful, and to
++# report actual input values of CONFIG_FILES etc. instead of their
++# values after options handling.
++ac_log="
++This file was extended by bolt plugin for ld $as_me 0.1, which was
++generated by GNU Autoconf 2.71.  Invocation command line was
++
++  CONFIG_FILES    = $CONFIG_FILES
++  CONFIG_HEADERS  = $CONFIG_HEADERS
++  CONFIG_LINKS    = $CONFIG_LINKS
++  CONFIG_COMMANDS = $CONFIG_COMMANDS
++  $ $0 $@
++
++on `(hostname || uname -n) 2>/dev/null | sed 1q`
++"
++
++_ACEOF
++
++case $ac_config_files in *"
++"*) set x $ac_config_files; shift; ac_config_files=$*;;
++esac
++
++case $ac_config_headers in *"
++"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
++esac
++
++
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++# Files that config.status was made for.
++config_files="$ac_config_files"
++config_headers="$ac_config_headers"
++config_commands="$ac_config_commands"
++
++_ACEOF
++
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++ac_cs_usage="\
++\`$as_me' instantiates files and other configuration actions
++from templates according to the current configuration.  Unless the files
++and actions are specified as TAGs, all are instantiated by default.
++
++Usage: $0 [OPTION]... [TAG]...
++
++  -h, --help       print this help, then exit
++  -V, --version    print version number and configuration settings, then exit
++      --config     print configuration, then exit
++  -q, --quiet, --silent
++                   do not print progress messages
++  -d, --debug      don't remove temporary files
++      --recheck    update $as_me by reconfiguring in the same conditions
++      --file=FILE[:TEMPLATE]
++                   instantiate the configuration file FILE
++      --header=FILE[:TEMPLATE]
++                   instantiate the configuration header FILE
++
++Configuration files:
++$config_files
++
++Configuration headers:
++$config_headers
++
++Configuration commands:
++$config_commands
++
++Report bugs to the package provider."
++
++_ACEOF
++ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
++ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++ac_cs_config='$ac_cs_config_escaped'
++ac_cs_version="\\
++bolt plugin for ld config.status 0.1
++configured by $0, generated by GNU Autoconf 2.71,
++  with options \\"\$ac_cs_config\\"
++
++Copyright (C) 2021 Free Software Foundation, Inc.
++This config.status script is free software; the Free Software Foundation
++gives unlimited permission to copy, distribute and modify it."
++
++ac_pwd='$ac_pwd'
++srcdir='$srcdir'
++INSTALL='$INSTALL'
++MKDIR_P='$MKDIR_P'
++AWK='$AWK'
++test -n "\$AWK" || AWK=awk
++_ACEOF
++
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++# The default lists apply if the user does not specify any file.
++ac_need_defaults=:
++while test $# != 0
++do
++  case $1 in
++  --*=?*)
++    ac_option=`expr "X$1" : 'X\([^=]*\)='`
++    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
++    ac_shift=:
++    ;;
++  --*=)
++    ac_option=`expr "X$1" : 'X\([^=]*\)='`
++    ac_optarg=
++    ac_shift=:
++    ;;
++  *)
++    ac_option=$1
++    ac_optarg=$2
++    ac_shift=shift
++    ;;
++  esac
++
++  case $ac_option in
++  # Handling of the options.
++  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
++    ac_cs_recheck=: ;;
++  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
++    printf "%s\n" "$ac_cs_version"; exit ;;
++  --config | --confi | --conf | --con | --co | --c )
++    printf "%s\n" "$ac_cs_config"; exit ;;
++  --debug | --debu | --deb | --de | --d | -d )
++    debug=: ;;
++  --file | --fil | --fi | --f )
++    $ac_shift
++    case $ac_optarg in
++    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
++    '') as_fn_error $? "missing file argument" ;;
++    esac
++    as_fn_append CONFIG_FILES " '$ac_optarg'"
++    ac_need_defaults=false;;
++  --header | --heade | --head | --hea )
++    $ac_shift
++    case $ac_optarg in
++    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
++    esac
++    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
++    ac_need_defaults=false;;
++  --he | --h)
++    # Conflict between --help and --header
++    as_fn_error $? "ambiguous option: \`$1'
++Try \`$0 --help' for more information.";;
++  --help | --hel | -h )
++    printf "%s\n" "$ac_cs_usage"; exit ;;
++  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
++  | -silent | --silent | --silen | --sile | --sil | --si | --s)
++    ac_cs_silent=: ;;
++
++  # This is an error.
++  -*) as_fn_error $? "unrecognized option: \`$1'
++Try \`$0 --help' for more information." ;;
++
++  *) as_fn_append ac_config_targets " $1"
++     ac_need_defaults=false ;;
++
++  esac
++  shift
++done
++
++ac_configure_extra_args=
++
++if $ac_cs_silent; then
++  exec 6>/dev/null
++  ac_configure_extra_args="$ac_configure_extra_args --silent"
++fi
++
++_ACEOF
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++if \$ac_cs_recheck; then
++  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
++  shift
++  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
++  CONFIG_SHELL='$SHELL'
++  export CONFIG_SHELL
++  exec "\$@"
++fi
++
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++exec 5>>config.log
++{
++  echo
++  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
++## Running $as_me. ##
++_ASBOX
++  printf "%s\n" "$ac_log"
++} >&5
++
++_ACEOF
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++#
++# INIT-COMMANDS
++#
++AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
++
++
++# The HP-UX ksh and POSIX shell print the target directory to stdout
++# if CDPATH is set.
++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
++
++sed_quote_subst='$sed_quote_subst'
++double_quote_subst='$double_quote_subst'
++delay_variable_subst='$delay_variable_subst'
++macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
++macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
++enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
++enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
++pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
++enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
++shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
++SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
++ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
++PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
++host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
++host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
++host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
++build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
++build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
++build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
++SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
++Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
++GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
++EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
++FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
++LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
++NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
++LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
++max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
++ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
++exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
++lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
++lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
++lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
++lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
++lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
++reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
++reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
++FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
++OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
++deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
++file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
++file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
++want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
++DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
++sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
++AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
++lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
++AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
++archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
++STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
++RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
++old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
++old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
++old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
++lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
++CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
++CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
++compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
++GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
++lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
++lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
++lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
++lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
++lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
++nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
++lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
++lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
++objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
++MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
++lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
++need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
++MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
++DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
++NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
++LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
++OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
++OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
++libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
++shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
++extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
++archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
++enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
++export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
++whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
++compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
++old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
++old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
++archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
++archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
++module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
++module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
++with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
++allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
++no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
++hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
++hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
++hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
++hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
++hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
++hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
++hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
++inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
++link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
++always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
++export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
++exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
++include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
++prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
++postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
++file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
++variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
++need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
++need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
++version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
++runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
++shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
++shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
++libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
++library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
++soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
++install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
++postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
++postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
++finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
++finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
++hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
++sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
++configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
++configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
++hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
++enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
++enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
++enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
++old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
++striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
++compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`'
++predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`'
++postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`'
++predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`'
++postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`'
++compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`'
++LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`'
++reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`'
++reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
++GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
++lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
++archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
++enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`'
++export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
++whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
++compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`'
++old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
++allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
++no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
++inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
++link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
++always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
++export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
++include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
++prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
++file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
++compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
++predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`'
++postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`'
++predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`'
++postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`'
++compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`'
++
++LTCC='$LTCC'
++LTCFLAGS='$LTCFLAGS'
++compiler='$compiler_DEFAULT'
++
++# A function that is used when there is no print builtin or printf.
++func_fallback_echo ()
++{
++  eval 'cat <<_LTECHO_EOF
++\$1
++_LTECHO_EOF'
++}
++
++# Quote evaled strings.
++for var in SHELL \
++ECHO \
++PATH_SEPARATOR \
++SED \
++GREP \
++EGREP \
++FGREP \
++LD \
++NM \
++LN_S \
++lt_SP2NL \
++lt_NL2SP \
++reload_flag \
++FILECMD \
++OBJDUMP \
++deplibs_check_method \
++file_magic_cmd \
++file_magic_glob \
++want_nocaseglob \
++DLLTOOL \
++sharedlib_from_linklib_cmd \
++AR \
++archiver_list_spec \
++STRIP \
++RANLIB \
++CC \
++CFLAGS \
++compiler \
++lt_cv_sys_global_symbol_pipe \
++lt_cv_sys_global_symbol_to_cdecl \
++lt_cv_sys_global_symbol_to_import \
++lt_cv_sys_global_symbol_to_c_name_address \
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
++lt_cv_nm_interface \
++nm_file_list_spec \
++lt_cv_truncate_bin \
++lt_prog_compiler_no_builtin_flag \
++lt_prog_compiler_pic \
++lt_prog_compiler_wl \
++lt_prog_compiler_static \
++lt_cv_prog_compiler_c_o \
++need_locks \
++MANIFEST_TOOL \
++DSYMUTIL \
++NMEDIT \
++LIPO \
++OTOOL \
++OTOOL64 \
++shrext_cmds \
++export_dynamic_flag_spec \
++whole_archive_flag_spec \
++compiler_needs_object \
++with_gnu_ld \
++allow_undefined_flag \
++no_undefined_flag \
++hardcode_libdir_flag_spec \
++hardcode_libdir_separator \
++exclude_expsyms \
++include_expsyms \
++file_list_spec \
++variables_saved_for_relink \
++libname_spec \
++library_names_spec \
++soname_spec \
++install_override_mode \
++finish_eval \
++old_striplib \
++striplib \
++compiler_lib_search_dirs \
++predep_objects \
++postdep_objects \
++predeps \
++postdeps \
++compiler_lib_search_path \
++LD_CXX \
++reload_flag_CXX \
++compiler_CXX \
++lt_prog_compiler_no_builtin_flag_CXX \
++lt_prog_compiler_pic_CXX \
++lt_prog_compiler_wl_CXX \
++lt_prog_compiler_static_CXX \
++lt_cv_prog_compiler_c_o_CXX \
++export_dynamic_flag_spec_CXX \
++whole_archive_flag_spec_CXX \
++compiler_needs_object_CXX \
++with_gnu_ld_CXX \
++allow_undefined_flag_CXX \
++no_undefined_flag_CXX \
++hardcode_libdir_flag_spec_CXX \
++hardcode_libdir_separator_CXX \
++exclude_expsyms_CXX \
++include_expsyms_CXX \
++file_list_spec_CXX \
++compiler_lib_search_dirs_CXX \
++predep_objects_CXX \
++postdep_objects_CXX \
++predeps_CXX \
++postdeps_CXX \
++compiler_lib_search_path_CXX; do
++    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++    *[\\\\\\\`\\"\\\$]*)
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++      ;;
++    *)
++      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++      ;;
++    esac
++done
++
++# Double-quote double-evaled strings.
++for var in reload_cmds \
++old_postinstall_cmds \
++old_postuninstall_cmds \
++old_archive_cmds \
++extract_expsyms_cmds \
++old_archive_from_new_cmds \
++old_archive_from_expsyms_cmds \
++archive_cmds \
++archive_expsym_cmds \
++module_cmds \
++module_expsym_cmds \
++export_symbols_cmds \
++prelink_cmds \
++postlink_cmds \
++postinstall_cmds \
++postuninstall_cmds \
++finish_cmds \
++sys_lib_search_path_spec \
++configure_time_dlsearch_path \
++configure_time_lt_sys_library_path \
++reload_cmds_CXX \
++old_archive_cmds_CXX \
++old_archive_from_new_cmds_CXX \
++old_archive_from_expsyms_cmds_CXX \
++archive_cmds_CXX \
++archive_expsym_cmds_CXX \
++module_cmds_CXX \
++module_expsym_cmds_CXX \
++export_symbols_cmds_CXX \
++prelink_cmds_CXX \
++postlink_cmds_CXX; do
++    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
++    *[\\\\\\\`\\"\\\$]*)
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++      ;;
++    *)
++      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
++      ;;
++    esac
++done
++
++ac_aux_dir='$ac_aux_dir'
++
++# See if we are running on zsh, and set the options that allow our
++# commands through without removal of \ escapes INIT.
++if test -n "\${ZSH_VERSION+set}"; then
++   setopt NO_GLOB_SUBST
++fi
++
++
++    PACKAGE='$PACKAGE'
++    VERSION='$VERSION'
++    RM='$RM'
++    ofile='$ofile'
++
++
++
++
++
++
++_ACEOF
++
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++
++# Handling of arguments.
++for ac_config_target in $ac_config_targets
++do
++  case $ac_config_target in
++    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
++    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
++    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
++    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
++
++  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
++  esac
++done
++
++
++# If the user did not use the arguments to specify the items to instantiate,
++# then the envvar interface is used.  Set only those that are not.
++# We use the long form for the default assignment because of an extremely
++# bizarre bug on SunOS 4.1.3.
++if $ac_need_defaults; then
++  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
++  test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
++  test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
++fi
++
++# Have a temporary directory for convenience.  Make it in the build tree
++# simply because there is no reason against having it here, and in addition,
++# creating and moving files from /tmp can sometimes cause problems.
++# Hook for its removal unless debugging.
++# Note that there is a small window in which the directory will not be cleaned:
++# after its creation but before its name has been assigned to `$tmp'.
++$debug ||
++{
++  tmp= ac_tmp=
++  trap 'exit_status=$?
++  : "${ac_tmp:=$tmp}"
++  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
++' 0
++  trap 'as_fn_exit 1' 1 2 13 15
++}
++# Create a (secure) tmp directory for tmp files.
++
++{
++  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
++  test -d "$tmp"
++}  ||
++{
++  tmp=./conf$$-$RANDOM
++  (umask 077 && mkdir "$tmp")
++} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
++ac_tmp=$tmp
++
++# Set up the scripts for CONFIG_FILES section.
++# No need to generate them if there are no CONFIG_FILES.
++# This happens for instance with `./config.status config.h'.
++if test -n "$CONFIG_FILES"; then
++
++
++ac_cr=`echo X | tr X '\015'`
++# On cygwin, bash can eat \r inside `` if the user requested igncr.
++# But we know of no other shell where ac_cr would be empty at this
++# point, so we can use a bashism as a fallback.
++if test "x$ac_cr" = x; then
++  eval ac_cr=\$\'\\r\'
++fi
++ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
++if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
++  ac_cs_awk_cr='\\r'
++else
++  ac_cs_awk_cr=$ac_cr
++fi
++
++echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
++_ACEOF
++
++
++{
++  echo "cat >conf$$subs.awk <<_ACEOF" &&
++  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
++  echo "_ACEOF"
++} >conf$$subs.sh ||
++  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
++ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
++ac_delim='%!_!# '
++for ac_last_try in false false false false false :; do
++  . ./conf$$subs.sh ||
++    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
++
++  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
++  if test $ac_delim_n = $ac_delim_num; then
++    break
++  elif $ac_last_try; then
++    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
++  else
++    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
++  fi
++done
++rm -f conf$$subs.sh
++
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
++_ACEOF
++sed -n '
++h
++s/^/S["/; s/!.*/"]=/
++p
++g
++s/^[^!]*!//
++:repl
++t repl
++s/'"$ac_delim"'$//
++t delim
++:nl
++h
++s/\(.\{148\}\)..*/\1/
++t more1
++s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
++p
++n
++b repl
++:more1
++s/["\\]/\\&/g; s/^/"/; s/$/"\\/
++p
++g
++s/.\{148\}//
++t nl
++:delim
++h
++s/\(.\{148\}\)..*/\1/
++t more2
++s/["\\]/\\&/g; s/^/"/; s/$/"/
++p
++b
++:more2
++s/["\\]/\\&/g; s/^/"/; s/$/"\\/
++p
++g
++s/.\{148\}//
++t delim
++' >$CONFIG_STATUS || ac_write_fail=1
++rm -f conf$$subs.awk
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++_ACAWK
++cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
++  for (key in S) S_is_set[key] = 1
++  FS = ""
++
++}
++{
++  line = $ 0
++  nfields = split(line, field, "@")
++  substed = 0
++  len = length(field[1])
++  for (i = 2; i < nfields; i++) {
++    key = field[i]
++    keylen = length(key)
++    if (S_is_set[key]) {
++      value = S[key]
++      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
++      len += length(value) + length(field[++i])
++      substed = 1
++    } else
++      len += 1 + keylen
++  }
++
++  print line
++}
++
++_ACAWK
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
++  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
++else
++  cat
++fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
++  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
++_ACEOF
++
++# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
++# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
++# trailing colons and then remove the whole line if VPATH becomes empty
++# (actually we leave an empty line to preserve line numbers).
++if test "x$srcdir" = x.; then
++  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
++h
++s///
++s/^/:/
++s/[	 ]*$/:/
++s/:\$(srcdir):/:/g
++s/:\${srcdir}:/:/g
++s/:@srcdir@:/:/g
++s/^:*//
++s/:*$//
++x
++s/\(=[	 ]*\).*/\1/
++G
++s/\n//
++s/^[^=]*=[	 ]*$//
++}'
++fi
++
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++fi # test -n "$CONFIG_FILES"
++
++# Set up the scripts for CONFIG_HEADERS section.
++# No need to generate them if there are no CONFIG_HEADERS.
++# This happens for instance with `./config.status Makefile'.
++if test -n "$CONFIG_HEADERS"; then
++cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
++BEGIN {
++_ACEOF
++
++# Transform confdefs.h into an awk script `defines.awk', embedded as
++# here-document in config.status, that substitutes the proper values into
++# config.h.in to produce config.h.
++
++# Create a delimiter string that does not exist in confdefs.h, to ease
++# handling of long lines.
++ac_delim='%!_!# '
++for ac_last_try in false false :; do
++  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
++  if test -z "$ac_tt"; then
++    break
++  elif $ac_last_try; then
++    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
++  else
++    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
++  fi
++done
++
++# For the awk script, D is an array of macro values keyed by name,
++# likewise P contains macro parameters if any.  Preserve backslash
++# newline sequences.
++
++ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
++sed -n '
++s/.\{148\}/&'"$ac_delim"'/g
++t rset
++:rset
++s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
++t def
++d
++:def
++s/\\$//
++t bsnl
++s/["\\]/\\&/g
++s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
++D["\1"]=" \3"/p
++s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
++d
++:bsnl
++s/["\\]/\\&/g
++s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
++D["\1"]=" \3\\\\\\n"\\/p
++t cont
++s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
++t cont
++d
++:cont
++n
++s/.\{148\}/&'"$ac_delim"'/g
++t clear
++:clear
++s/\\$//
++t bsnlc
++s/["\\]/\\&/g; s/^/"/; s/$/"/p
++d
++:bsnlc
++s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
++b cont
++' >$CONFIG_STATUS || ac_write_fail=1
++
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++  for (key in D) D_is_set[key] = 1
++  FS = ""
++}
++/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
++  line = \$ 0
++  split(line, arg, " ")
++  if (arg[1] == "#") {
++    defundef = arg[2]
++    mac1 = arg[3]
++  } else {
++    defundef = substr(arg[1], 2)
++    mac1 = arg[2]
++  }
++  split(mac1, mac2, "(") #)
++  macro = mac2[1]
++  prefix = substr(line, 1, index(line, defundef) - 1)
++  if (D_is_set[macro]) {
++    # Preserve the white space surrounding the "#".
++    print prefix "define", macro P[macro] D[macro]
++    next
++  } else {
++    # Replace #undef with comments.  This is necessary, for example,
++    # in the case of _POSIX_SOURCE, which is predefined and required
++    # on some systems where configure will not decide to define it.
++    if (defundef == "undef") {
++      print "/*", prefix defundef, macro, "*/"
++      next
++    }
++  }
++}
++{ print }
++_ACAWK
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
++fi # test -n "$CONFIG_HEADERS"
++
++
++eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
++shift
++for ac_tag
++do
++  case $ac_tag in
++  :[FHLC]) ac_mode=$ac_tag; continue;;
++  esac
++  case $ac_mode$ac_tag in
++  :[FHL]*:*);;
++  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
++  :[FH]-) ac_tag=-:-;;
++  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
++  esac
++  ac_save_IFS=$IFS
++  IFS=:
++  set x $ac_tag
++  IFS=$ac_save_IFS
++  shift
++  ac_file=$1
++  shift
++
++  case $ac_mode in
++  :L) ac_source=$1;;
++  :[FH])
++    ac_file_inputs=
++    for ac_f
++    do
++      case $ac_f in
++      -) ac_f="$ac_tmp/stdin";;
++      *) # Look for the file first in the build tree, then in the source tree
++	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
++	 # because $ac_f cannot contain `:'.
++	 test -f "$ac_f" ||
++	   case $ac_f in
++	   [\\/$]*) false;;
++	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
++	   esac ||
++	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
++      esac
++      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
++      as_fn_append ac_file_inputs " '$ac_f'"
++    done
++
++    # Let's still pretend it is `configure' which instantiates (i.e., don't
++    # use $as_me), people would be surprised to read:
++    #    /* config.h.  Generated by config.status.  */
++    configure_input='Generated from '`
++	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
++	`' by configure.'
++    if test x"$ac_file" != x-; then
++      configure_input="$ac_file.  $configure_input"
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
++printf "%s\n" "$as_me: creating $ac_file" >&6;}
++    fi
++    # Neutralize special characters interpreted by sed in replacement strings.
++    case $configure_input in #(
++    *\&* | *\|* | *\\* )
++       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
++       sed 's/[\\\\&|]/\\\\&/g'`;; #(
++    *) ac_sed_conf_input=$configure_input;;
++    esac
++
++    case $ac_tag in
++    *:-:* | *:-) cat >"$ac_tmp/stdin" \
++      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
++    esac
++    ;;
++  esac
++
++  ac_dir=`$as_dirname -- "$ac_file" ||
++$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$ac_file" : 'X\(//\)[^/]' \| \
++	 X"$ac_file" : 'X\(//\)$' \| \
++	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X"$ac_file" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)[^/].*/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++  as_dir="$ac_dir"; as_fn_mkdir_p
++  ac_builddir=.
++
++case "$ac_dir" in
++.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
++*)
++  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
++  # A ".." for each directory in $ac_dir_suffix.
++  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
++  case $ac_top_builddir_sub in
++  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
++  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
++  esac ;;
++esac
++ac_abs_top_builddir=$ac_pwd
++ac_abs_builddir=$ac_pwd$ac_dir_suffix
++# for backward compatibility:
++ac_top_builddir=$ac_top_build_prefix
++
++case $srcdir in
++  .)  # We are building in place.
++    ac_srcdir=.
++    ac_top_srcdir=$ac_top_builddir_sub
++    ac_abs_top_srcdir=$ac_pwd ;;
++  [\\/]* | ?:[\\/]* )  # Absolute name.
++    ac_srcdir=$srcdir$ac_dir_suffix;
++    ac_top_srcdir=$srcdir
++    ac_abs_top_srcdir=$srcdir ;;
++  *) # Relative name.
++    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
++    ac_top_srcdir=$ac_top_build_prefix$srcdir
++    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
++esac
++ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
++
++
++  case $ac_mode in
++  :F)
++  #
++  # CONFIG_FILE
++  #
++
++  case $INSTALL in
++  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
++  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
++  esac
++  ac_MKDIR_P=$MKDIR_P
++  case $MKDIR_P in
++  [\\/$]* | ?:[\\/]* ) ;;
++  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
++  esac
++_ACEOF
++
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++# If the template does not know about datarootdir, expand it.
++# FIXME: This hack should be removed a few years after 2.60.
++ac_datarootdir_hack=; ac_datarootdir_seen=
++ac_sed_dataroot='
++/datarootdir/ {
++  p
++  q
++}
++/@datadir@/p
++/@docdir@/p
++/@infodir@/p
++/@localedir@/p
++/@mandir@/p'
++case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
++*datarootdir*) ac_datarootdir_seen=yes;;
++*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
++printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
++_ACEOF
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++  ac_datarootdir_hack='
++  s&@datadir@&$datadir&g
++  s&@docdir@&$docdir&g
++  s&@infodir@&$infodir&g
++  s&@localedir@&$localedir&g
++  s&@mandir@&$mandir&g
++  s&\\\${datarootdir}&$datarootdir&g' ;;
++esac
++_ACEOF
++
++# Neutralize VPATH when `$srcdir' = `.'.
++# Shell code in configure.ac might set extrasub.
++# FIXME: do we really want to maintain this feature?
++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
++ac_sed_extra="$ac_vpsub
++$extrasub
++_ACEOF
++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
++:t
++/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
++s|@configure_input@|$ac_sed_conf_input|;t t
++s&@top_builddir@&$ac_top_builddir_sub&;t t
++s&@top_build_prefix@&$ac_top_build_prefix&;t t
++s&@srcdir@&$ac_srcdir&;t t
++s&@abs_srcdir@&$ac_abs_srcdir&;t t
++s&@top_srcdir@&$ac_top_srcdir&;t t
++s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
++s&@builddir@&$ac_builddir&;t t
++s&@abs_builddir@&$ac_abs_builddir&;t t
++s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
++s&@INSTALL@&$ac_INSTALL&;t t
++s&@MKDIR_P@&$ac_MKDIR_P&;t t
++$ac_datarootdir_hack
++"
++eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
++  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
++
++test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
++  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
++  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
++      "$ac_tmp/out"`; test -z "$ac_out"; } &&
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
++which seems to be undefined.  Please make sure it is defined" >&5
++printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
++which seems to be undefined.  Please make sure it is defined" >&2;}
++
++  rm -f "$ac_tmp/stdin"
++  case $ac_file in
++  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
++  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
++  esac \
++  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
++ ;;
++  :H)
++  #
++  # CONFIG_HEADER
++  #
++  if test x"$ac_file" != x-; then
++    {
++      printf "%s\n" "/* $configure_input  */" >&1 \
++      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
++    } >"$ac_tmp/config.h" \
++      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
++    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
++      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
++printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
++    else
++      rm -f "$ac_file"
++      mv "$ac_tmp/config.h" "$ac_file" \
++	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
++    fi
++  else
++    printf "%s\n" "/* $configure_input  */" >&1 \
++      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
++      || as_fn_error $? "could not create -" "$LINENO" 5
++  fi
++# Compute "$ac_file"'s index in $config_headers.
++_am_arg="$ac_file"
++_am_stamp_count=1
++for _am_header in $config_headers :; do
++  case $_am_header in
++    $_am_arg | $_am_arg:* )
++      break ;;
++    * )
++      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
++  esac
++done
++echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
++$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$_am_arg" : 'X\(//\)[^/]' \| \
++	 X"$_am_arg" : 'X\(//\)$' \| \
++	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X"$_am_arg" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)[^/].*/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`/stamp-h$_am_stamp_count
++ ;;
++
++  :C)  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
++printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
++ ;;
++  esac
++
++
++  case $ac_file$ac_mode in
++    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
++  # Older Autoconf quotes --file arguments for eval, but not when files
++  # are listed without --file.  Let's play safe and only enable the eval
++  # if we detect the quoting.
++  # TODO: see whether this extra hack can be removed once we start
++  # requiring Autoconf 2.70 or later.
++  case $CONFIG_FILES in #(
++  *\'*) :
++    eval set x "$CONFIG_FILES" ;; #(
++  *) :
++    set x $CONFIG_FILES ;; #(
++  *) :
++     ;;
++esac
++  shift
++  # Used to flag and report bootstrapping failures.
++  am_rc=0
++  for am_mf
++  do
++    # Strip MF so we end up with the name of the file.
++    am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'`
++    # Check whether this is an Automake generated Makefile which includes
++    # dependency-tracking related rules and includes.
++    # Grep'ing the whole file directly is not great: AIX grep has a line
++    # limit of 2048, but all sed's we know have understand at least 4000.
++    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
++      || continue
++    am_dirpart=`$as_dirname -- "$am_mf" ||
++$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
++	 X"$am_mf" : 'X\(//\)[^/]' \| \
++	 X"$am_mf" : 'X\(//\)$' \| \
++	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X"$am_mf" |
++    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)[^/].*/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++    am_filepart=`$as_basename -- "$am_mf" ||
++$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
++	 X"$am_mf" : 'X\(//\)$' \| \
++	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
++printf "%s\n" X/"$am_mf" |
++    sed '/^.*\/\([^/][^/]*\)\/*$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\/\(\/\/\)$/{
++	    s//\1/
++	    q
++	  }
++	  /^X\/\(\/\).*/{
++	    s//\1/
++	    q
++	  }
++	  s/.*/./; q'`
++    { echo "$as_me:$LINENO: cd "$am_dirpart" \
++      && sed -e '/# am--include-marker/d' "$am_filepart" \
++        | $MAKE -f - am--depfiles" >&5
++   (cd "$am_dirpart" \
++      && sed -e '/# am--include-marker/d' "$am_filepart" \
++        | $MAKE -f - am--depfiles) >&5 2>&5
++   ac_status=$?
++   echo "$as_me:$LINENO: \$? = $ac_status" >&5
++   (exit $ac_status); } || am_rc=$?
++  done
++  if test $am_rc -ne 0; then
++    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "Something went wrong bootstrapping makefile fragments
++    for automatic dependency tracking.  If GNU make was not used, consider
++    re-running the configure script with MAKE=\"gmake\" (or whatever is
++    necessary).  You can also try re-running configure with the
++    '--disable-dependency-tracking' option to at least be able to build
++    the package (albeit without support for automatic dependency tracking).
++See \`config.log' for more details" "$LINENO" 5; }
++  fi
++  { am_dirpart=; unset am_dirpart;}
++  { am_filepart=; unset am_filepart;}
++  { am_mf=; unset am_mf;}
++  { am_rc=; unset am_rc;}
++  rm -f conftest-deps.mk
++}
++ ;;
++    "libtool":C)
++
++    # See if we are running on zsh, and set the options that allow our
++    # commands through without removal of \ escapes.
++    if test -n "${ZSH_VERSION+set}"; then
++      setopt NO_GLOB_SUBST
++    fi
++
++    cfgfile=${ofile}T
++    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
++    $RM "$cfgfile"
++
++    cat <<_LT_EOF >> "$cfgfile"
++#! $SHELL
++# Generated automatically by $as_me ($PACKAGE) $VERSION
++# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
++# NOTE: Changes made to this file will be lost: look at ltmain.sh.
++
++# Provide generalized library-building support services.
++# Written by Gordon Matzigkeit, 1996
++
++# Copyright (C) 2014 Free Software Foundation, Inc.
++# This is free software; see the source for copying conditions.  There is NO
++# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++
++# GNU Libtool 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 2 of of the License, or
++# (at your option) any later version.
++#
++# As a special exception to the GNU General Public License, if you
++# distribute this file as part of a program or library that is built
++# using GNU Libtool, you may include this file under the  same
++# distribution terms that you use for the rest of that program.
++#
++# GNU Libtool is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see .
++
++
++# The names of the tagged configurations supported by this script.
++available_tags='CXX '
++
++# Configured defaults for sys_lib_dlsearch_path munging.
++: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
++
++# ### BEGIN LIBTOOL CONFIG
++
++# Which release of libtool.m4 was used?
++macro_version=$macro_version
++macro_revision=$macro_revision
++
++# Whether or not to build shared libraries.
++build_libtool_libs=$enable_shared
++
++# Whether or not to build static libraries.
++build_old_libs=$enable_static
++
++# What type of objects to build.
++pic_mode=$pic_mode
++
++# Whether or not to optimize for fast installation.
++fast_install=$enable_fast_install
++
++# Shared archive member basename,for filename based shared library versioning on AIX.
++shared_archive_member_spec=$shared_archive_member_spec
++
++# Shell to use when invoking shell scripts.
++SHELL=$lt_SHELL
++
++# An echo program that protects backslashes.
++ECHO=$lt_ECHO
++
++# The PATH separator for the build system.
++PATH_SEPARATOR=$lt_PATH_SEPARATOR
++
++# The host system.
++host_alias=$host_alias
++host=$host
++host_os=$host_os
++
++# The build system.
++build_alias=$build_alias
++build=$build
++build_os=$build_os
++
++# A sed program that does not truncate output.
++SED=$lt_SED
++
++# Sed that helps us avoid accidentally triggering echo(1) options like -n.
++Xsed="\$SED -e 1s/^X//"
++
++# A grep program that handles long lines.
++GREP=$lt_GREP
++
++# An ERE matcher.
++EGREP=$lt_EGREP
++
++# A literal string matcher.
++FGREP=$lt_FGREP
++
++# A BSD- or MS-compatible name lister.
++NM=$lt_NM
++
++# Whether we need soft or hard links.
++LN_S=$lt_LN_S
++
++# What is the maximum length of a command?
++max_cmd_len=$max_cmd_len
++
++# Object file suffix (normally "o").
++objext=$ac_objext
++
++# Executable file suffix (normally "").
++exeext=$exeext
++
++# whether the shell understands "unset".
++lt_unset=$lt_unset
++
++# turn spaces into newlines.
++SP2NL=$lt_lt_SP2NL
++
++# turn newlines into spaces.
++NL2SP=$lt_lt_NL2SP
++
++# convert \$build file names to \$host format.
++to_host_file_cmd=$lt_cv_to_host_file_cmd
++
++# convert \$build files to toolchain format.
++to_tool_file_cmd=$lt_cv_to_tool_file_cmd
++
++# A file(cmd) program that detects file types.
++FILECMD=$lt_FILECMD
++
++# An object symbol dumper.
++OBJDUMP=$lt_OBJDUMP
++
++# Method to check whether dependent libraries are shared objects.
++deplibs_check_method=$lt_deplibs_check_method
++
++# Command to use when deplibs_check_method = "file_magic".
++file_magic_cmd=$lt_file_magic_cmd
++
++# How to find potential files when deplibs_check_method = "file_magic".
++file_magic_glob=$lt_file_magic_glob
++
++# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
++want_nocaseglob=$lt_want_nocaseglob
++
++# DLL creation program.
++DLLTOOL=$lt_DLLTOOL
++
++# Command to associate shared and link libraries.
++sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
++
++# The archiver.
++AR=$lt_AR
++
++# Flags to create an archive (by configure).
++lt_ar_flags=$lt_ar_flags
++
++# Flags to create an archive.
++AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
++
++# How to feed a file listing to the archiver.
++archiver_list_spec=$lt_archiver_list_spec
++
++# A symbol stripping program.
++STRIP=$lt_STRIP
++
++# Commands used to install an old-style archive.
++RANLIB=$lt_RANLIB
++old_postinstall_cmds=$lt_old_postinstall_cmds
++old_postuninstall_cmds=$lt_old_postuninstall_cmds
++
++# Whether to use a lock for old archive extraction.
++lock_old_archive_extraction=$lock_old_archive_extraction
++
++# A C compiler.
++LTCC=$lt_CC
++
++# LTCC compiler flags.
++LTCFLAGS=$lt_CFLAGS
++
++# Take the output of nm and produce a listing of raw symbols and C names.
++global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
++
++# Transform the output of nm in a proper C declaration.
++global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
++
++# Transform the output of nm into a list of symbols to manually relocate.
++global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
++
++# Transform the output of nm in a C name address pair.
++global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
++
++# Transform the output of nm in a C name address pair when lib prefix is needed.
++global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
++
++# The name lister interface.
++nm_interface=$lt_lt_cv_nm_interface
++
++# Specify filename containing input files for \$NM.
++nm_file_list_spec=$lt_nm_file_list_spec
++
++# The root where to search for dependent libraries,and where our libraries should be installed.
++lt_sysroot=$lt_sysroot
++
++# Command to truncate a binary pipe.
++lt_truncate_bin=$lt_lt_cv_truncate_bin
++
++# The name of the directory that contains temporary libtool files.
++objdir=$objdir
++
++# Used to examine libraries when file_magic_cmd begins with "file".
++MAGIC_CMD=$MAGIC_CMD
++
++# Must we lock files when doing compilation?
++need_locks=$lt_need_locks
++
++# Manifest tool.
++MANIFEST_TOOL=$lt_MANIFEST_TOOL
++
++# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
++DSYMUTIL=$lt_DSYMUTIL
++
++# Tool to change global to local symbols on Mac OS X.
++NMEDIT=$lt_NMEDIT
++
++# Tool to manipulate fat objects and archives on Mac OS X.
++LIPO=$lt_LIPO
++
++# ldd/readelf like tool for Mach-O binaries on Mac OS X.
++OTOOL=$lt_OTOOL
++
++# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
++OTOOL64=$lt_OTOOL64
++
++# Old archive suffix (normally "a").
++libext=$libext
++
++# Shared library suffix (normally ".so").
++shrext_cmds=$lt_shrext_cmds
++
++# The commands to extract the exported symbol list from a shared archive.
++extract_expsyms_cmds=$lt_extract_expsyms_cmds
++
++# Variables whose values should be saved in libtool wrapper scripts and
++# restored at link time.
++variables_saved_for_relink=$lt_variables_saved_for_relink
++
++# Do we need the "lib" prefix for modules?
++need_lib_prefix=$need_lib_prefix
++
++# Do we need a version for libraries?
++need_version=$need_version
++
++# Library versioning type.
++version_type=$version_type
++
++# Shared library runtime path variable.
++runpath_var=$runpath_var
++
++# Shared library path variable.
++shlibpath_var=$shlibpath_var
++
++# Is shlibpath searched before the hard-coded library search path?
++shlibpath_overrides_runpath=$shlibpath_overrides_runpath
++
++# Format of library name prefix.
++libname_spec=$lt_libname_spec
++
++# List of archive names.  First name is the real one, the rest are links.
++# The last name is the one that the linker finds with -lNAME
++library_names_spec=$lt_library_names_spec
++
++# The coded name of the library, if different from the real name.
++soname_spec=$lt_soname_spec
++
++# Permission mode override for installation of shared libraries.
++install_override_mode=$lt_install_override_mode
++
++# Command to use after installation of a shared archive.
++postinstall_cmds=$lt_postinstall_cmds
++
++# Command to use after uninstallation of a shared archive.
++postuninstall_cmds=$lt_postuninstall_cmds
++
++# Commands used to finish a libtool library installation in a directory.
++finish_cmds=$lt_finish_cmds
++
++# As "finish_cmds", except a single script fragment to be evaled but
++# not shown.
++finish_eval=$lt_finish_eval
++
++# Whether we should hardcode library paths into libraries.
++hardcode_into_libs=$hardcode_into_libs
++
++# Compile-time system search path for libraries.
++sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
++
++# Detected run-time system search path for libraries.
++sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
++
++# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
++configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
++
++# Whether dlopen is supported.
++dlopen_support=$enable_dlopen
++
++# Whether dlopen of programs is supported.
++dlopen_self=$enable_dlopen_self
++
++# Whether dlopen of statically linked programs is supported.
++dlopen_self_static=$enable_dlopen_self_static
++
++# Commands to strip libraries.
++old_striplib=$lt_old_striplib
++striplib=$lt_striplib
++
++
++# The linker used to build libraries.
++LD=$lt_LD
++
++# How to create reloadable object files.
++reload_flag=$lt_reload_flag
++reload_cmds=$lt_reload_cmds
++
++# Commands used to build an old-style archive.
++old_archive_cmds=$lt_old_archive_cmds
++
++# A language specific compiler.
++CC=$lt_compiler
++
++# Is the compiler the GNU compiler?
++with_gcc=$GCC
++
++# Compiler flag to turn off builtin functions.
++no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
++
++# Additional compiler flags for building library objects.
++pic_flag=$lt_lt_prog_compiler_pic
++
++# How to pass a linker flag through the compiler.
++wl=$lt_lt_prog_compiler_wl
++
++# Compiler flag to prevent dynamic linking.
++link_static_flag=$lt_lt_prog_compiler_static
++
++# Does compiler simultaneously support -c and -o options?
++compiler_c_o=$lt_lt_cv_prog_compiler_c_o
++
++# Whether or not to add -lc for building shared libraries.
++build_libtool_need_lc=$archive_cmds_need_lc
++
++# Whether or not to disallow shared libs when runtime libs are static.
++allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
++
++# Compiler flag to allow reflexive dlopens.
++export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
++
++# Compiler flag to generate shared objects directly from archives.
++whole_archive_flag_spec=$lt_whole_archive_flag_spec
++
++# Whether the compiler copes with passing no objects directly.
++compiler_needs_object=$lt_compiler_needs_object
++
++# Create an old-style archive from a shared archive.
++old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
++
++# Create a temporary old-style archive to link instead of a shared archive.
++old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
++
++# Commands used to build a shared archive.
++archive_cmds=$lt_archive_cmds
++archive_expsym_cmds=$lt_archive_expsym_cmds
++
++# Commands used to build a loadable module if different from building
++# a shared archive.
++module_cmds=$lt_module_cmds
++module_expsym_cmds=$lt_module_expsym_cmds
++
++# Whether we are building with GNU ld or not.
++with_gnu_ld=$lt_with_gnu_ld
++
++# Flag that allows shared libraries with undefined symbols to be built.
++allow_undefined_flag=$lt_allow_undefined_flag
++
++# Flag that enforces no undefined symbols.
++no_undefined_flag=$lt_no_undefined_flag
++
++# Flag to hardcode \$libdir into a binary during linking.
++# This must work even if \$libdir does not exist
++hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
++
++# Whether we need a single "-rpath" flag with a separated argument.
++hardcode_libdir_separator=$lt_hardcode_libdir_separator
++
++# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# DIR into the resulting binary.
++hardcode_direct=$hardcode_direct
++
++# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# DIR into the resulting binary and the resulting library dependency is
++# "absolute",i.e impossible to change by setting \$shlibpath_var if the
++# library is relocated.
++hardcode_direct_absolute=$hardcode_direct_absolute
++
++# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
++# into the resulting binary.
++hardcode_minus_L=$hardcode_minus_L
++
++# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
++# into the resulting binary.
++hardcode_shlibpath_var=$hardcode_shlibpath_var
++
++# Set to "yes" if building a shared library automatically hardcodes DIR
++# into the library and all subsequent libraries and executables linked
++# against it.
++hardcode_automatic=$hardcode_automatic
++
++# Set to yes if linker adds runtime paths of dependent libraries
++# to runtime path list.
++inherit_rpath=$inherit_rpath
++
++# Whether libtool must link a program against all its dependency libraries.
++link_all_deplibs=$link_all_deplibs
++
++# Set to "yes" if exported symbols are required.
++always_export_symbols=$always_export_symbols
++
++# The commands to list exported symbols.
++export_symbols_cmds=$lt_export_symbols_cmds
++
++# Symbols that should not be listed in the preloaded symbols.
++exclude_expsyms=$lt_exclude_expsyms
++
++# Symbols that must always be exported.
++include_expsyms=$lt_include_expsyms
++
++# Commands necessary for linking programs (against libraries) with templates.
++prelink_cmds=$lt_prelink_cmds
++
++# Commands necessary for finishing linking programs.
++postlink_cmds=$lt_postlink_cmds
++
++# Specify filename containing input files.
++file_list_spec=$lt_file_list_spec
++
++# How to hardcode a shared library path into an executable.
++hardcode_action=$hardcode_action
++
++# The directories searched by this compiler when creating a shared library.
++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs
++
++# Dependencies to place before and after the objects being linked to
++# create a shared library.
++predep_objects=$lt_predep_objects
++postdep_objects=$lt_postdep_objects
++predeps=$lt_predeps
++postdeps=$lt_postdeps
++
++# The library search path used internally by the compiler when linking
++# a shared library.
++compiler_lib_search_path=$lt_compiler_lib_search_path
++
++# ### END LIBTOOL CONFIG
++
++_LT_EOF
++
++    cat <<'_LT_EOF' >> "$cfgfile"
++
++# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
++
++# func_munge_path_list VARIABLE PATH
++# -----------------------------------
++# VARIABLE is name of variable containing _space_ separated list of
++# directories to be munged by the contents of PATH, which is string
++# having a format:
++# "DIR[:DIR]:"
++#       string "DIR[ DIR]" will be prepended to VARIABLE
++# ":DIR[:DIR]"
++#       string "DIR[ DIR]" will be appended to VARIABLE
++# "DIRP[:DIRP]::[DIRA:]DIRA"
++#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
++#       "DIRA[ DIRA]" will be appended to VARIABLE
++# "DIR[:DIR]"
++#       VARIABLE will be replaced by "DIR[ DIR]"
++func_munge_path_list ()
++{
++    case x$2 in
++    x)
++        ;;
++    *:)
++        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
++        ;;
++    x:*)
++        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
++        ;;
++    *::*)
++        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
++        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
++        ;;
++    *)
++        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
++        ;;
++    esac
++}
++
++
++# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
++func_cc_basename ()
++{
++    for cc_temp in $*""; do
++      case $cc_temp in
++        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
++        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
++        \-*) ;;
++        *) break;;
++      esac
++    done
++    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
++}
++
++
++# ### END FUNCTIONS SHARED WITH CONFIGURE
++
++_LT_EOF
++
++  case $host_os in
++  aix3*)
++    cat <<\_LT_EOF >> "$cfgfile"
++# AIX sometimes has problems with the GCC collect2 program.  For some
++# reason, if we set the COLLECT_NAMES environment variable, the problems
++# vanish in a puff of smoke.
++if test set != "${COLLECT_NAMES+set}"; then
++  COLLECT_NAMES=
++  export COLLECT_NAMES
++fi
++_LT_EOF
++    ;;
++  esac
++
++
++
++ltmain=$ac_aux_dir/ltmain.sh
++
++
++  # We use sed instead of cat because bash on DJGPP gets confused if
++  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
++  # text mode, it properly converts lines to CR/LF.  This bash problem
++  # is reportedly fixed, but why not run on old versions too?
++  $SED '$q' "$ltmain" >> "$cfgfile" \
++     || (rm -f "$cfgfile"; exit 1)
++
++   mv -f "$cfgfile" "$ofile" ||
++    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
++  chmod +x "$ofile"
++
++
++    cat <<_LT_EOF >> "$ofile"
++
++# ### BEGIN LIBTOOL TAG CONFIG: CXX
++
++# The linker used to build libraries.
++LD=$lt_LD_CXX
++
++# How to create reloadable object files.
++reload_flag=$lt_reload_flag_CXX
++reload_cmds=$lt_reload_cmds_CXX
++
++# Commands used to build an old-style archive.
++old_archive_cmds=$lt_old_archive_cmds_CXX
++
++# A language specific compiler.
++CC=$lt_compiler_CXX
++
++# Is the compiler the GNU compiler?
++with_gcc=$GCC_CXX
++
++# Compiler flag to turn off builtin functions.
++no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
++
++# Additional compiler flags for building library objects.
++pic_flag=$lt_lt_prog_compiler_pic_CXX
++
++# How to pass a linker flag through the compiler.
++wl=$lt_lt_prog_compiler_wl_CXX
++
++# Compiler flag to prevent dynamic linking.
++link_static_flag=$lt_lt_prog_compiler_static_CXX
++
++# Does compiler simultaneously support -c and -o options?
++compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
++
++# Whether or not to add -lc for building shared libraries.
++build_libtool_need_lc=$archive_cmds_need_lc_CXX
++
++# Whether or not to disallow shared libs when runtime libs are static.
++allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
++
++# Compiler flag to allow reflexive dlopens.
++export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
++
++# Compiler flag to generate shared objects directly from archives.
++whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
++
++# Whether the compiler copes with passing no objects directly.
++compiler_needs_object=$lt_compiler_needs_object_CXX
++
++# Create an old-style archive from a shared archive.
++old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
++
++# Create a temporary old-style archive to link instead of a shared archive.
++old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
++
++# Commands used to build a shared archive.
++archive_cmds=$lt_archive_cmds_CXX
++archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
++
++# Commands used to build a loadable module if different from building
++# a shared archive.
++module_cmds=$lt_module_cmds_CXX
++module_expsym_cmds=$lt_module_expsym_cmds_CXX
++
++# Whether we are building with GNU ld or not.
++with_gnu_ld=$lt_with_gnu_ld_CXX
++
++# Flag that allows shared libraries with undefined symbols to be built.
++allow_undefined_flag=$lt_allow_undefined_flag_CXX
++
++# Flag that enforces no undefined symbols.
++no_undefined_flag=$lt_no_undefined_flag_CXX
++
++# Flag to hardcode \$libdir into a binary during linking.
++# This must work even if \$libdir does not exist
++hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
++
++# Whether we need a single "-rpath" flag with a separated argument.
++hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
++
++# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# DIR into the resulting binary.
++hardcode_direct=$hardcode_direct_CXX
++
++# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# DIR into the resulting binary and the resulting library dependency is
++# "absolute",i.e impossible to change by setting \$shlibpath_var if the
++# library is relocated.
++hardcode_direct_absolute=$hardcode_direct_absolute_CXX
++
++# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
++# into the resulting binary.
++hardcode_minus_L=$hardcode_minus_L_CXX
++
++# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
++# into the resulting binary.
++hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
++
++# Set to "yes" if building a shared library automatically hardcodes DIR
++# into the library and all subsequent libraries and executables linked
++# against it.
++hardcode_automatic=$hardcode_automatic_CXX
++
++# Set to yes if linker adds runtime paths of dependent libraries
++# to runtime path list.
++inherit_rpath=$inherit_rpath_CXX
++
++# Whether libtool must link a program against all its dependency libraries.
++link_all_deplibs=$link_all_deplibs_CXX
++
++# Set to "yes" if exported symbols are required.
++always_export_symbols=$always_export_symbols_CXX
++
++# The commands to list exported symbols.
++export_symbols_cmds=$lt_export_symbols_cmds_CXX
++
++# Symbols that should not be listed in the preloaded symbols.
++exclude_expsyms=$lt_exclude_expsyms_CXX
++
++# Symbols that must always be exported.
++include_expsyms=$lt_include_expsyms_CXX
++
++# Commands necessary for linking programs (against libraries) with templates.
++prelink_cmds=$lt_prelink_cmds_CXX
++
++# Commands necessary for finishing linking programs.
++postlink_cmds=$lt_postlink_cmds_CXX
++
++# Specify filename containing input files.
++file_list_spec=$lt_file_list_spec_CXX
++
++# How to hardcode a shared library path into an executable.
++hardcode_action=$hardcode_action_CXX
++
++# The directories searched by this compiler when creating a shared library.
++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
++
++# Dependencies to place before and after the objects being linked to
++# create a shared library.
++predep_objects=$lt_predep_objects_CXX
++postdep_objects=$lt_postdep_objects_CXX
++predeps=$lt_predeps_CXX
++postdeps=$lt_postdeps_CXX
++
++# The library search path used internally by the compiler when linking
++# a shared library.
++compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
++
++# ### END LIBTOOL TAG CONFIG: CXX
++_LT_EOF
++
++ ;;
++
++  esac
++done # for ac_tag
++
++
++as_fn_exit 0
++_ACEOF
++ac_clean_files=$ac_clean_files_save
++
++test $ac_write_fail = 0 ||
++  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
++
++
++# configure is writing to config.log, and then calls config.status.
++# config.status does its own redirection, appending to config.log.
++# Unfortunately, on DOS this fails, as config.log is still kept open
++# by configure, so config.status won't be able to write to it; its
++# output is simply discarded.  So we exec the FD to /dev/null,
++# effectively closing config.log, so it can be properly (re)opened and
++# appended to by config.status.  When coming back to configure, we
++# need to make the FD available again.
++if test "$no_create" != yes; then
++  ac_cs_success=:
++  ac_config_status_args=
++  test "$silent" = yes &&
++    ac_config_status_args="$ac_config_status_args --quiet"
++  exec 5>/dev/null
++  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
++  exec 5>>config.log
++  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
++  # would make configure fail if this is the last instruction.
++  $ac_cs_success || as_fn_exit 1
++fi
++if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
++printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
++fi
++
++
++
+diff --git a/bolt-plugin/configure.ac b/bolt-plugin/configure.ac
+new file mode 100644
+index 000000000..111d0ac48
+--- /dev/null
++++ b/bolt-plugin/configure.ac
+@@ -0,0 +1,60 @@
++AC_INIT([bolt plugin for ld],[0.1],[],[bolt-plugin])
++AC_CANONICAL_TARGET
++GCC_TOPLEV_SUBDIRS
++AM_INIT_AUTOMAKE([foreign no-dist])
++AM_MAINTAINER_MODE
++AC_ARG_WITH(libiberty,
++  [AS_HELP_STRING([--with-libiberty=PATH],
++    [specify the directory where to find libiberty [../libiberty]])],
++  [], with_libiberty=../libiberty)
++AC_SUBST(with_libiberty)
++AC_USE_SYSTEM_EXTENSIONS
++AC_PROG_CC
++AC_PROG_CXX
++AC_SYS_LARGEFILE
++ACX_PROG_CC_WARNING_OPTS([-Wall], [ac_bolt_plugin_warn_cflags])
++
++# Check whether -static-libgcc is supported.
++saved_LDFLAGS="$LDFLAGS"
++LDFLAGS="$LDFLAGS -static-libgcc"
++AC_MSG_CHECKING([for -static-libgcc])
++AC_LINK_IFELSE([AC_LANG_SOURCE([
++  int main() {}])], [have_static_libgcc=yes], [have_static_libgcc=no])
++AC_MSG_RESULT($have_static_libgcc); 
++LDFLAGS="$saved_LDFLAGS"
++# Need -Wc to get it through libtool.
++if test "x$have_static_libgcc" = xyes; then
++   ac_bolt_plugin_ldflags="-Wc,-static-libgcc"
++fi
++AC_SUBST(ac_bolt_plugin_ldflags)
++
++if test x"$host_subdir" = x.; then
++   gcc_build_dir=../gcc
++else
++   gcc_build_dir=../../$host_subdir/gcc
++fi
++AC_SUBST(gcc_build_dir)
++
++# Used for constructing correct paths for offload compilers.
++accel_dir_suffix=
++real_target_noncanonical=${target_noncanonical}
++if test x"$enable_as_accelerator_for" != x; then
++  accel_dir_suffix=/accel/${target_noncanonical}
++  real_target_noncanonical=${enable_as_accelerator_for}
++fi
++AC_SUBST(accel_dir_suffix)
++AC_SUBST(real_target_noncanonical)
++
++# Determine what GCC version number to use in filesystem paths.
++GCC_BASE_VER
++
++LT_INIT
++ACX_LT_HOST_FLAGS
++AC_SUBST(target_noncanonical)
++AC_TYPE_INT64_T
++AC_TYPE_UINT64_T
++AC_HEADER_SYS_WAIT
++AC_CONFIG_FILES(Makefile)
++AC_CONFIG_HEADERS(config.h)
++AC_OUTPUT
++
+diff --git a/gcc/common.opt b/gcc/common.opt
+index e69947fc2..44638fe83 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2554,6 +2554,22 @@ fauto-bolt=
+ Common Joined RejectNegative
+ Specify the feedback data directory required by BOLT-plugin.  The default is the current directory.
+ 
++fbolt-use
++Common Var(flag_bolt_use)
++Do BOLT optimization after linkage with BOLT profile read from this option.  The default is data.fdata.
++
++fbolt-use=
++Common Joined RejectNegative Var
++Do BOLT optimization after linkage with BOLT profile read from this option.
++
++fbolt-target=
++Common Joined RejectNegative Var
++Specify the BOLT optimization target binary.
++
++fbolt-option=
++Common Joined RejectNegative Var
++Specify BOLT optimization options separated by commas.
++
+ frerun-cse-after-loop
+ Common Var(flag_rerun_cse_after_loop) Optimization
+ Add a common subexpression elimination pass after loop optimizations.
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 6d57e7d69..2bba88140 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -1283,6 +1283,10 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
+   if (opts->x_flag_auto_bolt && opts->x_flag_lto)
+     sorry ("%<-fauto-bolt%> is not supported with LTO");
+ 
++  /* Currently -fbolt-use is not supported for LTO.  */
++  if (opts->x_flag_bolt_use && opts->x_flag_lto)
++    sorry ("-fbolt-use is not supported with LTO");
++
+   /* Control IPA optimizations based on different -flive-patching level.  */
+   if (opts->x_flag_live_patching)
+     control_options_for_live_patching (opts, opts_set,
+@@ -3284,9 +3288,28 @@ common_handle_option (struct gcc_options *opts,
+       break;
+     
+     case OPT_fauto_bolt_:
++      opts->x_flag_auto_bolt = true;
++      /* FALLTHRU */
+     case OPT_fauto_bolt:
+-      /* Deferred.  */  
+-      break;  
++      if (opts->x_flag_bolt_use)
++        error_at (loc,
++		  "-fauto-bolt conflicts with -fbolt-use.");
++      break;
++
++    case OPT_fbolt_use_:
++    case OPT_fbolt_use:
++      if (opts->x_flag_auto_bolt)
++        error_at (loc,
++		  "-fauto-bolt conflicts with -fbolt-use.");
++    break;
++
++    case OPT_fbolt_target_:
++      /* Deferred.  */
++      break;
++
++    case OPT_fbolt_option_:
++      /* Defferred */  
++      break;
+ 
+     case OPT_ftabstop_:
+       /* It is documented that we silently ignore silly values.  */
+-- 
+2.33.0
+
diff --git a/0033-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch b/0033-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
new file mode 100644
index 0000000..e850a4d
--- /dev/null
+++ b/0033-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
@@ -0,0 +1,345 @@
+From 94242286383a80e6ab83d824a4d7ea23ea311f75 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Mon, 22 Jan 2024 15:38:24 +0800
+Subject: [PATCH] [AutoBOLT] Enable BOLT linker plugin on aarch64 3/3
+
+---
+ Makefile.def     | 10 ++++++++++
+ configure        | 27 ++++++++++++++++++++++++++-
+ configure.ac     | 22 +++++++++++++++++++++-
+ gcc/config.host  |  1 +
+ gcc/config.in    | 13 +++++++++++++
+ gcc/configure    | 10 ++++++++--
+ gcc/configure.ac |  4 ++++
+ gcc/gcc.cc       | 23 +++++++++++++++++++++++
+ 8 files changed, 106 insertions(+), 4 deletions(-)
+
+diff --git a/Makefile.def b/Makefile.def
+index 72d585496..0ba868890 100644
+--- a/Makefile.def
++++ b/Makefile.def
+@@ -145,6 +145,9 @@ host_modules= { module= gnattools; };
+ host_modules= { module= lto-plugin; bootstrap=true;
+ 		extra_configure_flags='--enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@';
+ 		extra_make_flags='@extra_linker_plugin_flags@'; };
++host_modules= { module= bolt-plugin; bootstrap=true;
++		extra_configure_flags='--enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@';
++		extra_make_flags='@extra_linker_plugin_flags@'; };
+ host_modules= { module= libcc1; extra_configure_flags=--enable-shared; };
+ host_modules= { module= gotools; };
+ host_modules= { module= libctf; bootstrap=true; };
+@@ -349,6 +352,7 @@ dependencies = { module=configure-gcc; on=all-mpfr; };
+ dependencies = { module=configure-gcc; on=all-mpc; };
+ dependencies = { module=configure-gcc; on=all-isl; };
+ dependencies = { module=configure-gcc; on=all-lto-plugin; };
++dependencies = { module=configure-gcc; on=all-bolt-plugin; };
+ dependencies = { module=configure-gcc; on=all-binutils; };
+ dependencies = { module=configure-gcc; on=all-gas; };
+ dependencies = { module=configure-gcc; on=all-ld; };
+@@ -374,6 +378,7 @@ dependencies = { module=all-gcc; on=all-libdecnumber; hard=true; };
+ dependencies = { module=all-gcc; on=all-libiberty; };
+ dependencies = { module=all-gcc; on=all-fixincludes; };
+ dependencies = { module=all-gcc; on=all-lto-plugin; };
++dependencies = { module=all-gcc; on=all-bolt-plugin; };
+ dependencies = { module=all-gcc; on=all-libiconv; };
+ dependencies = { module=info-gcc; on=all-build-libiberty; };
+ dependencies = { module=dvi-gcc; on=all-build-libiberty; };
+@@ -381,8 +386,10 @@ dependencies = { module=pdf-gcc; on=all-build-libiberty; };
+ dependencies = { module=html-gcc; on=all-build-libiberty; };
+ dependencies = { module=install-gcc ; on=install-fixincludes; };
+ dependencies = { module=install-gcc ; on=install-lto-plugin; };
++dependencies = { module=install-gcc ; on=install-bolt-plugin; };
+ dependencies = { module=install-strip-gcc ; on=install-strip-fixincludes; };
+ dependencies = { module=install-strip-gcc ; on=install-strip-lto-plugin; };
++dependencies = { module=install-strip-gcc ; on=install-strip-bolt-plugin; };
+ 
+ dependencies = { module=configure-libcpp; on=configure-libiberty; hard=true; };
+ dependencies = { module=configure-libcpp; on=configure-intl; };
+@@ -401,6 +408,9 @@ dependencies = { module=all-gnattools; on=all-target-libstdc++-v3; };
+ dependencies = { module=all-lto-plugin; on=all-libiberty; };
+ dependencies = { module=all-lto-plugin; on=all-libiberty-linker-plugin; };
+ 
++dependencies = { module=all-bolt-plugin; on=all-libiberty; };
++dependencies = { module=all-bolt-plugin; on=all-libiberty-linker-plugin; };
++
+ dependencies = { module=configure-libcc1; on=configure-gcc; };
+ dependencies = { module=all-libcc1; on=all-gcc; };
+ 
+diff --git a/configure b/configure
+index 5dcaab14a..aff62c464 100755
+--- a/configure
++++ b/configure
+@@ -826,6 +826,7 @@ with_isl
+ with_isl_include
+ with_isl_lib
+ enable_isl_version_check
++enable_bolt
+ enable_lto
+ enable_linker_plugin_configure_flags
+ enable_linker_plugin_flags
+@@ -1550,6 +1551,7 @@ Optional Features:
+                           enable the PGO build
+   --disable-isl-version-check
+                           disable check for isl version
++  --enable-bolt           enable bolt optimization support
+   --enable-lto            enable link time optimization support
+   --enable-linker-plugin-configure-flags=FLAGS
+                           additional flags for configuring linker plugins
+@@ -8564,6 +8566,15 @@ fi
+ 
+ 
+ 
++# Check for BOLT support.
++# Check whether --enable-bolt was given.
++if test "${enable_bolt+set}" = set; then :
++  enableval=$enable_bolt; enable_bolt=$enableval
++else
++  enable_bolt=no; default_enable_bolt=no
++fi
++
++
+ # Check for LTO support.
+ # Check whether --enable-lto was given.
+ if test "${enable_lto+set}" = set; then :
+@@ -8593,6 +8604,16 @@ if test $target_elf = yes; then :
+   # ELF platforms build the lto-plugin always.
+   build_lto_plugin=yes
+ 
++  # ELF platforms can build the bolt-plugin.
++  # NOT BUILD BOLT BY DEFAULT.
++  case $target in
++    aarch64*-*-linux*)
++    if test $enable_bolt = yes; then :
++      build_bolt_plugin=yes
++    fi
++    ;;
++  esac
++
+ else
+   if test x"$default_enable_lto" = x"yes" ; then
+     case $target in
+@@ -8780,6 +8801,10 @@ if test -d ${srcdir}/gcc; then
+     fi
+   fi
+ 
++  if test "${build_bolt_plugin}" = "yes" ; then
++      configdirs="$configdirs bolt-plugin"
++  fi
++
+   # If we're building an offloading compiler, add the LTO front end.
+   if test x"$enable_as_accelerator_for" != x ; then
+     case ,${enable_languages}, in
+@@ -9202,7 +9227,7 @@ fi
+ extra_host_libiberty_configure_flags=
+ extra_host_zlib_configure_flags=
+ case " $configdirs " in
+-  *" lto-plugin "* | *" libcc1 "*)
++  *" lto-plugin "* | *" libcc1 "* | *" bolt-plugin "*)
+     # When these are to be built as shared libraries, the same applies to
+     # libiberty.
+     extra_host_libiberty_configure_flags=--enable-shared
+diff --git a/configure.ac b/configure.ac
+index 85977482a..f310d75ca 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1863,6 +1863,12 @@ fi
+ AC_SUBST(isllibs)
+ AC_SUBST(islinc)
+ 
++# Check for BOLT support.
++AC_ARG_ENABLE(bolt,
++[AS_HELP_STRING([--enable-bolt], [enable bolt optimization support])],
++enable_bolt=$enableval,
++enable_bolt=no; default_enable_bolt=no)
++
+ # Check for LTO support.
+ AC_ARG_ENABLE(lto,
+ [AS_HELP_STRING([--enable-lto], [enable link time optimization support])],
+@@ -1871,6 +1877,16 @@ enable_lto=yes; default_enable_lto=yes)
+ 
+ ACX_ELF_TARGET_IFELSE([# ELF platforms build the lto-plugin always.
+   build_lto_plugin=yes
++
++  # ELF platforms can build the bolt-plugin.
++  # NOT BUILD BOLT BY DEFAULT.
++  case $target in
++    aarch64*-*-linux*)
++    if test $enable_bolt = yes; then :
++      build_bolt_plugin=yes
++    fi
++    ;;
++  esac
+ ],[if test x"$default_enable_lto" = x"yes" ; then
+     case $target in
+       *-apple-darwin[[912]]* | *-cygwin* | *-mingw* | *djgpp*) ;;
+@@ -2049,6 +2065,10 @@ if test -d ${srcdir}/gcc; then
+     fi
+   fi
+ 
++  if test "${build_bolt_plugin}" = "yes" ; then
++      configdirs="$configdirs bolt-plugin"
++  fi
++
+   # If we're building an offloading compiler, add the LTO front end.
+   if test x"$enable_as_accelerator_for" != x ; then
+     case ,${enable_languages}, in
+@@ -2457,7 +2477,7 @@ fi
+ extra_host_libiberty_configure_flags=
+ extra_host_zlib_configure_flags=
+ case " $configdirs " in
+-  *" lto-plugin "* | *" libcc1 "*)
++  *" lto-plugin "* | *" libcc1 "* | *" bolt-plugin "*)    
+     # When these are to be built as shared libraries, the same applies to
+     # libiberty.
+     extra_host_libiberty_configure_flags=--enable-shared
+diff --git a/gcc/config.host b/gcc/config.host
+index 4ca300f11..bf7dcb4cc 100644
+--- a/gcc/config.host
++++ b/gcc/config.host
+@@ -75,6 +75,7 @@ out_host_hook_obj=host-default.o
+ host_can_use_collect2=yes
+ use_long_long_for_widest_fast_int=no
+ host_lto_plugin_soname=liblto_plugin.so
++host_bolt_plugin_soname=libbolt_plugin.so
+ 
+ # Unsupported hosts list.  Generally, only include hosts known to fail here,
+ # since we allow hosts not listed to be supported generically.
+diff --git a/gcc/config.in b/gcc/config.in
+index 64c27c9cf..6bb25b25b 100644
+--- a/gcc/config.in
++++ b/gcc/config.in
+@@ -24,6 +24,13 @@
+ #endif
+ 
+ 
++/* Define to the name of the BOLT plugin DSO that must be passed to the
++   linker's -plugin=LIB option. */
++#ifndef USED_FOR_TARGET
++#undef BOLTPLUGINSONAME
++#endif
++
++
+ /* Define to the root for URLs about GCC changes. */
+ #ifndef USED_FOR_TARGET
+ #undef CHANGES_ROOT_URL
+@@ -2208,6 +2215,12 @@
+ #endif
+ 
+ 
++/* Define which stat syscall is able to handle 64bit indodes. */
++#ifndef USED_FOR_TARGET
++#undef HOST_STAT_FOR_64BIT_INODES
++#endif
++
++
+ /* Define as const if the declaration of iconv() needs const. */
+ #ifndef USED_FOR_TARGET
+ #undef ICONV_CONST
+diff --git a/gcc/configure b/gcc/configure
+index 98bbf0f85..30f386789 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -13578,6 +13578,12 @@ case $use_collect2 in
+ esac
+ 
+ 
++cat >>confdefs.h <<_ACEOF
++#define BOLTPLUGINSONAME "${host_bolt_plugin_soname}"
++_ACEOF
++
++
++
+ cat >>confdefs.h <<_ACEOF
+ #define LTOPLUGINSONAME "${host_lto_plugin_soname}"
+ _ACEOF
+@@ -19668,7 +19674,7 @@ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line 19671 "configure"
++#line 19677 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -19774,7 +19780,7 @@ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line 19777 "configure"
++#line 19783 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+diff --git a/gcc/configure.ac b/gcc/configure.ac
+index c74f4b555..dd6cd60f8 100644
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -2531,6 +2531,10 @@ case $use_collect2 in
+     ;;
+ esac
+ 
++AC_DEFINE_UNQUOTED(BOLTPLUGINSONAME,"${host_bolt_plugin_soname}",
++[Define to the name of the BOLT plugin DSO that must be
++  passed to the linker's -plugin=LIB option.])
++
+ AC_DEFINE_UNQUOTED(LTOPLUGINSONAME,"${host_lto_plugin_soname}",
+ [Define to the name of the LTO plugin DSO that must be
+   passed to the linker's -plugin=LIB option.])
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index fbcc9d033..b0d03430e 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -1156,6 +1156,8 @@ proper position among the other output files.  */
+ %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+     %(linker) " \
+     LINK_PLUGIN_SPEC \
++   "%{fauto-bolt|fauto-bolt=*|fbolt-use|fbolt-use=*: \
++    -plugin %(linker_auto_bolt_plugin_file) }"\
+    "%{flto|flto=*:%
+Date: Sat, 23 Mar 2024 22:56:09 +0800
+Subject: [PATCH] [Autofdo]Enable discrimibator and MCF algorithm on Autofdo
+
+---
+ gcc/auto-profile.cc | 171 +++++++++++++++++++++++++++++++++++++++++++-
+ gcc/cfghooks.cc     |   7 ++
+ gcc/opts.cc         |   5 +-
+ gcc/tree-inline.cc  |  14 ++++
+ 4 files changed, 193 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
+index 2b34b80b8..f45f0ec66 100644
+--- a/gcc/auto-profile.cc
++++ b/gcc/auto-profile.cc
+@@ -466,6 +466,17 @@ string_table::get_index (const char *name) const
+   if (name == NULL)
+     return -1;
+   string_index_map::const_iterator iter = map_.find (name);
++  /* Function name may be duplicate.  Try to distinguish by the
++     #file_name#function_name defined by the autofdo tool chain.  */
++  if (iter == map_.end ())
++    {
++      char* file_name = get_original_name (lbasename (dump_base_name));
++      char* file_func_name
++	= concat ("#", file_name, "#", name, NULL);
++      iter = map_.find (file_func_name);
++      free (file_name);
++      free (file_func_name);
++    }
+   if (iter == map_.end ())
+     return -1;
+ 
+@@ -654,7 +665,7 @@ function_instance::read_function_instance (function_instance_stack *stack,
+ 
+   for (unsigned i = 0; i < num_pos_counts; i++)
+     {
+-      unsigned offset = gcov_read_unsigned () & 0xffff0000;
++      unsigned offset = gcov_read_unsigned ();
+       unsigned num_targets = gcov_read_unsigned ();
+       gcov_type count = gcov_read_counter ();
+       s->pos_counts[offset].count = count;
+@@ -733,6 +744,10 @@ autofdo_source_profile::get_count_info (gimple *stmt, count_info *info) const
+   function_instance *s = get_function_instance_by_inline_stack (stack);
+   if (s == NULL)
+     return false;
++  if (s->get_count_info (stack[0].second + stmt->bb->discriminator, info))
++    {
++      return true;
++    }
+   return s->get_count_info (stack[0].second, info);
+ }
+ 
+@@ -1395,6 +1410,66 @@ afdo_propagate (bb_set *annotated_bb)
+     }
+ }
+ 
++/* Process the following scene when the branch probability
++   inversion when do function afdo_propagate (). E.g.
++   BB_NUM (sample count)
++      BB1 (1000)
++       /    \
++    BB2 (10) BB3 (0)
++      \       /
++	BB4
++   In afdo_propagate ().count of BB3 is calculated by
++   COUNT (BB3) = 990 (990 = COUNT (BB1) - COUNT (BB2) = 1000 - 10)
++   In fact, BB3 may be colder than BB2 by sample count.
++   This function allocate source BB count to wach succ BB by sample
++   rate, E.g.
++   BB2_COUNT = BB1_COUNT * (BB2_COUNT / (BB2_COUNT + BB3_COUNT))  */
++
++static void
++afdo_preprocess_bb_count ()
++{
++  basic_block bb;
++  FOR_ALL_BB_FN (bb, cfun)
++    {
++      if (bb->count.ipa_p () && EDGE_COUNT (bb->succs) > 1
++	  && bb->count > profile_count::zero ().afdo ())
++	{
++	  basic_block bb1 = EDGE_SUCC (bb, 0)->dest;
++	  basic_block bb2 = EDGE_SUCC (bb, 1)->dest;
++	  if (single_succ_edge (bb1) && single_succ_edge (bb2)
++	      && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
++	    {
++	      gcov_type max_count = 0;
++	      gcov_type total_count = 0;
++	      edge e;
++	      edge_iterator ei;
++	      FOR_EACH_EDGE (e, ei, bb->succs)
++		{
++		  if (!e->dest->count.ipa_p ())
++		    {
++		      continue;
++		    }
++		  max_count = MAX (max_count, e->dest->count.to_gcov_type ());
++		  total_count += e->dest->count.to_gcov_type ();
++		}
++	      /* Only bb_count > max_count * 2, branch probability will
++		 inversion.  */
++	      if (max_count > 0 && bb->count.to_gcov_type () > max_count * 2)
++		{
++		  FOR_EACH_EDGE (e, ei, bb->succs)
++		    {
++		      gcov_type target_count = bb->count.to_gcov_type ()
++			* e->dest->count.to_gcov_type ()/ total_count;
++		      e->dest->count
++			= profile_count::from_gcov_type
++			  (target_count).afdo ();
++		    }
++		}
++	    }
++	}
++    }
++}
++
+ /* Propagate counts on control flow graph and calculate branch
+    probabilities.  */
+ 
+@@ -1420,6 +1495,7 @@ afdo_calculate_branch_prob (bb_set *annotated_bb)
+     }
+ 
+   afdo_find_equiv_class (annotated_bb);
++  afdo_preprocess_bb_count ();
+   afdo_propagate (annotated_bb);
+ 
+   FOR_EACH_BB_FN (bb, cfun)
+@@ -1523,6 +1599,83 @@ afdo_vpt_for_early_inline (stmt_set *promoted_stmts)
+   return false;
+ }
+ 
++/* Preparation before executing MCF algorithm.  */
++
++static void
++afdo_init_mcf ()
++{
++  basic_block bb;
++  edge e;
++  edge_iterator ei;
++
++  if (dump_file)
++    {
++      fprintf (dump_file, "\n init calling mcf_smooth_cfg (). \n");
++    }
++
++  /* Step1: when use mcf, BB id must be continous,
++     so we need compact_blocks ().  */
++  compact_blocks ();
++
++  /* Step2: allocate memory for MCF input data.  */
++  bb_gcov_counts.safe_grow_cleared (cfun->cfg->x_last_basic_block);
++  edge_gcov_counts = new hash_map;
++
++  /* Step3: init MCF input data from cfg.  */
++  FOR_ALL_BB_FN (bb, cfun)
++    {
++      /* Init BB count for MCF.  */
++      bb_gcov_count (bb) = bb->count.to_gcov_type ();
++
++      gcov_type total_count = 0;
++      FOR_EACH_EDGE (e, ei, bb->succs)
++	{
++	  total_count += e->dest->count.to_gcov_type ();
++	}
++
++      /* If there is no sample in each successor blocks, source
++	 BB samples are allocated to each edge by branch static prob.  */
++
++      FOR_EACH_EDGE (e, ei, bb->succs)
++	{
++	  if (total_count == 0)
++	    {
++	      edge_gcov_count (e) = e->src->count.to_gcov_type ()
++		* e->probability.to_reg_br_prob_base () / REG_BR_PROB_BASE;
++	    }
++	  else
++	    {
++	      edge_gcov_count (e) = e->src->count.to_gcov_type ()
++		* e->dest->count.to_gcov_type () / total_count;
++	    }
++	}
++    }
++}
++
++
++/* Free the resources used by MCF and reset BB count from MCF result.
++   branch probability has been updated in mcf_smooth_cfg ().  */
++
++static void
++afdo_process_after_mcf ()
++{
++  basic_block bb;
++  /* Reset BB count from MCF result.  */
++  FOR_EACH_BB_FN (bb, cfun)
++    {
++      if (bb_gcov_count (bb))
++	{
++	  bb->count
++	    = profile_count::from_gcov_type (bb_gcov_count (bb)).afdo ();
++	}
++    }
++
++    /* Clean up MCF resource.  */
++    bb_gcov_counts.release ();
++    delete edge_gcov_counts;
++    edge_gcov_counts = NULL;
++}
++
+ /* Annotate auto profile to the control flow graph. Do not annotate value
+    profile for stmts in PROMOTED_STMTS.  */
+ 
+@@ -1574,8 +1727,20 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts)
+   afdo_source_profile->mark_annotated (cfun->function_end_locus);
+   if (max_count > profile_count::zero ())
+     {
+-      /* Calculate, propagate count and probability information on CFG.  */
+-      afdo_calculate_branch_prob (&annotated_bb);
++      /* 1 means -fprofile-correction is enbaled manually, and MCF
++	 algorithm will be used to calculate count and probability.
++	 Otherwise, use the default calculate algorithm.  */
++      if (flag_profile_correction == 1)
++	{
++	  afdo_init_mcf ();
++	  mcf_smooth_cfg ();
++	  afdo_process_after_mcf ();
++	}
++      else
++	{
++	  /* Calculate, propagate count and probability information on CFG.  */
++	  afdo_calculate_branch_prob (&annotated_bb);
++	}
+     }
+   update_max_bb_count ();
+   profile_status_for_fn (cfun) = PROFILE_READ;
+diff --git a/gcc/cfghooks.cc b/gcc/cfghooks.cc
+index c0b7bdcd9..323663010 100644
+--- a/gcc/cfghooks.cc
++++ b/gcc/cfghooks.cc
+@@ -542,6 +542,9 @@ split_block_1 (basic_block bb, void *i)
+     return NULL;
+ 
+   new_bb->count = bb->count;
++  /* Copy discriminator from original bb for distinguishes among
++     several basic blocks that share a common locus, allowing for
++     more accurate autofdo.  */
+   new_bb->discriminator = bb->discriminator;
+ 
+   if (dom_info_available_p (CDI_DOMINATORS))
+@@ -1113,6 +1116,10 @@ duplicate_block (basic_block bb, edge e, basic_block after, copy_bb_data *id)
+     move_block_after (new_bb, after);
+ 
+   new_bb->flags = (bb->flags & ~BB_DUPLICATED);
++  /* Copy discriminator from original bb for distinguishes among
++     several basic blocks that share a common locus, allowing for
++     more accurate autofdo.  */
++  new_bb->discriminator = bb->discriminator;
+   FOR_EACH_EDGE (s, ei, bb->succs)
+     {
+       /* Since we are creating edges from a new block to successors
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 2bba88140..4b4925331 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -3014,7 +3014,10 @@ common_handle_option (struct gcc_options *opts,
+       /* FALLTHRU */
+     case OPT_fauto_profile:
+       enable_fdo_optimizations (opts, opts_set, value);
+-      SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value);
++	  /* 2 is special and means flag_profile_correction trun on by
++	     -fauto-profile.  */
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction,
++			   (value ? 2 : 0));
+       break;
+ 
+     case OPT_fipa_struct_reorg_:
+diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
+index f892cee3f..f50dbbc52 100644
+--- a/gcc/tree-inline.cc
++++ b/gcc/tree-inline.cc
+@@ -2038,6 +2038,10 @@ copy_bb (copy_body_data *id, basic_block bb,
+      basic_block_info automatically.  */
+   copy_basic_block = create_basic_block (NULL, (basic_block) prev->aux);
+   copy_basic_block->count = bb->count.apply_scale (num, den);
++  /* Copy discriminator from original bb for distinguishes among
++     several basic blocks that share a common locus, allowing for
++     more accurate autofdo.  */
++  copy_basic_block->discriminator = bb->discriminator;
+ 
+   copy_gsi = gsi_start_bb (copy_basic_block);
+ 
+@@ -3058,6 +3062,16 @@ copy_cfg_body (copy_body_data * id,
+ 	  den += e->count ();
+       ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = den;
+     }
++  /* When autofdo uses PMU as the sampling unit, the number of
++     ENTRY_BLOCK_PTR_FOR_FN cannot be obtained directly and will
++     be zero.  It using for adjust_for_ipa_scaling will cause the
++     inlined BB count incorrectly overestimated.  So set den equal
++     to num, which is the source inline BB count to avoid
++     overestimated.  */
++  if (den == profile_count::zero ().afdo ())
++    {
++      den = num;
++    }
+ 
+   profile_count::adjust_for_ipa_scaling (&num, &den);
+ 
+-- 
+2.33.0
+
diff --git a/0035-Add-insn-defs-and-correct-costs-for-cmlt-generation.patch b/0035-Add-insn-defs-and-correct-costs-for-cmlt-generation.patch
new file mode 100644
index 0000000..c40886a
--- /dev/null
+++ b/0035-Add-insn-defs-and-correct-costs-for-cmlt-generation.patch
@@ -0,0 +1,194 @@
+From aa39a66f6029fe16a656d7c6339908b953fb1e04 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia WX1215920 
+Date: Thu, 22 Feb 2024 11:27:43 +0300
+Subject: [PATCH 01/18] Add insn defs and correct costs for cmlt generation
+
+---
+ gcc/config/aarch64/aarch64-simd.md  | 48 +++++++++++++++++++++++++++++
+ gcc/config/aarch64/aarch64.cc       | 15 +++++++++
+ gcc/config/aarch64/aarch64.opt      |  4 +++
+ gcc/config/aarch64/iterators.md     |  3 +-
+ gcc/config/aarch64/predicates.md    | 25 +++++++++++++++
+ gcc/testsuite/gcc.dg/combine-cmlt.c | 20 ++++++++++++
+ 6 files changed, 114 insertions(+), 1 deletion(-)
+ create mode 100755 gcc/testsuite/gcc.dg/combine-cmlt.c
+
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index ee7f0b89c..82f73805f 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -6454,6 +6454,54 @@
+   [(set_attr "type" "neon_compare, neon_compare_zero")]
+ )
+ 
++;; Use cmlt to replace vector arithmetic operations like this (SImode example):
++;; B = (((A >> 15) & 0x00010001) << 16) - ((A >> 15) & 0x00010001)
++;; TODO: maybe extend to scalar operations or other cm** instructions.
++
++(define_insn "*aarch64_cmlt_as_arith"
++  [(set (match_operand: 0 "register_operand" "=w")
++	(minus:
++	  (ashift:
++	    (and:
++	      (lshiftrt:
++		(match_operand:VDQHSD 1 "register_operand" "w")
++		(match_operand:VDQHSD 2 "half_size_minus_one_operand"))
++	      (match_operand:VDQHSD 3 "cmlt_arith_mask_operand"))
++	    (match_operand:VDQHSD 4 "half_size_operand"))
++	  (and:
++	    (lshiftrt:
++	      (match_dup 1)
++	      (match_dup 2))
++	    (match_dup 3))))]
++  "TARGET_SIMD && flag_cmlt_arith"
++  "cmlt\t%0., %1., #0"
++  [(set_attr "type" "neon_compare_zero")]
++)
++
++;; The helper definition that allows combiner to use the previous pattern.
++
++(define_insn_and_split "*arch64_cmlt_tmp"
++  [(set (match_operand: 0 "register_operand" "=w")
++	(and:
++	  (lshiftrt:
++	    (match_operand:VDQHSD 1 "register_operand" "w")
++	    (match_operand:VDQHSD 2 "half_size_minus_one_operand"))
++	  (match_operand:VDQHSD 3 "cmlt_arith_mask_operand")))]
++  "TARGET_SIMD && flag_cmlt_arith"
++  "#"
++  "&& reload_completed"
++  [(set (match_operand: 0 "register_operand")
++	(lshiftrt:
++	  (match_operand:VDQHSD 1 "register_operand")
++	  (match_operand:VDQHSD 2 "half_size_minus_one_operand")))
++   (set (match_dup 0)
++	(and:
++	  (match_dup 0)
++	  (match_operand:VDQHSD 3 "cmlt_arith_mask_operand")))]
++  ""
++  [(set_attr "type" "neon_compare_zero")]
++)
++
+ (define_insn_and_split "aarch64_cmdi"
+   [(set (match_operand:DI 0 "register_operand" "=w,w,r")
+ 	(neg:DI
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index a3da4ca30..04072ca25 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -14064,6 +14064,21 @@ cost_minus:
+ 	    return true;
+ 	  }
+ 
++	/* Detect aarch64_cmlt_as_arith instruction. Now only this pattern
++	   matches the condition. The costs of cmlt and sub instructions
++	   are comparable, so we are not increasing the cost here.  */
++	if (flag_cmlt_arith && GET_CODE (op0) == ASHIFT
++	    && GET_CODE (op1) == AND)
++	  {
++	    rtx op0_subop0 = XEXP (op0, 0);
++	    if (rtx_equal_p (op0_subop0, op1))
++	      {
++		rtx lshrt_op = XEXP (op0_subop0, 0);
++		if (GET_CODE (lshrt_op) == LSHIFTRT)
++		  return true;
++	      }
++	  }
++
+ 	/* Look for SUB (extended register).  */
+ 	if (is_a  (mode)
+ 	    && aarch64_rtx_arith_op_extract_p (op1))
+diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
+index a64b927e9..101664c7c 100644
+--- a/gcc/config/aarch64/aarch64.opt
++++ b/gcc/config/aarch64/aarch64.opt
+@@ -262,6 +262,10 @@ Use an immediate to offset from the stack protector guard register, sp_el0.
+ This option is for use with fstack-protector-strong and not for use in
+ user-land code.
+ 
++mcmlt-arith
++Target Var(flag_cmlt_arith) Optimization Init(0)
++Use SIMD cmlt instruction to perform some arithmetic/logic calculations.
++
+ TargetVariable
+ long aarch64_stack_protector_guard_offset = 0
+ 
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index 26a840d7f..967e6b0b1 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -1485,7 +1485,8 @@
+ 			  (V2DI "2s")])
+ 
+ ;; Register suffix narrowed modes for VQN.
+-(define_mode_attr V2ntype [(V8HI "16b") (V4SI "8h")
++(define_mode_attr V2ntype [(V4HI "8b") (V2SI "4h")
++			   (V8HI "16b") (V4SI "8h")
+ 			   (V2DI "4s")])
+ 
+ ;; Widened modes of vector modes.
+diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
+index c308015ac..07c14aacb 100644
+--- a/gcc/config/aarch64/predicates.md
++++ b/gcc/config/aarch64/predicates.md
+@@ -49,6 +49,31 @@
+   return CONST_INT_P (op) && IN_RANGE (INTVAL (op), 1, 3);
+ })
+ 
++(define_predicate "half_size_minus_one_operand"
++  (match_code "const_vector")
++{
++  op = unwrap_const_vec_duplicate (op);
++  unsigned int size = GET_MODE_UNIT_BITSIZE (mode) / 2;
++  return CONST_INT_P (op) && (UINTVAL (op) == size - 1);
++})
++
++(define_predicate "half_size_operand"
++  (match_code "const_vector")
++{
++  op = unwrap_const_vec_duplicate (op);
++  unsigned int size = GET_MODE_UNIT_BITSIZE (mode) / 2;
++  return CONST_INT_P (op) && (UINTVAL (op) == size);
++})
++
++(define_predicate "cmlt_arith_mask_operand"
++  (match_code "const_vector")
++{
++  op = unwrap_const_vec_duplicate (op);
++  unsigned int size = GET_MODE_UNIT_BITSIZE (mode) / 2;
++  unsigned long long mask = ((unsigned long long) 1 << size) | 1;
++  return CONST_INT_P (op) && (UINTVAL (op) == mask);
++})
++
+ (define_predicate "subreg_lowpart_operator"
+   (ior (match_code "truncate")
+        (and (match_code "subreg")
+diff --git a/gcc/testsuite/gcc.dg/combine-cmlt.c b/gcc/testsuite/gcc.dg/combine-cmlt.c
+new file mode 100755
+index 000000000..b4c9a37ff
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/combine-cmlt.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-options "-O3 -mcmlt-arith" } */
++
++/* The test checks usage of cmlt insns for arithmetic/logic calculations
++ * in foo ().  It's inspired by sources of x264 codec.  */
++
++typedef unsigned short int uint16_t;
++typedef unsigned int uint32_t;
++
++void foo( uint32_t *a, uint32_t *b)
++{
++  for (unsigned i = 0; i < 4; i++)
++    {
++      uint32_t s = ((a[i]>>((8 * sizeof(uint16_t))-1))
++		    &(((uint32_t)1<<(8 * sizeof(uint16_t)))+1))*((uint16_t)-1);
++      b[i] = (a[i]+s)^s;
++    }
++}
++
++/* { dg-final { scan-assembler-times {cmlt\t} 1 } }  */
+-- 
+2.33.0
+
diff --git a/0036-rtl-ifcvt-introduce-rtl-ifcvt-enchancements.patch b/0036-rtl-ifcvt-introduce-rtl-ifcvt-enchancements.patch
new file mode 100644
index 0000000..813eba9
--- /dev/null
+++ b/0036-rtl-ifcvt-introduce-rtl-ifcvt-enchancements.patch
@@ -0,0 +1,560 @@
+From 4cae948c1c00ad7a59f0f234f809fbd9a0208eb4 Mon Sep 17 00:00:00 2001
+From: vchernon 
+Date: Wed, 28 Feb 2024 23:05:12 +0800
+Subject: [PATCH 02/18] [rtl-ifcvt] introduce rtl ifcvt enchancements     new
+ option:       -fifcvt-allow-complicated-cmps:         allows ifcvt to deal
+ with complicated cmps like
+
+        cmp reg1 (reg2 + reg3)
+
+        can increase compilation time
+    new param:
+      -param=ifcvt-allow-register-renaming=[0,1,2]
+        1 : allows ifcvt to rename registers in then and else bb
+        2 : allows to rename registers in condition and else/then bb
+        can increase compilation time and register pressure
+---
+ gcc/common.opt                                |   4 +
+ gcc/ifcvt.cc                                  | 291 +++++++++++++++---
+ gcc/params.opt                                |   4 +
+ .../gcc.c-torture/execute/ifcvt-renaming-1.c  |  35 +++
+ gcc/testsuite/gcc.dg/ifcvt-6.c                |  27 ++
+ 5 files changed, 311 insertions(+), 50 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.c-torture/execute/ifcvt-renaming-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/ifcvt-6.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index c7c6bc256..aa00fb7b0 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -3691,4 +3691,8 @@ fipa-ra
+ Common Var(flag_ipa_ra) Optimization
+ Use caller save register across calls if possible.
+ 
++fifcvt-allow-complicated-cmps
++Common Var(flag_ifcvt_allow_complicated_cmps) Optimization
++Allow RTL if-conversion pass to deal with complicated cmps (can increase compilation time).
++
+ ; This comment is to ensure we retain the blank line above.
+diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
+index 2c1eba312..584db7b55 100644
+--- a/gcc/ifcvt.cc
++++ b/gcc/ifcvt.cc
+@@ -886,7 +886,9 @@ noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
+     }
+ 
+   /* Don't even try if the comparison operands or the mode of X are weird.  */
+-  if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
++  if (!flag_ifcvt_allow_complicated_cmps
++      && (cond_complex
++	  || !SCALAR_INT_MODE_P (GET_MODE (x))))
+     return NULL_RTX;
+ 
+   return emit_store_flag (x, code, XEXP (cond, 0),
+@@ -1965,7 +1967,8 @@ insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
+   /* Currently support only simple single sets in test_bb.  */
+   if (!sset
+       || !noce_operand_ok (SET_DEST (sset))
+-      || contains_ccmode_rtx_p (SET_DEST (sset))
++      || (!flag_ifcvt_allow_complicated_cmps
++	  && contains_ccmode_rtx_p (SET_DEST (sset)))
+       || !noce_operand_ok (SET_SRC (sset)))
+     return false;
+ 
+@@ -1979,13 +1982,17 @@ insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
+    in this function.  */
+ 
+ static bool
+-bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
++bbs_ok_for_cmove_arith (basic_block bb_a,
++			basic_block bb_b,
++			rtx to_rename,
++			bitmap conflict_regs)
+ {
+   rtx_insn *a_insn;
+   bitmap bba_sets = BITMAP_ALLOC (®_obstack);
+-
++  bitmap intersections = BITMAP_ALLOC (®_obstack);
+   df_ref def;
+   df_ref use;
++  rtx_insn *last_a = last_active_insn (bb_a, FALSE);
+ 
+   FOR_BB_INSNS (bb_a, a_insn)
+     {
+@@ -1995,18 +2002,15 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
+       rtx sset_a = single_set (a_insn);
+ 
+       if (!sset_a)
+-	{
+-	  BITMAP_FREE (bba_sets);
+-	  return false;
+-	}
++	goto end_cmove_arith_check_and_fail;
+       /* Record all registers that BB_A sets.  */
+       FOR_EACH_INSN_DEF (def, a_insn)
+-	if (!(to_rename && DF_REF_REG (def) == to_rename))
++	if (!(to_rename && DF_REF_REG (def) == to_rename && a_insn == last_a))
+ 	  bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
+     }
+ 
++  bitmap_and (intersections, df_get_live_in (bb_b), bba_sets);
+   rtx_insn *b_insn;
+-
+   FOR_BB_INSNS (bb_b, b_insn)
+     {
+       if (!active_insn_p (b_insn))
+@@ -2015,10 +2019,7 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
+       rtx sset_b = single_set (b_insn);
+ 
+       if (!sset_b)
+-	{
+-	  BITMAP_FREE (bba_sets);
+-	  return false;
+-	}
++	goto end_cmove_arith_check_and_fail;
+ 
+       /* Make sure this is a REG and not some instance
+ 	 of ZERO_EXTRACT or SUBREG or other dangerous stuff.
+@@ -2030,25 +2031,34 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
+       if (MEM_P (SET_DEST (sset_b)))
+ 	gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
+       else if (!REG_P (SET_DEST (sset_b)))
+-	{
+-	  BITMAP_FREE (bba_sets);
+-	  return false;
+-	}
++	goto end_cmove_arith_check_and_fail;
+ 
+-      /* If the insn uses a reg set in BB_A return false.  */
++      /* If the insn uses a reg set in BB_A return false
++	 or try to collect register list for renaming.  */
+       FOR_EACH_INSN_USE (use, b_insn)
+ 	{
+-	  if (bitmap_bit_p (bba_sets, DF_REF_REGNO (use)))
++	  if (bitmap_bit_p (intersections, DF_REF_REGNO (use)))
+ 	    {
+-	      BITMAP_FREE (bba_sets);
+-	      return false;
++	      if (param_ifcvt_allow_register_renaming < 1)
++		  goto end_cmove_arith_check_and_fail;
++
++	      /* Those regs should be renamed.  We can't rename CC reg, but
++		 possibly we can provide combined comparison in the future.  */
++	      if (GET_MODE_CLASS (GET_MODE (DF_REF_REG (use))) == MODE_CC)
++		goto end_cmove_arith_check_and_fail;
++	      bitmap_set_bit (conflict_regs, DF_REF_REGNO (use));
+ 	    }
+ 	}
+-
+     }
+ 
+   BITMAP_FREE (bba_sets);
++  BITMAP_FREE (intersections);
+   return true;
++
++end_cmove_arith_check_and_fail:
++  BITMAP_FREE (bba_sets);
++  BITMAP_FREE (intersections);
++  return false;
+ }
+ 
+ /* Emit copies of all the active instructions in BB except the last.
+@@ -2103,6 +2113,142 @@ noce_emit_bb (rtx last_insn, basic_block bb, bool simple)
+   return true;
+ }
+ 
++/* This function tries to rename regs that intersect with considered bb
++   inside condition expression.  Condition expression will be moved down
++   if the optimization will be applied, so it is essential to be sure that
++   all intersected registers will be renamed otherwise transformation
++   can't be applied.  Function returns true if renaming was successful
++   and optimization can proceed futher.  */
++
++static bool
++noce_rename_regs_in_cond (struct noce_if_info *if_info, bitmap cond_rename_regs)
++{
++  bool success = true;
++  if (bitmap_empty_p (cond_rename_regs))
++    return true;
++  if (param_ifcvt_allow_register_renaming < 2)
++    return false;
++  df_ref use;
++  rtx_insn *cmp_insn = if_info->cond_earliest;
++  /*  Jump instruction as a condion currently unsupported.  */
++  if (JUMP_P (cmp_insn))
++    return false;
++  rtx_insn *before_cmp = PREV_INSN (cmp_insn);
++  start_sequence ();
++  rtx_insn *copy_of_cmp = as_a  (copy_rtx (cmp_insn));
++  basic_block cmp_block = BLOCK_FOR_INSN (cmp_insn);
++  FOR_EACH_INSN_USE (use, cmp_insn)
++    {
++      if (bitmap_bit_p (cond_rename_regs, DF_REF_REGNO (use)))
++	{
++	  rtx use_reg = DF_REF_REG (use);
++	  rtx tmp = gen_reg_rtx (GET_MODE (use_reg));
++	  if (!validate_replace_rtx (use_reg, tmp, copy_of_cmp))
++	    {
++	      end_sequence ();
++	      return false;
++	    }
++	  noce_emit_move_insn (tmp, use_reg);
++	}
++    }
++
++  emit_insn (PATTERN (copy_of_cmp));
++  rtx_insn *seq = get_insns ();
++  unshare_all_rtl_in_chain (seq);
++  end_sequence ();
++
++  emit_insn_after_setloc (seq, before_cmp, INSN_LOCATION (cmp_insn));
++  delete_insn_and_edges (cmp_insn);
++  rtx_insn *insn;
++  FOR_BB_INSNS (cmp_block, insn)
++    df_insn_rescan (insn);
++
++  if_info->cond = noce_get_condition (if_info->jump,
++				      ©_of_cmp,
++				      if_info->then_else_reversed);
++  if_info->cond_earliest = copy_of_cmp;
++  if_info->rev_cond = NULL_RTX;
++
++  return success;
++}
++
++/* This function tries to rename regs that intersect with considered bb.
++   return true if the renaming was successful and optimization can
++   proceed futher, false otherwise.  */
++static bool
++noce_rename_regs_in_bb (basic_block test_bb, bitmap rename_regs)
++{
++  if (bitmap_empty_p (rename_regs))
++    return true;
++  rtx_insn *insn;
++  rtx_insn *last_insn = last_active_insn (test_bb, FALSE);
++  bool res = true;
++  start_sequence ();
++  FOR_BB_INSNS (test_bb, insn)
++    {
++      if (!active_insn_p (insn))
++	continue;
++      /* Only ssets are supported for now.  */
++      rtx sset = single_set (insn);
++      gcc_assert (sset);
++      rtx x = SET_DEST (sset);
++      if (!REG_P (x) || !bitmap_bit_p (rename_regs, REGNO (x)))
++	continue;
++      /* Do not need to rename dest in the last instruction
++	 it will be renamed anyway.  */
++      if (insn == last_insn)
++	continue;
++      machine_mode mode = GET_MODE (x);
++      rtx tmp = gen_reg_rtx (mode);
++      if (!validate_replace_rtx_part (x, tmp, &SET_DEST (sset), insn))
++	{
++	  gcc_assert (insn != last_insn);
++	  /* We can generate additional move for such case,
++	     but it will increase register preasure.
++	     For now just stop transformation.  */
++	  rtx result_rtx = SET_DEST (single_set (last_insn));
++	  if (REG_P (result_rtx) && (x != result_rtx))
++	    {
++	      res = false;
++	      break;
++	    }
++	  if (!validate_replace_rtx (x, tmp, insn))
++	    gcc_unreachable ();
++	  noce_emit_move_insn (tmp,x);
++	}
++      set_used_flags (insn);
++      rtx_insn *rename_candidate;
++      for (rename_candidate = NEXT_INSN (insn);
++	   rename_candidate && rename_candidate!= NEXT_INSN (BB_END (test_bb));
++	   rename_candidate = NEXT_INSN (rename_candidate))
++	{
++	  if (!reg_overlap_mentioned_p (x, rename_candidate))
++	    continue;
++
++	  int replace_res = TRUE;
++	  if (rename_candidate == last_insn)
++	    {
++	      validate_replace_src_group (x, tmp, rename_candidate);
++	      replace_res = apply_change_group ();
++	    }
++	  else
++	    replace_res = validate_replace_rtx (x, tmp, rename_candidate);
++	  gcc_assert (replace_res);
++	  set_used_flags (rename_candidate);
++	}
++      set_used_flags (x);
++      set_used_flags (tmp);
++    }
++    rtx_insn *seq = get_insns ();
++    unshare_all_rtl_in_chain (seq);
++    end_sequence ();
++    emit_insn_before_setloc (seq, first_active_insn (test_bb),
++			     INSN_LOCATION (first_active_insn (test_bb)));
++    FOR_BB_INSNS (test_bb, insn)
++      df_insn_rescan (insn);
++  return res;
++}
++
+ /* Try more complex cases involving conditional_move.  */
+ 
+ static int
+@@ -2185,11 +2331,30 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
+ 	  std::swap (then_bb, else_bb);
+ 	}
+     }
+-
++  bitmap else_bb_rename_regs = BITMAP_ALLOC (®_obstack);
++  bitmap then_bb_rename_regs = BITMAP_ALLOC (®_obstack);
+   if (then_bb && else_bb
+-      && (!bbs_ok_for_cmove_arith (then_bb, else_bb,  if_info->orig_x)
+-	  || !bbs_ok_for_cmove_arith (else_bb, then_bb,  if_info->orig_x)))
+-    return FALSE;
++      && (!bbs_ok_for_cmove_arith (then_bb, else_bb,
++				   if_info->orig_x,
++				   then_bb_rename_regs)
++	  || !bbs_ok_for_cmove_arith (else_bb, then_bb,
++				      if_info->orig_x,
++				      else_bb_rename_regs)))
++    {
++      BITMAP_FREE (then_bb_rename_regs);
++      BITMAP_FREE (else_bb_rename_regs);
++      return FALSE;
++    }
++  bool prepass_renaming = noce_rename_regs_in_bb (then_bb,
++						  then_bb_rename_regs)
++			  && noce_rename_regs_in_bb (else_bb,
++						     else_bb_rename_regs);
++
++  BITMAP_FREE (then_bb_rename_regs);
++  BITMAP_FREE (else_bb_rename_regs);
++
++  if (!prepass_renaming)
++   return FALSE;
+ 
+   start_sequence ();
+ 
+@@ -3072,7 +3237,8 @@ noce_operand_ok (const_rtx op)
+ 
+ static bool
+ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
+-			      unsigned int *cost, bool *simple_p)
++			     unsigned int *cost, bool *simple_p,
++			     bitmap cond_rename_regs)
+ {
+   if (!test_bb)
+     return false;
+@@ -3112,8 +3278,9 @@ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
+   rtx_insn *prev_last_insn = PREV_INSN (last_insn);
+   gcc_assert (prev_last_insn);
+ 
+-  /* For now, disallow setting x multiple times in test_bb.  */
+-  if (REG_P (x) && reg_set_between_p (x, first_insn, prev_last_insn))
++  if (REG_P (x)
++      && reg_set_between_p (x, first_insn, prev_last_insn)
++      && param_ifcvt_allow_register_renaming < 1)
+     return false;
+ 
+   bitmap test_bb_temps = BITMAP_ALLOC (®_obstack);
+@@ -3125,25 +3292,35 @@ bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
+   rtx_insn *insn;
+   FOR_BB_INSNS (test_bb, insn)
+     {
+-      if (insn != last_insn)
+-	{
+-	  if (!active_insn_p (insn))
+-	    continue;
++      if (insn == last_insn)
++	continue;
++      if (!active_insn_p (insn))
++	continue;
+ 
+-	  if (!insn_valid_noce_process_p (insn, cc))
+-	    goto free_bitmap_and_fail;
++      if (!insn_valid_noce_process_p (insn, cc))
++	goto free_bitmap_and_fail;
+ 
+-	  rtx sset = single_set (insn);
+-	  gcc_assert (sset);
++      rtx sset = single_set (insn);
++      gcc_assert (sset);
+ 
+-	  if (contains_mem_rtx_p (SET_SRC (sset))
+-	      || !REG_P (SET_DEST (sset))
+-	      || reg_overlap_mentioned_p (SET_DEST (sset), cond))
+-	    goto free_bitmap_and_fail;
++      if (contains_mem_rtx_p (SET_SRC (sset))
++	  || !REG_P (SET_DEST (sset)))
++	goto free_bitmap_and_fail;
+ 
+-	  potential_cost += pattern_cost (sset, speed_p);
+-	  bitmap_set_bit (test_bb_temps, REGNO (SET_DEST (sset)));
++      if (reg_overlap_mentioned_p (SET_DEST (sset), cond))
++	{
++	  if (param_ifcvt_allow_register_renaming < 1)
++	    goto free_bitmap_and_fail;
++	  rtx sset_dest = SET_DEST (sset);
++	  if (REG_P (sset_dest)
++	      && (GET_MODE_CLASS (GET_MODE (sset_dest)) != MODE_CC))
++	    bitmap_set_bit (cond_rename_regs, REGNO (sset_dest));
++	  else
++	    goto free_bitmap_and_fail;
+ 	}
++	potential_cost += pattern_cost (sset, speed_p);
++	if (SET_DEST (sset) != SET_DEST (last_set))
++	  bitmap_set_bit (test_bb_temps, REGNO (SET_DEST (sset)));
+     }
+ 
+   /* If any of the intermediate results in test_bb are live after test_bb
+@@ -3777,15 +3954,29 @@ noce_process_if_block (struct noce_if_info *if_info)
+ 
+   bool speed_p = optimize_bb_for_speed_p (test_bb);
+   unsigned int then_cost = 0, else_cost = 0;
++  bitmap cond_rename_regs = BITMAP_ALLOC (®_obstack);
+   if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
+-				    &if_info->then_simple))
+-    return false;
++				    &if_info->then_simple, cond_rename_regs))
++    {
++      BITMAP_FREE (cond_rename_regs);
++      return false;
++    }
+ 
+   if (else_bb
+       && !bb_valid_for_noce_process_p (else_bb, cond, &else_cost,
+-				       &if_info->else_simple))
+-    return false;
++				       &if_info->else_simple, cond_rename_regs))
++    {
++      BITMAP_FREE (cond_rename_regs);
++      return false;
++    }
+ 
++  if (!noce_rename_regs_in_cond (if_info, cond_rename_regs))
++    {
++      BITMAP_FREE (cond_rename_regs);
++      return false;
++    }
++  BITMAP_FREE (cond_rename_regs);
++  cond = if_info->cond;
+   if (speed_p)
+     if_info->original_cost += average_cost (then_cost, else_cost,
+ 					    find_edge (test_bb, then_bb));
+@@ -5823,12 +6014,13 @@ if_convert (bool after_combine)
+ {
+   basic_block bb;
+   int pass;
+-
+   if (optimize == 1)
+     {
+       df_live_add_problem ();
+       df_live_set_all_dirty ();
+     }
++  free_dominance_info (CDI_DOMINATORS);
++  cleanup_cfg (CLEANUP_EXPENSIVE);
+ 
+   /* Record whether we are after combine pass.  */
+   ifcvt_after_combine = after_combine;
+@@ -5933,7 +6125,6 @@ rest_of_handle_if_conversion (void)
+ 	  dump_reg_info (dump_file);
+ 	  dump_flow_info (dump_file, dump_flags);
+ 	}
+-      cleanup_cfg (CLEANUP_EXPENSIVE);
+       if_convert (false);
+       if (num_updated_if_blocks)
+ 	/* Get rid of any dead CC-related instructions.  */
+diff --git a/gcc/params.opt b/gcc/params.opt
+index d2196dc68..ba87f820b 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -669,6 +669,10 @@ Maximum permissible cost for the sequence that would be generated by the RTL if-
+ Common Joined UInteger Var(param_max_rtl_if_conversion_unpredictable_cost) Init(40) IntegerRange(0, 200) Param Optimization
+ Maximum permissible cost for the sequence that would be generated by the RTL if-conversion pass for a branch that is considered unpredictable.
+ 
++-param=ifcvt-allow-register-renaming=
++Common Joined UInteger Var(param_ifcvt_allow_register_renaming) IntegerRange(0, 2) Param Optimization
++Allow RTL if-conversion pass to aggressively rename registers in basic blocks.  Sometimes additional moves will be created.
++
+ -param=max-sched-extend-regions-iters=
+ Common Joined UInteger Var(param_max_sched_extend_regions_iters) Param Optimization
+ The maximum number of iterations through CFG to extend regions.
+diff --git a/gcc/testsuite/gcc.c-torture/execute/ifcvt-renaming-1.c b/gcc/testsuite/gcc.c-torture/execute/ifcvt-renaming-1.c
+new file mode 100644
+index 000000000..65c4d4140
+--- /dev/null
++++ b/gcc/testsuite/gcc.c-torture/execute/ifcvt-renaming-1.c
+@@ -0,0 +1,35 @@
++
++extern void abort(void);
++
++__attribute__ ((noinline))
++int foo (int x, int y, int z, int a, int b)
++{
++  if (a < 2) {
++      if (a == 0) {
++	  if (x - y < 0)
++	    x = x - y + z;
++	  else
++	    x = x - y;
++	}
++      else {
++	  if (x + y >= z)
++	    x = x + y - z;
++	  else
++	    x = x + y;
++	}
++    }
++  return x;
++}
++
++int main(void) {
++  if (foo (5,10,7,0,1) != 2) // x - y + z = -5 + 7 = 2
++    abort ();
++  if (foo (50,10,7,0,1) != 40) // x - y = 40
++    abort ();
++  if (foo (5,10,7,1,1) != 8) // x + y - z = 5 + 10 - 7 = 8
++    abort ();
++  if (foo (5,10,70,1,1) != 15) // x + y = 15
++    abort ();
++  return 0;
++}
++
+diff --git a/gcc/testsuite/gcc.dg/ifcvt-6.c b/gcc/testsuite/gcc.dg/ifcvt-6.c
+new file mode 100644
+index 000000000..be9a67b3f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/ifcvt-6.c
+@@ -0,0 +1,27 @@
++/* { dg-do compile { target { aarch64*-*-* } } } */
++/* { dg-options "-fdump-rtl-ce1 -O2 --param max-rtl-if-conversion-unpredictable-cost=100 --param max-rtl-if-conversion-predictable-cost=100 --param=ifcvt-allow-register-renaming=2 -fifcvt-allow-complicated-cmps" } */
++
++typedef unsigned int uint16_t;
++
++uint16_t
++foo (uint16_t x, uint16_t y, uint16_t z, uint16_t a,
++     uint16_t b, uint16_t c, uint16_t d) {
++  int i = 1;
++  int j = 1;
++  if (a > b) {
++      j = x;
++      if (b > c)
++	i = y;
++      else
++	i = z;
++    }
++  else {
++      j = y;
++      if (c > d)
++	i = z;
++    }
++  return i * j;
++}
++
++/* { dg-final { scan-rtl-dump "7 true changes made" "ce1" } } */
++
+-- 
+2.33.0
+
diff --git a/0037-Perform-early-if-conversion-of-simple-arithmetic.patch b/0037-Perform-early-if-conversion-of-simple-arithmetic.patch
new file mode 100644
index 0000000..14de678
--- /dev/null
+++ b/0037-Perform-early-if-conversion-of-simple-arithmetic.patch
@@ -0,0 +1,109 @@
+From 310eade1450995b55d9f8120561022fbf164b2ec Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 00812787 
+Date: Thu, 12 Jan 2023 14:52:49 +0300
+Subject: [PATCH 03/18] Perform early if-conversion of simple arithmetic
+
+---
+ gcc/common.opt                      |  4 ++++
+ gcc/match.pd                        | 25 +++++++++++++++++++
+ gcc/testsuite/gcc.dg/ifcvt-gimple.c | 37 +++++++++++++++++++++++++++++
+ 3 files changed, 66 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/ifcvt-gimple.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index aa00fb7b0..dac477c04 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1821,6 +1821,10 @@ fif-conversion2
+ Common Var(flag_if_conversion2) Optimization
+ Perform conversion of conditional jumps to conditional execution.
+ 
++fif-conversion-gimple
++Common Var(flag_if_conversion_gimple) Optimization
++Perform conversion of conditional jumps to branchless equivalents during gimple transformations.
++
+ fstack-reuse=
+ Common Joined RejectNegative Enum(stack_reuse_level) Var(flag_stack_reuse) Init(SR_ALL) Optimization
+ -fstack-reuse=[all|named_vars|none]	Set stack reuse level for local variables.
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 6f24d5079..3cbaf2a5b 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -4278,6 +4278,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+   )
+  )
+ )
++
++(if (flag_if_conversion_gimple)
++ (for simple_op (plus minus bit_and bit_ior bit_xor)
++  (simplify
++   (cond @0 (simple_op @1 INTEGER_CST@2) @1)
++   (switch
++    /* a = cond ? a + 1 : a -> a = a + ((int) cond) */
++    (if (integer_onep (@2))
++     (simple_op @1 (convert (convert:boolean_type_node @0))))
++    /* a = cond ? a + powerof2cst : a ->
++       a = a + ((int) cond) << log2 (powerof2cst) */
++    (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2))
++     (with
++      {
++	tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
++      }
++      (simple_op @1 (lshift (convert (convert:boolean_type_node @0))
++			    { shift; })
++      )
++     )
++    )
++   )
++  )
++ )
++)
+ #endif
+ 
+ #if GIMPLE
+diff --git a/gcc/testsuite/gcc.dg/ifcvt-gimple.c b/gcc/testsuite/gcc.dg/ifcvt-gimple.c
+new file mode 100644
+index 000000000..0f7c87e5c
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/ifcvt-gimple.c
+@@ -0,0 +1,37 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fif-conversion-gimple -fdump-tree-optimized" } */
++
++int test_int (int optimizable_int) {
++    if (optimizable_int > 5)
++	++optimizable_int;
++    return optimizable_int;
++}
++
++int test_int_pow2 (int optimizable_int_pow2) {
++    if (optimizable_int_pow2 <= 4)
++	optimizable_int_pow2 += 1024;
++    return optimizable_int_pow2;
++}
++
++int test_int_non_pow2 (int not_optimizable_int_non_pow2) {
++    if (not_optimizable_int_non_pow2 == 1)
++	not_optimizable_int_non_pow2 += 513;
++    return not_optimizable_int_non_pow2;
++}
++
++float test_float (float not_optimizable_float) {
++    if (not_optimizable_float > 5)
++	not_optimizable_float += 1;
++    return not_optimizable_float;
++}
++
++/* Expecting if-else block in test_float and test_int_non_pow2 only. */
++/* { dg-final { scan-tree-dump-not "if \\(optimizable" "optimized" } } */
++/* { dg-final { scan-tree-dump "if \\(not_optimizable_int_non_pow2" "optimized" } } */
++/* { dg-final { scan-tree-dump "if \\(not_optimizable_float" "optimized" } } */
++/* { dg-final { scan-tree-dump-times "if " 2 "optimized" } } */
++/* { dg-final { scan-tree-dump-times "else" 2 "optimized" } } */
++
++/* Expecting shifted result only for optimizable_int_pow2. */
++/* { dg-final { scan-tree-dump-times " << " 1 "optimized" } } */
++/* { dg-final { scan-tree-dump " << 10;" "optimized" } } */
+-- 
+2.33.0
+
diff --git a/0038-Add-option-to-allow-matching-uaddsub-overflow-for-wi.patch b/0038-Add-option-to-allow-matching-uaddsub-overflow-for-wi.patch
new file mode 100644
index 0000000..9b2be00
--- /dev/null
+++ b/0038-Add-option-to-allow-matching-uaddsub-overflow-for-wi.patch
@@ -0,0 +1,252 @@
+From 6684509e81e4341675c73a7dc853180229a8abcb Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 00812787 
+Date: Tue, 24 Jan 2023 16:43:40 +0300
+Subject: [PATCH 04/18] Add option to allow matching uaddsub overflow for widen
+ ops too.
+
+---
+ gcc/common.opt                 |   5 ++
+ gcc/testsuite/gcc.dg/uaddsub.c | 143 +++++++++++++++++++++++++++++++++
+ gcc/tree-ssa-math-opts.cc      |  43 ++++++++--
+ 3 files changed, 184 insertions(+), 7 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/uaddsub.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index dac477c04..39c90604e 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -3106,6 +3106,11 @@ freciprocal-math
+ Common Var(flag_reciprocal_math) SetByCombined Optimization
+ Same as -fassociative-math for expressions which include division.
+ 
++fuaddsub-overflow-match-all
++Common Var(flag_uaddsub_overflow_match_all)
++Match unsigned add/sub overflow even if the target does not support
++the corresponding instruction.
++
+ ; Nonzero means that unsafe floating-point math optimizations are allowed
+ ; for the sake of speed.  IEEE compliance is not guaranteed, and operations
+ ; are allowed to assume that their arguments and results are "normal"
+diff --git a/gcc/testsuite/gcc.dg/uaddsub.c b/gcc/testsuite/gcc.dg/uaddsub.c
+new file mode 100644
+index 000000000..96c26d308
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/uaddsub.c
+@@ -0,0 +1,143 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fuaddsub-overflow-match-all -fdump-tree-optimized" } */
++#include 
++
++typedef unsigned __int128 uint128_t;
++typedef struct uint256_t
++{
++  uint128_t lo;
++  uint128_t hi;
++} uint256_t;
++
++uint16_t add16 (uint8_t a, uint8_t b)
++{
++  uint8_t tmp = a + b;
++  uint8_t overflow = 0;
++  if (tmp < a)
++    overflow = 1;
++
++  uint16_t res = overflow;
++  res <<= 8;
++  res += tmp;
++  return res;
++}
++
++uint32_t add32 (uint16_t a, uint16_t b)
++{
++  uint16_t tmp = a + b;
++  uint16_t overflow = 0;
++  if (tmp < a)
++    overflow = 1;
++
++  uint32_t res = overflow;
++  res <<= 16;
++  res += tmp;
++  return res;
++}
++
++uint64_t add64 (uint32_t a, uint32_t b)
++{
++  uint32_t tmp = a + b;
++  uint32_t overflow = 0;
++  if (tmp < a)
++    overflow = 1;
++
++  uint64_t res = overflow;
++  res <<= 32;
++  res += tmp;
++  return res;
++}
++
++uint128_t add128 (uint64_t a, uint64_t b)
++{
++  uint64_t tmp = a + b;
++  uint64_t overflow = 0;
++  if (tmp < a)
++    overflow = 1;
++
++  uint128_t res = overflow;
++  res <<= 64;
++  res += tmp;
++  return res;
++}
++
++uint256_t add256 (uint128_t a, uint128_t b)
++{
++  uint128_t tmp = a + b;
++  uint128_t overflow = 0;
++  if (tmp < a)
++    overflow = 1;
++
++  uint256_t res;
++  res.hi = overflow;
++  res.lo = tmp;
++  return res;
++}
++
++uint16_t sub16 (uint8_t a, uint8_t b)
++{
++  uint8_t tmp = a - b;
++  uint8_t overflow = 0;
++  if (tmp > a)
++    overflow = -1;
++
++  uint16_t res = overflow;
++  res <<= 8;
++  res += tmp;
++  return res;
++}
++
++uint32_t sub32 (uint16_t a, uint16_t b)
++{
++  uint16_t tmp = a - b;
++  uint16_t overflow = 0;
++  if (tmp > a)
++    overflow = -1;
++
++  uint32_t res = overflow;
++  res <<= 16;
++  res += tmp;
++  return res;
++}
++
++uint64_t sub64 (uint32_t a, uint32_t b)
++{
++  uint32_t tmp = a - b;
++  uint32_t overflow = 0;
++  if (tmp > a)
++    overflow = -1;
++
++  uint64_t res = overflow;
++  res <<= 32;
++  res += tmp;
++  return res;
++}
++
++uint128_t sub128 (uint64_t a, uint64_t b)
++{
++  uint64_t tmp = a - b;
++  uint64_t overflow = 0;
++  if (tmp > a)
++    overflow = -1;
++
++  uint128_t res = overflow;
++  res <<= 64;
++  res += tmp;
++  return res;
++}
++
++uint256_t sub256 (uint128_t a, uint128_t b)
++{
++  uint128_t tmp = a - b;
++  uint128_t overflow = 0;
++  if (tmp > a)
++    overflow = -1;
++
++  uint256_t res;
++  res.hi = overflow;
++  res.lo = tmp;
++  return res;
++}
++
++/* { dg-final { scan-tree-dump-times "= .ADD_OVERFLOW \\(a_\[0-9\]+\\(D\\), b_\[0-9\]+\\(D\\)\\)" 5 "optimized" } } */
++/* { dg-final { scan-tree-dump-times "= .SUB_OVERFLOW \\(a_\[0-9\]+\\(D\\), b_\[0-9\]+\\(D\\)\\)" 5 "optimized" } } */
+diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
+index 232e903b0..55d6ee8ae 100644
+--- a/gcc/tree-ssa-math-opts.cc
++++ b/gcc/tree-ssa-math-opts.cc
+@@ -3468,6 +3468,27 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
+     }
+ }
+ 
++/* Check if the corresponding operation has wider equivalent on the target.  */
++
++static bool
++wider_optab_check_p (optab op, machine_mode mode, int unsignedp)
++{
++  machine_mode wider_mode;
++  FOR_EACH_WIDER_MODE (wider_mode, mode)
++    {
++      machine_mode next_mode;
++      if (optab_handler (op, wider_mode) != CODE_FOR_nothing
++	  || (op == smul_optab
++	      && GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode)
++	      && (find_widening_optab_handler ((unsignedp
++						? umul_widen_optab
++						: smul_widen_optab),
++						next_mode, mode))))
++	return true;
++    }
++
++  return false;
++}
+ 
+ /* Helper function of match_arith_overflow.  For MUL_OVERFLOW, if we have
+    a check for non-zero like:
+@@ -3903,15 +3924,22 @@ match_arith_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
+ 		       || code == MINUS_EXPR
+ 		       || code == MULT_EXPR
+ 		       || code == BIT_NOT_EXPR);
++  int unsignedp = TYPE_UNSIGNED (type);
+   if (!INTEGRAL_TYPE_P (type)
+-      || !TYPE_UNSIGNED (type)
+-      || has_zero_uses (lhs)
+-      || (code != PLUS_EXPR
+-	  && code != MULT_EXPR
+-	  && optab_handler (code == MINUS_EXPR ? usubv4_optab : uaddv4_optab,
+-			    TYPE_MODE (type)) == CODE_FOR_nothing))
++      || !unsignedp
++      || has_zero_uses (lhs))
+     return false;
+ 
++  if (code == PLUS_EXPR || code == MINUS_EXPR)
++    {
++      machine_mode mode = TYPE_MODE (type);
++      optab op = code == PLUS_EXPR ? uaddv4_optab : usubv4_optab;
++      if (optab_handler (op, mode) == CODE_FOR_nothing
++	  && (!flag_uaddsub_overflow_match_all
++	      || !wider_optab_check_p (op, mode, unsignedp)))
++	return false;
++    }
++
+   tree rhs1 = gimple_assign_rhs1 (stmt);
+   tree rhs2 = gimple_assign_rhs2 (stmt);
+   FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+@@ -3986,7 +4014,8 @@ match_arith_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
+       || (code != MULT_EXPR && (code == BIT_NOT_EXPR ? use_seen : !use_seen))
+       || (code == PLUS_EXPR
+ 	  && optab_handler (uaddv4_optab,
+-			    TYPE_MODE (type)) == CODE_FOR_nothing)
++			    TYPE_MODE (type)) == CODE_FOR_nothing
++	  && !flag_uaddsub_overflow_match_all)
+       || (code == MULT_EXPR
+ 	  && optab_handler (cast_stmt ? mulv4_optab : umulv4_optab,
+ 			    TYPE_MODE (type)) == CODE_FOR_nothing))
+-- 
+2.33.0
+
diff --git a/0039-Match-double-sized-mul-pattern.patch b/0039-Match-double-sized-mul-pattern.patch
new file mode 100644
index 0000000..9d4e56f
--- /dev/null
+++ b/0039-Match-double-sized-mul-pattern.patch
@@ -0,0 +1,488 @@
+From e7b22f97f960b62e555dfd6f2e3ae43973fcbb3e Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 00812787 
+Date: Wed, 25 Jan 2023 15:04:07 +0300
+Subject: [PATCH 05/18] Match double sized mul pattern
+
+---
+ gcc/match.pd                              | 136 +++++++++++++++++++++
+ gcc/testsuite/gcc.dg/double_sized_mul-1.c | 141 ++++++++++++++++++++++
+ gcc/testsuite/gcc.dg/double_sized_mul-2.c |  62 ++++++++++
+ gcc/tree-ssa-math-opts.cc                 |  80 ++++++++++++
+ 4 files changed, 419 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/double_sized_mul-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/double_sized_mul-2.c
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 3cbaf2a5b..61866cb90 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -7895,3 +7895,139 @@ and,
+ 	       == TYPE_UNSIGNED (TREE_TYPE (@3))))
+        && single_use (@4)
+        && single_use (@5))))
++
++/* Match multiplication with double sized result.
++
++   Consider the following calculations:
++   arg0 * arg1 = (2^(bit_size/2) * arg0_hi + arg0_lo)
++	       * (2^(bit_size/2) * arg1_hi + arg1_lo)
++   arg0 * arg1 = 2^bit_size * arg0_hi * arg1_hi
++	       + 2^(bit_size/2) * (arg0_hi * arg1_lo + arg0_lo * arg1_hi)
++	       + arg0_lo * arg1_lo
++
++   The products of high and low parts fits in bit_size values, thus they are
++   placed in high and low parts of result respectively.
++
++   The sum of the mixed products may overflow, so we need a detection for that.
++   Also it has a bit_size/2 offset, thus it intersects with both high and low
++   parts of result.  Overflow detection constant is bit_size/2 due to this.
++
++   With this info:
++   arg0 * arg1 = 2^bit_size * arg0_hi * arg1_hi
++	       + 2^(bit_size/2) * middle
++	       + 2^bit_size * possible_middle_overflow
++	       + arg0_lo * arg1_lo
++   arg0 * arg1 = 2^bit_size * (arg0_hi * arg1_hi + possible_middle_overflow)
++	       + 2^(bit_size/2) * (2^(bit_size/2) * middle_hi + middle_lo)
++	       + arg0_lo * arg1_lo
++   arg0 * arg1 = 2^bit_size * (arg0_hi * arg1_hi + middle_hi
++	       +	       possible_middle_overflow)
++	       + 2^(bit_size/2) * middle_lo
++	       + arg0_lo * arg1_lo
++
++   The last sum can produce overflow for the high result part.  With this:
++   arg0 * arg1 = 2^bit_size * (arg0_hi * arg1_hi + possible_middle_overflow
++	       +	       possible_res_lo_overflow + middle_hi)
++	       + res_lo
++	       = res_hi + res_lo
++
++   This formula is quite big to fit into one match pattern with all of the
++   combinations of terms inside it.  There are many helpers for better code
++   readability.
++
++   The simplification basis is res_hi: assuming that res_lo only is not
++   real practical case for such calculations.
++
++   Overflow handling is done via matching complex calculations:
++   the realpart and imagpart are quite handy here.  */
++/* Match low and high parts of the argument.  */
++(match (double_size_mul_arg_lo @0 @1)
++ (bit_and @0 INTEGER_CST@1)
++  (if (wi::to_wide (@1)
++       == wi::mask (TYPE_PRECISION (type) / 2, false, TYPE_PRECISION (type)))))
++(match (double_size_mul_arg_hi @0 @1)
++ (rshift @0 INTEGER_CST@1)
++  (if (wi::to_wide (@1) == TYPE_PRECISION (type) / 2)))
++
++/* Match various argument parts products.  */
++(match (double_size_mul_lolo @0 @1)
++ (mult@4 (double_size_mul_arg_lo @0 @2) (double_size_mul_arg_lo @1 @3))
++  (if (single_use (@4))))
++(match (double_size_mul_hihi @0 @1)
++ (mult@4 (double_size_mul_arg_hi @0 @2) (double_size_mul_arg_hi @1 @3))
++  (if (single_use (@4))))
++(match (double_size_mul_lohi @0 @1)
++ (mult:c@4 (double_size_mul_arg_lo @0 @2) (double_size_mul_arg_hi @1 @3))
++  (if (single_use (@4))))
++
++/* Match complex middle sum.  */
++(match (double_size_mul_middle_complex @0 @1)
++ (IFN_ADD_OVERFLOW@2 (double_size_mul_lohi @0 @1) (double_size_mul_lohi @1 @0))
++  (if (num_imm_uses (@2) == 2)))
++
++/* Match real middle results.  */
++(match (double_size_mul_middle @0 @1)
++ (realpart@2 (double_size_mul_middle_complex @0 @1))
++  (if (num_imm_uses (@2) == 2)))
++(match (double_size_mul_middleres_lo @0 @1)
++ (lshift@3 (double_size_mul_middle @0 @1) INTEGER_CST@2)
++  (if (wi::to_wide (@2) == TYPE_PRECISION (type) / 2
++       && single_use (@3))))
++(match (double_size_mul_middleres_hi @0 @1)
++ (rshift@3 (double_size_mul_middle @0 @1) INTEGER_CST@2)
++  (if (wi::to_wide (@2) == TYPE_PRECISION (type) / 2
++       && single_use (@3))))
++
++/* Match low result part.  */
++/* Number of uses may be < 2 in case when we are interested in
++   high part only.  */
++(match (double_size_mul_res_lo_complex @0 @1)
++ (IFN_ADD_OVERFLOW:c@2
++  (double_size_mul_lolo:c @0 @1) (double_size_mul_middleres_lo @0 @1))
++  (if (num_imm_uses (@2) <= 2)))
++(match (double_size_mul_res_lo @0 @1)
++ (realpart (double_size_mul_res_lo_complex @0 @1)))
++
++/* Match overflow terms.  */
++(match (double_size_mul_overflow_check_lo @0 @1 @5)
++ (convert@4 (ne@3
++  (imagpart@2 (double_size_mul_res_lo_complex@5 @0 @1)) integer_zerop))
++  (if (single_use (@2) && single_use (@3) && single_use (@4))))
++(match (double_size_mul_overflow_check_hi @0 @1)
++ (lshift@6 (convert@5 (ne@4
++  (imagpart@3 (double_size_mul_middle_complex @0 @1)) integer_zerop))
++	   INTEGER_CST@2)
++  (if (wi::to_wide (@2) == TYPE_PRECISION (type) / 2
++       && single_use (@3) && single_use (@4) && single_use (@5)
++       && single_use (@6))))
++
++/* Match all possible permutations for high result part calculations.  */
++(for op1 (double_size_mul_hihi
++	  double_size_mul_overflow_check_hi
++	  double_size_mul_middleres_hi)
++     op2 (double_size_mul_overflow_check_hi
++	  double_size_mul_middleres_hi
++	  double_size_mul_hihi)
++     op3 (double_size_mul_middleres_hi
++	  double_size_mul_hihi
++	  double_size_mul_overflow_check_hi)
++ (match (double_size_mul_candidate @0 @1 @2 @3)
++  (plus:c@2
++   (plus:c@4 (double_size_mul_overflow_check_lo @0 @1 @3) (op1:c @0 @1))
++   (plus:c@5 (op2:c @0 @1) (op3:c @0 @1)))
++    (if (single_use (@4) && single_use (@5))))
++ (match (double_size_mul_candidate @0 @1 @2 @3)
++  (plus:c@2 (double_size_mul_overflow_check_lo @0 @1 @3)
++   (plus:c@4 (op1:c @0 @1)
++    (plus:c@5 (op2:c @0 @1) (op3:c @0 @1))))
++     (if (single_use (@4) && single_use (@5))))
++ (match (double_size_mul_candidate @0 @1 @2 @3)
++  (plus:c@2 (op1:c @0 @1)
++   (plus:c@4 (double_size_mul_overflow_check_lo @0 @1 @3)
++    (plus:c@5 (op2:c @0 @1) (op3:c @0 @1))))
++     (if (single_use (@4) && single_use (@5))))
++ (match (double_size_mul_candidate @0 @1 @2 @3)
++  (plus:c@2 (op1:c @0 @1)
++   (plus:c@4 (op2:c @0 @1)
++    (plus:c@5 (double_size_mul_overflow_check_lo @0 @1 @3) (op3:c @0 @1))))
++     (if (single_use (@4) && single_use (@5)))))
+diff --git a/gcc/testsuite/gcc.dg/double_sized_mul-1.c b/gcc/testsuite/gcc.dg/double_sized_mul-1.c
+new file mode 100644
+index 000000000..4d475cc8a
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/double_sized_mul-1.c
+@@ -0,0 +1,141 @@
++/* { dg-do compile } */
++/* fif-conversion-gimple and fuaddsub-overflow-match-all are required for
++   proper overflow detection in some cases.  */
++/* { dg-options "-O2 -fif-conversion-gimple -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++#include 
++
++typedef unsigned __int128 uint128_t;
++
++uint16_t mul16 (uint8_t a, uint8_t b)
++{
++  uint8_t a_lo = a & 0xF;
++  uint8_t b_lo = b & 0xF;
++  uint8_t a_hi = a >> 4;
++  uint8_t b_hi = b >> 4;
++  uint8_t lolo = a_lo * b_lo;
++  uint8_t lohi = a_lo * b_hi;
++  uint8_t hilo = a_hi * b_lo;
++  uint8_t hihi = a_hi * b_hi;
++  uint8_t middle = hilo + lohi;
++  uint8_t middle_hi = middle >> 4;
++  uint8_t middle_lo = middle << 4;
++  uint8_t res_lo = lolo + middle_lo;
++  uint8_t res_hi = hihi + middle_hi;
++  res_hi += (res_lo < middle_lo ? 1 : 0);
++  res_hi += (middle < hilo ? 0x10 : 0);
++  uint16_t res = ((uint16_t) res_hi) << 8;
++  res += res_lo;
++  return res;
++}
++
++uint32_t mul32 (uint16_t a, uint16_t b)
++{
++  uint16_t a_lo = a & 0xFF;
++  uint16_t b_lo = b & 0xFF;
++  uint16_t a_hi = a >> 8;
++  uint16_t b_hi = b >> 8;
++  uint16_t lolo = a_lo * b_lo;
++  uint16_t lohi = a_lo * b_hi;
++  uint16_t hilo = a_hi * b_lo;
++  uint16_t hihi = a_hi * b_hi;
++  uint16_t middle = hilo + lohi;
++  uint16_t middle_hi = middle >> 8;
++  uint16_t middle_lo = middle << 8;
++  uint16_t res_lo = lolo + middle_lo;
++  uint16_t res_hi = hihi + middle_hi;
++  res_hi += (res_lo < middle_lo ? 1 : 0);
++  res_hi += (middle < hilo ? 0x100 : 0);
++  uint32_t res = ((uint32_t) res_hi) << 16;
++  res += res_lo;
++  return res;
++}
++
++uint64_t mul64 (uint32_t a, uint32_t b)
++{
++  uint32_t a_lo = a & 0xFFFF;
++  uint32_t b_lo = b & 0xFFFF;
++  uint32_t a_hi = a >> 16;
++  uint32_t b_hi = b >> 16;
++  uint32_t lolo = a_lo * b_lo;
++  uint32_t lohi = a_lo * b_hi;
++  uint32_t hilo = a_hi * b_lo;
++  uint32_t hihi = a_hi * b_hi;
++  uint32_t middle = hilo + lohi;
++  uint32_t middle_hi = middle >> 16;
++  uint32_t middle_lo = middle << 16;
++  uint32_t res_lo = lolo + middle_lo;
++  uint32_t res_hi = hihi + middle_hi;
++  res_hi += (res_lo < middle_lo ? 1 : 0);
++  res_hi += (middle < hilo ? 0x10000 : 0);
++  uint64_t res = ((uint64_t) res_hi) << 32;
++  res += res_lo;
++  return res;
++}
++
++uint128_t mul128 (uint64_t a, uint64_t b)
++{
++  uint64_t a_lo = a & 0xFFFFFFFF;
++  uint64_t b_lo = b & 0xFFFFFFFF;
++  uint64_t a_hi = a >> 32;
++  uint64_t b_hi = b >> 32;
++  uint64_t lolo = a_lo * b_lo;
++  uint64_t lohi = a_lo * b_hi;
++  uint64_t hilo = a_hi * b_lo;
++  uint64_t hihi = a_hi * b_hi;
++  uint64_t middle = hilo + lohi;
++  uint64_t middle_hi = middle >> 32;
++  uint64_t middle_lo = middle << 32;
++  uint64_t res_lo = lolo + middle_lo;
++  uint64_t res_hi = hihi + middle_hi;
++  res_hi += (res_lo < middle_lo ? 1 : 0);
++  res_hi += (middle < hilo ? 0x100000000 : 0);
++  uint128_t res = ((uint128_t) res_hi) << 64;
++  res += res_lo;
++  return res;
++}
++
++uint64_t mul64_perm (uint32_t a, uint32_t b)
++{
++  uint32_t a_lo = a & 0xFFFF;
++  uint32_t b_lo = b & 0xFFFF;
++  uint32_t a_hi = a >> 16;
++  uint32_t b_hi = b >> 16;
++  uint32_t lolo = a_lo * b_lo;
++  uint32_t lohi = a_lo * b_hi;
++  uint32_t hilo = a_hi * b_lo;
++  uint32_t hihi = a_hi * b_hi;
++  uint32_t middle = hilo + lohi;
++  uint32_t middle_hi = middle >> 16;
++  uint32_t middle_lo = middle << 16;
++  uint32_t res_lo = lolo + middle_lo;
++  uint32_t res_hi = hihi + middle_hi;
++  res_hi = res_lo < middle_lo ? res_hi + 1 : res_hi;
++  res_hi = middle < hilo ? res_hi + 0x10000 : res_hi;
++  uint64_t res = ((uint64_t) res_hi) << 32;
++  res += res_lo;
++  return res;
++}
++
++uint128_t mul128_perm (uint64_t a, uint64_t b)
++{
++  uint64_t a_lo = a & 0xFFFFFFFF;
++  uint64_t b_lo = b & 0xFFFFFFFF;
++  uint64_t a_hi = a >> 32;
++  uint64_t b_hi = b >> 32;
++  uint64_t lolo = a_lo * b_lo;
++  uint64_t lohi = a_lo * b_hi;
++  uint64_t hilo = a_hi * b_lo;
++  uint64_t hihi = a_hi * b_hi;
++  uint64_t middle = hilo + lohi;
++  uint64_t middle_hi = middle >> 32;
++  uint64_t middle_lo = middle << 32;
++  uint64_t res_lo = lolo + middle_lo;
++  uint64_t res_hi = hihi + middle_hi;
++  res_hi = res_lo < middle_lo ? res_hi + 1 : res_hi;
++  res_hi = middle < hilo ? res_hi + 0x100000000 : res_hi;
++  uint128_t res = ((uint128_t) res_hi) << 64;
++  res += res_lo;
++  return res;
++}
++
++/* { dg-final { scan-tree-dump-times "double sized mul optimized: 1" 6 "widening_mul" } } */
+diff --git a/gcc/testsuite/gcc.dg/double_sized_mul-2.c b/gcc/testsuite/gcc.dg/double_sized_mul-2.c
+new file mode 100644
+index 000000000..cc6e5af25
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/double_sized_mul-2.c
+@@ -0,0 +1,62 @@
++/* { dg-do compile } */
++/* fif-conversion-gimple is required for proper overflow detection
++   in some cases.  */
++/* { dg-options "-O2 -fif-conversion-gimple -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++#include 
++
++typedef unsigned __int128 uint128_t;
++typedef struct uint256_t
++{
++    uint128_t lo;
++    uint128_t hi;
++} uint256_t;
++
++uint64_t mul64_double_use (uint32_t a, uint32_t b)
++{
++  uint32_t a_lo = a & 0xFFFF;
++  uint32_t b_lo = b & 0xFFFF;
++  uint32_t a_hi = a >> 16;
++  uint32_t b_hi = b >> 16;
++  uint32_t lolo = a_lo * b_lo;
++  uint32_t lohi = a_lo * b_hi;
++  uint32_t hilo = a_hi * b_lo;
++  uint32_t hihi = a_hi * b_hi;
++  uint32_t middle = hilo + lohi;
++  uint32_t middle_hi = middle >> 16;
++  uint32_t middle_lo = middle << 16;
++  uint32_t res_lo = lolo + middle_lo;
++  uint32_t res_hi = hihi + middle_hi;
++  res_hi += (res_lo < middle_lo ? 1 : 0);
++  res_hi += (middle < hilo ? 0x10000 : 0);
++  uint64_t res = ((uint64_t) res_hi) << 32;
++  res += res_lo;
++  return res + lolo;
++}
++
++uint256_t mul256 (uint128_t a, uint128_t b)
++{
++  uint128_t a_lo = a & 0xFFFFFFFFFFFFFFFF;
++  uint128_t b_lo = b & 0xFFFFFFFFFFFFFFFF;
++  uint128_t a_hi = a >> 64;
++  uint128_t b_hi = b >> 64;
++  uint128_t lolo = a_lo * b_lo;
++  uint128_t lohi = a_lo * b_hi;
++  uint128_t hilo = a_hi * b_lo;
++  uint128_t hihi = a_hi * b_hi;
++  uint128_t middle = hilo + lohi;
++  uint128_t middle_hi = middle >> 64;
++  uint128_t middle_lo = middle << 64;
++  uint128_t res_lo = lolo + middle_lo;
++  uint128_t res_hi = hihi + middle_hi;
++  res_hi += (res_lo < middle_lo ? 1 : 0);
++  /* Constant is to big warning WA */
++  uint128_t overflow_tmp = (middle < hilo ? 1 : 0);
++  overflow_tmp <<= 64;
++  res_hi += overflow_tmp;
++  uint256_t res;
++  res.lo = res_lo;
++  res.hi = res_hi;
++  return res;
++}
++
++/* { dg-final { scan-tree-dump-not "double sized mul optimized" "widening_mul" } } */
+diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
+index 55d6ee8ae..2c06b8a60 100644
+--- a/gcc/tree-ssa-math-opts.cc
++++ b/gcc/tree-ssa-math-opts.cc
+@@ -210,6 +210,9 @@ static struct
+ 
+   /* Number of highpart multiplication ops inserted.  */
+   int highpart_mults_inserted;
++
++  /* Number of optimized double sized multiplications.  */
++  int double_sized_mul_optimized;
+ } widen_mul_stats;
+ 
+ /* The instance of "struct occurrence" representing the highest
+@@ -4893,6 +4896,78 @@ optimize_spaceship (gimple *stmt)
+ }
+ 
+ 
++/* Pattern matcher for double sized multiplication defined in match.pd.  */
++extern bool gimple_double_size_mul_candidate (tree, tree*, tree (*)(tree));
++
++static bool
++convert_double_size_mul (gimple_stmt_iterator *gsi, gimple *stmt)
++{
++  gimple *use_stmt, *complex_res_lo;
++  gimple_stmt_iterator insert_before;
++  imm_use_iterator use_iter;
++  tree match[4]; // arg0, arg1, res_hi, complex_res_lo
++  tree arg0, arg1, widen_mult, new_type, tmp;
++  tree lhs = gimple_assign_lhs (stmt);
++  location_t loc = UNKNOWN_LOCATION;
++  machine_mode mode;
++
++  if (!gimple_double_size_mul_candidate (lhs, match, NULL))
++    return false;
++
++  new_type = build_nonstandard_integer_type (
++	  TYPE_PRECISION (TREE_TYPE (match[0])) * 2, 1);
++  mode = TYPE_MODE (new_type);
++
++  /* Early return if the target multiplication doesn't exist on target.  */
++  if (optab_handler (smul_optab, mode) == CODE_FOR_nothing
++      && !wider_optab_check_p (smul_optab, mode, 1))
++    return false;
++
++  /* Determine the point where the wide multiplication
++     should be inserted.  Complex low res is OK since it is required
++     by both high and low part getters, thus it dominates both of them.  */
++  complex_res_lo = SSA_NAME_DEF_STMT (match[3]);
++  insert_before = gsi_for_stmt (complex_res_lo);
++  gsi_next (&insert_before);
++
++  /* Create the widen multiplication.  */
++  arg0 = build_and_insert_cast (&insert_before, loc, new_type, match[0]);
++  arg1 = build_and_insert_cast (&insert_before, loc, new_type, match[1]);
++  widen_mult = build_and_insert_binop (&insert_before, loc, "widen_mult",
++				       MULT_EXPR, arg0, arg1);
++
++  /* Find the mult low part getter.  */
++  FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, match[3])
++    if (gimple_assign_rhs_code (use_stmt) == REALPART_EXPR)
++      break;
++
++  /* Create high and low (if needed) parts extractors.  */
++  /* Low part.  */
++  if (use_stmt)
++    {
++      loc = gimple_location (use_stmt);
++      tmp = build_and_insert_cast (&insert_before, loc,
++	  	      		   TREE_TYPE (gimple_get_lhs (use_stmt)),
++	  			   widen_mult);
++      gassign *new_stmt = gimple_build_assign (gimple_get_lhs (use_stmt),
++	    				       NOP_EXPR, tmp);
++      gsi_replace (&insert_before, new_stmt, true);
++    }
++
++  /* High part.  */
++  loc = gimple_location (stmt);
++  tmp = build_and_insert_binop (gsi, loc, "widen_mult_hi",
++				RSHIFT_EXPR, widen_mult,
++				build_int_cst (new_type,
++					       TYPE_PRECISION (new_type) / 2));
++  tmp = build_and_insert_cast (gsi, loc, TREE_TYPE (lhs), tmp);
++  gassign *new_stmt = gimple_build_assign (lhs, NOP_EXPR, tmp);
++  gsi_replace (gsi, new_stmt, true);
++
++  widen_mul_stats.double_sized_mul_optimized++;
++  return true;
++}
++
+ /* Find integer multiplications where the operands are extended from
+    smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR
+    or MULT_HIGHPART_EXPR where appropriate.  */
+@@ -4987,6 +5062,9 @@ math_opts_dom_walker::after_dom_children (basic_block bb)
+ 	      break;
+ 
+ 	    case PLUS_EXPR:
++	      if (convert_double_size_mul (&gsi, stmt))
++		break;
++	      __attribute__ ((fallthrough));
+ 	    case MINUS_EXPR:
+ 	      if (!convert_plusminus_to_widen (&gsi, stmt, code))
+ 		match_arith_overflow (&gsi, stmt, code, m_cfg_changed_p);
+@@ -5091,6 +5169,8 @@ pass_optimize_widening_mul::execute (function *fun)
+ 			    widen_mul_stats.divmod_calls_inserted);
+   statistics_counter_event (fun, "highpart multiplications inserted",
+ 			    widen_mul_stats.highpart_mults_inserted);
++  statistics_counter_event (fun, "double sized mul optimized",
++			    widen_mul_stats.double_sized_mul_optimized);
+ 
+   return cfg_changed ? TODO_cleanup_cfg : 0;
+ }
+-- 
+2.33.0
+
diff --git a/0040-Port-icp-patch-to-GCC-12.patch b/0040-Port-icp-patch-to-GCC-12.patch
new file mode 100644
index 0000000..d0b3412
--- /dev/null
+++ b/0040-Port-icp-patch-to-GCC-12.patch
@@ -0,0 +1,2387 @@
+From b73462757734c62f64e7a4379340679ec6f19669 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Tue, 27 Feb 2024 07:28:12 +0800
+Subject: [PATCH 06/18] Port icp patch to GCC 12
+
+---
+ gcc/common.opt              |    8 +
+ gcc/dbgcnt.def              |    1 +
+ gcc/ipa-devirt.cc           | 1855 +++++++++++++++++++++++++++++++++++
+ gcc/passes.def              |    1 +
+ gcc/testsuite/gcc.dg/icp1.c |   40 +
+ gcc/testsuite/gcc.dg/icp2.c |   38 +
+ gcc/testsuite/gcc.dg/icp3.c |   52 +
+ gcc/testsuite/gcc.dg/icp4.c |   55 ++
+ gcc/testsuite/gcc.dg/icp5.c |   66 ++
+ gcc/testsuite/gcc.dg/icp6.c |   66 ++
+ gcc/testsuite/gcc.dg/icp7.c |   48 +
+ gcc/timevar.def             |    1 +
+ gcc/tree-pass.h             |    1 +
+ 13 files changed, 2232 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/icp1.c
+ create mode 100644 gcc/testsuite/gcc.dg/icp2.c
+ create mode 100644 gcc/testsuite/gcc.dg/icp3.c
+ create mode 100644 gcc/testsuite/gcc.dg/icp4.c
+ create mode 100644 gcc/testsuite/gcc.dg/icp5.c
+ create mode 100644 gcc/testsuite/gcc.dg/icp6.c
+ create mode 100644 gcc/testsuite/gcc.dg/icp7.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 39c90604e..16aadccf6 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1316,6 +1316,14 @@ fdevirtualize
+ Common Var(flag_devirtualize) Optimization
+ Try to convert virtual calls to direct ones.
+ 
++ficp
++Common Var(flag_icp) Optimization Init(0)
++Try to promote indirect calls to direct ones.
++
++ficp-speculatively
++Common Var(flag_icp_speculatively) Optimization
++Promote indirect calls speculatively.
++
+ fdiagnostics-show-location=
+ Common Joined RejectNegative Enum(diagnostic_prefixing_rule)
+ -fdiagnostics-show-location=[once|every-line]	How often to emit source location at the beginning of line-wrapped diagnostics.
+diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def
+index 3aa18cd0c..a00bbc31b 100644
+--- a/gcc/dbgcnt.def
++++ b/gcc/dbgcnt.def
+@@ -170,6 +170,7 @@ DEBUG_COUNTER (graphite_scop)
+ DEBUG_COUNTER (hoist)
+ DEBUG_COUNTER (hoist_insn)
+ DEBUG_COUNTER (ia64_sched2)
++DEBUG_COUNTER (icp)
+ DEBUG_COUNTER (if_after_combine)
+ DEBUG_COUNTER (if_after_reload)
+ DEBUG_COUNTER (if_conversion)
+diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
+index 74fe65608..383839189 100644
+--- a/gcc/ipa-devirt.cc
++++ b/gcc/ipa-devirt.cc
+@@ -103,9 +103,14 @@ along with GCC; see the file COPYING3.  If not see
+   indirect polymorphic edge all possible polymorphic call targets of the call.
+ 
+   pass_ipa_devirt performs simple speculative devirtualization.
++  pass_ipa_icp performs simple indirect call promotion.
+ */
+ 
+ #include "config.h"
++#define INCLUDE_ALGORITHM
++#define INCLUDE_SET
++#define INCLUDE_MAP
++#define INCLUDE_LIST
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -127,6 +132,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "ipa-fnsummary.h"
+ #include "demangle.h"
+ #include "dbgcnt.h"
++#include "gimple-iterator.h"
+ #include "gimple-pretty-print.h"
+ #include "intl.h"
+ #include "stringpool.h"
+@@ -4401,5 +4407,1854 @@ make_pass_ipa_odr (gcc::context *ctxt)
+   return new pass_ipa_odr (ctxt);
+ }
+ 
++/* Function signature map used to look up function decl which corresponds to
++   the given function type.  */
++typedef std::set type_set;
++typedef std::set decl_set;
++typedef std::map type_alias_map;
++typedef std::map type_decl_map;
++typedef std::map uid_to_type_map;
++typedef std::map type_map;
++
++static bool has_address_taken_functions_with_varargs = false;
++static type_set *unsafe_types = NULL;
++static type_alias_map *fta_map = NULL;
++static type_alias_map *ta_map = NULL;
++static type_map *ctype_map = NULL;
++static type_alias_map *cbase_to_ptype = NULL;
++static type_decl_map *fs_map = NULL;
++static uid_to_type_map *type_uid_map = NULL;
++
++static void
++print_type_set(unsigned ftype_uid, type_alias_map *map)
++{
++  if (!map->count (ftype_uid))
++    return;
++  type_set* s = (*map)[ftype_uid];
++  for (type_set::const_iterator it = s->begin (); it != s->end (); it++)
++    fprintf (dump_file, it == s->begin () ? "%d" : ", %d", *it);
++}
++
++static void
++dump_type_with_uid (const char *msg, tree type, dump_flags_t flags = TDF_NONE)
++{
++  fprintf (dump_file, msg);
++  print_generic_expr (dump_file, type, flags);
++  fprintf (dump_file, " (%d)\n", TYPE_UID (type));
++}
++
++/* Walk aggregate type and collect types of scalar elements.  */
++
++static void
++collect_scalar_types (tree tp, std::list &types)
++{
++  /* TODO: take into account different field offsets.
++     Also support array casts.  */
++  if (tp && dump_file && (dump_flags & TDF_DETAILS))
++    dump_type_with_uid ("Walk var's type: ", tp, TDF_UID);
++  if (RECORD_OR_UNION_TYPE_P (tp))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Record's fields {\n");
++      for (tree field = TYPE_FIELDS (tp); field;
++	   field = DECL_CHAIN (field))
++	{
++	  if (TREE_CODE (field) != FIELD_DECL)
++	    continue;
++	  collect_scalar_types (TREE_TYPE (field), types);
++	}
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "}\n");
++      return;
++    }
++  if (TREE_CODE (tp) == ARRAY_TYPE)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Array's innermost type:\n");
++      /* Take the innermost component type.  */
++      tree elt;
++      for (elt = TREE_TYPE (tp); TREE_CODE (elt) == ARRAY_TYPE;
++	   elt = TREE_TYPE (elt))
++	if (dump_file && (dump_flags & TDF_DETAILS))
++	  print_generic_expr (dump_file, elt);
++      collect_scalar_types (elt, types);
++      return;
++    }
++  types.push_back (tp);
++}
++
++static void maybe_register_aliases (tree type1, tree type2);
++
++/* Walk type lists and maybe register type aliases.  */
++
++static void
++compare_type_lists (std::list tlist1, std::list tlist2)
++{
++  for (std::list::iterator ti1 = tlist1.begin (), ti2 = tlist2.begin ();
++       ti1 != tlist1.end (); ++ti1, ++ti2)
++    {
++      /* TODO: correct the analysis results if lists have different length.  */
++      if (ti2 == tlist2.end ())
++	{
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    fprintf (dump_file, "Type lists with different length!\n");
++	  break;
++	}
++      maybe_register_aliases (*ti1, *ti2);
++    }
++}
++
++/* For two given types collect scalar element types and
++   compare the result lists to find type aliases.  */
++
++static void
++collect_scalar_types_and_find_aliases (tree t1, tree t2)
++{
++  std::list tlist1;
++  std::list tlist2;
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "First type list: ");
++  collect_scalar_types (t1, tlist1);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "Second type list: ");
++  collect_scalar_types (t2, tlist2);
++  compare_type_lists (tlist1, tlist2);
++}
++
++/* Dump type with the corresponding set from the map.  */
++
++static void
++dump_type_uid_with_set (const char *msg, tree type, type_alias_map *map,
++			bool dump_type = true, bool with_newline = true)
++{
++  fprintf (dump_file, msg, TYPE_UID (type));
++  if (dump_type)
++    print_generic_expr (dump_file, type);
++  fprintf (dump_file, " (");
++  print_type_set (TYPE_UID (type), map);
++  fprintf (dump_file, ")");
++  fprintf (dump_file, with_newline ? "\n" : " ");
++}
++
++static void
++dump_two_types_uids_with_set (const char *msg, unsigned t1_uid,
++			      unsigned t2_uid, type_alias_map *map)
++{
++  fprintf (dump_file, msg, t1_uid, t2_uid);
++  fprintf (dump_file, " (");
++  print_type_set (t1_uid, map);
++  fprintf (dump_file, ")\n");
++}
++
++/* Register type aliases in the map.  Return true if new alias
++   is registered.  */
++
++static bool
++register_ailas_type (tree type, tree alias_type, type_alias_map *map,
++		     bool only_merge = false)
++{
++  /* TODO: maybe support the case with one missed type.  */
++  if (!type || !alias_type)
++    return false;
++  unsigned type_uid = TYPE_UID (type);
++  unsigned alias_type_uid = TYPE_UID (alias_type);
++  if (type_uid_map->count (type_uid) == 0)
++    (*type_uid_map)[type_uid] = type;
++  if (type_uid_map->count (alias_type_uid) == 0)
++    (*type_uid_map)[alias_type_uid] = alias_type;
++
++  if (map->count (type_uid) == 0 && map->count (alias_type_uid) == 0)
++    {
++      (*map)[type_uid] = new type_set ();
++      (*map)[alias_type_uid] = (*map)[type_uid];
++    }
++  else if (map->count (type_uid) == 0)
++    (*map)[type_uid] = (*map)[alias_type_uid];
++  else if (map->count (alias_type_uid) == 0)
++    (*map)[alias_type_uid] = (*map)[type_uid];
++  else if (map->count (type_uid) && map->count (alias_type_uid))
++    {
++      if ((*map)[type_uid] == (*map)[alias_type_uid])
++	{
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    dump_two_types_uids_with_set ("Types (%d) and (%d) are already in",
++					  type_uid, alias_type_uid, map);
++	  return false;
++	}
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  dump_type_uid_with_set ("T1 (%d) in set", type, map, false, true);
++	  dump_type_uid_with_set ("T2 (%d) in set", alias_type, map,
++				  false, true);
++	}
++      (*map)[type_uid]->insert ((*map)[alias_type_uid]->begin (),
++				(*map)[alias_type_uid]->end ());
++      type_set *type_set = (*map)[alias_type_uid];
++      for (type_set::const_iterator it1 = type_set->begin ();
++	   it1 != type_set->end (); ++it1)
++	(*map)[*it1] = (*map)[type_uid];
++      delete type_set;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "MERGE: ");
++    }
++   if (!only_merge)
++     {
++       (*map)[type_uid]->insert (alias_type_uid);
++       (*map)[type_uid]->insert (type_uid);
++     }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_two_types_uids_with_set ("Insert types (%d) and (%d) into set",
++				  type_uid, alias_type_uid, map);
++  return true;
++}
++
++static void
++dump_two_types_with_uids (const char *msg, tree t1, tree t2)
++{
++  fprintf (dump_file, msg);
++  print_generic_expr (dump_file, t1, TDF_UID);
++  fprintf (dump_file, " (%d), ", TYPE_UID (t1));
++  print_generic_expr (dump_file, t2, TDF_UID);
++  fprintf (dump_file, " (%d)\n", TYPE_UID (t2));
++}
++
++static void
++analyze_pointees (tree type1, tree type2)
++{
++  gcc_assert (POINTER_TYPE_P (type1) && POINTER_TYPE_P (type2));
++  tree base1 = TREE_TYPE (type1);
++  tree base2 = TREE_TYPE (type2);
++  /* TODO: maybe analyze void pointers.  */
++  if (VOID_TYPE_P(base1) || VOID_TYPE_P(base2))
++    return;
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_two_types_with_uids ("Walk pointee types: ", base1, base2);
++  collect_scalar_types_and_find_aliases (base1, base2);
++}
++
++static void
++map_canonical_base_to_pointer (tree type, tree to_insert)
++{
++  type = TYPE_MAIN_VARIANT (type);
++  tree base_type = TREE_TYPE (type);
++  tree cbase_type = TYPE_CANONICAL (base_type);
++  if (!cbase_type)
++    return;
++  unsigned cbase_type_uid = TYPE_UID (cbase_type);
++  if (type_uid_map->count (cbase_type_uid) == 0)
++    (*type_uid_map)[cbase_type_uid] = cbase_type;
++
++  if (cbase_to_ptype->count (cbase_type_uid) == 0)
++    {
++      (*cbase_to_ptype)[cbase_type_uid] = new type_set ();
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "New map cb-to-p=(%d): ", cbase_type_uid);
++    }
++  else if (!(*cbase_to_ptype)[cbase_type_uid]->count (TYPE_UID (to_insert)))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Found map cb-to-p=(%d): ", cbase_type_uid);
++    }
++  else
++    return;
++  /* Add all variants of 'to_insert' type.  */
++  for (tree t = to_insert; t; t = TYPE_NEXT_VARIANT (t))
++    {
++      unsigned t_uid = TYPE_UID (t);
++      if (!(*cbase_to_ptype)[cbase_type_uid]->count (t_uid))
++	{
++	  (*cbase_to_ptype)[cbase_type_uid]->insert (t_uid);
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	     fprintf (dump_file, "(%d) ", t_uid);
++	}
++      if (type_uid_map->count (t_uid) == 0)
++	(*type_uid_map)[t_uid] = t;
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\n");
++}
++
++/* Analyse two types and maybe register them as aliases. Also collect
++   unsafe function types and map canonical base types to corresponding
++   pointer types.  */
++
++static void
++maybe_register_aliases (tree type1, tree type2)
++{
++  if (type1 && POINTER_TYPE_P (type1) && !FUNCTION_POINTER_TYPE_P (type1))
++    map_canonical_base_to_pointer (type1, type1);
++  if (type2 && POINTER_TYPE_P (type2) && !FUNCTION_POINTER_TYPE_P (type2))
++    map_canonical_base_to_pointer (type2, type2);
++
++  if (type1 == type2 || !type1 || !type2)
++    return;
++
++  if (POINTER_TYPE_P (type1) && POINTER_TYPE_P (type2))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_two_types_with_uids ("Pointer types: ", type1, type2);
++      if (register_ailas_type (type1, type2, ta_map))
++	analyze_pointees (type1, type2);
++    }
++  /* If function and non-function type pointers alias,
++     the function type is unsafe.  */
++  if (FUNCTION_POINTER_TYPE_P (type1) && !FUNCTION_POINTER_TYPE_P (type2))
++    unsafe_types->insert (TYPE_UID (type1));
++  if (FUNCTION_POINTER_TYPE_P (type2) && !FUNCTION_POINTER_TYPE_P (type1))
++    unsafe_types->insert (TYPE_UID (type2));
++
++  /* Try to figure out with pointers to incomplete types.  */
++  if (POINTER_TYPE_P (type1) && POINTER_TYPE_P (type2))
++    {
++      type1 = TYPE_MAIN_VARIANT (type1);
++      type2 = TYPE_MAIN_VARIANT (type2);
++      tree base1 = TREE_TYPE (type1);
++      tree base2 = TREE_TYPE (type2);
++      if (RECORD_OR_UNION_TYPE_P (base1) && RECORD_OR_UNION_TYPE_P (base2))
++	{
++	  tree cb1 = TYPE_CANONICAL (base1);
++	  tree cb2 = TYPE_CANONICAL (base2);
++	  if (cb1 && !cb2)
++	    map_canonical_base_to_pointer (type1, type2);
++	  if (cb2 && !cb1)
++	    map_canonical_base_to_pointer (type2, type1);
++	}
++    }
++}
++
++/* Maybe register non-void/equal type aliases.  */
++
++static void
++maybe_register_non_void_aliases (tree t1, tree t2)
++{
++  gcc_assert (t1 && t2);
++  if (type_uid_map->count (TYPE_UID (t1)) == 0)
++    (*type_uid_map)[TYPE_UID (t1)] = t1;
++  if (type_uid_map->count (TYPE_UID (t2)) == 0)
++    (*type_uid_map)[TYPE_UID (t2)] = t2;
++
++  /* Skip equal and void types.  */
++  if (t1 == t2 || VOID_TYPE_P (t1) || VOID_TYPE_P (t2))
++    return;
++  maybe_register_aliases (t1, t2);
++}
++
++/* Detect function type in call stmt.  */
++
++static tree
++get_call_fntype (gcall *stmt)
++{
++  tree fntype = NULL;
++  if (gimple_call_fndecl (stmt) && TREE_TYPE (gimple_call_fndecl (stmt)))
++    fntype = TREE_TYPE (gimple_call_fndecl (stmt));
++  else
++    {
++      tree call_fn = gimple_call_fn (stmt);
++      tree ptype = TREE_TYPE (call_fn);
++      gcc_assert (ptype && TREE_TYPE (ptype));
++      fntype = TREE_TYPE (ptype);
++    }
++  gcc_assert (fntype && fntype != void_type_node
++	      && (TREE_CODE (fntype) == FUNCTION_TYPE
++		  || TREE_CODE (fntype) == METHOD_TYPE));
++  return fntype;
++}
++
++static void
++dump_global_var (tree decl)
++{
++  fprintf (dump_file, "Analyze global var: ");
++  print_generic_decl (dump_file, decl, TDF_NONE);
++  fprintf (dump_file, "\n");
++}
++
++static void
++collect_block_elt_types (tree tp, std::list &types, tree block)
++{
++  tree vt = TREE_TYPE (tp);
++  gcc_assert (vt);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      const char *msg = TREE_CODE (block) == BLOCK ? "VAR's block: " :
++						     "VAR's ctor: ";
++      fprintf (dump_file, msg);
++      print_generic_expr (dump_file, tp);
++      dump_type_with_uid (" with type ", vt);
++    }
++  collect_scalar_types (vt, types);
++}
++
++/* Compare types of initialization block's or constructor's elements and
++   fields of the initializer type to find type aliases.  */
++
++static void
++compare_block_and_init_type (tree block, tree t1)
++{
++  std::list tlist1;
++  std::list tlist2;
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "Init's type list: ");
++  collect_scalar_types (t1, tlist1);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "Block's type list: ");
++  if (TREE_CODE (block) == CONSTRUCTOR)
++    {
++      unsigned HOST_WIDE_INT idx;
++      tree value;
++      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (block), idx, value)
++	{
++	  gcc_assert (value);
++	  collect_block_elt_types (value, tlist2, block);
++	}
++    }
++  else if (TREE_CODE (block) == BLOCK)
++    for (tree var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
++      {
++	if (TREE_CODE (var) != VAR_DECL)
++	  continue;
++	collect_block_elt_types (var, tlist2, block);
++      }
++  else
++    gcc_unreachable ();
++  compare_type_lists (tlist1, tlist2);
++}
++
++/* Analyze global var to find type aliases comparing types of var and
++   initializer elements.  */
++
++static void
++analyze_global_var (varpool_node *var)
++{
++  var->get_constructor();
++  tree decl = var->decl;
++  if (TREE_CODE (decl) == SSA_NAME || !DECL_INITIAL (decl)
++      || integer_zerop (DECL_INITIAL (decl)))
++    return;
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_global_var (decl);
++  tree var_type = TREE_TYPE (decl);
++  tree init_type = TREE_TYPE (DECL_INITIAL (decl));
++  gcc_assert (var_type && init_type);
++  if (RECORD_OR_UNION_TYPE_P (init_type)
++      && !initializer_zerop (DECL_INITIAL (decl)))
++    compare_block_and_init_type (DECL_INITIAL (decl), init_type);
++  else if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "Is not a record with nonzero init\n");
++
++  if (var_type == init_type)
++    return;
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_two_types_with_uids ("Mismatch of var and init types: ",
++			      var_type, init_type);
++  collect_scalar_types_and_find_aliases (var_type, init_type);
++}
++
++static void
++dump_function_node_info (struct cgraph_node *n)
++{
++  fprintf (dump_file, "\nAnalyse function node: ");
++  print_generic_expr (dump_file, n->decl);
++  fprintf (dump_file, "\n");
++  tree fndecl_type = TREE_TYPE (n->decl);
++  dump_type_with_uid ("Function decl type: ", fndecl_type, TDF_UID);
++  if (TREE_TYPE (fndecl_type))
++    dump_type_with_uid ("Return type: ", TREE_TYPE (fndecl_type));
++  tree argt = TYPE_ARG_TYPES (fndecl_type);
++  for (unsigned i = 1; argt && argt != void_type_node
++       && !VOID_TYPE_P (TREE_VALUE (argt)); ++i, argt = TREE_CHAIN (argt))
++    {
++      tree atype = TREE_VALUE (argt);
++      fprintf (dump_file, "%d-arg type: ", i);
++      dump_type_with_uid ("", atype);
++    }
++  fprintf (dump_file, "\n");
++}
++
++static void
++dump_call_stmt_info (gcall *stmt, tree fntype)
++{
++  fprintf (dump_file, "\nAnalyse call stmt: ");
++  if (stmt)
++    print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++  else
++    fprintf (dump_file, "(no stmt)\n");
++  dump_type_with_uid ("fntype=", fntype, TDF_UID);
++  if (gimple_call_fntype (stmt))
++    dump_type_with_uid ("fntype1=", gimple_call_fntype (stmt), TDF_UID);
++  if (gimple_call_fndecl (stmt) && TREE_TYPE (gimple_call_fndecl (stmt)))
++    dump_type_with_uid ("fntype2=", TREE_TYPE (gimple_call_fndecl (stmt)),
++			TDF_UID);
++}
++
++/* Dump actual and formal arg types.  */
++
++static void
++dump_arg_types_with_uids (int i, tree t1, tree t2)
++{
++  if (i >= 0)
++    fprintf (dump_file, "Call's %d-arg types: ", i);
++  else
++    fprintf (dump_file, "Call's return types: ");
++  fprintf (dump_file, "(%d) and (%d) ", TYPE_UID (t1), TYPE_UID (t2));
++  print_generic_expr (dump_file, t1, TDF_UID);
++  fprintf (dump_file, " ");
++  print_generic_expr (dump_file, t2, TDF_UID);
++  fprintf (dump_file, "\n");
++}
++
++/* Analyze call graph edge with connected call stmt to find type aliases in
++   arguments and return value casts.  */
++
++static void
++analyze_cgraph_edge (cgraph_edge *e)
++{
++  gcall *stmt = e->call_stmt;
++  gcc_assert (stmt != NULL);
++  tree fntype = get_call_fntype (stmt);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_call_stmt_info (stmt, fntype);
++  if (gimple_has_lhs (stmt))
++    {
++      tree t1 = TREE_TYPE (gimple_call_lhs (stmt));
++      tree t2 = TREE_TYPE (fntype);
++      const int is_return_arg = -1;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_arg_types_with_uids (is_return_arg, t1, t2);
++      maybe_register_non_void_aliases (t1, t2);
++    }
++
++  tree argt = TYPE_ARG_TYPES (fntype);
++  if (!argt)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Finish call stmt analysis\n");
++      return;
++    }
++  gcc_assert (argt);
++  unsigned num_args = gimple_call_num_args (stmt);
++  for (unsigned i = 0; i < num_args && argt; ++i, argt = TREE_CHAIN (argt))
++    {
++      tree arg = gimple_call_arg (stmt, i);
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_arg_types_with_uids (i, TREE_VALUE (argt), TREE_TYPE (arg));
++      if (TREE_VALUE (argt) == TREE_TYPE (arg)
++	  || !POINTER_TYPE_P (TREE_VALUE (argt))
++	  || !POINTER_TYPE_P (TREE_TYPE (arg)))
++	continue;
++      maybe_register_non_void_aliases (TREE_VALUE (argt), TREE_TYPE (arg));
++      tree t1 = TREE_TYPE (TREE_VALUE (argt));
++      tree t2 = TREE_TYPE (TREE_TYPE (arg));
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Call's %d-arg base types: (%d) and (%d)\n",
++		 i, (t1 ? TYPE_UID (t1) : 0), (t2 ? TYPE_UID (t2) : 0));
++      maybe_register_non_void_aliases (t1, t2);
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "End list of args\n");
++  tree fndecl_type = NULL;
++  if (e->callee && e->callee->decl)
++    fndecl_type = TREE_TYPE (e->callee->decl);
++  if (fndecl_type && fndecl_type != fntype)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Function decl and edge types mismatch:\n");
++      register_ailas_type (fntype, fndecl_type, fta_map);
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "End call stmt analysis\n");
++}
++
++static void
++dump_assign_info (gimple *stmt, tree rhs, tree lhs_type, tree rhs_type)
++{
++  fprintf (dump_file, "\nAnalyse assign cast/copy stmt, rhs=%s: ",
++	   get_tree_code_name (TREE_CODE (rhs)));
++  print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++  fprintf (dump_file, "Types: ");
++  print_generic_expr (dump_file, lhs_type);
++  fprintf (dump_file, ", ");
++  print_generic_expr (dump_file, rhs_type);
++  fprintf (dump_file, "\n");
++}
++
++/* Analyze cast/copy assign stmt to find type aliases.  */
++
++static void
++analyze_assign_stmt (gimple *stmt)
++{
++  gcc_assert (is_gimple_assign (stmt));
++  tree rhs_type = NULL_TREE;
++  tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
++  tree rhs = gimple_assign_rhs1 (stmt);
++  if (TREE_CODE (rhs) == MEM_REF)
++    {
++      rhs = TREE_OPERAND (rhs, 0);
++      tree ptr_type = TREE_TYPE (rhs);
++      gcc_assert (POINTER_TYPE_P (ptr_type));
++      rhs_type = TREE_TYPE (ptr_type);
++    }
++  else if (TREE_CODE (rhs) == ADDR_EXPR)
++    {
++      rhs = TREE_OPERAND (rhs, 0);
++      if (VAR_OR_FUNCTION_DECL_P (rhs) || TREE_CODE (rhs) == STRING_CST
++	  || TREE_CODE (rhs) == ARRAY_REF || TREE_CODE (rhs) == PARM_DECL)
++	rhs_type = build_pointer_type (TREE_TYPE (rhs));
++      else if (TREE_CODE (rhs) == COMPONENT_REF)
++	{
++	  rhs = TREE_OPERAND (rhs, 1);
++	  rhs_type = build_pointer_type (TREE_TYPE (rhs));
++	}
++      else if (TREE_CODE (rhs) == MEM_REF)
++	{
++	  rhs = TREE_OPERAND (rhs, 0);
++	  rhs_type = TREE_TYPE (rhs);
++	  gcc_assert (POINTER_TYPE_P (rhs_type));
++	}
++      else
++	gcc_unreachable();
++    }
++  else
++    rhs_type = TREE_TYPE (rhs);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_assign_info (stmt, rhs, lhs_type, rhs_type);
++  if (CONSTANT_CLASS_P (rhs) && !zerop (rhs)
++      && FUNCTION_POINTER_TYPE_P (TREE_TYPE (rhs)))
++    {
++      tree ftype = TREE_TYPE (rhs_type);
++      unsafe_types->insert (TYPE_UID (ftype));
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Function type (%d) is unsafe due to assign "
++		 "non-zero cst to function pointer\n", TYPE_UID (ftype));
++    }
++  maybe_register_non_void_aliases (lhs_type, rhs_type);
++}
++
++/* Walk all fn's stmt to analyze assigns.  */
++
++static void
++analyze_assigns (function* fn)
++{
++  push_cfun (fn);
++  basic_block bb;
++  gimple_stmt_iterator si;
++  FOR_EACH_BB_FN (bb, fn)
++    for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
++      {
++	gimple *stmt = gsi_stmt (si);
++	if (!gimple_assign_cast_p (stmt) && !gimple_assign_copy_p (stmt))
++	  continue;
++	analyze_assign_stmt (stmt);
++      }
++  pop_cfun ();
++}
++
++/* Walk all functions to collect sets of type aliases.  */
++
++static void
++collect_type_alias_sets ()
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\n\nCollect type alias sets walking global vars.\n");
++
++  varpool_node *var;
++  FOR_EACH_VARIABLE (var)
++    if (var->real_symbol_p ())
++      analyze_global_var (var);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\nCollect type alias sets walking functions.\n");
++
++  struct cgraph_node *n;
++  FOR_EACH_FUNCTION (n)
++    {
++      if (!n->has_gimple_body_p ())
++	continue;
++      n->get_body ();
++      function *fn = DECL_STRUCT_FUNCTION (n->decl);
++      if (!fn)
++	continue;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_function_node_info (n);
++      /* Analyze direct/indirect function calls.  */
++      for (cgraph_edge *e = n->callees; e; e = e->next_callee)
++	analyze_cgraph_edge (e);
++      for (cgraph_edge *e = n->indirect_calls; e; e = e->next_callee)
++	analyze_cgraph_edge (e);
++      /* Analyze assign (with casts) statements.  */
++      analyze_assigns (fn);
++    }
++}
++
++static void
++process_cbase_to_ptype_map ()
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\nProcess types in cbase-to-ptypes map:\n");
++
++  for (type_alias_map::iterator it1 = cbase_to_ptype->begin ();
++       it1 != cbase_to_ptype->end (); ++it1)
++    {
++      type_set *set = it1->second;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_type_uid_with_set ("cb=(%d): ", (*type_uid_map)[it1->first],
++				cbase_to_ptype);
++      tree ctype = NULL;
++      for (type_set::const_iterator it2 = set->begin ();
++	   it2 != set->end (); it2++)
++	{
++	  tree t2 = (*type_uid_map)[*it2];
++	  if (t2 == TYPE_MAIN_VARIANT (t2))
++	    {
++	      ctype = t2;
++	      break;
++	    }
++	}
++      if (!ctype)
++	continue;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_type_with_uid ("Select canonical type: ", ctype);
++      for (type_set::const_iterator it2 = set->begin ();
++	   it2 != set->end (); it2++)
++	{
++	  tree t = (*type_uid_map)[*it2];
++	  if (!ctype_map->count (t))
++	    {
++	      (*ctype_map)[t] = ctype;
++	      if (dump_file && (dump_flags & TDF_DETAILS))
++		fprintf (dump_file, "Set canonical type for (%d)->c(%d)\n",
++			 *it2, TYPE_UID (ctype));
++	    }
++	  else if (dump_file && (dump_flags & TDF_DETAILS))
++	    fprintf (dump_file, "Canonical type is already set (%d)->c(%d)\n",
++		     *it2, TYPE_UID ((*ctype_map)[t]));
++	}
++    }
++}
++
++static void
++set_canonical_type_for_type_set (type_set *set)
++{
++  tree one_canonical = NULL;
++  for (type_set::const_iterator it = set->begin (); it != set->end (); it++)
++    {
++      tree t = (*type_uid_map)[*it];
++      gcc_assert (t);
++      if ((TYPE_CANONICAL (t) || ctype_map->count (t)))
++	{
++	  one_canonical = TYPE_CANONICAL (t) ? TYPE_CANONICAL (t)
++					     : (*ctype_map)[t];
++	  gcc_assert (COMPLETE_TYPE_P (t));
++	  break;
++	}
++    }
++  for (type_set::const_iterator it = set->begin (); it != set->end (); it++)
++    {
++      tree t = (*type_uid_map)[*it];
++      if (!ctype_map->count (t))
++	{
++	  (*ctype_map)[t] = one_canonical;
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    {
++	      if (one_canonical)
++		fprintf (dump_file, "Set canonical type for (%d)->c(%d)\n",
++			 TYPE_UID (t), TYPE_UID (one_canonical));
++	      else
++		fprintf (dump_file, "Set NULL canonical for (%d)\n", *it);
++	    }
++	}
++      else if (dump_file && (dump_flags & TDF_DETAILS))
++	{
++	  tree ct = (*ctype_map)[t];
++	  fprintf (dump_file, "Canonical type is already set (%d)->c(%d)\n",
++		   TYPE_UID (t), ct ? TYPE_UID (ct) : -1);
++	}
++    }
++}
++
++static void
++dump_is_type_set_incomplete (type_set * set)
++{
++  bool has_complete_types = false;
++  for (type_set::const_iterator it = set->begin (); it != set->end (); it++)
++    if (COMPLETE_TYPE_P ((*type_uid_map)[*it]))
++      {
++	has_complete_types = true;
++	break;
++      }
++  if (!has_complete_types)
++    fprintf (dump_file, "Set of incomplete types\n");
++}
++
++static void
++process_alias_type_sets ()
++{
++  if (dump_file)
++    fprintf (dump_file, "\nProcess alias sets of types:\n");
++  /* Keep processed types to process each type set (in ta_map) only once.  */
++  type_set processed_types;
++  for (type_alias_map::iterator it1 = ta_map->begin ();
++       it1 != ta_map->end (); ++it1)
++    {
++      tree type = (*type_uid_map)[it1->first];
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_type_uid_with_set ("(%d) ", type, ta_map);
++      if (processed_types.count (TYPE_UID (type)) != 0
++	  || unsafe_types->count (TYPE_UID (type)) != 0)
++	continue;
++      type_set *set = it1->second;
++      for (type_set::const_iterator it2 = set->begin ();
++	   it2 != set->end (); it2++)
++	processed_types.insert (*it2);
++      /* Check if this type set contains function pointers and
++	 non-function pointers.  */
++      bool has_no_fp = false, has_fp = false;
++      for (type_set::const_iterator it2 = set->begin ();
++	   it2 != set->end (); it2++)
++	{
++	  tree t2 = (*type_uid_map)[*it2];
++	  if (FUNCTION_POINTER_TYPE_P (t2))
++	    has_fp = true;
++	  else
++	    has_no_fp = true;
++	  if (has_fp && has_no_fp)
++	    break;
++	}
++      if (has_fp)
++	{
++	  for (type_set::const_iterator it2 = set->begin ();
++	       it2 != set->end (); it2++)
++	    {
++	      tree t2 = (*type_uid_map)[*it2];
++	      /* If it's a type set with mixed function and not-function types,
++		 mark all function pointer types in the set as unsafe.  */
++	      if (has_no_fp && FUNCTION_POINTER_TYPE_P (t2))
++		{
++		  tree ftype = TREE_TYPE (t2);
++		  unsafe_types->insert (TYPE_UID (ftype));
++		  if (dump_file && (dump_flags & TDF_DETAILS))
++		    fprintf (dump_file, "Insert function type (%d) to unsafe "
++			     "due to escape its pointer type (%d) to mixed "
++			     "alias set (printed before)\n",
++			     TYPE_UID (ftype), TYPE_UID (t2));
++		}
++	      /* If it's a type set with only function pointer types,
++		 mark all base function types in the set as aliases.  */
++	      if (!has_no_fp)
++		{
++		  gcc_assert (FUNCTION_POINTER_TYPE_P (type)
++			      && FUNCTION_POINTER_TYPE_P (t2));
++		  if (dump_file && (dump_flags & TDF_DETAILS))
++		    fprintf (dump_file, "Insert function type aliases by "
++			     "function pointer aliases:\n");
++		  register_ailas_type (TREE_TYPE (type), TREE_TYPE (t2),
++				       fta_map);
++		}
++	    }
++	}
++      set_canonical_type_for_type_set (set);
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_is_type_set_incomplete (set);
++    }
++}
++
++static void
++dump_unsafe_and_canonical_types ()
++{
++  fprintf (dump_file, "\nList of unsafe types:\n");
++  for (type_set::iterator it = unsafe_types->begin ();
++       it != unsafe_types->end (); ++it)
++    {
++      print_generic_expr (dump_file, (*type_uid_map)[*it]);
++      fprintf (dump_file, " (%d)\n", *it);
++    }
++  fprintf (dump_file, "\nList of alias canonical types:\n");
++  for (type_alias_map::iterator it = ta_map->begin ();
++       it != ta_map->end (); ++it)
++    {
++      tree type = (*type_uid_map)[it->first];
++      if (ctype_map->count (type) == 0)
++	continue;
++      print_generic_expr (dump_file, type);
++      fprintf (dump_file, " -> ");
++      tree ctype = (*ctype_map)[type];
++      if (ctype != NULL)
++	{
++	  print_generic_expr (dump_file, ctype);
++	  fprintf (dump_file, " (%d)->(%d)\n",
++		   TYPE_UID (type), TYPE_UID (ctype));
++	}
++      else
++	 fprintf (dump_file, " null\n");
++    }
++}
++
++static void
++init_function_type_alias_for_edge (cgraph_edge *e)
++{
++  gcall *stmt = e->call_stmt;
++  gcc_assert (stmt != NULL);
++  tree fntype = get_call_fntype (stmt);
++  if (fta_map->count (TYPE_UID (fntype)) == 0)
++    register_ailas_type (fntype, fntype, fta_map);
++}
++
++/* This pass over all function types makes each function type to have
++   at least one alias (itself).  */
++
++static void
++init_function_type_aliases ()
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\nInit aliases for all function types.\n");
++
++  struct cgraph_node *n;
++  FOR_EACH_FUNCTION (n)
++    {
++      tree fntype = TREE_TYPE (n->decl);
++      if (fta_map->count (TYPE_UID (fntype)) == 0)
++	register_ailas_type (fntype, fntype, fta_map);
++
++      if (!n->has_gimple_body_p ())
++	continue;
++      n->get_body ();
++      function *fn = DECL_STRUCT_FUNCTION (n->decl);
++      if (!fn)
++	continue;
++
++      /* Init for function types of direct/indirect callees.  */
++      for (cgraph_edge *e = n->callees; e; e = e->next_callee)
++	init_function_type_alias_for_edge (e);
++      for (cgraph_edge *e = n->indirect_calls; e; e = e->next_callee)
++	init_function_type_alias_for_edge (e);
++    }
++}
++
++/* In lto-common.c there is the global canonical type table and the
++   corresponding machinery which detects the same types from differens
++   modules and joins them assigning the one canonical type.  However
++   lto does not set the goal to do a complete and precise matching, so
++   sometimes a few types has no TYPE_CANONICAL set.  Since ICP relies on
++   precise type matching, we create the similar table and register all
++   the required types in it.  */
++
++static std::map *canonical_type_hash_cache = NULL;
++static std::map *icp_canonical_types = NULL;
++
++static hashval_t hash_canonical_type (tree type);
++
++/* Register canonical type in icp_canonical_types and ctype_map evaluating
++   its hash (using hash_canonical_type) if it's needed.  */
++
++static hashval_t
++icp_register_canonical_type (tree t)
++{
++  hashval_t hash;
++  if (canonical_type_hash_cache->count ((const_tree) t) == 0)
++    {
++      tree t1 = TYPE_MAIN_VARIANT (t);
++      if (!COMPLETE_TYPE_P (t1) && TYPE_CANONICAL (t1)
++	  && COMPLETE_TYPE_P (TYPE_CANONICAL (t1)))
++	{
++	  t1 = TYPE_CANONICAL (t1);
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    fprintf (dump_file, "Use complete canonical (%d) for (%d)\n",
++		     TYPE_UID (t1), TYPE_UID (t));
++	}
++      hash = hash_canonical_type (t1);
++      /* Cache the just computed hash value.  */
++      (*canonical_type_hash_cache)[(const_tree) t] = hash;
++    }
++  else
++    hash = (*canonical_type_hash_cache)[(const_tree) t];
++
++  tree new_type = t;
++  if (icp_canonical_types->count (hash))
++    {
++      new_type = (*icp_canonical_types)[hash];
++      gcc_checking_assert (new_type != t);
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Found canonical (%d) for (%d), h=%u\n",
++		 TYPE_UID (new_type), TYPE_UID (t), (unsigned int) hash);
++    }
++  else
++    {
++      (*icp_canonical_types)[hash] = t;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Register canonical %d, h=%u\n", TYPE_UID (t),
++		 (unsigned int) hash);
++    }
++  if (ctype_map->count (t) == 0)
++    (*ctype_map)[t] = new_type;
++  return hash;
++}
++
++/* Merge hstate with hash of the given type.  If the type is not registered,
++   register it in the maps of the canonical types. */
++
++static void
++iterative_hash_canonical_type (tree type, inchash::hash &hstate)
++{
++  hashval_t v;
++  /* All type variants have same TYPE_CANONICAL.  */
++  type = TYPE_MAIN_VARIANT (type);
++  if (canonical_type_hash_cache->count ((const_tree) type))
++    v = (*canonical_type_hash_cache)[(const_tree) type];
++  else
++    v = icp_register_canonical_type (type);
++  hstate.merge_hash (v);
++}
++
++/* Compute and return hash for the given type.  It does not take into account
++   base types of pointer types.  */
++
++static hashval_t
++hash_canonical_type (tree type)
++{
++  inchash::hash hstate;
++  enum tree_code code;
++  /* Combine a few common features of types so that types are grouped into
++     smaller sets; when searching for existing matching types to merge,
++     only existing types having the same features as the new type will be
++     checked.  */
++  code = tree_code_for_canonical_type_merging (TREE_CODE (type));
++  hstate.add_int (code);
++  if (!RECORD_OR_UNION_TYPE_P (type))
++    hstate.add_int (TYPE_MODE (type));
++  /* Incorporate common features of numerical types.  */
++  if (INTEGRAL_TYPE_P (type)
++      || SCALAR_FLOAT_TYPE_P (type)
++      || FIXED_POINT_TYPE_P (type)
++      || TREE_CODE (type) == OFFSET_TYPE
++      || POINTER_TYPE_P (type))
++    {
++      hstate.add_int (TYPE_PRECISION (type));
++      if (!type_with_interoperable_signedness (type))
++	hstate.add_int (TYPE_UNSIGNED (type));
++    }
++  if (VECTOR_TYPE_P (type))
++    {
++      hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type));
++      hstate.add_int (TYPE_UNSIGNED (type));
++    }
++  if (TREE_CODE (type) == COMPLEX_TYPE)
++    hstate.add_int (TYPE_UNSIGNED (type));
++  if (POINTER_TYPE_P (type))
++    hstate.add_int (TYPE_ADDR_SPACE (TREE_TYPE (type)));
++  /* For array types hash the domain bounds and the string flag.  */
++  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
++    {
++      hstate.add_int (TYPE_STRING_FLAG (type));
++      /* OMP lowering can introduce error_mark_node in place of
++	 random local decls in types.  */
++      if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
++	inchash::add_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), hstate);
++      if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
++	inchash::add_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), hstate);
++    }
++  /* Recurse for aggregates with a single element type.  */
++  if (TREE_CODE (type) == ARRAY_TYPE
++      || TREE_CODE (type) == COMPLEX_TYPE
++      || TREE_CODE (type) == VECTOR_TYPE)
++    iterative_hash_canonical_type (TREE_TYPE (type), hstate);
++  /* Incorporate function return and argument types.  */
++  if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
++    {
++      unsigned nargs = 0;
++      iterative_hash_canonical_type (TREE_TYPE (type), hstate);
++      for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
++	{
++	  iterative_hash_canonical_type (TREE_VALUE (p), hstate);
++	  nargs++;
++	}
++      hstate.add_int (nargs);
++    }
++  if (RECORD_OR_UNION_TYPE_P (type))
++    {
++      unsigned nfields = 0;
++      for (tree f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
++	if (TREE_CODE (f) == FIELD_DECL)
++	  {
++	    iterative_hash_canonical_type (TREE_TYPE (f), hstate);
++	    nfields++;
++	  }
++      hstate.add_int (nfields);
++    }
++  return hstate.end ();
++}
++
++/* It finds canonical type in ctype_map and icp_canonical_types maps.  */
++
++static tree
++find_canonical_type (tree type)
++{
++  if (ctype_map->count (type))
++    return (*ctype_map)[type];
++  if (canonical_type_hash_cache->count ((const_tree) type) == 0)
++    return NULL;
++  hashval_t h = (*canonical_type_hash_cache)[(const_tree) type];
++  if (icp_canonical_types->count (h))
++    return (*icp_canonical_types)[h];
++  return NULL;
++}
++
++/* It updates hash for the given type taking into account pointees in pointer
++   types.  If the type is incomplete function type, it returns true.  It's used
++   only for function type hash calculation. */
++
++static bool
++initial_hash_canonical_type (tree type, inchash::hash &hstate)
++{
++  /* All type variants have same TYPE_CANONICAL.  */
++  type = TYPE_MAIN_VARIANT (type);
++  if (VOID_TYPE_P (type))
++    {
++      hstate.add_int (POINTER_TYPE);
++      return false;
++    }
++  hstate.add_int (TREE_CODE (type));
++  hstate.add_int (TYPE_MODE (type));
++  if (POINTER_TYPE_P (type))
++    {
++      tree base_type = TREE_TYPE (type);
++      hstate.add_int (TYPE_ADDR_SPACE (base_type));
++      return initial_hash_canonical_type (base_type, hstate);
++    }
++  tree ctype = find_canonical_type (type);
++  if (!ctype)
++    {
++      if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
++	{
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    fprintf (dump_file, "Due to ftype (%d)\n", TYPE_UID (type));
++	  return true;
++	}
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	dump_type_with_uid ("Has NO canonical type: ", type, TDF_UID);
++      icp_register_canonical_type (type);
++      if (ctype_map->count(type))
++	ctype = (*ctype_map)[type];
++      if (ctype && dump_file && (dump_flags & TDF_DETAILS))
++	dump_type_with_uid ("Found canonical type: ", ctype, TDF_UID);
++    }
++  else if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_type_with_uid ("Canonical type: ", ctype, TDF_UID);
++  hstate.add_int (TYPE_UID (ctype));
++  return false;
++}
++
++/* It returns hash value for the given function type. If the function type is
++   incomplete, insert it in the incomplete_hash_ftype set.  */
++
++static hashval_t
++get_hash_for_ftype (tree type, type_set *incomplete_hash_ftype)
++{
++  bool incomplete = false;
++  inchash::hash hstate;
++  /* Function type is expected.  */
++  gcc_assert (TREE_CODE (type) == FUNCTION_TYPE
++	      || TREE_CODE (type) == METHOD_TYPE);
++  /* Hash return type.  */
++  tree rt = TREE_TYPE (type);
++  tree ct = rt ? find_canonical_type (rt) : void_type_node;
++  incomplete |= initial_hash_canonical_type (ct ? ct : rt, hstate);
++  /* Hash arg types.  */
++  tree argt = TYPE_ARG_TYPES (type);
++  if (!argt)
++    incomplete |= initial_hash_canonical_type (void_type_node, hstate);
++  else
++    for (unsigned i = 1; argt; ++i, argt = TREE_CHAIN (argt))
++      {
++	tree ct = find_canonical_type (TREE_VALUE (argt));
++	ct = ct ? ct : TREE_VALUE (argt);
++	incomplete |= initial_hash_canonical_type (ct, hstate);
++      }
++  if (incomplete && incomplete_hash_ftype->count (TYPE_UID (type)) == 0)
++    incomplete_hash_ftype->insert (TYPE_UID (type));
++  else if (!incomplete && incomplete_hash_ftype->count (TYPE_UID (type)) != 0)
++    incomplete_hash_ftype->erase (TYPE_UID (type));
++  return hstate.end();
++}
++
++/* Find type aliases evaluating type hashes and connecting types with
++   the same hash values.  */
++
++static void
++find_type_aliases_by_compatibility ()
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\nFind type aliases checking their compatibility.\n");
++
++  std::map hash_to_ftype;
++  type_set *incomplete_hash_ftype = new type_set;
++  canonical_type_hash_cache = new std::map;
++  icp_canonical_types = new std::map;
++
++  bool changed;
++  int i = 0;
++  do
++    {
++      changed = false;
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Iteration %d\n", i);
++      for (type_alias_map::iterator it = fta_map->begin ();
++	   it != fta_map->end (); ++it)
++	{
++	  tree type = (*type_uid_map)[it->first];
++	  if (TYPE_CANONICAL (type))
++	    continue;
++	  hashval_t hash = get_hash_for_ftype (type, incomplete_hash_ftype);
++	  if (incomplete_hash_ftype->count (TYPE_UID (type)) != 0)
++	    {
++	      if (dump_file && (dump_flags & TDF_DETAILS))
++		fprintf (dump_file, "Incomplete (%d), h=%u\n", TYPE_UID (type),
++			 (unsigned int) hash);
++	      continue;
++	    }
++	  if (hash_to_ftype.count (hash) == 0)
++	    hash_to_ftype[hash] = type;
++	  TYPE_CANONICAL (type) = hash_to_ftype[hash];
++	  changed = true;
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    fprintf (dump_file, "(%d)->(%d), h=%u\n", TYPE_UID (type),
++		     TYPE_UID (TYPE_CANONICAL (type)), (unsigned int) hash);
++	}
++      i++;
++    }
++  while (changed);
++
++  delete incomplete_hash_ftype;
++  delete icp_canonical_types;
++  delete canonical_type_hash_cache;
++}
++
++static void
++dump_function_type_aliases_list ()
++{
++  fprintf (dump_file, "\nList of function type aliases:\n");
++  for (type_alias_map::iterator it = fta_map->begin ();
++       it != fta_map->end (); ++it)
++    dump_type_uid_with_set ("(%d) ", (*type_uid_map)[it->first], fta_map);
++}
++
++/* Collect type aliases and find missed canonical types.  */
++
++static void
++collect_function_type_aliases ()
++{
++  collect_type_alias_sets ();
++  process_cbase_to_ptype_map ();
++  process_alias_type_sets ();
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_unsafe_and_canonical_types ();
++
++  /* TODO: maybe remove this pass.  */
++  init_function_type_aliases ();
++  for (type_alias_map::iterator it = fta_map->begin ();
++       it != fta_map->end (); ++it)
++    set_canonical_type_for_type_set (it->second);
++  find_type_aliases_by_compatibility ();
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    dump_function_type_aliases_list ();
++}
++
++static void
++dump_function_signature_info (struct cgraph_node *n, tree ftype, bool varargs)
++{
++  fprintf (dump_file, "Function decl: ");
++  print_generic_expr (dump_file, n->decl);
++  dump_type_uid_with_set (" with type (%d) ", ftype, fta_map, true, false);
++  if (varargs)
++    fprintf (dump_file, "has varargs, ");
++  if (TREE_CODE (ftype) == METHOD_TYPE)
++    fprintf (dump_file, "is method, ");
++  if (!n->address_taken)
++    fprintf (dump_file, "is not address taken, ");
++  if (unsafe_types->count (TYPE_UID (ftype)))
++    fprintf (dump_file, "is unsafe, ");
++  fprintf (dump_file, "\n");
++}
++
++/* Check if the function has variadic arguments.
++   It's corrected count_num_arguments ().  */
++
++static bool
++has_varargs (tree decl)
++{
++  tree t;
++  unsigned int num = 0;
++  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl));
++       t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t))
++    num++;
++  if (!t && num)
++    return true;
++  return false;
++}
++
++/* Join fs_map's sets for function type aliases.  */
++
++static void
++merge_fs_map_for_ftype_aliases ()
++{
++  if (dump_file)
++    fprintf (dump_file, "\n\nMerge decl sets for function type aliases:\n");
++  type_set processed_types;
++  for (type_decl_map::iterator it1 = fs_map->begin ();
++       it1 != fs_map->end (); ++it1)
++    {
++      if (processed_types.count (it1->first) != 0)
++	continue;
++      decl_set *d_set = it1->second;
++      tree type = (*type_uid_map)[it1->first];
++      type_set *set = (*fta_map)[it1->first];
++      for (type_set::const_iterator it2 = set->begin ();
++	   it2 != set->end (); it2++)
++	{
++	  tree t2 = (*type_uid_map)[*it2];
++	  processed_types.insert (*it2);
++	  if (type == t2)
++	    continue;
++	  gcc_assert ((TREE_CODE (type) == FUNCTION_TYPE
++		       || TREE_CODE (type) == METHOD_TYPE)
++		      && (TREE_CODE (t2) == FUNCTION_TYPE
++			  || TREE_CODE (t2) == METHOD_TYPE));
++	  if (fs_map->count (*it2) == 0 || (*fs_map)[*it2] == NULL)
++	    (*fs_map)[*it2] = d_set;
++	  else
++	    {
++	      decl_set *t2_decl_set = (*fs_map)[*it2];
++	      (*fs_map)[*it2] = d_set;
++	      gcc_assert (t2_decl_set && t2_decl_set->size() > 0);
++	      d_set->insert (t2_decl_set->begin (), t2_decl_set->end ());
++	      delete t2_decl_set;
++	    }
++	}
++    }
++}
++
++/* Dump function types with set of functions corresponding to it.  */
++
++static void
++dump_function_signature_sets ()
++{
++  fprintf (dump_file, "\n\nUnique sets of function signatures:\n");
++  std::set processed_sets;
++  for (type_decl_map::iterator it1 = fs_map->begin ();
++       it1 != fs_map->end (); ++it1)
++    {
++      decl_set *set = it1->second;
++      if (processed_sets.count (set) != 0)
++	continue;
++      processed_sets.insert (set);
++      fprintf (dump_file, "{ ");
++      print_type_set (it1->first, fta_map);
++      fprintf (dump_file, " : ");
++      for (decl_set::const_iterator it2 = set->begin ();
++	   it2 != set->end (); it2++)
++	{
++	  fprintf (dump_file, it2 == set->begin () ? "" : ", ");
++	  print_generic_expr (dump_file, *it2);
++	  fprintf (dump_file, "(%d)", DECL_UID (*it2));
++	}
++      fprintf (dump_file, "}\n");
++    }
++}
++
++/* Fill the map of function types to sets of function decls.  */
++
++static void
++collect_function_signatures ()
++{
++  if (dump_file)
++    fprintf (dump_file, "\n\nCollect function signatures:\n");
++  struct cgraph_node *n;
++  FOR_EACH_FUNCTION (n)
++    {
++      gcc_assert (n->decl && TREE_TYPE (n->decl));
++      tree ftype = TREE_TYPE (n->decl);
++      bool varargs = has_varargs (n->decl);
++      if (varargs && n->address_taken)
++	has_address_taken_functions_with_varargs = true;
++      if (dump_file)
++	dump_function_signature_info (n, ftype, varargs);
++      if (!n->address_taken)
++	continue;
++      /* TODO: make a separate pass at the end to remove canonicals.  */
++      tree ctype = TYPE_CANONICAL (ftype);
++      unsigned alias_type_fs = ctype ? TYPE_UID (ctype) : 0;
++      if (dump_file)
++	fprintf (dump_file, "canonical type: %d %ld\n",
++		 alias_type_fs, fs_map->count (alias_type_fs));
++      if (alias_type_fs)
++	{
++	  if (fs_map->count (TYPE_UID (ctype)) == 0)
++	    (*fs_map)[TYPE_UID (ctype)] = new decl_set ();
++	  if (dump_file)
++	    fprintf (dump_file, "insert decl (%d) to set of map [%d]\n",
++		     DECL_UID (n->decl), TYPE_UID (ctype));
++	  (*fs_map)[TYPE_UID (ctype)]->insert (n->decl);
++	}
++    }
++  merge_fs_map_for_ftype_aliases ();
++  if (dump_file)
++    dump_function_signature_sets ();
++}
++
++#define MAX_TARG_STAT 4
++struct icp_stats
++{
++  int npolymorphic;
++  int nspeculated;
++  int nsubst;
++  int ncold;
++  int nmultiple;
++  int noverwritable;
++  int nnotdefined;
++  int nexternal;
++  int nartificial;
++  int nremove;
++  int nicp;
++  int nspec;
++  int nf;
++  int ncalls;
++  int nindir;
++  int nind_only;
++  int ntargs[MAX_TARG_STAT + 1];
++};
++
++static void
++dump_processing_function (struct cgraph_node *n, struct icp_stats &stats)
++{
++  fprintf (dump_file, "\n\nProcesing function %s\n", n->dump_name ());
++  print_generic_expr (dump_file, n->decl);
++  fprintf (dump_file, "\n");
++  dump_type_with_uid ("Func's type: ", TREE_TYPE (n->decl));
++  if (dump_file && (dump_flags & TDF_STATS))
++    {
++      struct cgraph_edge *e;
++      stats.nf++;
++      for (e = n->indirect_calls; e; e = e->next_callee)
++	stats.nindir++;
++      for (e = n->callees; e; e = e->next_callee)
++	stats.ncalls++;
++      stats.ncalls += stats.nindir;
++      if (n->callers == NULL)
++	{
++	  fprintf (dump_file, "Function has NO callers\n");
++	  stats.nind_only++;
++	}
++    }
++}
++
++static void
++dump_indirect_call_site (tree call_fn, tree call_fn_ty)
++{
++  fprintf (dump_file, "Indirect call site: ");
++  print_generic_expr (dump_file, call_fn);
++  dump_type_with_uid ("\nFunction pointer type: ", call_fn_ty);
++}
++
++static void
++erase_from_unreachable (unsigned type_uid, type_set &unreachable)
++{
++  unreachable.erase (type_uid);
++  if (!fta_map->count (type_uid))
++    return;
++  type_set *set = (*fta_map)[type_uid];
++  for (type_set::const_iterator it = set->begin (); it != set->end (); it++)
++    unreachable.erase (*it);
++}
++
++static void
++dump_found_fdecls (decl_set *decls, unsigned ctype_uid)
++{
++  fprintf (dump_file, "Signature analysis FOUND decls (%d):", ctype_uid);
++  for (decl_set::const_iterator it = decls->begin (); it != decls->end (); it++)
++    {
++      print_generic_expr (dump_file, *it);
++      fprintf (dump_file, "(%d), ", DECL_UID (*it));
++    }
++  if (unsafe_types->count (ctype_uid))
++    fprintf (dump_file, "type is UNSAFE");
++  fprintf (dump_file, "\n");
++}
++
++static void
++count_found_targets (struct icp_stats &stats, unsigned size)
++{
++  gcc_assert (size > 0);
++  stats.ntargs[size > MAX_TARG_STAT ? MAX_TARG_STAT : size - 1]++;
++}
++
++/* Promote the indirect call.  */
++
++static void
++promote_call (struct cgraph_edge *e, struct cgraph_node *n,
++	      struct cgraph_node *likely_target, struct icp_stats *stats)
++{
++  if (dump_enabled_p ())
++    {
++      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, e->call_stmt,
++		       "promoting indirect call in %s to %s\n",
++		       n->dump_name (), likely_target->dump_name ());
++    }
++  if (!likely_target->can_be_discarded_p ())
++    {
++      symtab_node *sn = likely_target->noninterposable_alias ();
++      cgraph_node *alias = dyn_cast (sn);
++      if (alias)
++	likely_target = alias;
++    }
++  gimple *new_call;
++  if (flag_icp_speculatively)
++    {
++      e->make_speculative (likely_target, e->count.apply_scale (5, 10));
++      new_call = e->call_stmt;
++      stats->nspec++;
++    }
++  else
++    {
++      cgraph_edge *e2 = cgraph_edge::make_direct (e, likely_target);
++      new_call = cgraph_edge::redirect_call_stmt_to_callee (e2);
++      stats->nsubst++;
++    }
++  if (dump_file)
++    {
++      fprintf (dump_file, "The call is substituted by: ");
++      print_gimple_stmt (dump_file, new_call, 0);
++      fprintf (dump_file, "\n");
++    }
++}
++
++/* Find functions which are called only indirectly and if they are not in
++   fs_map, they can be removed.  For now it is used only to print stats.  */
++
++static int
++find_functions_can_be_removed (type_set &unreachable)
++{
++  int nremove = 0;
++  if (dump_file)
++    fprintf (dump_file, "\nRemove unused functions:\n");
++  struct cgraph_node *n;
++  FOR_EACH_FUNCTION (n)
++    {
++      gcc_assert (n->decl && TREE_TYPE (n->decl));
++      if (n->callers != NULL)
++	continue;
++      tree ftype = TREE_TYPE (n->decl);
++      tree ctype = TYPE_CANONICAL (ftype);
++      if (!ctype || !unreachable.count (TYPE_UID (ctype))
++	  || unsafe_types->count (TYPE_UID (ftype))
++	  || TREE_CODE (ftype) == METHOD_TYPE || n->callers != NULL
++	  || !n->definition || n->alias || n->thunk || n->clones)
++	continue;
++      if (dump_file)
++	fprintf (dump_file, "%s is not used\n", n->dump_name ());
++      nremove++;
++    }
++  return nremove;
++}
++
++static void
++dump_stats (struct icp_stats &st)
++{
++  fprintf (dump_file, "\nSTATS: %i candidates for indirect call promotion,"
++	   " %i substituted, %i speculatively promoted, %i cold\n"
++	   "%i have multiple targets, %i already speculated, %i external,"
++	   " %i not defined, %i artificial, %i polymorphic calls,"
++	   " %i overwritable\n", st.nicp, st.nsubst, st.nspec, st.ncold,
++	   st.nmultiple, st.nspeculated, st.nexternal, st.nnotdefined,
++	   st.nartificial, st.npolymorphic, st.noverwritable);
++  if (!(dump_flags & TDF_STATS))
++    return;
++  fprintf (dump_file, "EXTRA STATS: %i functions, %i indirect calls,"
++	   " %i total calls, %i called only indirectly, %i may be removed\n"
++	   "Indirect call sites with found targets ", st.nf, st.nindir,
++	   st.ncalls, st.nind_only, st.nremove);
++  for (unsigned i = 0; i < MAX_TARG_STAT; i++)
++    fprintf (dump_file, "%u:%i, ", i + 1, st.ntargs[i]);
++  fprintf (dump_file, "more:%i\n", st.ntargs[MAX_TARG_STAT]);
++}
++
++/* Optimize indirect calls.  When an indirect call has only one target,
++   promote it into a direct call.  */
++
++static bool
++optimize_indirect_calls ()
++{
++  /* TODO: maybe move to the top of ipa_icp.  */
++  if (has_address_taken_functions_with_varargs)
++    {
++      if (dump_file)
++	fprintf (dump_file, "\n\nAddress taken function with varargs is found."
++		 " Skip the optimization.\n");
++      return false;
++    }
++  struct icp_stats stats = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++			    0, 0, 0, 0, 0, {0, 0, 0, 0, 0}};
++  /* At first assume all function types are unreadchable.  */
++  type_set unreachable_ftypes;
++  if (dump_file && (dump_flags & TDF_STATS))
++    for (type_decl_map::iterator it = fs_map->begin ();
++	 it != fs_map->end (); ++it)
++      unreachable_ftypes.insert (it->first);
++
++  struct cgraph_node *n;
++  FOR_EACH_DEFINED_FUNCTION (n)
++    {
++      if (dump_file)
++	dump_processing_function (n, stats);
++      struct cgraph_edge *e;
++      bool update = false;
++      if (!opt_for_fn (n->decl, flag_icp) || !n->has_gimple_body_p ()
++	  || n->inlined_to || !n->indirect_calls)
++	{
++	  if (dump_file)
++	    fprintf (dump_file, "Skip the function\n");
++	  continue;
++	}
++      /* If the function has indirect calls which are not polymorphic,
++	 process its body, otherwise continue.  */
++      bool non_polymorphic_calls = false;
++      for (e = n->indirect_calls; e; e = e->next_callee)
++	if (!e->indirect_info->polymorphic)
++	  {
++	    non_polymorphic_calls = true;
++	    break;
++	  }
++      if (!non_polymorphic_calls)
++	{
++	  if (dump_file)
++	    fprintf (dump_file, "All indirect calls are polymorphic,"
++		     "skip...\n");
++	  continue;
++	}
++      /* Get the function body to operate with call statements.  */
++      n->get_body ();
++      /* Walk indirect call sites and apply the optimization.  */
++      cgraph_edge *next;
++      for (e = n->indirect_calls; e; e = next)
++	{
++	  next = e->next_callee;
++	  if (e->indirect_info->polymorphic)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Target is polymorphic, skip...\n\n");
++	      stats.npolymorphic++;
++	      continue;
++	    }
++	  stats.nicp++;
++	  struct cgraph_node *likely_target = NULL;
++	  gcall *stmt = e->call_stmt;
++	  gcc_assert (stmt != NULL);
++	  tree call_fn = gimple_call_fn (stmt);
++	  tree call_fn_ty = TREE_TYPE (call_fn);
++	  if (dump_file)
++	    dump_indirect_call_site (call_fn, call_fn_ty);
++	  tree decl = NULL_TREE;
++	  if (POINTER_TYPE_P (call_fn_ty))
++	    {
++	      if (dump_file)
++		dump_type_with_uid ("Pointee type: ", TREE_TYPE (call_fn_ty));
++	      if (dump_file && (dump_flags & TDF_STATS))
++		erase_from_unreachable (TYPE_UID (TREE_TYPE (call_fn_ty)),
++					unreachable_ftypes);
++	      /* Try to use the signature analysis results.  */
++	      tree ctype = TYPE_CANONICAL (TREE_TYPE (call_fn_ty));
++	      unsigned ctype_uid = ctype ? TYPE_UID (ctype) : 0;
++	      if (ctype_uid && fs_map->count (ctype_uid))
++		{
++		  if (dump_flags && (dump_flags & TDF_STATS))
++		    erase_from_unreachable (ctype_uid, unreachable_ftypes);
++		  decl_set *decls = (*fs_map)[ctype_uid];
++		  if (dump_file)
++		    dump_found_fdecls (decls, ctype_uid);
++		  /* TODO: optimize for multple targets.  */
++		  if (!unsafe_types->count (ctype_uid) && decls->size () == 1)
++		    {
++		      decl = *(decls->begin ());
++		      likely_target = cgraph_node::get (decl);
++		    }
++		  if (!unsafe_types->count (ctype_uid)
++		      && (dump_flags & TDF_STATS))
++		    count_found_targets (stats, decls->size ());
++		}
++	    }
++	  if (!decl || !likely_target)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Callee is unknown\n\n");
++	      continue;
++	    }
++	  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Callee is method\n\n");
++	      continue;
++	    }
++	  if (e->speculative)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Call is already speculated\n\n");
++	      stats.nspeculated++;
++	      continue;
++	    }
++	  if (!likely_target->definition)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Target is not a definition\n\n");
++	      stats.nnotdefined++;
++	      continue;
++	    }
++	  /* Do not introduce new references to external symbols.  While we
++	     can handle these just well, it is common for programs to
++	     incorrectly with headers defining methods they are linked
++	     with.  */
++	  if (DECL_EXTERNAL (likely_target->decl))
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Target is external\n\n");
++	      stats.nexternal++;
++	      continue;
++	    }
++	  /* Don't use an implicitly-declared destructor (c++/58678).  */
++	  struct cgraph_node *non_thunk_target
++	    = likely_target->function_symbol ();
++	  if (DECL_ARTIFICIAL (non_thunk_target->decl))
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Target is artificial\n\n");
++	      stats.nartificial++;
++	      continue;
++	    }
++	  if (likely_target->get_availability () <= AVAIL_INTERPOSABLE
++	      && likely_target->can_be_discarded_p ())
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Target is overwritable\n\n");
++	      stats.noverwritable++;
++	      continue;
++	    }
++	  else if (dbg_cnt (icp))
++	    {
++	      promote_call (e, n, likely_target, &stats);
++	      update = true;
++	    }
++	}
++      if (update)
++	ipa_update_overall_fn_summary (n);
++    }
++
++  if (dump_file && (dump_flags & TDF_STATS))
++    stats.nremove = find_functions_can_be_removed (unreachable_ftypes);
++
++  if (dump_file)
++    dump_stats (stats);
++  return stats.nsubst || stats.nspec;
++}
++
++/* Delete the given MAP with allocated sets.  One set may be associated with
++   more then one type/decl.  */
++
++template 
++static void
++remove_type_alias_map (MAP *map)
++{
++  std::set processed_sets;
++  for (typename MAP::iterator it = map->begin (); it != map->end (); it++)
++    {
++      typename MAP::mapped_type set = it->second;
++      if (processed_sets.count (set) != 0)
++	continue;
++      processed_sets.insert (set);
++      delete set;
++    }
++  delete map;
++}
++
++/* The ipa indirect call promotion pass. Run required analysis and optimize
++   indirect calls.
++   When indirect call has only one target, promote it into a direct call.  */
++
++static unsigned int
++ipa_icp (void)
++{
++  ta_map = new type_alias_map;
++  fta_map = new type_alias_map;
++  cbase_to_ptype = new type_alias_map;
++  fs_map = new type_decl_map;
++  ctype_map = new type_map;
++  unsafe_types = new type_set;
++  type_uid_map = new uid_to_type_map;
++
++  /* Find type aliases, fill the function signature map and
++     optimize indirect calls.  */
++  collect_function_type_aliases ();
++  collect_function_signatures ();
++  bool optimized = optimize_indirect_calls ();
++
++  remove_type_alias_map (ta_map);
++  remove_type_alias_map (fta_map);
++  remove_type_alias_map (cbase_to_ptype);
++  remove_type_alias_map (fs_map);
++  delete ctype_map;
++  delete unsafe_types;
++  delete type_uid_map;
++
++  return optimized ? TODO_remove_functions : 0;
++}
++
++namespace {
++
++const pass_data pass_data_ipa_icp =
++{
++  IPA_PASS, /* type */
++  "icp", /* name */
++  OPTGROUP_NONE, /* optinfo_flags */
++  TV_IPA_ICP, /* tv_id */
++  0, /* properties_required */
++  0, /* properties_provided */
++  0, /* properties_destroyed */
++  0, /* todo_flags_start */
++  0, /* todo_flags_finish */
++};
++
++class pass_ipa_icp : public ipa_opt_pass_d
++{
++public:
++  pass_ipa_icp (gcc::context *ctxt)
++    : ipa_opt_pass_d (pass_data_ipa_icp, ctxt,
++		      NULL, /* generate_summary */
++		      NULL, /* write_summary */
++		      NULL, /* read_summary */
++		      NULL, /* write_optimization_summary */
++		      NULL, /* read_optimization_summary */
++		      NULL, /* stmt_fixup */
++		      0, /* function_transform_todo_flags_start */
++		      NULL, /* function_transform */
++		      NULL) /* variable_transform */
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *)
++    {
++      return (optimize && flag_icp && !seen_error ()
++	      && (in_lto_p || flag_whole_program));
++    }
++
++  virtual unsigned int execute (function *) { return ipa_icp (); }
++
++}; // class pass_ipa_icp
++
++} // anon namespace
++
++ipa_opt_pass_d *
++make_pass_ipa_icp (gcc::context *ctxt)
++{
++  return new pass_ipa_icp (ctxt);
++}
+ 
+ #include "gt-ipa-devirt.h"
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 9692066e4..d6db9be6e 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -156,6 +156,7 @@ along with GCC; see the file COPYING3.  If not see
+   NEXT_PASS (pass_ipa_profile);
+   NEXT_PASS (pass_ipa_icf);
+   NEXT_PASS (pass_ipa_devirt);
++  NEXT_PASS (pass_ipa_icp);
+   NEXT_PASS (pass_ipa_cp);
+   NEXT_PASS (pass_ipa_sra);
+   NEXT_PASS (pass_ipa_cdtor_merge);
+diff --git a/gcc/testsuite/gcc.dg/icp1.c b/gcc/testsuite/gcc.dg/icp1.c
+new file mode 100644
+index 000000000..c2117f738
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp1.c
+@@ -0,0 +1,40 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp1.c.077i.icp" } */
++
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++
++ftype1 func1;
++
++struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++} my_str;
++
++int foo(int a) {
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++float bar(int a) {
++  my_str.myf2 = &bar;
++  func1 = &foo;
++  return foo(a);
++}
++
++int main() {
++  bar(1);
++  my_str.myf2(3);
++  return (my_str.myf1(2) + func1(4)) != 8;
++}
++
++/* { dg-final { scan-ipa-dump "The call is substituted by:.*= foo \\(4\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "The call is substituted by:.*= foo \\(2\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "The call is substituted by: bar \\(3\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "STATS: 3 candidates for indirect call promotion, 3 substituted, 0 speculatively promoted, 0 cold" "icp" } } */
+diff --git a/gcc/testsuite/gcc.dg/icp2.c b/gcc/testsuite/gcc.dg/icp2.c
+new file mode 100644
+index 000000000..03d31d407
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp2.c
+@@ -0,0 +1,38 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp2.c.077i.icp" } */
++
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++
++ftype1 func1;
++
++struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++} my_str;
++
++int foo(int a) {
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++float bar(int a) {
++  my_str.myf2 = dummy ? (ftype2) &foo : &bar;
++  func1 = (ftype1) &bar;
++  return foo(a);
++}
++
++int main() {
++  bar(1);
++  my_str.myf2(3);
++  return (my_str.myf1(2) + func1(4)) != 8;
++}
++
++/* { dg-final { scan-ipa-dump-not "The call is substituted by.*" "icp" } } */
++/* { dg-final { scan-ipa-dump "STATS: 3 candidates for indirect call promotion, 0 substituted, 0 speculatively promoted, 0 cold" "icp" } } */
+diff --git a/gcc/testsuite/gcc.dg/icp3.c b/gcc/testsuite/gcc.dg/icp3.c
+new file mode 100644
+index 000000000..2a7d1e6f5
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp3.c
+@@ -0,0 +1,52 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp3.c.077i.icp" } */
++
++#include 
++
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++typedef ftype1 (*ftype3) (ftype2);
++
++ftype1 func1;
++
++struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++ ftype3 myf3;
++} my_str;
++
++ftype1 boo(ftype2 a) {
++  printf ("Call boo\n");
++  return (ftype1) a;
++}
++
++int foo(int a) {
++  printf ("Call foo\n");
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++float bar(int a) {
++  printf("Call bar\n");
++  my_str.myf2 = (ftype2) my_str.myf3((ftype2) foo);
++  func1 = &foo;
++  return foo(a);
++}
++
++int main() {
++  my_str.myf3 = &boo;
++  bar(1);
++  my_str.myf2(3);
++  return (my_str.myf1(2) + func1(4)) != 8;
++}
++
++/* { dg-final { scan-ipa-dump "The call is substituted by:.*= foo \\(4\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "The call is substituted by:.*= foo \\(2\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "The call is substituted by: foo \\(3\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "STATS: 4 candidates for indirect call promotion, 3 substituted, 0 speculatively promoted, 0 cold" "icp" } } */
+diff --git a/gcc/testsuite/gcc.dg/icp4.c b/gcc/testsuite/gcc.dg/icp4.c
+new file mode 100644
+index 000000000..e3e1d5116
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp4.c
+@@ -0,0 +1,55 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp4.c.077i.icp" } */
++
++#include 
++
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++typedef ftype1 (*ftype3) (ftype2);
++
++ftype1 func1;
++ftype1 boo(ftype2 a);
++int foo(int a);
++float bar(int a);
++
++typedef struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++ ftype3 myf3;
++} T;
++
++T my_str = {0, (int*) &dummy, (ftype1) &boo, (ftype2) &foo, (ftype3) &bar};
++
++ftype1 boo(ftype2 a) {
++  printf ("Call boo\n");
++  return (ftype1) a;
++}
++
++int foo(int a) {
++  printf ("Call foo\n");
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++float bar(int a) {
++  printf("Call bar\n");
++  my_str.myf2 = (ftype2) my_str.myf3((ftype2) foo);
++  func1 = &foo;
++  return foo(a);
++}
++
++int main() {
++  my_str.myf3 = &boo;
++  bar(1);
++  my_str.myf2(3);
++  return (my_str.myf1(2) + func1(4)) != 8;
++}
++
++/* { dg-final { scan-ipa-dump-not "The call is substituted by.*" "icp" } } */
++/* { dg-final { scan-ipa-dump "STATS: 4 candidates for indirect call promotion, 0 substituted, 0 speculatively promoted, 0 cold" "icp" } } */
+diff --git a/gcc/testsuite/gcc.dg/icp5.c b/gcc/testsuite/gcc.dg/icp5.c
+new file mode 100644
+index 000000000..c7709243c
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp5.c
+@@ -0,0 +1,66 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp5.c.077i.icp" } */
++
++#include 
++
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++typedef ftype1 (*ftype3) (ftype2);
++
++ftype1 func1;
++ftype1 boo(ftype2 a);
++int foo(int a);
++float bar(int a);
++
++typedef struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++ ftype3 myf3;
++} T;
++
++T my_str;
++
++typedef struct {
++ int a;
++ int* b;
++ ftype3 myf1;
++ ftype2 myf2;
++ ftype1 myf3;
++} T1;
++
++T1 my1 = {0, &dummy, boo, &bar, &foo};
++
++ftype1 boo(ftype2 a) {
++  printf("Call boo\n");
++  return (ftype1) a;
++}
++
++int foo(int a) {
++  printf("Call foo\n");
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++float bar(int a) {
++  printf("Call bar\n");
++  my_str.myf2 = (ftype2) my_str.myf3((ftype2) foo);
++  func1 = &foo;
++  return foo(a);
++}
++
++int main() {
++  my_str = *(T*)&my1;
++  my_str.myf3 = &boo;
++  bar(1);
++  my_str.myf2(3);
++  return (my_str.myf1(2) + func1(4)) != 8;
++}
++
++/* { dg-final { scan-ipa-dump-not "The call is substituted by.*" "icp" } } */
++/* { dg-final { scan-ipa-dump "STATS: 4 candidates for indirect call promotion, 0 substituted, 0 speculatively promoted, 0 cold" "icp" } } */
+diff --git a/gcc/testsuite/gcc.dg/icp6.c b/gcc/testsuite/gcc.dg/icp6.c
+new file mode 100644
+index 000000000..5a9f15045
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp6.c
+@@ -0,0 +1,66 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp6.c.077i.icp -Wno-int-conversion -Wno-incompatible-pointer-types" } */
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++typedef int (*ftype3)();
++typedef int (*ftype4)(int a, int b);
++
++ftype1 func1;
++ftype4 func2;
++
++struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++ ftype3 myf3;
++} my_str;
++
++int foo3(float a) {
++  return dummy;
++}
++
++int foo4(int a, int b) {
++  return a*b;
++}
++
++int foo(int a) {
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++int foo2(float a) {
++ func1 = (ftype1) &foo;
++ func2 = &foo4;
++ return dummy + foo3 (a);
++}
++
++float bar2(int a) {
++  my_str.myf2 = (ftype2)(0x864213);
++  func2 = 0x65378;
++  return foo(a);
++}
++
++float bar(int a) {
++  my_str.myf3 = &foo2;
++  my_str.myf2 = &bar;
++  func1 = (ftype1) &dummy;
++  func2 = (ftype4) &bar2;
++  return foo(a);
++}
++
++int main() {
++  bar(1);
++  bar2(1);
++  bar(0);
++  my_str.myf2(3);
++  ((ftype1) my_str.myf3)(0.0);
++  int sum = func1(4);
++  return (sum + my_str.myf1(2) + func2(5, 6)) != 38;
++}
++/* { dg-final { scan-ipa-dump "The call is substituted by.*foo2 \\(0\\);" "icp" } } */
++/* { dg-final { scan-ipa-dump "STATS: 5 candidates for indirect call promotion, 1 substituted, 0 speculatively promoted, 0 cold" "icp" } } */
+diff --git a/gcc/testsuite/gcc.dg/icp7.c b/gcc/testsuite/gcc.dg/icp7.c
+new file mode 100644
+index 000000000..fa52197f4
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/icp7.c
+@@ -0,0 +1,48 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -flto -ficp -fdump-ipa-icp=./icp7.c.077i.icp" } */
++
++#include 
++
++int dummy = 0;
++
++typedef int (*ftype1)(int a);
++typedef float (*ftype2)(int a);
++
++ftype1 func1;
++
++struct {
++ int a;
++ int* b;
++ ftype1 myf1;
++ ftype2 myf2;
++} my_str;
++
++int boo(int a, ...) {
++  va_list ap;
++  va_start(ap, a);
++  if (a == 0)
++    dummy += va_arg(ap, int);
++  va_end(ap);
++  return dummy;
++}
++
++int foo(int a) {
++  my_str.myf1 = func1;
++  if (a % 2 == 0)
++    dummy += dummy % (dummy - a);
++  return a + 1;
++}
++
++float bar(int a) {
++  my_str.myf2 = &bar;
++  func1 = (ftype1) &boo;
++  return foo(a);
++}
++
++int main() {
++  bar(1);
++  my_str.myf2(3);
++  return (my_str.myf1(2) + func1(4));
++}
++
++/* { dg-final { scan-ipa-dump "Address taken function with varargs is found. Skip the optimization." "icp" } } */
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 98a5a490f..ca4156066 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -71,6 +71,7 @@ DEFTIMEVAR (TV_CGRAPHOPT             , "callgraph optimization")
+ DEFTIMEVAR (TV_CGRAPH_FUNC_EXPANSION , "callgraph functions expansion")
+ DEFTIMEVAR (TV_CGRAPH_IPA_PASSES     , "callgraph ipa passes")
+ DEFTIMEVAR (TV_IPA_ODR		     , "ipa ODR types")
++DEFTIMEVAR (TV_IPA_ICP               , "ipa indirect call promotion")
+ DEFTIMEVAR (TV_IPA_FNSUMMARY         , "ipa function summary")
+ DEFTIMEVAR (TV_IPA_UNREACHABLE       , "ipa dead code removal")
+ DEFTIMEVAR (TV_IPA_INHERITANCE       , "ipa inheritance graph")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 56898e019..5f09e4f8b 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -524,6 +524,7 @@ extern ipa_opt_pass_d *make_pass_ipa_cp (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_sra (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_icf (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt);
++extern ipa_opt_pass_d *make_pass_ipa_icp (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt);
+-- 
+2.33.0
+
diff --git a/0041-Port-fixes-in-icp-to-GCC-12.patch b/0041-Port-fixes-in-icp-to-GCC-12.patch
new file mode 100644
index 0000000..723f8b0
--- /dev/null
+++ b/0041-Port-fixes-in-icp-to-GCC-12.patch
@@ -0,0 +1,100 @@
+From aaa117a9ff58fb208e8c8859e075ca425f995f63 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Tue, 27 Feb 2024 07:43:57 +0800
+Subject: [PATCH 07/18] Port fixes in icp to GCC 12
+
+---
+ gcc/ipa-devirt.cc | 37 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 30 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
+index 383839189..318535d06 100644
+--- a/gcc/ipa-devirt.cc
++++ b/gcc/ipa-devirt.cc
+@@ -4431,6 +4431,11 @@ print_type_set(unsigned ftype_uid, type_alias_map *map)
+   if (!map->count (ftype_uid))
+     return;
+   type_set* s = (*map)[ftype_uid];
++  if (!s)
++    {
++      fprintf (dump_file, "%d (no set)", ftype_uid);
++      return;
++    }
+   for (type_set::const_iterator it = s->begin (); it != s->end (); it++)
+     fprintf (dump_file, it == s->begin () ? "%d" : ", %d", *it);
+ }
+@@ -4696,12 +4701,19 @@ maybe_register_aliases (tree type1, tree type2)
+       if (register_ailas_type (type1, type2, ta_map))
+ 	analyze_pointees (type1, type2);
+     }
++  unsigned type1_uid = TYPE_UID (type1);
++  unsigned type2_uid = TYPE_UID (type2);
++  if (type_uid_map->count (type1_uid) == 0)
++    (*type_uid_map)[type1_uid] = type1;
++  if (type_uid_map->count (type2_uid) == 0)
++    (*type_uid_map)[type2_uid] = type2;
++
+   /* If function and non-function type pointers alias,
+      the function type is unsafe.  */
+   if (FUNCTION_POINTER_TYPE_P (type1) && !FUNCTION_POINTER_TYPE_P (type2))
+-    unsafe_types->insert (TYPE_UID (type1));
++    unsafe_types->insert (type1_uid);
+   if (FUNCTION_POINTER_TYPE_P (type2) && !FUNCTION_POINTER_TYPE_P (type1))
+-    unsafe_types->insert (TYPE_UID (type2));
++    unsafe_types->insert (type2_uid);
+ 
+   /* Try to figure out with pointers to incomplete types.  */
+   if (POINTER_TYPE_P (type1) && POINTER_TYPE_P (type2))
+@@ -4825,10 +4837,12 @@ compare_block_and_init_type (tree block, tree t1)
+ static void
+ analyze_global_var (varpool_node *var)
+ {
+-  var->get_constructor();
+   tree decl = var->decl;
+-  if (TREE_CODE (decl) == SSA_NAME || !DECL_INITIAL (decl)
+-      || integer_zerop (DECL_INITIAL (decl)))
++  if (decl || !DECL_INITIAL (decl))
++    return;
++  var->get_constructor ();
++  if (TREE_CODE (decl) == SSA_NAME || integer_zerop (DECL_INITIAL (decl))
++      || TREE_CODE (DECL_INITIAL (decl)) == ERROR_MARK)
+     return;
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+@@ -4998,7 +5012,9 @@ analyze_assign_stmt (gimple *stmt)
+     {
+       rhs = TREE_OPERAND (rhs, 0);
+       if (VAR_OR_FUNCTION_DECL_P (rhs) || TREE_CODE (rhs) == STRING_CST
+-	  || TREE_CODE (rhs) == ARRAY_REF || TREE_CODE (rhs) == PARM_DECL)
++	  || TREE_CODE (rhs) == ARRAY_REF || TREE_CODE (rhs) == PARM_DECL
++	  || TREE_CODE (rhs) == LABEL_DECL || TREE_CODE (rhs) == CONST_DECL
++	  || TREE_CODE (rhs) == RESULT_DECL)
+ 	rhs_type = build_pointer_type (TREE_TYPE (rhs));
+       else if (TREE_CODE (rhs) == COMPONENT_REF)
+ 	{
+@@ -5012,7 +5028,12 @@ analyze_assign_stmt (gimple *stmt)
+ 	  gcc_assert (POINTER_TYPE_P (rhs_type));
+ 	}
+       else
+-	gcc_unreachable();
++	{
++	  fprintf (dump_file, "\nUnsupported rhs type %s in assign stmt: ",
++		   get_tree_code_name (TREE_CODE (rhs)));
++	  print_gimple_stmt (dump_file, stmt, 0);
++	  gcc_unreachable ();
++	}
+     }
+   else
+     rhs_type = TREE_TYPE (rhs);
+@@ -5710,6 +5731,8 @@ merge_fs_map_for_ftype_aliases ()
+       decl_set *d_set = it1->second;
+       tree type = (*type_uid_map)[it1->first];
+       type_set *set = (*fta_map)[it1->first];
++      if (!set)
++	continue;
+       for (type_set::const_iterator it2 = set->begin ();
+ 	   it2 != set->end (); it2++)
+ 	{
+-- 
+2.33.0
+
diff --git a/0042-Add-split-complex-instructions-pass.patch b/0042-Add-split-complex-instructions-pass.patch
new file mode 100644
index 0000000..b73affd
--- /dev/null
+++ b/0042-Add-split-complex-instructions-pass.patch
@@ -0,0 +1,1245 @@
+From 9a8e5716543972dec36bae1f9d380d27bfbcdae1 Mon Sep 17 00:00:00 2001
+From: Agrachev Andrey WX1228450 
+Date: Mon, 21 Aug 2023 12:35:19 +0300
+Subject: [PATCH 09/18] Add split-complex-instructions pass
+
+ - Add option -fsplit-ldp-stp
+ - Add functionality to detect and split depended from store LDP instructions.
+ - Add -param=param-ldp-dependency-search-range= to configure ldp dependency search range
+ - Add RTL tests
+
+Co-authored-by: Chernonog Vyacheslav 00812786 
+Co-authored-by: Zinin Ivan WX1305386 
+Co-authored-by: Gadzhiev Emin WX1195297 
+---
+ gcc/common.opt                                |   5 +
+ gcc/config/aarch64/aarch64.cc                 |  42 ++
+ gcc/doc/tm.texi                               |   8 +
+ gcc/doc/tm.texi.in                            |   4 +
+ gcc/params.opt                                |   3 +
+ gcc/passes.def                                |   1 +
+ gcc/sched-rgn.cc                              | 704 +++++++++++++++++-
+ gcc/target.def                                |  10 +
+ .../gcc.dg/rtl/aarch64/test-ldp-dont-split.c  |  74 ++
+ .../rtl/aarch64/test-ldp-split-rearrange.c    |  40 +
+ .../gcc.dg/rtl/aarch64/test-ldp-split.c       | 174 +++++
+ gcc/timevar.def                               |   1 +
+ gcc/tree-pass.h                               |   1 +
+ 13 files changed, 1066 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c
+ create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c
+ create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index a42bee250..c0e3f5687 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1797,6 +1797,11 @@ floop-nest-optimize
+ Common Var(flag_loop_nest_optimize) Optimization
+ Enable the loop nest optimizer.
+ 
++fsplit-ldp-stp
++Common Var(flag_split_ldp_stp) Optimization
++Split load/store pair instructions into separate load/store operations
++for better performance.
++
+ fstrict-volatile-bitfields
+ Common Var(flag_strict_volatile_bitfields) Init(-1) Optimization
+ Force bitfield accesses to match their type width.
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 04072ca25..48e2eded0 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -27507,6 +27507,48 @@ aarch64_run_selftests (void)
+ 
+ #endif /* #if CHECKING_P */
+ 
++/* TODO: refuse to use ranges intead of full list of an instruction codes.  */
++
++bool
++is_aarch64_ldp_insn (int icode)
++{
++  if ((icode >= CODE_FOR_load_pair_sw_sisi
++	  && icode <= CODE_FOR_load_pair_dw_tftf)
++      || (icode >= CODE_FOR_loadwb_pairsi_si
++	     && icode <= CODE_FOR_loadwb_pairtf_di)
++      || (icode >= CODE_FOR_load_pairv8qiv8qi
++	     && icode <= CODE_FOR_load_pairdfdf)
++      || (icode >= CODE_FOR_load_pairv16qiv16qi
++	     && icode <= CODE_FOR_load_pairv8bfv2df)
++      || (icode >= CODE_FOR_load_pair_lanesv8qi
++	     && icode <= CODE_FOR_load_pair_lanesdf))
++    return true;
++  return false;
++}
++
++bool
++is_aarch64_stp_insn (int icode)
++{
++  if ((icode >= CODE_FOR_store_pair_sw_sisi
++	  && icode <= CODE_FOR_store_pair_dw_tftf)
++      || (icode >= CODE_FOR_storewb_pairsi_si
++	     && icode <= CODE_FOR_storewb_pairtf_di)
++      || (icode >= CODE_FOR_vec_store_pairv8qiv8qi
++	     && icode <= CODE_FOR_vec_store_pairdfdf)
++      || (icode >= CODE_FOR_vec_store_pairv16qiv16qi
++	     && icode <= CODE_FOR_vec_store_pairv8bfv2df)
++      || (icode >= CODE_FOR_store_pair_lanesv8qi
++	     && icode <= CODE_FOR_store_pair_lanesdf))
++    return true;
++  return false;
++}
++
++#undef TARGET_IS_LDP_INSN
++#define TARGET_IS_LDP_INSN is_aarch64_ldp_insn
++
++#undef TARGET_IS_STP_INSN
++#define TARGET_IS_STP_INSN is_aarch64_stp_insn
++
+ #undef TARGET_STACK_PROTECT_GUARD
+ #define TARGET_STACK_PROTECT_GUARD aarch64_stack_protect_guard
+ 
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index c5006afc0..0c6415a9c 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -12113,6 +12113,14 @@ object files that are not referenced from @code{main} and uses export
+ lists.
+ @end defmac
+ 
++@deftypefn {Target Hook} bool TARGET_IS_LDP_INSN (int @var{icode})
++Return true if icode is corresponding to any of the LDP instruction types.
++@end deftypefn
++
++@deftypefn {Target Hook} bool TARGET_IS_STP_INSN (int @var{icode})
++Return true if icode is corresponding to any of the STP instruction types.
++@end deftypefn
++
+ @deftypefn {Target Hook} bool TARGET_CANNOT_MODIFY_JUMPS_P (void)
+ This target hook returns @code{true} past the point in which new jump
+ instructions could be created.  On machines that require a register for
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index f869ddd5e..6ff60e562 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -7977,6 +7977,10 @@ object files that are not referenced from @code{main} and uses export
+ lists.
+ @end defmac
+ 
++@hook TARGET_IS_LDP_INSN
++
++@hook TARGET_IS_STP_INSN
++
+ @hook TARGET_CANNOT_MODIFY_JUMPS_P
+ 
+ @hook TARGET_HAVE_CONDITIONAL_EXECUTION
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 7fcc2398d..6176d4790 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1217,4 +1217,7 @@ Enum(vrp_mode) String(ranger) Value(VRP_MODE_RANGER)
+ Common Joined UInteger Var(param_pointer_compression_size) Init(32) IntegerRange(8, 32) Param Optimization
+ Target size of compressed pointer, which should be 8, 16 or 32.
+ 
++-param=param-ldp-dependency-search-range=
++Common Joined UInteger Var(param_ldp_dependency_search_range) Init(16) IntegerRange(1, 32) Param Optimization
++Range for depended ldp search in split-ldp-stp path.
+ ; This comment is to ensure we retain the blank line above.
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 941bbadf0..a30e05688 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -514,6 +514,7 @@ along with GCC; see the file COPYING3.  If not see
+ 	  NEXT_PASS (pass_reorder_blocks);
+ 	  NEXT_PASS (pass_leaf_regs);
+ 	  NEXT_PASS (pass_split_before_sched2);
++	  NEXT_PASS (pass_split_complex_instructions);
+ 	  NEXT_PASS (pass_sched2);
+ 	  NEXT_PASS (pass_stack_regs);
+ 	  PUSH_INSERT_PASSES_WITHIN (pass_stack_regs)
+diff --git a/gcc/sched-rgn.cc b/gcc/sched-rgn.cc
+index a0dfdb788..b4df8bdc5 100644
+--- a/gcc/sched-rgn.cc
++++ b/gcc/sched-rgn.cc
+@@ -44,6 +44,8 @@ along with GCC; see the file COPYING3.  If not see
+    are actually scheduled.  */
+ 
+ #include "config.h"
++#define INCLUDE_SET
++#define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -65,6 +67,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "dbgcnt.h"
+ #include "pretty-print.h"
+ #include "print-rtl.h"
++#include "cfgrtl.h"
+ 
+ /* Disable warnings about quoting issues in the pp_xxx calls below
+    that (intentionally) don't follow GCC diagnostic conventions.  */
+@@ -3951,6 +3954,705 @@ make_pass_sched_fusion (gcc::context *ctxt)
+   return new pass_sched_fusion (ctxt);
+ }
+ 
++namespace {
++
++/* Def-use analisys special functions implementation.  */
++
++static struct df_link *
++get_defs (rtx_insn *insn, rtx reg)
++{
++  df_ref use;
++  struct df_link *ref_chain, *ref_link;
++
++  FOR_EACH_INSN_USE (use, insn)
++    {
++      if (GET_CODE (DF_REF_REG (use)) == SUBREG)
++	return NULL;
++      if (REGNO (DF_REF_REG (use)) == REGNO (reg))
++	break;
++    }
++
++  gcc_assert (use != NULL);
++
++  ref_chain = DF_REF_CHAIN (use);
++
++  for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
++    {
++      /* Problem getting some definition for this instruction.  */
++      if (ref_link->ref == NULL)
++	return NULL;
++      if (DF_REF_INSN_INFO (ref_link->ref) == NULL)
++	return NULL;
++      /* As global regs are assumed to be defined at each function call
++	  dataflow can report a call_insn as being a definition of REG.
++	  But we can't do anything with that in this pass so proceed only
++	  if the instruction really sets REG in a way that can be deduced
++	  from the RTL structure.  */
++      if (global_regs[REGNO (reg)]
++	  && !set_of (reg, DF_REF_INSN (ref_link->ref)))
++	return NULL;
++    }
++
++  return ref_chain;
++}
++
++static struct df_link *
++get_uses (rtx_insn *insn, rtx reg)
++{
++  df_ref def;
++  struct df_link *ref_chain, *ref_link;
++
++  FOR_EACH_INSN_DEF (def, insn)
++    if (REGNO (DF_REF_REG (def)) == REGNO (reg))
++      break;
++
++  gcc_assert (def != NULL && "Broken def-use analisys chain.");
++
++  ref_chain = DF_REF_CHAIN (def);
++
++  for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
++    {
++      /* Problem getting some use for this instruction.  */
++      if (ref_link->ref == NULL)
++	return NULL;
++    }
++
++  return ref_chain;
++}
++
++const pass_data pass_data_split_complex_instructions = {
++  RTL_PASS,			     /* Type.  */
++  "split_complex_instructions",	     /* Name.  */
++  OPTGROUP_NONE,		     /* Optinfo_flags.  */
++  TV_SPLIT_CMP_INS,		     /* Tv_id.  */
++  0,				     /* Properties_required.  */
++  0,				     /* Properties_provided.  */
++  0,				     /* Properties_destroyed.  */
++  0,				     /* Todo_flags_start.  */
++  (TODO_df_verify | TODO_df_finish), /* Todo_flags_finish.  */
++};
++
++class pass_split_complex_instructions : public rtl_opt_pass
++{
++private:
++  enum complex_instructions_t
++  {
++    UNDEFINED,
++    LDP,
++    LDP_TI,
++    STP,
++    STR
++  };
++
++  void split_complex_insn (rtx_insn *insn);
++  void split_ldp_ti (rtx_insn *insn);
++  void split_ldp_with_offset (rtx_insn *ldp_insn);
++  void split_simple_ldp (rtx_insn *ldp_insn);
++  void split_ldp_stp (rtx_insn *insn);
++  complex_instructions_t get_insn_type (rtx_insn *insn);
++
++  basic_block bb;
++  rtx_insn *insn;
++  std::set dependent_stores_candidates;
++  std::set ldp_to_split_list;
++
++  complex_instructions_t complex_insn_type = UNDEFINED;
++  bool is_store_insn (rtx_insn *insn);
++  bool is_ldp_dependent_on_store (rtx_insn *ldp_insn, basic_block bb);
++  bool bfs_for_reg_dependent_store (rtx_insn *ldp_insn, basic_block search_bb,
++				    rtx_insn *search_insn,
++				    int search_range
++				    = param_ldp_dependency_search_range);
++  bool is_store_reg_dependent (rtx_insn *ldp_insn, rtx_insn *str_insn);
++  void init_df ();
++  void find_dependent_stores_candidates (rtx_insn *ldp_insn);
++  int get_insn_offset (rtx_insn *insn, complex_instructions_t insn_type,
++		       int *arith_operation_ptr = NULL);
++
++public:
++  pass_split_complex_instructions (gcc::context *ctxt)
++      : rtl_opt_pass (pass_data_split_complex_instructions, ctxt)
++  {
++  }
++  /* opt_pass methods: */
++  virtual bool gate (function *);
++
++  virtual unsigned int
++  execute (function *)
++  {
++    enum rtx_code ldp_memref_code;
++    init_df ();
++    ldp_to_split_list.clear ();
++    FOR_EACH_BB_FN (bb, cfun)
++      {
++	FOR_BB_INSNS (bb, insn)
++	  {
++	    complex_instructions_t insn_type = get_insn_type (insn);
++	    /* TODO: Add splitting of STP instructions.  */
++	    if (insn_type != LDP && insn_type != LDP_TI)
++	      continue;
++	    /* TODO: Currently support only ldp_ti and ldp with REG or
++	       PLUS/MINUS offset expression.  */
++	    if (insn_type == LDP_TI)
++	      {
++		ldp_memref_code = GET_CODE (XEXP (XEXP (PATTERN (insn), 1),
++						  0));
++		if (ldp_memref_code != REG && ldp_memref_code != PLUS
++		    && ldp_memref_code != MINUS)
++		  continue;
++	      }
++	    if (is_ldp_dependent_on_store (insn, bb))
++	      {
++		ldp_to_split_list.insert (insn);
++	      }
++	  }
++      }
++
++    for (std::set::iterator i = ldp_to_split_list.begin ();
++	 i != ldp_to_split_list.end (); ++i)
++      split_complex_insn (*i);
++
++    return 0;
++  }
++}; // class pass_split_complex_instructions
++
++bool
++pass_split_complex_instructions::is_ldp_dependent_on_store (rtx_insn *ldp_insn,
++							    basic_block bb)
++{
++  find_dependent_stores_candidates (ldp_insn);
++  return bfs_for_reg_dependent_store (ldp_insn, bb, ldp_insn);
++}
++
++bool
++pass_split_complex_instructions::bfs_for_reg_dependent_store (
++    rtx_insn *ldp_insn, basic_block search_bb, rtx_insn *search_insn,
++    int search_range)
++{
++  rtx_insn *current_search_insn = search_insn;
++
++  for (int i = search_range; i > 0; --i)
++    {
++      if (!current_search_insn)
++	return false;
++      bool checking_result
++	  = is_store_reg_dependent (ldp_insn, current_search_insn);
++      if (checking_result)
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "LDP to split:\n");
++	      print_rtl_single (dump_file, ldp_insn);
++	      fprintf (dump_file, "Found STR:\n");
++	      print_rtl_single (dump_file, current_search_insn);
++	    }
++	  return true;
++	}
++      if (current_search_insn == BB_HEAD (search_bb))
++	{
++	  /* Search in all parent BBs for the reg_dependent store.  */
++	  edge_iterator ei;
++	  edge e;
++
++	  FOR_EACH_EDGE (e, ei, search_bb->preds)
++	    if (e->src->index != 0
++		&& bfs_for_reg_dependent_store (ldp_insn, e->src,
++						BB_END (e->src), i - 1))
++	      return true;
++	  return false;
++	}
++      else
++	{
++	  if (!active_insn_p (current_search_insn))
++	    i++;
++	  current_search_insn = PREV_INSN (current_search_insn);
++	}
++    }
++  return false;
++}
++
++void
++pass_split_complex_instructions::init_df ()
++{
++  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
++  df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
++  df_mir_add_problem ();
++  df_live_add_problem ();
++  df_live_set_all_dirty ();
++  df_analyze ();
++  df_set_flags (DF_DEFER_INSN_RESCAN);
++}
++
++void
++pass_split_complex_instructions::find_dependent_stores_candidates (
++    rtx_insn *ldp_insn)
++{
++  dependent_stores_candidates.clear ();
++  df_ref use;
++
++  FOR_EACH_INSN_USE (use, ldp_insn)
++    {
++      df_link *defs = get_defs (ldp_insn, DF_REF_REG (use));
++      if (!defs)
++	return;
++
++      for (df_link *def = defs; def; def = def->next)
++	{
++	  df_link *uses
++	      = get_uses (DF_REF_INSN (def->ref), DF_REF_REG (def->ref));
++	  if (!uses)
++	    continue;
++
++	  for (df_link *use = uses; use; use = use->next)
++	    {
++	      if (DF_REF_CLASS (use->ref) == DF_REF_REGULAR
++		  && is_store_insn (DF_REF_INSN (use->ref)))
++		dependent_stores_candidates.insert (DF_REF_INSN (use->ref));
++	    }
++	}
++    }
++}
++
++bool
++pass_split_complex_instructions::is_store_reg_dependent (rtx_insn *ldp_insn,
++							 rtx_insn *str_insn)
++{
++  if (!is_store_insn (str_insn)
++      || dependent_stores_candidates.find (str_insn)
++	     == dependent_stores_candidates.end ())
++    return false;
++
++  int ldp_offset_sign = UNDEFINED;
++  int ldp_offset
++      = get_insn_offset (ldp_insn, get_insn_type (ldp_insn), &ldp_offset_sign);
++  if (ldp_offset_sign == MINUS)
++    ldp_offset = -ldp_offset;
++
++  int str_offset_sign = UNDEFINED;
++  int str_offset = get_insn_offset (str_insn, STR, &str_offset_sign);
++  if (str_offset_sign == MINUS)
++    str_offset = -str_offset;
++
++  if (str_offset == ldp_offset || str_offset == ldp_offset + 8)
++    return true;
++
++  return false;
++}
++
++bool
++pass_split_complex_instructions::is_store_insn (rtx_insn *insn)
++{
++  if (!insn)
++    return false;
++  rtx sset_b = single_set (insn);
++  /* TODO: The condition below allow to take only store instructions in which
++     the memory location's operand is either a register (base) or an plus/minus
++     operation (base + #imm). So it might make sense to add support for other
++     cases (e.g. multiply and shift).  */
++  if (sset_b && MEM_P (SET_DEST (sset_b))
++      && GET_MODE (XEXP (sset_b, 0)) != BLKmode
++      && (GET_CODE (XEXP (XEXP (sset_b, 0), 0)) == REG
++	  || (GET_CODE (XEXP (XEXP (sset_b, 0), 0)) == PLUS
++	      || GET_CODE (XEXP (XEXP (sset_b, 0), 0)) == MINUS)
++	  && (GET_CODE (XEXP (XEXP (XEXP (sset_b, 0), 0), 1)) == CONST_INT)))
++    return true;
++
++  return false;
++}
++
++int
++pass_split_complex_instructions::get_insn_offset (
++    rtx_insn *insn, complex_instructions_t insn_type, int *arith_operation_ptr)
++{
++  rtx insn_pat = PATTERN (insn);
++  int returned_offset = 0;
++
++  rtx offset_expr = NULL;
++  rtx offset_value_expr = NULL;
++
++  switch (insn_type)
++    {
++    case LDP:
++      {
++	int number_of_sub_insns = XVECLEN (insn_pat, 0);
++
++	/* Calculate it's own ofsset of first load insn.  */
++	rtx_insn *first_load_insn = NULL;
++	if (number_of_sub_insns == 2)
++	  {
++	    first_load_insn
++		= make_insn_raw (copy_rtx (XVECEXP (insn_pat, 0, 0)));
++	    arith_operation_ptr = NULL;
++
++	    offset_expr = XEXP (XEXP (PATTERN (first_load_insn), 1), 0);
++	    if (GET_CODE (offset_expr) == PLUS
++		|| GET_CODE (offset_expr) == MINUS)
++	      offset_value_expr
++		  = XEXP (XEXP (XEXP (PATTERN (first_load_insn), 1), 0), 1);
++	    else
++	      offset_expr = NULL;
++	  }
++	else if (number_of_sub_insns == 3)
++	  {
++	    rtx_insn *offset_sub_insn
++		= make_insn_raw (copy_rtx (XVECEXP (insn_pat, 0, 0)));
++
++	    offset_expr = XEXP (PATTERN (offset_sub_insn), 1);
++	    offset_value_expr = XEXP (XEXP (PATTERN (offset_sub_insn), 1), 1);
++	  }
++	else
++	  {
++	    gcc_assert (false
++			&& "Wrong number of elements in the ldp_insn vector");
++	  }
++	break;
++      }
++    case LDP_TI:
++      {
++	offset_expr = XEXP (XEXP (insn_pat, 1), 0);
++	if (GET_CODE (offset_expr) != PLUS && GET_CODE (offset_expr) != MINUS)
++	  return 0;
++	offset_value_expr = XEXP (XEXP (XEXP (insn_pat, 1), 0), 1);
++	break;
++      }
++    case STR:
++      {
++	offset_expr = XEXP (XEXP (insn_pat, 0), 0);
++	/* If memory location is specified by single base register then the
++	   offset is zero.  */
++	if (GET_CODE (offset_expr) == REG)
++	  return 0;
++	offset_value_expr = XEXP (XEXP (XEXP (insn_pat, 0), 0), 1);
++	break;
++      }
++    default:
++      {
++	if (dumps_are_enabled && dump_file)
++	  {
++	    fprintf (dump_file, "Instruction that was tried to split:\n");
++	    print_rtl_single (dump_file, insn);
++	  }
++	gcc_assert (false && "Unsupported instruction type");
++	break;
++      }
++    }
++
++  if (offset_expr != NULL && offset_value_expr
++      && GET_CODE (offset_value_expr) == CONST_INT)
++    returned_offset = XINT (offset_value_expr, 0);
++
++  if (arith_operation_ptr != NULL)
++    {
++      *arith_operation_ptr = GET_CODE (offset_expr);
++      gcc_assert ((*arith_operation_ptr == MINUS
++		   || *arith_operation_ptr == PLUS)
++		  && "Unexpected arithmetic operation in the offset expr");
++    }
++
++  return returned_offset;
++}
++
++void
++pass_split_complex_instructions::split_simple_ldp (rtx_insn *ldp_insn)
++{
++  rtx pat = PATTERN (ldp_insn);
++
++  rtx_insn *mem_insn_1 = make_insn_raw (copy_rtx (XVECEXP (pat, 0, 0)));
++  rtx_insn *mem_insn_2 = make_insn_raw (copy_rtx (XVECEXP (pat, 0, 1)));
++
++  int dest_regno = REGNO (SET_DEST (PATTERN (mem_insn_1)));
++  int src_regno;
++
++  rtx srs_reg_insn = XEXP (SET_SRC (PATTERN (mem_insn_1)), 0);
++
++  if (GET_CODE (srs_reg_insn) == REG)
++    src_regno = REGNO (srs_reg_insn);
++  else
++    src_regno = REGNO (XEXP (srs_reg_insn, 0));
++
++  rtx_insn *emited_insn_1, *emited_insn_2;
++
++  /* in cases like ldp r1,r2,[r1] we emit ldr r2,[r1] first.  */
++  if (src_regno == dest_regno)
++    std::swap (mem_insn_1, mem_insn_2);
++
++  emited_insn_1 = emit_insn (PATTERN (mem_insn_1));
++  emited_insn_2 = emit_insn (PATTERN (mem_insn_2));
++
++  int sub_insn_1_code = recog (PATTERN (mem_insn_1), mem_insn_1, 0);
++  int sub_insn_2_code = recog (PATTERN (mem_insn_2), mem_insn_2, 0);
++
++  INSN_CODE (emited_insn_1) = sub_insn_1_code;
++  INSN_CODE (emited_insn_2) = sub_insn_2_code;
++}
++
++void
++pass_split_complex_instructions::split_ldp_with_offset (rtx_insn *ldp_insn)
++{
++  rtx pat = PATTERN (ldp_insn);
++  bool post_index = true;
++
++  rtx_insn offset_insn;
++  rtx_insn mem_insn_1;
++  rtx_insn mem_insn_2;
++
++  int offset_insn_code;
++  int mem_insn_1_code = -1;
++  int mem_insn_2_code = -1;
++
++  int offset = 0;
++  int arith_operation = UNDEFINED;
++
++  for (int i = 0; i < 3; i++)
++    {
++      rtx sub_insn = XVECEXP (pat, 0, i);
++      rtx_insn *copy_of_sub_insn = make_insn_raw (copy_rtx (sub_insn));
++      int sub_insn_code
++	  = recog (PATTERN (copy_of_sub_insn), copy_of_sub_insn, 0);
++
++      /* If sub_insn is offset related.  */
++      if (GET_RTX_CLASS (sub_insn_code) == RTX_UNARY)
++	{
++	  offset_insn = *copy_of_sub_insn;
++	  offset_insn_code = sub_insn_code;
++	  gcc_assert (i == 0
++		      && "Offset related insn must be the first "
++			 "element of a parallel insn vector");
++
++	  offset = get_insn_offset (ldp_insn, LDP, &arith_operation);
++	}
++      else
++	{
++	  if (GET_CODE (XEXP (PATTERN (copy_of_sub_insn), 0)) != REG)
++	    {
++	      rtx &offset_expr
++		  = XEXP (XEXP (XEXP (PATTERN (copy_of_sub_insn), 0), 0), 1);
++	      if (GET_CODE (offset_expr) == CONST_INT)
++		{
++		  int local_offset = XINT (offset_expr, 0);
++		  offset = (arith_operation == PLUS ? offset : -offset);
++
++		  offset_expr = GEN_INT (local_offset + offset);
++
++		  gcc_assert (
++		      (arith_operation == MINUS || arith_operation == PLUS)
++		      && "Unexpected arithmetic operation in offset related "
++			 "sub_insn");
++
++		  if (i == 1)
++		    post_index = false;
++		}
++	      else
++		{
++		  post_index = true;
++		}
++	    }
++	}
++      if (i == 1)
++	{
++	  mem_insn_1 = *copy_of_sub_insn;
++	  mem_insn_1_code = sub_insn_code;
++	}
++      if (i == 2)
++	{
++	  mem_insn_2 = *copy_of_sub_insn;
++	  mem_insn_2_code = sub_insn_code;
++	}
++    }
++  gcc_assert (mem_insn_1_code != -1 && mem_insn_2_code != -1
++	      && "Uninitialized memory insns");
++
++  int dest_regno = REGNO (SET_DEST (PATTERN (&mem_insn_1)));
++  int src_regno;
++
++  rtx srs_reg_insn = XEXP (SET_SRC (PATTERN (&mem_insn_1)), 0);
++
++  if (GET_CODE (srs_reg_insn) == REG)
++    src_regno = REGNO (srs_reg_insn);
++  else
++    src_regno = REGNO (XEXP (srs_reg_insn, 0));
++
++  /* Don't split such weird LDP.  */
++  if (src_regno == dest_regno)
++    return;
++
++  rtx_insn *emited_offset_insn;
++  if (!post_index)
++    {
++      emited_offset_insn = emit_insn (PATTERN (&offset_insn));
++      INSN_CODE (emited_offset_insn) = offset_insn_code;
++    }
++
++  rtx_insn *emited_insn_1 = emit_insn (PATTERN (&mem_insn_1));
++  rtx_insn *emited_insn_2 = emit_insn (PATTERN (&mem_insn_2));
++
++
++  INSN_CODE (emited_insn_1) = mem_insn_1_code;
++  INSN_CODE (emited_insn_2) = mem_insn_2_code;
++
++  if (post_index)
++    {
++      emited_offset_insn = emit_insn (PATTERN (&offset_insn));
++      INSN_CODE (emited_offset_insn) = offset_insn_code;
++    }
++}
++
++void
++pass_split_complex_instructions::split_ldp_stp (rtx_insn *insn)
++{
++  rtx_insn *prev_insn = PREV_INSN (insn);
++  int number_of_sub_insns = XVECLEN (PATTERN (insn), 0);
++
++  start_sequence ();
++
++  if (number_of_sub_insns == 2)
++    split_simple_ldp (insn);
++  else if (number_of_sub_insns == 3)
++    split_ldp_with_offset (insn);
++  else
++    gcc_assert (false && "Broken complex insn vector");
++
++  rtx_insn *seq = get_insns ();
++  unshare_all_rtl_in_chain (seq);
++  end_sequence ();
++
++  emit_insn_after_setloc (seq, prev_insn, INSN_LOCATION (insn));
++  delete_insn_and_edges (insn);
++}
++
++void
++pass_split_complex_instructions::split_ldp_ti (rtx_insn *insn)
++{
++  rtx_insn *prev_insn = PREV_INSN (insn);
++  rtx_insn *load_insn_1 = make_insn_raw (copy_rtx (PATTERN (insn)));
++  rtx_insn *load_insn_2 = make_insn_raw (copy_rtx (PATTERN (insn)));
++
++  rtx reg_insn_1 = XEXP (PATTERN (load_insn_1), 0);
++  rtx mem_insn_1 = XEXP (PATTERN (load_insn_1), 1);
++  rtx mem_insn_2 = XEXP (PATTERN (load_insn_2), 1);
++
++  PUT_MODE (mem_insn_1, DImode);
++  PUT_MODE (mem_insn_2, DImode);
++
++  int reg_no_1 = REGNO (reg_insn_1);
++
++  XEXP (PATTERN (load_insn_1), 0) = gen_rtx_REG (DImode, reg_no_1);
++  XEXP (PATTERN (load_insn_2), 0) = gen_rtx_REG (DImode, reg_no_1 + 1);
++
++  rtx load_insn_2_plus_expr = XEXP (XEXP (PATTERN (load_insn_2), 1), 0);
++  if (GET_CODE (load_insn_2_plus_expr) == REG)
++    {
++	XEXP (XEXP (PATTERN (load_insn_2), 1), 0)
++	  = gen_rtx_PLUS (DImode,
++			  gen_rtx_REG (DImode, REGNO (load_insn_2_plus_expr)),
++			  GEN_INT (GET_MODE_SIZE (DImode)));
++    }
++  else
++    {
++      rtx load_insn_2_offset_expr
++      = XEXP (XEXP (XEXP (PATTERN (load_insn_2), 1), 0), 1);
++
++      if (load_insn_2_offset_expr == NULL)
++	return;
++
++      if (GET_CODE (load_insn_2_offset_expr) == CONST_INT)
++	{
++	  int load_insn_2_offset = XINT (load_insn_2_offset_expr, 0);
++	  XEXP (XEXP (XEXP (PATTERN (load_insn_2), 1), 0), 1)
++	    = GEN_INT (load_insn_2_offset + GET_MODE_SIZE (DImode));
++	}
++    }
++
++  start_sequence ();
++
++  int src_regno;
++  rtx srs_reg_insn = XEXP (XEXP (PATTERN (load_insn_1), 1), 0);
++
++  if (GET_CODE (srs_reg_insn) == REG)
++    src_regno = REGNO (srs_reg_insn);
++  else
++    src_regno = REGNO (XEXP (srs_reg_insn, 0));
++
++  /* in cases like ldp r1,r2,[r1] we emit ldr r2,[r1] first.  */
++  if (src_regno == reg_no_1)
++    std::swap (load_insn_1, load_insn_2);
++
++  rtx_insn *emited_load_insn_1 = emit_insn (PATTERN (load_insn_1));
++  rtx_insn *emited_load_insn_2 = emit_insn (PATTERN (load_insn_2));
++
++  INSN_CODE (emited_load_insn_1)
++      = recog (PATTERN (emited_load_insn_1), emited_load_insn_1, 0);
++  INSN_CODE (emited_load_insn_2)
++      = recog (PATTERN (emited_load_insn_2), emited_load_insn_2, 0);
++
++  rtx_insn *seq = get_insns ();
++  unshare_all_rtl_in_chain (seq);
++  end_sequence ();
++
++  emit_insn_after_setloc (seq, prev_insn, INSN_LOCATION (insn));
++  delete_insn_and_edges (insn);
++}
++
++void
++pass_split_complex_instructions::split_complex_insn (rtx_insn *insn)
++{
++  complex_instructions_t insn_type = get_insn_type (insn);
++  /* TODO: Add splitting of STP instructions.  */
++  if (insn_type == LDP || insn_type == STP)
++    split_ldp_stp (insn);
++  else if (insn_type == LDP_TI)
++    split_ldp_ti (insn);
++  else
++    gcc_assert (false && "Unsupported type of insn to split");
++}
++
++pass_split_complex_instructions::complex_instructions_t
++pass_split_complex_instructions::get_insn_type (rtx_insn *insn)
++{
++  if (!INSN_P (insn))
++    return UNDEFINED;
++
++  rtx pat = PATTERN (insn);
++  int icode = recog (PATTERN (insn), insn, NULL);
++
++  if (GET_CODE (pat) == PARALLEL)
++    {
++      if (targetm.is_ldp_insn (icode))
++	{
++	  return LDP;
++	}
++      if (targetm.is_stp_insn (icode))
++	{
++	  return STP;
++	}
++      else
++	{
++	  return UNDEFINED;
++	}
++    }
++  rtx set_insn = single_set (insn);
++  if (set_insn && GET_CODE (XEXP (set_insn, 1)) == MEM
++      && GET_MODE (XEXP (set_insn, 1)) == E_TImode)
++    return LDP_TI;
++
++  return UNDEFINED;
++}
++
++bool
++pass_split_complex_instructions::gate (function *)
++{
++  return targetm.is_ldp_insn && targetm.is_stp_insn && optimize > 0
++	 && flag_split_ldp_stp > 0;
++}
++
++} // anon namespace
++
++rtl_opt_pass *
++make_pass_split_complex_instructions (gcc::context *ctxt)
++{
++  return new pass_split_complex_instructions (ctxt);
++}
++
+ #if __GNUC__ >= 10
+ #  pragma GCC diagnostic pop
+-#endif
++#endif
+\ No newline at end of file
+diff --git a/gcc/target.def b/gcc/target.def
+index d85adf36a..a3a50b474 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -2677,6 +2677,16 @@ modes and they have different conditional execution capability, such as ARM.",
+  bool, (void),
+  default_have_conditional_execution)
+ 
++DEFHOOK
++(is_ldp_insn,
++  "Return true if icode is corresponding to any of the LDP instruction types.",
++  bool, (int icode), NULL)
++
++DEFHOOK
++(is_stp_insn,
++  "Return true if icode is corresponding to any of the STP instruction types.",
++  bool, (int icode), NULL)
++
+ DEFHOOK
+ (gen_ccmp_first,
+  "This function prepares to emit a comparison insn for the first compare in a\n\
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c
+new file mode 100644
+index 000000000..3918d43f6
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c
+@@ -0,0 +1,74 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-additional-options "-fsplit-ldp-stp" } */
++/*
++ *    Tests are:
++ *          Patterns where LDP insns should NOT be split
++ *                       */
++
++int __RTL (startwith ("split_complex_instructions"))
++simple_ldp_after_store ()
++{
++(function "simple_ldp_after_store"
++  (insn-chain
++    (block 2
++      (edge-from entry (flags "FALLTHRU"))
++      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 228 (set (reg/i:DI sp) 
++                   (reg/i:DI x0)))
++      (cinsn 101 (set (mem/c:DI
++                        (plus:DI (reg/f:DI sp)
++                          (const_int 32))[1 S4 A32])(reg:DI x0)))
++      (cinsn 10 (parallel [
++        (set (reg:DI x29)
++          (mem:DI (plus:DI (reg/f:DI sp) (const_int 8)) [1 S4 A32]))
++        (set (reg:DI x30)
++          (mem:DI (plus:DI (reg/f:DI sp)
++            (const_int 16)) [1 S4 A32]))]))
++      (cinsn 11 (use (reg/i:DI sp)))
++      (cinsn 12 (use (reg/i:DI cc)))
++      (cinsn 13 (use (reg/i:DI x29)))
++      (cinsn 14 (use (reg/i:DI x30)))
++      (cinsn 15 (use (reg/i:DI x0)))
++      (edge-to exit (flags "FALLTHRU"))
++    ) ;; block 2
++  ) ;; insn-chain
++) ;; function "simple_ldp_after_store"
++}
++
++int __RTL (startwith ("split_complex_instructions"))
++ldp_after_store_in_different_bb ()
++{
++(function "ldp_after_store_in_different_bb"
++  (insn-chain
++    (block 2
++      (edge-from entry (flags "FALLTHRU"))
++      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 228 (set (reg/i:DI sp) 
++                   (reg/i:DI x0)))
++      (cinsn 101 (set (mem/c:DI
++                        (plus:DI (reg/f:DI sp)
++                          (const_int 32))[1 S4 A32])(reg:DI x0)))
++      (edge-to 3 (flags "FALLTHRU"))
++    ) ;; block 2
++    (block 3
++      (edge-from 2 (flags "FALLTHRU"))
++      (cnote 4 [bb 3] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 10 (parallel [
++        (set (reg:DI x29)
++          (mem:DI (plus:DI (reg/f:DI sp) (const_int 8)) [1 S4 A32]))
++        (set (reg:DI x30)
++          (mem:DI (plus:DI (reg/f:DI sp)
++            (const_int 16)) [1 S4 A32]))]))
++      (cinsn 11 (use (reg/i:DI sp)))
++      (cinsn 12 (use (reg/i:DI cc)))
++      (cinsn 13 (use (reg/i:DI x29)))
++      (cinsn 14 (use (reg/i:DI x30)))
++      (cinsn 15 (use (reg/i:DI x0)))
++      (edge-to exit (flags "FALLTHRU"))
++    ) ;; block 3
++  ) ;; insn-chain
++) ;; function "ldp_after_store_in_different_bb"
++}
++
++/* Verify that the output code contains exactly 2 ldp.  */
++/* { dg-final { scan-assembler-times {ldp\t} 2 } }  */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c
+new file mode 100644
+index 000000000..653c30f83
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c
+@@ -0,0 +1,40 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-additional-options "-fsplit-ldp-stp" } */
++/*
++ *    Test is:
++ *        Pattern where LDP insns should be split with rearrangement in order
++ *        to deal with data dependecy betwen subinstruction.  
++ *                                                                          */
++
++int __RTL (startwith ("split_complex_instructions"))
++simple_ldp_after_store ()
++{
++(function "ldp_equal_registers"
++  (insn-chain
++    (block 2
++      (edge-from entry (flags "FALLTHRU"))
++      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 228 (set (reg/i:DI x1) 
++                   (reg/i:DI x0)))
++      (cinsn 101 (set (mem/c:DI
++                        (plus:DI (reg/f:DI x1)
++                          (const_int 8))[1 S4 A32])(reg:DI x0)))
++      (cinsn 10 (parallel [
++        (set (reg:DI x1)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int 8)) [1 S4 A32]))
++        (set (reg:DI x2)
++          (mem:DI (plus:DI (reg/f:DI x1)
++            (const_int 16)) [1 S4 A32]))]))
++      (cinsn 11 (use (reg/i:DI sp)))
++      (cinsn 12 (use (reg/i:DI cc)))
++      (cinsn 13 (use (reg/i:DI x0)))
++      (cinsn 14 (use (reg/i:DI x1)))
++      (cinsn 15 (use (reg/i:DI x2)))
++      (edge-to exit (flags "FALLTHRU"))
++    ) ;; block 2
++  ) ;; insn-chain
++) ;; function "ldp_equal_registers"
++}
++
++/* Verify that the output code rearrange ldrs.  */
++/* { dg-final { scan-assembler-times ".*ldr.*x2.*x1,.*16.*ldr.*x1.*x1.*8" 1 } }  */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c
+new file mode 100644
+index 000000000..dc9f26efb
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c
+@@ -0,0 +1,174 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-additional-options "-O1 -fsplit-ldp-stp" } */
++/*
++ *    Tests are:
++ *          Patterns where LDP insns should be split
++ *                       */
++
++int __RTL (startwith ("split_complex_instructions"))
++simple_ldp_after_store ()
++{
++(function "simple_ldp_after_store"
++  (insn-chain
++    (block 2
++      (edge-from entry (flags "FALLTHRU"))
++      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 228 (set (reg/i:DI sp)
++                   (reg/i:DI x0)))
++      (cinsn 238 (set (reg/i:DI x1)
++                   (reg/i:DI x0)))
++
++      (cinsn 101 (set (mem/c:DI
++                        (plus:DI (reg/f:DI sp)
++                          (const_int 8))[1 S4 A32])(reg:DI x0)))
++      (cinsn 10 (parallel [
++        (set (reg:DI x29)
++          (mem:DI (plus:DI (reg/f:DI sp) (const_int 8)) [1 S4 A32]))
++        (set (reg:DI x30)
++          (mem:DI (plus:DI (reg/f:DI sp)
++            (const_int 16)) [1 S4 A32]))]))
++
++      (cinsn 102 (set (mem/c:DI (plus:DI (reg/f:DI x1)
++                                          (const_int -16)) [1 S4 A32])
++                      (reg:DI x0)))
++      (cinsn 11 (parallel [
++        (set (reg:DI x3)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int -16)) [1 S4 A32]))
++        (set (reg:DI x4)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int -8)) [1 S4 A32]))
++      ]))
++
++      (cinsn 103 (set (mem/c:DI (reg/f:DI x1) [1 S4 A32])
++                      (reg:DI x0)))
++      (cinsn 12 (parallel [
++        (set (reg:DI x5) (mem:DI (reg/f:DI x1) [1 S4 A32]))
++        (set (reg:DI x6) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 8)) [1 S4 A32]))
++      ]))
++
++      (cinsn 13 (use (reg/i:DI sp)))
++      (cinsn 14 (use (reg/i:DI cc)))
++      (cinsn 15 (use (reg/i:DI x29)))
++      (cinsn 16 (use (reg/i:DI x30)))
++      (cinsn 17 (use (reg/i:DI x0)))
++      (cinsn 18 (use (reg/i:DI x3)))
++      (cinsn 19 (use (reg/i:DI x4)))
++      (cinsn 20 (use (reg/i:DI x5)))
++      (cinsn 21 (use (reg/i:DI x6)))
++      (edge-to exit (flags "FALLTHRU"))
++    ) ;; block 2
++  ) ;; insn-chain
++) ;; function "simple_ldp_after_store"
++}
++
++int __RTL (startwith ("split_complex_instructions"))
++ldp_ti_after_store ()
++{
++  (function "ldp_ti_after_store"
++    (insn-chain
++      (block 2
++      (edge-from entry (flags "FALLTHRU"))
++      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 228 (set (reg/i:DI sp)
++                   (reg/i:DI x0)))
++      (cinsn 238 (set (reg/i:DI x2)
++                   (reg/i:DI x0)))
++
++      (cinsn 101 (set (mem/c:DI
++                        (plus:DI (reg/f:DI sp)
++                          (const_int 136))[1 S4 A32])(reg:DI x0)))
++      (insn 81 (set (reg:TI x0 [1 S4 A32])
++              (mem/c:TI (plus:DI (reg/f:DI sp)
++                      (const_int 136 )) [1 S4 A32]))
++           (expr_list:REG_EQUIV (mem/c:TI (plus:DI (reg/f:DI sfp)
++                      (const_int -24 )) [1 S4 A32])
++              (nil)))
++
++      (cinsn 102 (set (mem/c:DI (plus:DI (reg/f:DI x2)
++                                          (const_int -16)) [1 S4 A32])
++                      (reg:DI x0)))
++      (insn 82 (set (reg:TI x3 [1 S4 A32])
++                    (mem/c:TI (plus:DI (reg/f:DI x2)
++                                        (const_int -16)) [1 S4 A32])))
++
++      (cinsn 103 (set (mem/c:DI (reg/f:DI x2) [1 S4 A32])
++                      (reg:DI x0)))
++      (insn 83 (set (reg:TI x5 [1 S4 A32])
++                    (mem/c:TI (reg/f:DI x2) [1 S4 A32])))
++
++      (cinsn 11 (use (reg/i:DI sp)))
++      (cinsn 12 (use (reg/i:DI cc)))
++      (cinsn 13 (use (reg/i:DI x29)))
++      (cinsn 14 (use (reg/i:DI x30)))
++      (cinsn 15 (use (reg/i:DI x0)))
++      (cinsn 16 (use (reg/i:DI x3)))
++      (cinsn 17 (use (reg/i:DI x5)))
++      (cinsn 18 (use (reg/i:DI x1)))
++      (cinsn 19 (use (reg/i:DI x4)))
++      (cinsn 20 (use (reg/i:DI x6)))
++      (edge-to exit (flags "FALLTHRU"))
++    ) ;; block 2
++  ) ;; insn-chain
++) ;; function "ldp_ti_after_store"
++}
++
++int __RTL (startwith ("split_complex_instructions"))
++ldp_after_store_in_different_bb ()
++{
++(function "ldp_after_store_in_different_bb"
++  (insn-chain
++    (block 2
++      (edge-from entry (flags "FALLTHRU"))
++      (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 228 (set (reg/i:DI sp)
++                   (reg/i:DI x0)))
++      (cinsn 238 (set (reg/i:DI x1)
++                   (reg/i:DI x0)))
++
++      (cinsn 101 (set (mem/c:DI
++                        (plus:DI (reg/f:DI sp)
++                          (const_int 8))[1 S4 A32])(reg:DI x0)))
++      (cinsn 102 (set (mem/c:DI (plus:DI (reg/f:DI x1)
++                                          (const_int -16)) [1 S4 A32])
++                      (reg:DI x0)))
++      (cinsn 103 (set (mem/c:DI (reg/f:DI x1) [1 S4 A32])
++                      (reg:DI x0)))
++      (edge-to 3 (flags "FALLTHRU"))
++    ) ;; block 2
++    (block 3
++      (edge-from 2 (flags "FALLTHRU"))
++      (cnote 4 [bb 3] NOTE_INSN_BASIC_BLOCK)
++      (cinsn 10 (parallel [
++        (set (reg:DI x29)
++          (mem:DI (plus:DI (reg/f:DI sp) (const_int 8)) [1 S4 A32]))
++        (set (reg:DI x30)
++          (mem:DI (plus:DI (reg/f:DI sp)
++            (const_int 16)) [1 S4 A32]))]))
++      (cinsn 11 (parallel [
++        (set (reg:DI x3)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int -16)) [1 S4 A32]))
++        (set (reg:DI x4)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int -8)) [1 S4 A32]))
++      ]))
++      (cinsn 12 (parallel [
++        (set (reg:DI x5) (mem:DI (reg/f:DI x1) [1 S4 A32]))
++        (set (reg:DI x6) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 8)) [1 S4 A32]))
++      ]))
++      (cinsn 13 (use (reg/i:DI sp)))
++      (cinsn 14 (use (reg/i:DI cc)))
++      (cinsn 15 (use (reg/i:DI x29)))
++      (cinsn 16 (use (reg/i:DI x30)))
++      (cinsn 17 (use (reg/i:DI x0)))
++      (cinsn 18 (use (reg/i:DI x3)))
++      (cinsn 19 (use (reg/i:DI x4)))
++      (cinsn 20 (use (reg/i:DI x5)))
++      (cinsn 21 (use (reg/i:DI x6)))
++      (edge-to exit (flags "FALLTHRU"))
++    ) ;; block 3
++  ) ;; insn-chain
++) ;; function "ldp_after_store_in_different_bb"
++}
++
++/* Verify that the output code doesn't contain ldp.  */
++/* { dg-final { scan-assembler-not {ldp\t} } }  */
+\ No newline at end of file
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 1e7d4e74b..2ccecffb5 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -280,6 +280,7 @@ DEFTIMEVAR (TV_RELOAD_CSE_REGS       , "reload CSE regs")
+ DEFTIMEVAR (TV_GCSE_AFTER_RELOAD     , "load CSE after reload")
+ DEFTIMEVAR (TV_REE		     , "ree")
+ DEFTIMEVAR (TV_THREAD_PROLOGUE_AND_EPILOGUE, "thread pro- & epilogue")
++DEFTIMEVAR (TV_SPLIT_CMP_INS         , "split complex instructions")
+ DEFTIMEVAR (TV_IFCVT2		     , "if-conversion 2")
+ DEFTIMEVAR (TV_SPLIT_PATHS	     , "split paths")
+ DEFTIMEVAR (TV_COMBINE_STACK_ADJUST  , "combine stack adjustments")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 86f38e2f2..6daac7fc1 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -612,6 +612,7 @@ extern rtl_opt_pass *make_pass_split_after_reload (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_thread_prologue_and_epilogue (gcc::context
+ 							     *ctxt);
+ extern rtl_opt_pass *make_pass_zero_call_used_regs (gcc::context *ctxt);
++extern rtl_opt_pass *make_pass_split_complex_instructions (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_stack_adjustments (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_sched_fusion (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_peephole2 (gcc::context *ctxt);
+-- 
+2.33.0
+
diff --git a/0043-Extending-and-refactoring-of-pass_split_complex_inst.patch b/0043-Extending-and-refactoring-of-pass_split_complex_inst.patch
new file mode 100644
index 0000000..509a534
--- /dev/null
+++ b/0043-Extending-and-refactoring-of-pass_split_complex_inst.patch
@@ -0,0 +1,1426 @@
+From a49db831320ac70ca8f46b94ee60d7c6951f65c3 Mon Sep 17 00:00:00 2001
+From: Gadzhiev Emin WX1195297 
+Date: Wed, 20 Dec 2023 21:36:07 +0300
+Subject: [PATCH 10/18] Extending and refactoring of
+ pass_split_complex_instructions
+
+- Add flag parameter in is_ldp_insn and is_stp_insn to know
+  if instruction has writeback operation
+- Add support of PRE_*, POST_* operands as a memory address
+  expression
+- Split only LDPs that intersect with a dependent store
+  instruction
+- Make the selection of dependent store instructions stricter
+  so it will be enough to check by BFS that dependent store
+  instruction appears in search range.
+- Add helper methods to retrieve fields of rtx
+- Remove redundant iterations in find_dependent_stores_candidates
+- Refactor generation of instructions
+- Add more test cases
+---
+ gcc/config/aarch64/aarch64.cc                 |  62 +-
+ gcc/doc/tm.texi                               |  12 +-
+ gcc/sched-rgn.cc                              | 771 +++++++++---------
+ gcc/target.def                                |  14 +-
+ .../gcc.dg/rtl/aarch64/test-ldp-dont-split.c  |  35 +-
+ .../rtl/aarch64/test-ldp-split-rearrange.c    |   2 +-
+ .../gcc.dg/rtl/aarch64/test-ldp-split.c       | 181 +++-
+ 7 files changed, 603 insertions(+), 474 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 48e2eded0..fa566dd80 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -27507,39 +27507,59 @@ aarch64_run_selftests (void)
+ 
+ #endif /* #if CHECKING_P */
+ 
+-/* TODO: refuse to use ranges intead of full list of an instruction codes.  */
++/* TODO: refuse to use ranges instead of full list of an instruction codes.  */
+ 
+ bool
+-is_aarch64_ldp_insn (int icode)
++is_aarch64_ldp_insn (int icode, bool *has_wb)
+ {
+   if ((icode >= CODE_FOR_load_pair_sw_sisi
+-	  && icode <= CODE_FOR_load_pair_dw_tftf)
++	  && icode <= CODE_FOR_load_pair_sw_sfsf)
++      || (icode >= CODE_FOR_load_pair_dw_didi
++	  && icode <= CODE_FOR_load_pair_dw_dfdf)
++      || (icode == CODE_FOR_load_pair_dw_tftf)
+       || (icode >= CODE_FOR_loadwb_pairsi_si
+-	     && icode <= CODE_FOR_loadwb_pairtf_di)
+-      || (icode >= CODE_FOR_load_pairv8qiv8qi
+-	     && icode <= CODE_FOR_load_pairdfdf)
+-      || (icode >= CODE_FOR_load_pairv16qiv16qi
+-	     && icode <= CODE_FOR_load_pairv8bfv2df)
+-      || (icode >= CODE_FOR_load_pair_lanesv8qi
+-	     && icode <= CODE_FOR_load_pair_lanesdf))
+-    return true;
++	  && icode <= CODE_FOR_loadwb_pairdi_di)
++      || (icode >= CODE_FOR_loadwb_pairsf_si
++	  && icode <= CODE_FOR_loadwb_pairdf_di)
++      || (icode >= CODE_FOR_loadwb_pairti_si
++	  && icode <= CODE_FOR_loadwb_pairtf_di))
++    {
++      if (has_wb)
++	*has_wb = ((icode >= CODE_FOR_loadwb_pairsi_si
++		     && icode <= CODE_FOR_loadwb_pairdi_di)
++		   || (icode >= CODE_FOR_loadwb_pairsf_si
++		     && icode <= CODE_FOR_loadwb_pairdf_di)
++		   || (icode >= CODE_FOR_loadwb_pairti_si
++		      && icode <= CODE_FOR_loadwb_pairtf_di));
++      return true;
++    }
+   return false;
+ }
+ 
+ bool
+-is_aarch64_stp_insn (int icode)
++is_aarch64_stp_insn (int icode, bool *has_wb)
+ {
+   if ((icode >= CODE_FOR_store_pair_sw_sisi
+-	  && icode <= CODE_FOR_store_pair_dw_tftf)
++	  && icode <= CODE_FOR_store_pair_sw_sfsf)
++      || (icode >= CODE_FOR_store_pair_dw_didi
++	  && icode <= CODE_FOR_store_pair_dw_dfdf)
++      || (icode == CODE_FOR_store_pair_dw_tftf)
+       || (icode >= CODE_FOR_storewb_pairsi_si
+-	     && icode <= CODE_FOR_storewb_pairtf_di)
+-      || (icode >= CODE_FOR_vec_store_pairv8qiv8qi
+-	     && icode <= CODE_FOR_vec_store_pairdfdf)
+-      || (icode >= CODE_FOR_vec_store_pairv16qiv16qi
+-	     && icode <= CODE_FOR_vec_store_pairv8bfv2df)
+-      || (icode >= CODE_FOR_store_pair_lanesv8qi
+-	     && icode <= CODE_FOR_store_pair_lanesdf))
+-    return true;
++	  && icode <= CODE_FOR_storewb_pairdi_di)
++      || (icode >= CODE_FOR_storewb_pairsf_si
++	  && icode <= CODE_FOR_storewb_pairdf_di)
++      || (icode >= CODE_FOR_storewb_pairti_si
++	  && icode <= CODE_FOR_storewb_pairtf_di))
++    {
++      if (has_wb)
++	*has_wb = ((icode >= CODE_FOR_storewb_pairsi_si
++		     && icode <= CODE_FOR_storewb_pairdi_di)
++		   || (icode >= CODE_FOR_storewb_pairsf_si
++		     && icode <= CODE_FOR_storewb_pairdf_di)
++		   || (icode >= CODE_FOR_storewb_pairti_si
++		     && icode <= CODE_FOR_storewb_pairtf_di));
++      return true;
++    }
+   return false;
+ }
+ 
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 0c6415a9c..3b6e90bf2 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -12113,12 +12113,16 @@ object files that are not referenced from @code{main} and uses export
+ lists.
+ @end defmac
+ 
+-@deftypefn {Target Hook} bool TARGET_IS_LDP_INSN (int @var{icode})
+-Return true if icode is corresponding to any of the LDP instruction types.
++@deftypefn {Target Hook} bool TARGET_IS_LDP_INSN (int @var{icode}, bool *@var{has_wb})
++Return true if @var{icode} is corresponding to any of the LDP instruction
++types.  If @var{has_wb} is not NULL then its value is set to true if LDP
++contains post-index or pre-index operation.
+ @end deftypefn
+ 
+-@deftypefn {Target Hook} bool TARGET_IS_STP_INSN (int @var{icode})
+-Return true if icode is corresponding to any of the STP instruction types.
++@deftypefn {Target Hook} bool TARGET_IS_STP_INSN (int @var{icode}, bool *@var{has_wb})
++Return true if @var{icode} is corresponding to any of the STP instruction
++types.  If @var{has_wb} is not NULL then its value is set to true if STP
++contains post-index or pre-index operation.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} bool TARGET_CANNOT_MODIFY_JUMPS_P (void)
+diff --git a/gcc/sched-rgn.cc b/gcc/sched-rgn.cc
+index b4df8bdc5..5f61de1c8 100644
+--- a/gcc/sched-rgn.cc
++++ b/gcc/sched-rgn.cc
+@@ -3956,7 +3956,7 @@ make_pass_sched_fusion (gcc::context *ctxt)
+ 
+ namespace {
+ 
+-/* Def-use analisys special functions implementation.  */
++/* Def-use analysis special functions implementation.  */
+ 
+ static struct df_link *
+ get_defs (rtx_insn *insn, rtx reg)
+@@ -4032,42 +4032,66 @@ const pass_data pass_data_split_complex_instructions = {
+   (TODO_df_verify | TODO_df_finish), /* Todo_flags_finish.  */
+ };
+ 
++/* Pass split_complex_instructions finds LOAD PAIR instructions (LDP) that can
++   be split into two LDR instructions.  It splits only those LDP for which one
++   half of the requested memory is contained in the preceding STORE (STR/STP)
++   instruction whose base register has the same definition.  This allows
++   to use hardware store-to-load forwarding mechanism and to get one half of
++   requested memory from the store queue of CPU.
++
++   TODO: Add split of STP.
++   TODO: Add split of vector STP and LDP.  */
+ class pass_split_complex_instructions : public rtl_opt_pass
+ {
+ private:
+-  enum complex_instructions_t
++  enum mem_access_insn_t
+   {
+     UNDEFINED,
+     LDP,
++    /* LDP with post-index (see loadwb_pair in config/aarch64.md).  */
++    LDP_WB,
++    /* LDP that contains one destination register in RTL IR
++       (see movti_aarch64 in config/aarch64.md).  */
+     LDP_TI,
+     STP,
++    /* STP with pre-index (see storewb_pair in config/aarch64.md).  */
++    STP_WB,
++    /* STP that contains one source register in RTL IR
++       (see movti_aarch64 in config/aarch64.md).  */
++    STP_TI,
+     STR
+   };
+ 
+-  void split_complex_insn (rtx_insn *insn);
+-  void split_ldp_ti (rtx_insn *insn);
+-  void split_ldp_with_offset (rtx_insn *ldp_insn);
+-  void split_simple_ldp (rtx_insn *ldp_insn);
+-  void split_ldp_stp (rtx_insn *insn);
+-  complex_instructions_t get_insn_type (rtx_insn *insn);
+-
+-  basic_block bb;
+-  rtx_insn *insn;
+   std::set dependent_stores_candidates;
+   std::set ldp_to_split_list;
+ 
+-  complex_instructions_t complex_insn_type = UNDEFINED;
+-  bool is_store_insn (rtx_insn *insn);
+-  bool is_ldp_dependent_on_store (rtx_insn *ldp_insn, basic_block bb);
++  void split_ldp_ti (rtx_insn *insn);
++  void split_ldp (rtx_insn *ldp_insn);
++  /* Emit a NEW_INSNS chain, recognize instruction code of each new instruction
++     and replace OLD_INSN with the emitted sequence.  */
++  void replace_insn (rtx_insn *old_insn, rtx_insn *new_insns);
++
++  mem_access_insn_t get_insn_type (rtx_insn *insn);
++  bool is_typeof_ldp (mem_access_insn_t insn_type);
++  bool is_typeof_stp (mem_access_insn_t insn_type);
++
+   bool bfs_for_reg_dependent_store (rtx_insn *ldp_insn, basic_block search_bb,
+ 				    rtx_insn *search_insn,
+ 				    int search_range
+ 				    = param_ldp_dependency_search_range);
+   bool is_store_reg_dependent (rtx_insn *ldp_insn, rtx_insn *str_insn);
+   void init_df ();
+-  void find_dependent_stores_candidates (rtx_insn *ldp_insn);
+-  int get_insn_offset (rtx_insn *insn, complex_instructions_t insn_type,
+-		       int *arith_operation_ptr = NULL);
++  void find_dependent_stores_candidates (rtx_insn *ldp_insn,
++					 mem_access_insn_t insn_type);
++
++  rtx get_memref (rtx_insn *insn, mem_access_insn_t insn_type);
++  rtx get_base_reg (rtx memref);
++  /* Set OFFSET to the offset value.  Returns TRUE if MEMREF's address
++     expression is supported, FALSE otherwise.  */
++  bool get_offset (rtx memref, int &offset);
++  /* Return size of memory referenced by MEMREF.  Returns -1 if INSN_TYPE
++     wasn't recognized.  */
++  int get_unit_size (rtx memref, mem_access_insn_t insn_type);
+ 
+ public:
+   pass_split_complex_instructions (gcc::context *ctxt)
+@@ -4080,28 +4104,22 @@ public:
+   virtual unsigned int
+   execute (function *)
+   {
+-    enum rtx_code ldp_memref_code;
++    basic_block bb;
++    rtx_insn *insn;
++
+     init_df ();
+     ldp_to_split_list.clear ();
+     FOR_EACH_BB_FN (bb, cfun)
+       {
+ 	FOR_BB_INSNS (bb, insn)
+ 	  {
+-	    complex_instructions_t insn_type = get_insn_type (insn);
+-	    /* TODO: Add splitting of STP instructions.  */
+-	    if (insn_type != LDP && insn_type != LDP_TI)
++	    mem_access_insn_t insn_type = get_insn_type (insn);
++	    if (!is_typeof_ldp (insn_type))
+ 	      continue;
+-	    /* TODO: Currently support only ldp_ti and ldp with REG or
+-	       PLUS/MINUS offset expression.  */
+-	    if (insn_type == LDP_TI)
+-	      {
+-		ldp_memref_code = GET_CODE (XEXP (XEXP (PATTERN (insn), 1),
+-						  0));
+-		if (ldp_memref_code != REG && ldp_memref_code != PLUS
+-		    && ldp_memref_code != MINUS)
+-		  continue;
+-	      }
+-	    if (is_ldp_dependent_on_store (insn, bb))
++
++	    find_dependent_stores_candidates (insn, insn_type);
++	    if (!dependent_stores_candidates.empty ()
++	       && bfs_for_reg_dependent_store (insn, bb, insn))
+ 	      {
+ 		ldp_to_split_list.insert (insn);
+ 	      }
+@@ -4110,18 +4128,107 @@ public:
+ 
+     for (std::set::iterator i = ldp_to_split_list.begin ();
+ 	 i != ldp_to_split_list.end (); ++i)
+-      split_complex_insn (*i);
++      split_ldp (*i);
+ 
+     return 0;
+   }
+ }; // class pass_split_complex_instructions
+ 
+ bool
+-pass_split_complex_instructions::is_ldp_dependent_on_store (rtx_insn *ldp_insn,
+-							    basic_block bb)
++pass_split_complex_instructions::is_typeof_ldp (
++    mem_access_insn_t insn_type)
+ {
+-  find_dependent_stores_candidates (ldp_insn);
+-  return bfs_for_reg_dependent_store (ldp_insn, bb, ldp_insn);
++  return (insn_type == LDP || insn_type == LDP_WB || insn_type == LDP_TI);
++}
++
++bool
++pass_split_complex_instructions::is_typeof_stp (
++    mem_access_insn_t insn_type)
++{
++  return (insn_type == STP || insn_type == STP_WB || insn_type == STP_TI);
++}
++
++rtx
++pass_split_complex_instructions::get_memref (
++    rtx_insn *insn, mem_access_insn_t insn_type)
++{
++  rtx insn_pat = PATTERN (insn);
++  rtx memref = NULL;
++
++  switch (insn_type)
++    {
++      case LDP:
++	memref = SET_SRC (XVECEXP (insn_pat, 0, 0));
++	break;
++      case LDP_WB:
++	memref = SET_SRC (XVECEXP (insn_pat, 0, 1));
++	break;
++      case LDP_TI:
++	memref = SET_SRC (insn_pat);
++	break;
++      case STP:
++	memref = SET_DEST (XVECEXP (insn_pat, 0, 0));
++	break;
++      case STP_WB:
++	memref = SET_DEST (XVECEXP (insn_pat, 0, 1));
++	break;
++      case STP_TI:
++      case STR:
++	memref = SET_DEST (insn_pat);
++	break;
++      default:
++	break;
++    }
++
++  if (memref && !MEM_P (memref))
++    return NULL;
++  return memref;
++}
++
++rtx
++pass_split_complex_instructions::get_base_reg (rtx memref)
++{
++  if (!memref || !MEM_P (memref))
++    return NULL;
++  rtx addr_exp = XEXP (memref, 0);
++
++  switch (GET_CODE (addr_exp))
++    {
++      case REG:
++	return addr_exp;
++      case PLUS:
++      case PRE_DEC:
++      case PRE_INC:
++      case POST_DEC:
++      case POST_INC:
++	if (REG_P (XEXP (addr_exp, 0)))
++	  return XEXP (addr_exp, 0);
++      default:
++	return NULL;
++    }
++}
++
++int
++pass_split_complex_instructions::get_unit_size (
++    rtx memref, mem_access_insn_t insn_type)
++{
++  if (!memref)
++    return -1;
++
++  switch (insn_type)
++    {
++      case LDP:
++      case STP:
++      case LDP_WB:
++      case STP_WB:
++      case STR:
++	return GET_MODE_SIZE (GET_MODE (memref)).to_constant ();
++      case LDP_TI:
++      case STP_TI:
++	return GET_MODE_SIZE (E_DImode).to_constant ();
++      default:
++	return -1;
++    }
+ }
+ 
+ bool
+@@ -4135,9 +4242,9 @@ pass_split_complex_instructions::bfs_for_reg_dependent_store (
+     {
+       if (!current_search_insn)
+ 	return false;
+-      bool checking_result
+-	  = is_store_reg_dependent (ldp_insn, current_search_insn);
+-      if (checking_result)
++
++      if (dependent_stores_candidates.find (current_search_insn)
++	  != dependent_stores_candidates.end ())
+ 	{
+ 	  if (dump_file)
+ 	    {
+@@ -4185,30 +4292,29 @@ pass_split_complex_instructions::init_df ()
+ 
+ void
+ pass_split_complex_instructions::find_dependent_stores_candidates (
+-    rtx_insn *ldp_insn)
++    rtx_insn *ldp_insn, mem_access_insn_t insn_type)
+ {
+   dependent_stores_candidates.clear ();
+-  df_ref use;
+ 
+-  FOR_EACH_INSN_USE (use, ldp_insn)
+-    {
+-      df_link *defs = get_defs (ldp_insn, DF_REF_REG (use));
+-      if (!defs)
+-	return;
++  rtx base_reg = get_base_reg (get_memref (ldp_insn, insn_type));
++  if (!base_reg)
++    return;
+ 
+-      for (df_link *def = defs; def; def = def->next)
+-	{
+-	  df_link *uses
+-	      = get_uses (DF_REF_INSN (def->ref), DF_REF_REG (def->ref));
+-	  if (!uses)
+-	    continue;
++  df_link *defs = get_defs (ldp_insn, base_reg);
++  if (!defs)
++    return;
+ 
+-	  for (df_link *use = uses; use; use = use->next)
+-	    {
+-	      if (DF_REF_CLASS (use->ref) == DF_REF_REGULAR
+-		  && is_store_insn (DF_REF_INSN (use->ref)))
+-		dependent_stores_candidates.insert (DF_REF_INSN (use->ref));
+-	    }
++  for (df_link *def = defs; def; def = def->next)
++    {
++      df_link *uses = get_uses (DF_REF_INSN (def->ref), DF_REF_REG (def->ref));
++      if (!uses)
++	continue;
++      for (df_link *use = uses; use; use = use->next)
++	{
++	  if (DF_REF_CLASS (use->ref) == DF_REF_REGULAR
++	      && DF_REF_INSN (use->ref) != ldp_insn
++	      && is_store_reg_dependent (ldp_insn, DF_REF_INSN (use->ref)))
++	    dependent_stores_candidates.insert (DF_REF_INSN (use->ref));
+ 	}
+     }
+ }
+@@ -4217,423 +4323,274 @@ bool
+ pass_split_complex_instructions::is_store_reg_dependent (rtx_insn *ldp_insn,
+ 							 rtx_insn *str_insn)
+ {
+-  if (!is_store_insn (str_insn)
+-      || dependent_stores_candidates.find (str_insn)
+-	     == dependent_stores_candidates.end ())
++  if (!str_insn)
+     return false;
+ 
+-  int ldp_offset_sign = UNDEFINED;
+-  int ldp_offset
+-      = get_insn_offset (ldp_insn, get_insn_type (ldp_insn), &ldp_offset_sign);
+-  if (ldp_offset_sign == MINUS)
+-    ldp_offset = -ldp_offset;
++  mem_access_insn_t st_type = get_insn_type (str_insn);
++  if (!is_typeof_stp (st_type) && st_type != STR)
++    return false;
+ 
+-  int str_offset_sign = UNDEFINED;
+-  int str_offset = get_insn_offset (str_insn, STR, &str_offset_sign);
+-  if (str_offset_sign == MINUS)
+-    str_offset = -str_offset;
++  mem_access_insn_t ld_type = get_insn_type (ldp_insn);
++  rtx ld_memref = get_memref (ldp_insn, ld_type);
++  rtx st_memref = get_memref (str_insn, st_type);
++  rtx ld_base_reg = get_base_reg (ld_memref);
++  rtx st_base_reg =  get_base_reg (st_memref);
+ 
+-  if (str_offset == ldp_offset || str_offset == ldp_offset + 8)
+-    return true;
++  if (!ld_base_reg || !st_base_reg
++      || REGNO (ld_base_reg) != REGNO (st_base_reg))
++    return false;
+ 
+-  return false;
+-}
++  int ld_offset = 0;
++  int st_offset = 0;
++  if (get_offset (ld_memref, ld_offset)
++      && get_offset (st_memref, st_offset))
++    {
++      int ld_unit_size = get_unit_size (ld_memref, ld_type);
++      int st_size = get_unit_size (st_memref, st_type);
++      if (st_type != STR)
++	st_size *= 2;
+ 
+-bool
+-pass_split_complex_instructions::is_store_insn (rtx_insn *insn)
+-{
+-  if (!insn)
+-    return false;
+-  rtx sset_b = single_set (insn);
+-  /* TODO: The condition below allow to take only store instructions in which
+-     the memory location's operand is either a register (base) or an plus/minus
+-     operation (base + #imm). So it might make sense to add support for other
+-     cases (e.g. multiply and shift).  */
+-  if (sset_b && MEM_P (SET_DEST (sset_b))
+-      && GET_MODE (XEXP (sset_b, 0)) != BLKmode
+-      && (GET_CODE (XEXP (XEXP (sset_b, 0), 0)) == REG
+-	  || (GET_CODE (XEXP (XEXP (sset_b, 0), 0)) == PLUS
+-	      || GET_CODE (XEXP (XEXP (sset_b, 0), 0)) == MINUS)
+-	  && (GET_CODE (XEXP (XEXP (XEXP (sset_b, 0), 0), 1)) == CONST_INT)))
+-    return true;
++      if (ld_unit_size < 0 || st_size < 0)
++	return false;
++
++      bool st_has_low_ld_part = (ld_offset >= st_offset
++	&& (ld_offset + ld_unit_size <= st_offset + st_size));
++      bool st_has_high_ld_part = ((ld_offset + ld_unit_size >= st_offset)
++	&& (ld_offset + 2 * ld_unit_size <= st_offset + st_size));
++      bool st_has_not_full_ld = (ld_offset < st_offset
++	|| (ld_offset + 2 * ld_unit_size > st_offset + st_size));
++
++      if ((st_has_low_ld_part || st_has_high_ld_part) && st_has_not_full_ld)
++	return true;
++    }
+ 
+   return false;
+ }
+ 
+-int
+-pass_split_complex_instructions::get_insn_offset (
+-    rtx_insn *insn, complex_instructions_t insn_type, int *arith_operation_ptr)
++bool
++pass_split_complex_instructions::get_offset (rtx memref, int &offset)
+ {
+-  rtx insn_pat = PATTERN (insn);
+-  int returned_offset = 0;
++  rtx addr_exp = XEXP (memref, 0);
+ 
+-  rtx offset_expr = NULL;
+-  rtx offset_value_expr = NULL;
+-
+-  switch (insn_type)
++  switch (GET_CODE (addr_exp))
+     {
+-    case LDP:
+-      {
+-	int number_of_sub_insns = XVECLEN (insn_pat, 0);
+-
+-	/* Calculate it's own ofsset of first load insn.  */
+-	rtx_insn *first_load_insn = NULL;
+-	if (number_of_sub_insns == 2)
++      case REG:
++      case POST_DEC:
++      case POST_INC:
++	offset = 0;
++	return true;
++      case PRE_DEC:
++	offset = -(GET_MODE_SIZE (GET_MODE (memref)).to_constant ());
++	return true;
++      case PRE_INC:
++	offset = GET_MODE_SIZE (GET_MODE (memref)).to_constant ();
++	return true;
++      case PLUS:
++	if (CONST_INT_P (XEXP (addr_exp, 1)))
+ 	  {
+-	    first_load_insn
+-		= make_insn_raw (copy_rtx (XVECEXP (insn_pat, 0, 0)));
+-	    arith_operation_ptr = NULL;
+-
+-	    offset_expr = XEXP (XEXP (PATTERN (first_load_insn), 1), 0);
+-	    if (GET_CODE (offset_expr) == PLUS
+-		|| GET_CODE (offset_expr) == MINUS)
+-	      offset_value_expr
+-		  = XEXP (XEXP (XEXP (PATTERN (first_load_insn), 1), 0), 1);
+-	    else
+-	      offset_expr = NULL;
++	    offset = INTVAL (XEXP (addr_exp, 1));
++	    return true;
+ 	  }
+-	else if (number_of_sub_insns == 3)
+-	  {
+-	    rtx_insn *offset_sub_insn
+-		= make_insn_raw (copy_rtx (XVECEXP (insn_pat, 0, 0)));
+-
+-	    offset_expr = XEXP (PATTERN (offset_sub_insn), 1);
+-	    offset_value_expr = XEXP (XEXP (PATTERN (offset_sub_insn), 1), 1);
+-	  }
+-	else
+-	  {
+-	    gcc_assert (false
+-			&& "Wrong number of elements in the ldp_insn vector");
+-	  }
+-	break;
+-      }
+-    case LDP_TI:
+-      {
+-	offset_expr = XEXP (XEXP (insn_pat, 1), 0);
+-	if (GET_CODE (offset_expr) != PLUS && GET_CODE (offset_expr) != MINUS)
+-	  return 0;
+-	offset_value_expr = XEXP (XEXP (XEXP (insn_pat, 1), 0), 1);
+-	break;
+-      }
+-    case STR:
+-      {
+-	offset_expr = XEXP (XEXP (insn_pat, 0), 0);
+-	/* If memory location is specified by single base register then the
+-	   offset is zero.  */
+-	if (GET_CODE (offset_expr) == REG)
+-	  return 0;
+-	offset_value_expr = XEXP (XEXP (XEXP (insn_pat, 0), 0), 1);
+-	break;
+-      }
+-    default:
+-      {
+-	if (dumps_are_enabled && dump_file)
+-	  {
+-	    fprintf (dump_file, "Instruction that was tried to split:\n");
+-	    print_rtl_single (dump_file, insn);
+-	  }
+-	gcc_assert (false && "Unsupported instruction type");
+-	break;
+-      }
+-    }
+-
+-  if (offset_expr != NULL && offset_value_expr
+-      && GET_CODE (offset_value_expr) == CONST_INT)
+-    returned_offset = XINT (offset_value_expr, 0);
+-
+-  if (arith_operation_ptr != NULL)
+-    {
+-      *arith_operation_ptr = GET_CODE (offset_expr);
+-      gcc_assert ((*arith_operation_ptr == MINUS
+-		   || *arith_operation_ptr == PLUS)
+-		  && "Unexpected arithmetic operation in the offset expr");
++      default:
++	return false;
+     }
+-
+-  return returned_offset;
+ }
+ 
+ void
+-pass_split_complex_instructions::split_simple_ldp (rtx_insn *ldp_insn)
++pass_split_complex_instructions::replace_insn (rtx_insn *old_insn,
++					       rtx_insn *new_insns)
+ {
+-  rtx pat = PATTERN (ldp_insn);
+-
+-  rtx_insn *mem_insn_1 = make_insn_raw (copy_rtx (XVECEXP (pat, 0, 0)));
+-  rtx_insn *mem_insn_2 = make_insn_raw (copy_rtx (XVECEXP (pat, 0, 1)));
+-
+-  int dest_regno = REGNO (SET_DEST (PATTERN (mem_insn_1)));
+-  int src_regno;
+-
+-  rtx srs_reg_insn = XEXP (SET_SRC (PATTERN (mem_insn_1)), 0);
+-
+-  if (GET_CODE (srs_reg_insn) == REG)
+-    src_regno = REGNO (srs_reg_insn);
+-  else
+-    src_regno = REGNO (XEXP (srs_reg_insn, 0));
+-
+-  rtx_insn *emited_insn_1, *emited_insn_2;
++  rtx_insn *prev_insn = PREV_INSN (old_insn);
++  start_sequence ();
+ 
+-  /* in cases like ldp r1,r2,[r1] we emit ldr r2,[r1] first.  */
+-  if (src_regno == dest_regno)
+-    std::swap (mem_insn_1, mem_insn_2);
++  emit_insn (new_insns);
++  if (dump_file)
++    {
++      fprintf (dump_file, "Split LDP:\n");
++      print_rtl_single (dump_file, old_insn);
++      fprintf (dump_file, "Split into:\n");
++    }
+ 
+-  emited_insn_1 = emit_insn (PATTERN (mem_insn_1));
+-  emited_insn_2 = emit_insn (PATTERN (mem_insn_2));
++  for (rtx_insn *insn = new_insns; insn; insn = NEXT_INSN (insn))
++    {
++	INSN_CODE (insn) = recog (PATTERN (insn), insn, NULL);
++	if (dump_file)
++	  {
++	    print_rtl_single (dump_file, insn);
++	  }
++    }
+ 
+-  int sub_insn_1_code = recog (PATTERN (mem_insn_1), mem_insn_1, 0);
+-  int sub_insn_2_code = recog (PATTERN (mem_insn_2), mem_insn_2, 0);
++  rtx_insn *seq = get_insns ();
++  unshare_all_rtl_in_chain (seq);
++  end_sequence ();
+ 
+-  INSN_CODE (emited_insn_1) = sub_insn_1_code;
+-  INSN_CODE (emited_insn_2) = sub_insn_2_code;
++  emit_insn_after_setloc (seq, prev_insn, INSN_LOCATION (old_insn));
++  delete_insn_and_edges (old_insn);
+ }
+ 
+ void
+-pass_split_complex_instructions::split_ldp_with_offset (rtx_insn *ldp_insn)
++pass_split_complex_instructions::split_ldp (rtx_insn *ldp_insn)
+ {
+   rtx pat = PATTERN (ldp_insn);
+-  bool post_index = true;
+-
+-  rtx_insn offset_insn;
+-  rtx_insn mem_insn_1;
+-  rtx_insn mem_insn_2;
++  mem_access_insn_t insn_type = get_insn_type (ldp_insn);
++  gcc_assert (is_typeof_ldp (insn_type));
+ 
+-  int offset_insn_code;
+-  int mem_insn_1_code = -1;
+-  int mem_insn_2_code = -1;
++  rtx load_rtx_1 = NULL;
++  rtx load_rtx_2 = NULL;
++  rtx post_index_rtx = NULL;
+ 
+-  int offset = 0;
+-  int arith_operation = UNDEFINED;
+-
+-  for (int i = 0; i < 3; i++)
++  switch (insn_type)
+     {
+-      rtx sub_insn = XVECEXP (pat, 0, i);
+-      rtx_insn *copy_of_sub_insn = make_insn_raw (copy_rtx (sub_insn));
+-      int sub_insn_code
+-	  = recog (PATTERN (copy_of_sub_insn), copy_of_sub_insn, 0);
+-
+-      /* If sub_insn is offset related.  */
+-      if (GET_RTX_CLASS (sub_insn_code) == RTX_UNARY)
+-	{
+-	  offset_insn = *copy_of_sub_insn;
+-	  offset_insn_code = sub_insn_code;
+-	  gcc_assert (i == 0
+-		      && "Offset related insn must be the first "
+-			 "element of a parallel insn vector");
+-
+-	  offset = get_insn_offset (ldp_insn, LDP, &arith_operation);
+-	}
+-      else
+-	{
+-	  if (GET_CODE (XEXP (PATTERN (copy_of_sub_insn), 0)) != REG)
+-	    {
+-	      rtx &offset_expr
+-		  = XEXP (XEXP (XEXP (PATTERN (copy_of_sub_insn), 0), 0), 1);
+-	      if (GET_CODE (offset_expr) == CONST_INT)
+-		{
+-		  int local_offset = XINT (offset_expr, 0);
+-		  offset = (arith_operation == PLUS ? offset : -offset);
+-
+-		  offset_expr = GEN_INT (local_offset + offset);
+-
+-		  gcc_assert (
+-		      (arith_operation == MINUS || arith_operation == PLUS)
+-		      && "Unexpected arithmetic operation in offset related "
+-			 "sub_insn");
+-
+-		  if (i == 1)
+-		    post_index = false;
+-		}
+-	      else
+-		{
+-		  post_index = true;
+-		}
+-	    }
+-	}
+-      if (i == 1)
+-	{
+-	  mem_insn_1 = *copy_of_sub_insn;
+-	  mem_insn_1_code = sub_insn_code;
+-	}
+-      if (i == 2)
+-	{
+-	  mem_insn_2 = *copy_of_sub_insn;
+-	  mem_insn_2_code = sub_insn_code;
+-	}
++      case LDP:
++	load_rtx_1 = copy_rtx (XVECEXP (pat, 0, 0));
++	load_rtx_2 = copy_rtx (XVECEXP (pat, 0, 1));
++	break;
++      case LDP_WB:
++	post_index_rtx = copy_rtx (XVECEXP (pat, 0, 0));
++	load_rtx_1 = copy_rtx (XVECEXP (pat, 0, 1));
++	load_rtx_2 = copy_rtx (XVECEXP (pat, 0, 2));
++	break;
++      case LDP_TI:
++	split_ldp_ti (ldp_insn);
++	return;
++      default:
++	return;
+     }
+-  gcc_assert (mem_insn_1_code != -1 && mem_insn_2_code != -1
+-	      && "Uninitialized memory insns");
+ 
+-  int dest_regno = REGNO (SET_DEST (PATTERN (&mem_insn_1)));
+-  int src_regno;
+-
+-  rtx srs_reg_insn = XEXP (SET_SRC (PATTERN (&mem_insn_1)), 0);
+-
+-  if (GET_CODE (srs_reg_insn) == REG)
+-    src_regno = REGNO (srs_reg_insn);
+-  else
+-    src_regno = REGNO (XEXP (srs_reg_insn, 0));
++  int dest_regno = REGNO (SET_DEST (load_rtx_1));
++  int base_regno = REGNO (get_base_reg (get_memref (ldp_insn, insn_type)));
+ 
+-  /* Don't split such weird LDP.  */
+-  if (src_regno == dest_regno)
+-    return;
+-
+-  rtx_insn *emited_offset_insn;
+-  if (!post_index)
++  /* In cases like ldp r1,r2,[r1[, #imm]] emit ldr r2,[r1[, #imm]] first.
++     For LDP with post-index don't split such instruction.  */
++  if (base_regno == dest_regno)
+     {
+-      emited_offset_insn = emit_insn (PATTERN (&offset_insn));
+-      INSN_CODE (emited_offset_insn) = offset_insn_code;
++      if (insn_type == LDP)
++	std::swap (load_rtx_1, load_rtx_2);
++      else
++	return;
+     }
+ 
+-  rtx_insn *emited_insn_1 = emit_insn (PATTERN (&mem_insn_1));
+-  rtx_insn *emited_insn_2 = emit_insn (PATTERN (&mem_insn_2));
+-
+-
+-  INSN_CODE (emited_insn_1) = mem_insn_1_code;
+-  INSN_CODE (emited_insn_2) = mem_insn_2_code;
+-
+-  if (post_index)
++  /* Construct the instruction chain for subsequent emitting.  */
++  rtx_insn *insn_seq = make_insn_raw (load_rtx_1);
++  rtx_insn *load_insn_2 = make_insn_raw (load_rtx_2);
++  SET_NEXT_INSN (insn_seq) = load_insn_2;
++  SET_NEXT_INSN (load_insn_2) = NULL;
++  if (post_index_rtx)
+     {
+-      emited_offset_insn = emit_insn (PATTERN (&offset_insn));
+-      INSN_CODE (emited_offset_insn) = offset_insn_code;
++      rtx_insn *post_index_insn = make_insn_raw (post_index_rtx);
++      SET_NEXT_INSN (load_insn_2) = post_index_insn;
++      SET_NEXT_INSN (post_index_insn) = NULL;
+     }
+-}
+-
+-void
+-pass_split_complex_instructions::split_ldp_stp (rtx_insn *insn)
+-{
+-  rtx_insn *prev_insn = PREV_INSN (insn);
+-  int number_of_sub_insns = XVECLEN (PATTERN (insn), 0);
+-
+-  start_sequence ();
+ 
+-  if (number_of_sub_insns == 2)
+-    split_simple_ldp (insn);
+-  else if (number_of_sub_insns == 3)
+-    split_ldp_with_offset (insn);
+-  else
+-    gcc_assert (false && "Broken complex insn vector");
+-
+-  rtx_insn *seq = get_insns ();
+-  unshare_all_rtl_in_chain (seq);
+-  end_sequence ();
+-
+-  emit_insn_after_setloc (seq, prev_insn, INSN_LOCATION (insn));
+-  delete_insn_and_edges (insn);
++  replace_insn (ldp_insn, insn_seq);
+ }
+ 
+ void
+ pass_split_complex_instructions::split_ldp_ti (rtx_insn *insn)
+ {
+-  rtx_insn *prev_insn = PREV_INSN (insn);
+-  rtx_insn *load_insn_1 = make_insn_raw (copy_rtx (PATTERN (insn)));
+-  rtx_insn *load_insn_2 = make_insn_raw (copy_rtx (PATTERN (insn)));
+-
+-  rtx reg_insn_1 = XEXP (PATTERN (load_insn_1), 0);
+-  rtx mem_insn_1 = XEXP (PATTERN (load_insn_1), 1);
+-  rtx mem_insn_2 = XEXP (PATTERN (load_insn_2), 1);
+-
+-  PUT_MODE (mem_insn_1, DImode);
+-  PUT_MODE (mem_insn_2, DImode);
+-
+-  int reg_no_1 = REGNO (reg_insn_1);
++  rtx pat = PATTERN (insn);
++  rtx memref = get_memref (insn, LDP_TI);
++  int unit_size = get_unit_size (memref, LDP_TI);
++  rtx base_reg = get_base_reg (memref);
++  rtx dest_reg = SET_DEST (pat);
++
++  rtx reg_index_rtx = NULL;
++  rtx load_rtx_1 = NULL;
++  rtx load_rtx_2 = NULL;
++  bool post_index = false;
++  int offset = 0;
+ 
+-  XEXP (PATTERN (load_insn_1), 0) = gen_rtx_REG (DImode, reg_no_1);
+-  XEXP (PATTERN (load_insn_2), 0) = gen_rtx_REG (DImode, reg_no_1 + 1);
++  rtx load_1_memref = gen_rtx_MEM (DImode, base_reg);
+ 
+-  rtx load_insn_2_plus_expr = XEXP (XEXP (PATTERN (load_insn_2), 1), 0);
+-  if (GET_CODE (load_insn_2_plus_expr) == REG)
++  rtx addr_expr = XEXP (memref, 0);
++  if (GET_CODE (addr_expr) == PLUS)
+     {
+-	XEXP (XEXP (PATTERN (load_insn_2), 1), 0)
+-	  = gen_rtx_PLUS (DImode,
+-			  gen_rtx_REG (DImode, REGNO (load_insn_2_plus_expr)),
+-			  GEN_INT (GET_MODE_SIZE (DImode)));
++      offset = INTVAL (XEXP (addr_expr, 1));
++      XEXP (load_1_memref, 0) = gen_rtx_PLUS (DImode, base_reg,
++					      GEN_INT (offset));
+     }
+-  else
+-    {
+-      rtx load_insn_2_offset_expr
+-      = XEXP (XEXP (XEXP (PATTERN (load_insn_2), 1), 0), 1);
+ 
+-      if (load_insn_2_offset_expr == NULL)
+-	return;
+-
+-      if (GET_CODE (load_insn_2_offset_expr) == CONST_INT)
+-	{
+-	  int load_insn_2_offset = XINT (load_insn_2_offset_expr, 0);
+-	  XEXP (XEXP (XEXP (PATTERN (load_insn_2), 1), 0), 1)
+-	    = GEN_INT (load_insn_2_offset + GET_MODE_SIZE (DImode));
+-	}
+-    }
+-
+-  start_sequence ();
++  rtx load_2_memref = gen_rtx_MEM (DImode,
++    gen_rtx_PLUS (DImode, base_reg, GEN_INT (offset + unit_size)));
+ 
+-  int src_regno;
+-  rtx srs_reg_insn = XEXP (XEXP (PATTERN (load_insn_1), 1), 0);
++  load_rtx_1 = gen_rtx_SET (gen_rtx_REG (DImode, REGNO (dest_reg)),
++			    load_1_memref);
++  load_rtx_2 = gen_rtx_SET (gen_rtx_REG (DImode, REGNO (dest_reg) + 1),
++			    load_2_memref);
+ 
+-  if (GET_CODE (srs_reg_insn) == REG)
+-    src_regno = REGNO (srs_reg_insn);
+-  else
+-    src_regno = REGNO (XEXP (srs_reg_insn, 0));
++  if (GET_CODE (addr_expr) == PRE_INC || GET_CODE (addr_expr) == PRE_DEC
++      || GET_CODE (addr_expr) == POST_INC || GET_CODE (addr_expr) == POST_DEC)
++    {
++      /* The amount of increment or decrement is equal to size of
++	 machine-mode of the containing MEMREF (see rtl.def).  */
++      int index_offset = GET_MODE_SIZE (GET_MODE (memref)).to_constant ();
+ 
+-  /* in cases like ldp r1,r2,[r1] we emit ldr r2,[r1] first.  */
+-  if (src_regno == reg_no_1)
+-    std::swap (load_insn_1, load_insn_2);
++      if (GET_CODE (addr_expr) == PRE_DEC || GET_CODE (addr_expr) == POST_DEC)
++	index_offset = -index_offset;
+ 
+-  rtx_insn *emited_load_insn_1 = emit_insn (PATTERN (load_insn_1));
+-  rtx_insn *emited_load_insn_2 = emit_insn (PATTERN (load_insn_2));
++      if (GET_CODE (addr_expr) == POST_INC || GET_CODE (addr_expr) == POST_DEC)
++	post_index = true;
+ 
+-  INSN_CODE (emited_load_insn_1)
+-      = recog (PATTERN (emited_load_insn_1), emited_load_insn_1, 0);
+-  INSN_CODE (emited_load_insn_2)
+-      = recog (PATTERN (emited_load_insn_2), emited_load_insn_2, 0);
++      reg_index_rtx = gen_rtx_SET (base_reg,
++				   gen_rtx_PLUS (DImode, base_reg,
++						 GEN_INT (index_offset)));
++    }
+ 
+-  rtx_insn *seq = get_insns ();
+-  unshare_all_rtl_in_chain (seq);
+-  end_sequence ();
++  /* In cases like ldp r1,r2,[r1] we emit ldr r2,[r1] first.  */
++  if (REGNO (base_reg) == REGNO (dest_reg))
++    std::swap (load_rtx_1, load_rtx_2);
+ 
+-  emit_insn_after_setloc (seq, prev_insn, INSN_LOCATION (insn));
+-  delete_insn_and_edges (insn);
+-}
++  /* Construct the instruction chain for subsequent emitting.  */
++  rtx_insn *insn_seq = make_insn_raw (load_rtx_1);
++  rtx_insn *load_insn_2 = make_insn_raw (load_rtx_2);
++  SET_NEXT_INSN (insn_seq) = load_insn_2;
++  SET_NEXT_INSN (load_insn_2) = NULL;
++  if (post_index && reg_index_rtx)
++    {
++      rtx_insn *post_index_insn = make_insn_raw (reg_index_rtx);
++      SET_NEXT_INSN (load_insn_2) = post_index_insn;
++      SET_NEXT_INSN (post_index_insn) = NULL;
++    }
++  else if (!post_index && reg_index_rtx)
++    {
++      rtx_insn *pre_index = make_insn_raw (reg_index_rtx);
++      SET_NEXT_INSN (pre_index) = insn_seq;
++      insn_seq = pre_index;
++    }
+ 
+-void
+-pass_split_complex_instructions::split_complex_insn (rtx_insn *insn)
+-{
+-  complex_instructions_t insn_type = get_insn_type (insn);
+-  /* TODO: Add splitting of STP instructions.  */
+-  if (insn_type == LDP || insn_type == STP)
+-    split_ldp_stp (insn);
+-  else if (insn_type == LDP_TI)
+-    split_ldp_ti (insn);
+-  else
+-    gcc_assert (false && "Unsupported type of insn to split");
++  replace_insn (insn, insn_seq);
+ }
+ 
+-pass_split_complex_instructions::complex_instructions_t
++pass_split_complex_instructions::mem_access_insn_t
+ pass_split_complex_instructions::get_insn_type (rtx_insn *insn)
+ {
+   if (!INSN_P (insn))
+     return UNDEFINED;
+ 
+-  rtx pat = PATTERN (insn);
+-  int icode = recog (PATTERN (insn), insn, NULL);
++  int icode = INSN_CODE (insn);
++  if (icode == -1)
++    icode = recog (PATTERN (insn), insn, 0);
++  bool has_wb = false;
++
++  if (targetm.is_ldp_insn (icode, &has_wb))
++    return (has_wb ? LDP_WB : LDP);
+ 
+-  if (GET_CODE (pat) == PARALLEL)
++  if (targetm.is_stp_insn (icode, &has_wb))
++    return (has_wb ? STP_WB : STP);
++
++  rtx set_insn = single_set (insn);
++  if (set_insn && (GET_MODE (SET_SRC (set_insn)) == E_TImode
++      || GET_MODE (SET_DEST (set_insn)) == E_TImode))
+     {
+-      if (targetm.is_ldp_insn (icode))
+-	{
+-	  return LDP;
+-	}
+-      if (targetm.is_stp_insn (icode))
+-	{
+-	  return STP;
+-	}
+-      else
+-	{
+-	  return UNDEFINED;
+-	}
++      if (MEM_P (SET_SRC (set_insn)) && REG_P (SET_DEST (set_insn)))
++	return LDP_TI;
++      if (MEM_P (SET_DEST (set_insn)) && REG_P (SET_SRC (set_insn)))
++	return STP_TI;
+     }
+-  rtx set_insn = single_set (insn);
+-  if (set_insn && GET_CODE (XEXP (set_insn, 1)) == MEM
+-      && GET_MODE (XEXP (set_insn, 1)) == E_TImode)
+-    return LDP_TI;
++
++  if (set_insn && MEM_P (SET_DEST (set_insn)) && REG_P (SET_SRC (set_insn))
++      && GET_MODE (SET_DEST (set_insn)) != BLKmode)
++    return STR;
+ 
+   return UNDEFINED;
+ }
+diff --git a/gcc/target.def b/gcc/target.def
+index a3a50b474..8797a21d5 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -2679,13 +2679,19 @@ modes and they have different conditional execution capability, such as ARM.",
+ 
+ DEFHOOK
+ (is_ldp_insn,
+-  "Return true if icode is corresponding to any of the LDP instruction types.",
+-  bool, (int icode), NULL)
++ "Return true if @var{icode} is corresponding to any of the LDP instruction\n\
++types.  If @var{has_wb} is not NULL then its value is set to true if LDP\n\
++contains post-index or pre-index operation.",
++  bool, (int icode, bool *has_wb),
++  NULL)
+ 
+ DEFHOOK
+ (is_stp_insn,
+-  "Return true if icode is corresponding to any of the STP instruction types.",
+-  bool, (int icode), NULL)
++ "Return true if @var{icode} is corresponding to any of the STP instruction\n\
++types.  If @var{has_wb} is not NULL then its value is set to true if STP\n\
++contains post-index or pre-index operation.",
++  bool, (int icode, bool *has_wb),
++  NULL)
+ 
+ DEFHOOK
+ (gen_ccmp_first,
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c
+index 3918d43f6..2d42231dc 100644
+--- a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-dont-split.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target aarch64-*-* } } */
+-/* { dg-additional-options "-fsplit-ldp-stp" } */
++/* { dg-additional-options "-O1 -fsplit-ldp-stp" } */
+ /*
+  *    Tests are:
+  *          Patterns where LDP insns should NOT be split
+@@ -15,6 +15,9 @@ simple_ldp_after_store ()
+       (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
+       (cinsn 228 (set (reg/i:DI sp) 
+                    (reg/i:DI x0)))
++      (cinsn 238 (set (reg/i:DI x1)
++                   (reg/i:DI x0)))
++
+       (cinsn 101 (set (mem/c:DI
+                         (plus:DI (reg/f:DI sp)
+                           (const_int 32))[1 S4 A32])(reg:DI x0)))
+@@ -24,11 +27,27 @@ simple_ldp_after_store ()
+         (set (reg:DI x30)
+           (mem:DI (plus:DI (reg/f:DI sp)
+             (const_int 16)) [1 S4 A32]))]))
+-      (cinsn 11 (use (reg/i:DI sp)))
+-      (cinsn 12 (use (reg/i:DI cc)))
+-      (cinsn 13 (use (reg/i:DI x29)))
+-      (cinsn 14 (use (reg/i:DI x30)))
+-      (cinsn 15 (use (reg/i:DI x0)))
++      (cinsn 11 (use (reg/i:DI x29)))
++      (cinsn 12 (use (reg/i:DI x30)))
++
++      /* stp x0, x2, [x1].  */
++      (cinsn 102 (parallel [
++        (set (mem:DI (reg/f:DI x1) [1 S4 A32])
++             (reg:DI x0))
++        (set (mem:DI (plus:DI (reg/f:DI x1) (const_int 8)) [1 S4 A32])
++             (reg:DI x2))]))
++      /* ldp x5, x6, [x1].  */
++      (cinsn 13 (parallel [
++        (set (reg:DI x5) (mem:DI (reg/f:DI x1) [1 S4 A32]))
++        (set (reg:DI x6) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 8)) [1 S4 A32]))
++      ]))
++      (cinsn 14 (use (reg/i:DI x5)))
++      (cinsn 15 (use (reg/i:DI x6)))
++
++      (cinsn 100 (use (reg/i:DI sp)))
++      (cinsn 200 (use (reg/i:DI cc)))
++      (cinsn 300 (use (reg/i:DI x0)))
+       (edge-to exit (flags "FALLTHRU"))
+     ) ;; block 2
+   ) ;; insn-chain
+@@ -70,5 +89,5 @@ ldp_after_store_in_different_bb ()
+ ) ;; function "ldp_after_store_in_different_bb"
+ }
+ 
+-/* Verify that the output code contains exactly 2 ldp.  */
+-/* { dg-final { scan-assembler-times {ldp\t} 2 } }  */
+\ No newline at end of file
++/* Verify that the output code contains exactly 3 ldp.  */
++/* { dg-final { scan-assembler-times {ldp\t} 3 } }  */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c
+index 653c30f83..59ff82df9 100644
+--- a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split-rearrange.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target aarch64-*-* } } */
+-/* { dg-additional-options "-fsplit-ldp-stp" } */
++/* { dg-additional-options "-O1 -fsplit-ldp-stp" } */
+ /*
+  *    Test is:
+  *        Pattern where LDP insns should be split with rearrangement in order
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c
+index dc9f26efb..e25762160 100644
+--- a/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/test-ldp-split.c
+@@ -13,48 +13,131 @@ simple_ldp_after_store ()
+     (block 2
+       (edge-from entry (flags "FALLTHRU"))
+       (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      /* mov sp, x0.  */
+       (cinsn 228 (set (reg/i:DI sp)
+-                   (reg/i:DI x0)))
++                      (reg/i:DI x0)))
++      /* mov x1, x0.  */
+       (cinsn 238 (set (reg/i:DI x1)
+-                   (reg/i:DI x0)))
++                      (reg/i:DI x0)))
+ 
++      /* str x0, [sp, 8].  */
+       (cinsn 101 (set (mem/c:DI
+                         (plus:DI (reg/f:DI sp)
+                           (const_int 8))[1 S4 A32])(reg:DI x0)))
++      /* ldp x29, x30, [sp, 8].  */
+       (cinsn 10 (parallel [
+         (set (reg:DI x29)
+           (mem:DI (plus:DI (reg/f:DI sp) (const_int 8)) [1 S4 A32]))
+         (set (reg:DI x30)
+           (mem:DI (plus:DI (reg/f:DI sp)
+             (const_int 16)) [1 S4 A32]))]))
++      (cinsn 11 (use (reg/i:DI x29)))
++      (cinsn 12 (use (reg/i:DI x30)))
+ 
++      /* str x0, [x1, -16].  */
+       (cinsn 102 (set (mem/c:DI (plus:DI (reg/f:DI x1)
+                                           (const_int -16)) [1 S4 A32])
+                       (reg:DI x0)))
+-      (cinsn 11 (parallel [
++      /* ldp x3, x4, [x1, -16].  */
++      (cinsn 13 (parallel [
+         (set (reg:DI x3)
+           (mem:DI (plus:DI (reg/f:DI x1) (const_int -16)) [1 S4 A32]))
+         (set (reg:DI x4)
+           (mem:DI (plus:DI (reg/f:DI x1) (const_int -8)) [1 S4 A32]))
+       ]))
++      (cinsn 14 (use (reg/i:DI x3)))
++      (cinsn 15 (use (reg/i:DI x4)))
+ 
++      /* str x0, [x1].  */
+       (cinsn 103 (set (mem/c:DI (reg/f:DI x1) [1 S4 A32])
+                       (reg:DI x0)))
+-      (cinsn 12 (parallel [
++      /* ldp x5, x6, [x1].  */
++      (cinsn 16 (parallel [
+         (set (reg:DI x5) (mem:DI (reg/f:DI x1) [1 S4 A32]))
+         (set (reg:DI x6) (mem:DI (plus:DI (reg/f:DI x1)
+                                           (const_int 8)) [1 S4 A32]))
+       ]))
++      (cinsn 17 (use (reg/i:DI x5)))
++      (cinsn 18 (use (reg/i:DI x6)))
+ 
+-      (cinsn 13 (use (reg/i:DI sp)))
+-      (cinsn 14 (use (reg/i:DI cc)))
+-      (cinsn 15 (use (reg/i:DI x29)))
+-      (cinsn 16 (use (reg/i:DI x30)))
+-      (cinsn 17 (use (reg/i:DI x0)))
+-      (cinsn 18 (use (reg/i:DI x3)))
+-      (cinsn 19 (use (reg/i:DI x4)))
+-      (cinsn 20 (use (reg/i:DI x5)))
+-      (cinsn 21 (use (reg/i:DI x6)))
++      /* ldp x29, x30, [sp], 96.  */
++      (cinsn 19 (parallel [
++        (set (reg/f:DI sp)
++          (plus:DI (reg/f:DI sp) (const_int 96)))
++        (set (reg:DI x29)
++          (mem:DI (reg/f:DI sp) [1 S4 A32]))
++        (set (reg:DI x30)
++          (mem:DI (plus:DI (reg/f:DI sp)
++            (const_int 8)) [1 S4 A32]))]))
++      (cinsn 20 (use (reg/i:DI x29)))
++      (cinsn 21 (use (reg/i:DI x30)))
++
++      /* stp x0, x2, [x1, 128].  */
++      (cinsn 104 (parallel [
++        (set (mem:DI (plus:DI (reg/f:DI x1) (const_int 128)) [1 S4 A32])
++             (reg:DI x0))
++        (set (mem:DI (plus:DI (reg/f:DI x1) (const_int 136)) [1 S4 A32])
++             (reg:DI x2))]))
++      /* ldp x29, x30, [x1, 120].  */
++      (cinsn 22 (parallel [
++        (set (reg:DI x29)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int 120)) [1 S4 A32]))
++        (set (reg:DI x30)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int 128)) [1 S4 A32]))]))
++      (cinsn 23 (use (reg/i:DI x29)))
++      (cinsn 24 (use (reg/i:DI x30)))
++
++      /* stp x0, x2, [x1, 128].  */
++      (cinsn 105 (parallel [
++        (set (mem:DI (plus:DI (reg/f:DI x1) (const_int 128)) [1 S4 A32])
++             (reg:DI x0))
++        (set (mem:DI (plus:DI (reg/f:DI x1) (const_int 136)) [1 S4 A32])
++             (reg:DI x2))]))
++      /* ldp x3, x4, [x1, 136].  */
++      (cinsn 25 (parallel [
++        (set (reg:DI x3)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int 136)) [1 S4 A32]))
++        (set (reg:DI x4)
++          (mem:DI (plus:DI (reg/f:DI x1) (const_int 144)) [1 S4 A32]))
++      ]))
++      (cinsn 26 (use (reg/i:DI x3)))
++      (cinsn 27 (use (reg/i:DI x4)))
++
++      /* stp w0, w2, [x1, 32].  */
++      (cinsn 106 (parallel [
++        (set (mem:SI (plus:DI (reg/f:DI x1) (const_int 32)) [1 S4 A32])
++             (reg:SI x0))
++        (set (mem:SI (plus:DI (reg/f:DI x1) (const_int 36)) [1 S4 A32])
++             (reg:SI x2))]))
++      /* ldp x5, x6, [x1, 32].  */
++      (cinsn 28 (parallel [
++        (set (reg:DI x5) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 32)) [1 S4 A32]))
++        (set (reg:DI x6) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 40)) [1 S4 A32]))
++      ]))
++      (cinsn 29 (use (reg/i:DI x5)))
++      (cinsn 30 (use (reg/i:DI x6)))
++
++      /* stp w0, w2, [x1, 40].  */
++      (cinsn 107 (parallel [
++        (set (mem:SI (plus:DI (reg/f:DI x1) (const_int 40)) [1 S4 A32])
++             (reg:SI x0))
++        (set (mem:SI (plus:DI (reg/f:DI x1) (const_int 44)) [1 S4 A32])
++             (reg:SI x2))]))
++      /* ldp x5, x6, [x1, 32].  */
++      (cinsn 31 (parallel [
++        (set (reg:DI x5) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 32)) [1 S4 A32]))
++        (set (reg:DI x6) (mem:DI (plus:DI (reg/f:DI x1)
++                                          (const_int 40)) [1 S4 A32]))
++      ]))
++      (cinsn 32 (use (reg/i:DI x5)))
++      (cinsn 33 (use (reg/i:DI x6)))
++
++      (cinsn 100 (use (reg/i:DI sp)))
++      (cinsn 200 (use (reg/i:DI cc)))
++      (cinsn 400 (use (reg/i:DI x0)))
+       (edge-to exit (flags "FALLTHRU"))
+     ) ;; block 2
+   ) ;; insn-chain
+@@ -69,43 +152,83 @@ ldp_ti_after_store ()
+       (block 2
+       (edge-from entry (flags "FALLTHRU"))
+       (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++      /* mov sp, x0.  */
+       (cinsn 228 (set (reg/i:DI sp)
+-                   (reg/i:DI x0)))
++                      (reg/i:DI x0)))
++      /* mov x2, x0.  */
+       (cinsn 238 (set (reg/i:DI x2)
+-                   (reg/i:DI x0)))
+-
++                      (reg/i:DI x0)))
++      /* str x0, [sp, 136].  */
+       (cinsn 101 (set (mem/c:DI
+                         (plus:DI (reg/f:DI sp)
+                           (const_int 136))[1 S4 A32])(reg:DI x0)))
+-      (insn 81 (set (reg:TI x0 [1 S4 A32])
++      /* ldp x0, x1, [sp, 136].  */
++      (cinsn 81 (set (reg:TI x0 [1 S4 A32])
+               (mem/c:TI (plus:DI (reg/f:DI sp)
+-                      (const_int 136 )) [1 S4 A32]))
+-           (expr_list:REG_EQUIV (mem/c:TI (plus:DI (reg/f:DI sfp)
+-                      (const_int -24 )) [1 S4 A32])
+-              (nil)))
+-
++                      (const_int 136)) [1 S4 A32])))
++      /* str x0, [x2, -16].  */
+       (cinsn 102 (set (mem/c:DI (plus:DI (reg/f:DI x2)
+-                                          (const_int -16)) [1 S4 A32])
++                                         (const_int -16)) [1 S4 A32])
+                       (reg:DI x0)))
+-      (insn 82 (set (reg:TI x3 [1 S4 A32])
++      /* ldp x3, x4, [x2, -16].  */
++      (cinsn 82 (set (reg:TI x3 [1 S4 A32])
+                     (mem/c:TI (plus:DI (reg/f:DI x2)
+-                                        (const_int -16)) [1 S4 A32])))
+-
++                                       (const_int -16)) [1 S4 A32])))
++      /* str x0, [x2].  */
+       (cinsn 103 (set (mem/c:DI (reg/f:DI x2) [1 S4 A32])
+                       (reg:DI x0)))
+-      (insn 83 (set (reg:TI x5 [1 S4 A32])
++      /* ldp x5, x6, [x2].  */
++      (cinsn 83 (set (reg:TI x5 [1 S4 A32])
+                     (mem/c:TI (reg/f:DI x2) [1 S4 A32])))
+ 
++      /* stp x0, x1, [sp, -8].  */
++      (cinsn 104 (set (mem:TI (plus:DI (reg/v/f:DI sp)
++                                       (const_int -8)) [1 S4 A32])
++                      (reg:TI x0)))
++      /* ldp x5, x6, [sp], -16.  */
++      (cinsn 84 (set (reg/v:TI x5 [1 S4 A32])
++                    (mem:TI (post_dec:DI (reg/v/f:DI sp)) [1 S4 A32])))
++      (cinsn 85 (use (reg/i:DI x5)))
++      (cinsn 86 (use (reg/i:DI x6)))
++
++      /* stp x0, x1, [sp, 8].  */
++      (cinsn 105 (set (mem:TI (plus:DI (reg/v/f:DI sp)
++                                       (const_int 8)) [1 S4 A32])
++                      (reg:TI x0)))
++      /* ldp x5, x6, [sp], -16.  */
++      (cinsn 87 (set (reg/v:TI x5 [1 S4 A32])
++                    (mem:TI (post_dec:DI (reg/v/f:DI sp)) [1 S4 A32])))
++      (cinsn 88 (use (reg/i:DI x5)))
++      (cinsn 89 (use (reg/i:DI x6)))
++
++      /* Intersects with insn 102.  */
++      /* ldp x2, x3, [x2, -16]!.  */
++      (cinsn 90 (set (reg/v:TI x2 [1 S4 A32])
++                    (mem:TI (pre_dec:DI (reg/v/f:DI x2)) [1 S4 A32])))
++      (cinsn 91 (use (reg/i:DI x2)))
++      (cinsn 92 (use (reg/i:DI x3)))
++
++      /* mov x2, x0.  */
++      (cinsn 248 (set (reg/i:DI x2)
++                      (reg/i:DI x0)))
++      /* str x0, [x2, 16].  */
++      (cinsn 106 (set (mem:DI (plus:DI (reg/v/f:DI x2)
++                                       (const_int 16)) [1 S4 A32])
++                      (reg:DI x0)))
++      /* ldp x3, x4, [x2, 16]!.  */
++      (cinsn 93 (set (reg/v:TI x3 [1 S4 A32])
++                    (mem:TI (pre_inc:DI (reg/v/f:DI x2)) [1 S4 A32])))
++      (cinsn 94 (use (reg/i:DI x3)))
++      (cinsn 95 (use (reg/i:DI x4)))
++
+       (cinsn 11 (use (reg/i:DI sp)))
+       (cinsn 12 (use (reg/i:DI cc)))
+       (cinsn 13 (use (reg/i:DI x29)))
+       (cinsn 14 (use (reg/i:DI x30)))
+       (cinsn 15 (use (reg/i:DI x0)))
+       (cinsn 16 (use (reg/i:DI x3)))
+-      (cinsn 17 (use (reg/i:DI x5)))
+       (cinsn 18 (use (reg/i:DI x1)))
+       (cinsn 19 (use (reg/i:DI x4)))
+-      (cinsn 20 (use (reg/i:DI x6)))
+       (edge-to exit (flags "FALLTHRU"))
+     ) ;; block 2
+   ) ;; insn-chain
+-- 
+2.33.0
+
diff --git a/0044-Port-maxmin-patch-to-GCC-12.patch b/0044-Port-maxmin-patch-to-GCC-12.patch
new file mode 100644
index 0000000..2423c12
--- /dev/null
+++ b/0044-Port-maxmin-patch-to-GCC-12.patch
@@ -0,0 +1,378 @@
+From a3013c074cd2ab5f71eb98a587a627f38c68656c Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Thu, 22 Feb 2024 17:07:24 +0800
+Subject: [PATCH 12/18] Port maxmin patch to GCC 12
+
+---
+ gcc/config/aarch64/aarch64-simd.md    | 256 ++++++++++++++++++++++++++
+ gcc/config/aarch64/predicates.md      |  19 ++
+ gcc/testsuite/gcc.dg/combine-maxmin.c |  46 +++++
+ 3 files changed, 321 insertions(+)
+ create mode 100755 gcc/testsuite/gcc.dg/combine-maxmin.c
+
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index 82f73805f..de92802f5 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -1138,6 +1138,82 @@
+   [(set_attr "type" "neon_compare,neon_shift_imm")]
+ )
+ 
++;; Simplify the extension with following truncation for shift+neg operation.
++
++(define_insn_and_split "*aarch64_sshr_neg_v8hi"
++  [(set (match_operand:V8HI 0 "register_operand" "=w")
++	(vec_concat:V8HI
++	  (truncate:V4HI
++	    (ashiftrt:V4SI
++	      (neg:V4SI
++		(sign_extend:V4SI
++		  (vec_select:V4HI
++		    (match_operand:V8HI 1 "register_operand")
++		    (match_operand:V8HI 3 "vect_par_cnst_lo_half"))))
++	      (match_operand:V4SI 2 "maxmin_arith_shift_operand")))
++	  (truncate:V4HI
++	    (ashiftrt:V4SI
++	      (neg:V4SI
++		(sign_extend:V4SI
++		  (vec_select:V4HI
++		    (match_dup 1)
++		    (match_operand:V8HI 4 "vect_par_cnst_hi_half"))))
++	      (match_dup 2)))))]
++  "TARGET_SIMD"
++  "#"
++  "&& true"
++  [(set (match_operand:V8HI 0 "register_operand" "=w")
++	(ashiftrt:V8HI
++	  (neg:V8HI
++	    (match_operand:V8HI 1 "register_operand" "w"))
++	  (match_operand:V8HI 2 "aarch64_simd_imm_minus_one")))]
++  {
++    /* Reduce the shift amount to smaller mode.  */
++    int val = INTVAL (CONST_VECTOR_ENCODED_ELT (operands[2], 0))
++	      - (GET_MODE_UNIT_BITSIZE (GET_MODE (operands[2])) / 2);
++    operands[2] = aarch64_simd_gen_const_vector_dup (V8HImode, val);
++  }
++  [(set_attr "type" "multiple")]
++)
++
++;; The helper definition that allows combiner to use the previous pattern.
++
++(define_insn_and_split "*aarch64_sshr_neg_tmpv8hi"
++  [(set (match_operand:V8HI 0 "register_operand" "=w")
++	(vec_concat:V8HI
++	  (truncate:V4HI
++	    (ashiftrt:V4SI
++	      (neg:V4SI
++		(match_operand:V4SI 1 "register_operand" "w"))
++	      (match_operand:V4SI 2 "maxmin_arith_shift_operand")))
++	  (truncate:V4HI
++	    (ashiftrt:V4SI
++	      (neg:V4SI
++		(match_operand:V4SI 3 "register_operand" "w"))
++	      (match_dup 2)))))]
++  "TARGET_SIMD"
++  "#"
++  "&& true"
++  [(set (match_operand:V4SI 1 "register_operand" "=w")
++	(ashiftrt:V4SI
++	  (neg:V4SI
++	    (match_dup 1))
++	  (match_operand:V4SI 2 "maxmin_arith_shift_operand")))
++   (set (match_operand:V4SI 3 "register_operand" "=w")
++	(ashiftrt:V4SI
++	  (neg:V4SI
++	    (match_dup 3))
++	  (match_dup 2)))
++   (set (match_operand:V8HI 0 "register_operand" "=w")
++	(vec_concat:V8HI
++	  (truncate:V4HI
++	    (match_dup 1))
++	  (truncate:V4HI
++	    (match_dup 3))))]
++  ""
++  [(set_attr "type" "multiple")]
++)
++
+ (define_insn "*aarch64_simd_sra"
+  [(set (match_operand:VDQ_I 0 "register_operand" "=w")
+ 	(plus:VDQ_I
+@@ -1714,6 +1790,26 @@
+  }
+ )
+ 
++(define_insn "vec_pack_trunc_shifted_"
++ [(set (match_operand: 0 "register_operand" "=&w")
++       (vec_concat:
++	 (truncate:
++	   (ashiftrt:VQN (match_operand:VQN 1 "register_operand" "w")
++	      (match_operand:VQN 2 "half_size_operand" "w")))
++	 (truncate:
++	   (ashiftrt:VQN (match_operand:VQN 3 "register_operand" "w")
++	      (match_operand:VQN 4 "half_size_operand" "w")))))]
++ "TARGET_SIMD"
++ {
++   if (BYTES_BIG_ENDIAN)
++     return "uzp2\\t%0., %3., %1.";
++   else
++     return "uzp2\\t%0., %1., %3.";
++ }
++  [(set_attr "type" "neon_permute")
++   (set_attr "length" "4")]
++)
++
+ (define_insn "aarch64_shrn_insn_le"
+   [(set (match_operand: 0 "register_operand" "=w")
+ 	(vec_concat:
+@@ -6652,6 +6748,166 @@
+   [(set_attr "type" "neon_tst")]
+ )
+ 
++;; Simplify the extension with following truncation for cmtst-like operation.
++
++(define_insn_and_split "*aarch64_cmtst_arith_v8hi"
++  [(set (match_operand:V8HI 0 "register_operand" "=w")
++	(vec_concat:V8HI
++	  (plus:V4HI
++	    (truncate:V4HI
++	      (eq:V4SI
++		(sign_extend:V4SI
++		  (vec_select:V4HI
++		    (and:V8HI
++		      (match_operand:V8HI 1 "register_operand")
++		      (match_operand:V8HI 2 "aarch64_bic_imm_for_maxmin"))
++		    (match_operand:V8HI 3 "vect_par_cnst_lo_half")))
++		(match_operand:V4SI 4 "aarch64_simd_or_scalar_imm_zero")))
++	    (match_operand:V4HI 5 "aarch64_simd_imm_minus_one"))
++	  (plus:V4HI
++	    (truncate:V4HI
++	      (eq:V4SI
++		(sign_extend:V4SI
++		  (vec_select:V4HI
++		    (and:V8HI
++		      (match_dup 1)
++		      (match_dup 2))
++		    (match_operand:V8HI 6 "vect_par_cnst_hi_half")))
++		(match_dup 4)))
++	    (match_dup 5))))]
++  "TARGET_SIMD && !reload_completed"
++  "#"
++  "&& true"
++  [(set (match_operand:V8HI 6 "register_operand" "=w")
++	(match_operand:V8HI 2 "aarch64_bic_imm_for_maxmin"))
++   (set (match_operand:V8HI 0 "register_operand" "=w")
++	(plus:V8HI
++	  (eq:V8HI
++	    (and:V8HI
++	      (match_operand:V8HI 1 "register_operand" "w")
++	      (match_dup 6))
++	    (match_operand:V8HI 4 "aarch64_simd_imm_zero"))
++	  (match_operand:V8HI 5 "aarch64_simd_imm_minus_one")))]
++  {
++    if (can_create_pseudo_p ())
++      {
++	int val = INTVAL (CONST_VECTOR_ENCODED_ELT (operands[4], 0));
++	operands[4] = aarch64_simd_gen_const_vector_dup (V8HImode, val);
++	int val2 = INTVAL (CONST_VECTOR_ENCODED_ELT (operands[5], 0));
++	operands[5] = aarch64_simd_gen_const_vector_dup (V8HImode, val2);
++
++	operands[6] = gen_reg_rtx (V8HImode);
++      }
++    else
++      FAIL;
++  }
++  [(set_attr "type" "neon_tst_q")]
++)
++
++;; Three helper definitions that allow combiner to use the previous pattern.
++
++(define_insn_and_split "*aarch64_cmtst_arith_tmp_lo_v8hi"
++  [(set (match_operand:V4SI 0 "register_operand" "=w")
++	(neg:V4SI
++	  (eq:V4SI
++	    (sign_extend:V4SI
++	      (vec_select:V4HI
++		(and:V8HI
++		  (match_operand:V8HI 1 "register_operand")
++		  (match_operand:V8HI 2 "aarch64_bic_imm_for_maxmin"))
++		(match_operand:V8HI 3 "vect_par_cnst_lo_half")))
++	    (match_operand:V4SI 4 "aarch64_simd_or_scalar_imm_zero"))))]
++  "TARGET_SIMD && !reload_completed"
++  "#"
++  "&& true"
++  [(set (match_operand:V8HI 5 "register_operand" "=w")
++	(and:V8HI
++	  (match_operand:V8HI 1 "register_operand")
++	  (match_operand:V8HI 2 "aarch64_bic_imm_for_maxmin")))
++   (set (match_operand:V4SI 0 "register_operand" "=w")
++	(sign_extend:V4SI
++	  (vec_select:V4HI
++	    (match_dup 5)
++	    (match_operand:V8HI 3 "vect_par_cnst_lo_half"))))
++   (set (match_dup 0)
++	(neg:V4SI
++	  (eq:V4SI
++	    (match_dup 0)
++	    (match_operand:V4SI 4 "aarch64_simd_or_scalar_imm_zero"))))]
++  {
++    if (can_create_pseudo_p ())
++      operands[5] = gen_reg_rtx (V8HImode);
++    else
++      FAIL;
++  }
++  [(set_attr "type" "multiple")]
++)
++
++(define_insn_and_split "*aarch64_cmtst_arith_tmp_hi_v8hi"
++  [(set (match_operand:V4SI 0 "register_operand" "=w")
++	  (neg:V4SI
++	    (eq:V4SI
++	      (sign_extend:V4SI
++		(vec_select:V4HI
++		  (and:V8HI
++		    (match_operand:V8HI 1 "register_operand")
++		    (match_operand:V8HI 2 "aarch64_bic_imm_for_maxmin"))
++		  (match_operand:V8HI 3 "vect_par_cnst_hi_half")))
++	      (match_operand:V4SI 4 "aarch64_simd_or_scalar_imm_zero"))))]
++  "TARGET_SIMD && !reload_completed"
++  "#"
++  "&& true"
++  [(set (match_operand:V8HI 5 "register_operand" "=w")
++	(and:V8HI
++	  (match_operand:V8HI 1 "register_operand")
++	  (match_operand:V8HI 2 "aarch64_bic_imm_for_maxmin")))
++   (set (match_operand:V4SI 0 "register_operand" "=w")
++	(sign_extend:V4SI
++	  (vec_select:V4HI
++	    (match_dup 5)
++	    (match_operand:V8HI 3 "vect_par_cnst_hi_half"))))
++   (set (match_dup 0)
++	  (neg:V4SI
++	    (eq:V4SI
++	      (match_dup 0)
++	      (match_operand:V4SI 4 "aarch64_simd_or_scalar_imm_zero"))))]
++  {
++    if (can_create_pseudo_p ())
++      operands[5] = gen_reg_rtx (V8HImode);
++    else
++      FAIL;
++  }
++  [(set_attr "type" "multiple")]
++)
++
++(define_insn_and_split "*aarch64_cmtst_arith_tmpv8hi"
++  [(set (match_operand:V8HI 0 "register_operand" "=w")
++	(vec_concat:V8HI
++	  (truncate:V4HI
++	    (not:V4SI
++	      (match_operand:V4SI 1 "register_operand" "w")))
++	  (truncate:V4HI
++	    (not:V4SI
++	      (match_operand:V4SI 2 "register_operand" "w")))))]
++  "TARGET_SIMD"
++  "#"
++  "&& true"
++  [(set (match_operand:V4SI 1 "register_operand" "=w")
++	(not:V4SI
++	  (match_dup 1)))
++   (set (match_operand:V4SI 2 "register_operand" "=w")
++	(not:V4SI
++	  (match_dup 2)))
++   (set (match_operand:V8HI 0 "register_operand" "=w")
++	(vec_concat:V8HI
++	  (truncate:V4HI
++	    (match_dup 1))
++	  (truncate:V4HI
++	    (match_dup 2))))]
++  ""
++  [(set_attr "type" "multiple")]
++)
++
+ (define_insn_and_split "aarch64_cmtstdi"
+   [(set (match_operand:DI 0 "register_operand" "=w,r")
+ 	(neg:DI
+diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
+index 07c14aacb..1b8496c07 100644
+--- a/gcc/config/aarch64/predicates.md
++++ b/gcc/config/aarch64/predicates.md
+@@ -118,6 +118,25 @@
+ 	     (match_test "aarch64_simd_valid_immediate (op, NULL,
+ 							AARCH64_CHECK_ORR)"))))
+ 
++(define_predicate "aarch64_bic_imm_for_maxmin"
++   (match_code "const_vector")
++{
++  if (!aarch64_simd_valid_immediate (op, NULL, AARCH64_CHECK_BIC))
++    return false;
++  op = unwrap_const_vec_duplicate (op);
++  unsigned int size = GET_MODE_UNIT_BITSIZE (mode);
++  return CONST_INT_P (op)
++	 && ((~UINTVAL (op)) < (((long unsigned int) 1 << size) - 1));
++})
++
++(define_predicate "maxmin_arith_shift_operand"
++   (match_code "const_vector")
++{
++  op = unwrap_const_vec_duplicate (op);
++  unsigned int size = GET_MODE_UNIT_BITSIZE (mode) - 1;
++  return CONST_INT_P (op) && (UINTVAL (op) == size);
++})
++
+ (define_predicate "aarch64_reg_or_bic_imm"
+    (ior (match_operand 0 "register_operand")
+ 	(and (match_code "const_vector")
+diff --git a/gcc/testsuite/gcc.dg/combine-maxmin.c b/gcc/testsuite/gcc.dg/combine-maxmin.c
+new file mode 100755
+index 000000000..06bce7029
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/combine-maxmin.c
+@@ -0,0 +1,46 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-options "-O3 -fdump-rtl-combine-all" } */
++
++/* The test checks usage of smax/smin insns for clip evaluation and
++ * uzp1/uzp2 insns for vector element narrowing.  It's inspired by
++ * sources of x264 codec.  */
++
++typedef unsigned char uint8_t;
++typedef long int intptr_t;
++typedef signed short int int16_t;
++
++static __attribute__((always_inline)) inline uint8_t clip (int x )
++{
++    return ( (x & ~((1 << 8)-1)) ? (-x)>>31 & ((1 << 8)-1) : x );
++}
++
++void hf (uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, uint8_t *src,
++	 intptr_t stride, int width, int height, int16_t *buf)
++{
++    const int pad = (8 > 9) ? (-10 * ((1 << 8)-1)) : 0;
++    for( int y = 0; y < height; y++ ) {
++        for( int x = -2; x < width+3; x++ ) {
++            int v = ((src)[x-2*stride] + (src)[x+3*stride] - 5*((src)[x-stride]
++		     + (src)[x+2*stride]) + 20*((src)[x] + (src)[x+stride]));
++            dstv[x] = clip ( (v + 16) >> 5 );
++            buf[x+2] = v + pad;
++        }
++        for( int x = 0; x < width; x++ )
++            dstc[x] = clip ((((buf+2)[x-2*1] + (buf+2)[x+3*1] - 5*((buf+2)[x-1]
++			      + (buf+2)[x+2*1]) + 20*((buf+2)[x] + (buf+2)[x+1]))
++			     - 32*pad + 512) >> 10);
++        for( int x = 0; x < width; x++ )
++            dsth[x] = clip ((((src)[x-2*1] + (src)[x+3*1] - 5*((src)[x-1]
++			      + (src)[x+2*1]) + 20*((src)[x] + (src)[x+1]))
++			     + 16) >> 5);
++        dsth += stride;
++        dstv += stride;
++        dstc += stride;
++        src += stride;
++    }
++}
++
++/* { dg-final { scan-assembler-times {smax\t} 4 } }  */
++/* { dg-final { scan-assembler-times {smin\t} 4 } }  */
++/* { dg-final { scan-assembler-times {cmtst\t} 2 } }  */
++/* { dg-final { scan-assembler-times {uzp1\t} 6 } }  */
+-- 
+2.33.0
+
diff --git a/0045-Port-moving-minmask-pattern-to-gimple-to-GCC-12.patch b/0045-Port-moving-minmask-pattern-to-gimple-to-GCC-12.patch
new file mode 100644
index 0000000..a5a786f
--- /dev/null
+++ b/0045-Port-moving-minmask-pattern-to-gimple-to-GCC-12.patch
@@ -0,0 +1,239 @@
+From 11da40d18e35219961226d40f11b0702b8649044 Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 00812787 
+Date: Thu, 22 Feb 2024 17:13:27 +0800
+Subject: [PATCH 13/18] Port moving minmask pattern to gimple to GCC 12
+
+---
+ gcc/common.opt                          |   4 +
+ gcc/match.pd                            | 104 ++++++++++++++++++++++++
+ gcc/testsuite/gcc.dg/combine-maxmin-1.c |  15 ++++
+ gcc/testsuite/gcc.dg/combine-maxmin-2.c |  14 ++++
+ gcc/testsuite/gcc.dg/combine-maxmin.c   |  19 +++--
+ 5 files changed, 151 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/combine-maxmin-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/combine-maxmin-2.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 6c6fabb31..3a5004271 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1846,6 +1846,10 @@ fif-conversion-gimple
+ Common Var(flag_if_conversion_gimple) Optimization
+ Perform conversion of conditional jumps to branchless equivalents during gimple transformations.
+ 
++fconvert-minmax
++Common Var(flag_convert_minmax) Optimization
++Convert saturating clipping to min max.
++
+ fstack-reuse=
+ Common Joined RejectNegative Enum(stack_reuse_level) Var(flag_stack_reuse) Init(SR_ALL) Optimization
+ -fstack-reuse=[all|named_vars|none]	Set stack reuse level for local variables.
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 61866cb90..3a19e93b3 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -8031,3 +8031,107 @@ and,
+    (plus:c@4 (op2:c @0 @1)
+     (plus:c@5 (double_size_mul_overflow_check_lo @0 @1 @3) (op3:c @0 @1))))
+      (if (single_use (@4) && single_use (@5)))))
++
++/* MinMax pattern matching helpers.  More info on the transformation below.  */
++
++/* Match (a & 0b11..100..0) pattern.  */
++(match (minmax_cmp_arg @0 @1)
++ (bit_and @0 INTEGER_CST@1)
++ (if (wi::popcount (~wi::to_widest (@1) + 1) == 1)))
++
++/* Match (inversed_sign_bit >> sign_bit_pos) pattern.
++   This statement is blocking for the transformation of unsigned integers.
++   Do type check here to avoid unnecessary duplications.  */
++(match (minmax_sat_arg @0)
++ (rshift (negate @0) INTEGER_CST@1)
++ (if (!TYPE_UNSIGNED (TREE_TYPE (@0))
++      && wi::eq_p (wi::to_widest (@1), TYPE_PRECISION (TREE_TYPE (@0)) - 1))))
++
++/* Transform ((x & ~mask) ? (-x)>>31 & mask : x) to (min (max (x, 0), mask)).
++   The matched pattern can be described as saturated clipping.
++
++   The pattern supports truncation via both casts and bit_and.
++   Also there are patterns for possible inverted conditions.  */
++(if (flag_convert_minmax)
++/* Truncation via casts.  Unfortunately convert? cannot be applied here
++   because convert and cond take different number of arguments.  */
++ (simplify
++  (convert
++   (cond
++    (ne (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++    (convert? (minmax_sat_arg @0))
++    (convert? @0)))
++  (if (wi::geu_p (~wi::to_widest (@1) + 1, TYPE_PRECISION (type)))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++ (simplify
++  (cond
++   (ne (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++   (convert? (minmax_sat_arg @0))
++   (convert? @0))
++  (if (wi::geu_p (~wi::to_widest (@1) + 1, TYPE_PRECISION (type)))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++
++ (simplify
++  (convert
++   (cond
++    (eq (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++    (convert? @0)
++    (convert? (minmax_sat_arg @0))))
++  (if (wi::geu_p (~wi::to_widest (@1) + 1, TYPE_PRECISION (type)))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++ (simplify
++  (cond
++   (eq (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++   (convert? @0)
++   (convert? (minmax_sat_arg @0)))
++  (if (wi::geu_p (~wi::to_widest (@1) + 1, TYPE_PRECISION (type)))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++
++ /* Truncation via bit_and with mask.  Same concerns on convert? here.  */
++ (simplify
++  (convert
++   (cond
++    (ne (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++    (convert? (bit_and (minmax_sat_arg @0) INTEGER_CST@2))
++    (convert? @0)))
++  (if (wi::to_widest (@2) == ~wi::to_widest (@1))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++ (simplify
++  (cond
++   (ne (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++   (convert? (bit_and (minmax_sat_arg @0) INTEGER_CST@2))
++   (convert? @0))
++  (if (wi::to_widest (@2) == ~wi::to_widest (@1))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++
++ (simplify
++  (convert
++   (cond
++    (eq (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++    (convert? @0)
++    (convert? (bit_and (minmax_sat_arg @0) INTEGER_CST@2))))
++  (if (wi::to_widest (@2) == ~wi::to_widest (@1))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; })))))
++ (simplify
++  (cond
++   (eq (minmax_cmp_arg @0 INTEGER_CST@1) integer_zerop)
++   (convert? @0)
++   (convert? (bit_and (minmax_sat_arg @0) INTEGER_CST@2)))
++  (if (wi::to_widest (@2) == ~wi::to_widest (@1))
++   (with { tree mask = build_int_cst (integer_type_node, ~tree_to_shwi (@1)); }
++    (convert (min (max @0 { integer_zero_node; })
++		  { mask; }))))))
+diff --git a/gcc/testsuite/gcc.dg/combine-maxmin-1.c b/gcc/testsuite/gcc.dg/combine-maxmin-1.c
+new file mode 100644
+index 000000000..859ff7df8
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/combine-maxmin-1.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-options "-O3 -fconvert-minmax" } */
++
++#include 
++
++__attribute__((noinline))
++void test (int32_t *restrict a, int32_t *restrict x)
++{
++  for (int i = 0; i < 4; i++)
++    a[i] = ((((-x[i]) >> 31) ^ x[i])
++            & (-((int32_t)((x[i] & (~((1 << 8)-1))) == 0)))) ^ ((-x[i]) >> 31);
++}
++
++/* { dg-final { scan-assembler-not {smax\t} } }  */
++/* { dg-final { scan-assembler-not {smin\t} } }  */
+diff --git a/gcc/testsuite/gcc.dg/combine-maxmin-2.c b/gcc/testsuite/gcc.dg/combine-maxmin-2.c
+new file mode 100644
+index 000000000..63d4d85b3
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/combine-maxmin-2.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile { target aarch64-*-* } } */
++/* { dg-options "-O3 -fconvert-minmax" } */
++
++#include 
++
++__attribute__((noinline))
++void test (int8_t *restrict a, int32_t *restrict x)
++{
++  for (int i = 0; i < 8; i++)
++    a[i] = ((x[i] & ~((1 << 9)-1)) ? (-x[i])>>31 & ((1 << 9)-1) : x[i]);
++}
++
++/* { dg-final { scan-assembler-times {smax\t} 4 } }  */
++/* { dg-final { scan-assembler-times {smin\t} 4 } }  */
+diff --git a/gcc/testsuite/gcc.dg/combine-maxmin.c b/gcc/testsuite/gcc.dg/combine-maxmin.c
+index 06bce7029..a984fa560 100755
+--- a/gcc/testsuite/gcc.dg/combine-maxmin.c
++++ b/gcc/testsuite/gcc.dg/combine-maxmin.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target aarch64-*-* } } */
+-/* { dg-options "-O3 -fdump-rtl-combine-all" } */
++/* { dg-options "-O3 -fconvert-minmax" } */
+ 
+ /* The test checks usage of smax/smin insns for clip evaluation and
+  * uzp1/uzp2 insns for vector element narrowing.  It's inspired by
+@@ -19,20 +19,26 @@ void hf (uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, uint8_t *src,
+ {
+     const int pad = (8 > 9) ? (-10 * ((1 << 8)-1)) : 0;
+     for( int y = 0; y < height; y++ ) {
++        /* This loop is not being vectorized now.  */
+         for( int x = -2; x < width+3; x++ ) {
+             int v = ((src)[x-2*stride] + (src)[x+3*stride] - 5*((src)[x-stride]
+ 		     + (src)[x+2*stride]) + 20*((src)[x] + (src)[x+stride]));
+             dstv[x] = clip ( (v + 16) >> 5 );
+             buf[x+2] = v + pad;
+         }
++
++        /* Produces two versions of the code: 3xUZP1/2xMAX/2xMIN + 1xUZP1/1xMAX/1xMIN.  */
+         for( int x = 0; x < width; x++ )
+             dstc[x] = clip ((((buf+2)[x-2*1] + (buf+2)[x+3*1] - 5*((buf+2)[x-1]
+ 			      + (buf+2)[x+2*1]) + 20*((buf+2)[x] + (buf+2)[x+1]))
+ 			     - 32*pad + 512) >> 10);
++
++        /* Priduces two versions of the code: 1xUZP1/2xMAX/2xMIN + 0xUZP1/1xMAX/1xMIN.  */
+         for( int x = 0; x < width; x++ )
+             dsth[x] = clip ((((src)[x-2*1] + (src)[x+3*1] - 5*((src)[x-1]
+ 			      + (src)[x+2*1]) + 20*((src)[x] + (src)[x+1]))
+ 			     + 16) >> 5);
++
+         dsth += stride;
+         dstv += stride;
+         dstc += stride;
+@@ -40,7 +46,10 @@ void hf (uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, uint8_t *src,
+     }
+ }
+ 
+-/* { dg-final { scan-assembler-times {smax\t} 4 } }  */
+-/* { dg-final { scan-assembler-times {smin\t} 4 } }  */
+-/* { dg-final { scan-assembler-times {cmtst\t} 2 } }  */
+-/* { dg-final { scan-assembler-times {uzp1\t} 6 } }  */
++/* Max is performed on 0 from signed values, match smax exactly.  */
++/* { dg-final { scan-assembler-times {smax\t} 6 } }  */
++/* Min is performed on signed val>0 and a mask, min sign doesn't matter.  */
++/* { dg-final { scan-assembler-times {[us]min\t} 6 } }  */
++/* All of the vectorized patterns are expected to be matched.  */
++/* { dg-final { scan-assembler-not {cmtst\t} } }  */
++/* { dg-final { scan-assembler-times {uzp1\t} 5 } }  */
+-- 
+2.33.0
+
diff --git a/0046-Add-new-pattern-to-pass-the-maxmin-tests.patch b/0046-Add-new-pattern-to-pass-the-maxmin-tests.patch
new file mode 100644
index 0000000..9ceba88
--- /dev/null
+++ b/0046-Add-new-pattern-to-pass-the-maxmin-tests.patch
@@ -0,0 +1,65 @@
+From dbcb2630c426c8dd2117b5ce625da8422dd8cd65 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Thu, 22 Feb 2024 17:20:17 +0800
+Subject: [PATCH 14/18] Add new pattern to pass the maxmin tests
+
+---
+ gcc/match.pd                          | 24 ++++++++++++++++++++++++
+ gcc/testsuite/gcc.dg/combine-maxmin.c |  2 +-
+ 2 files changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 3a19e93b3..aee58e47b 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -8038,6 +8038,10 @@ and,
+ (match (minmax_cmp_arg @0 @1)
+  (bit_and @0 INTEGER_CST@1)
+  (if (wi::popcount (~wi::to_widest (@1) + 1) == 1)))
++/* Match ((unsigned) a > 0b0..01..1) pattern.  */
++(match (minmax_cmp_arg1 @0 @1)
++ (gt @0 INTEGER_CST@1)
++ (if (wi::popcount (wi::to_widest (@1) + 1) == 1)))
+ 
+ /* Match (inversed_sign_bit >> sign_bit_pos) pattern.
+    This statement is blocking for the transformation of unsigned integers.
+@@ -8095,6 +8099,26 @@ and,
+     (convert (min (max @0 { integer_zero_node; })
+ 		  { mask; })))))
+ 
++ (simplify
++  (convert
++   (cond
++    (minmax_cmp_arg1 (convert? @0) INTEGER_CST@1)
++    (convert? (minmax_sat_arg @0))
++    (convert? @0)))
++  (if (wi::geu_p (wi::to_widest (@1) + 1, TYPE_PRECISION (type)))
++   (with { tree mask = build_int_cst (integer_type_node, tree_to_shwi (@1)); }
++    (convert (min (max (convert:integer_type_node @0) { integer_zero_node; })
++		  { mask; })))))
++ (simplify
++  (cond
++   (minmax_cmp_arg1 (convert? @0) INTEGER_CST@1)
++   (convert? (minmax_sat_arg @0))
++   (convert? @0))
++  (if (wi::geu_p (wi::to_widest (@1) + 1, TYPE_PRECISION (type)))
++   (with { tree mask = build_int_cst (integer_type_node, tree_to_shwi (@1)); }
++    (convert (min (max (convert:integer_type_node @0) { integer_zero_node; })
++		  { mask; })))))
++
+  /* Truncation via bit_and with mask.  Same concerns on convert? here.  */
+  (simplify
+   (convert
+diff --git a/gcc/testsuite/gcc.dg/combine-maxmin.c b/gcc/testsuite/gcc.dg/combine-maxmin.c
+index a984fa560..5c0c9cc49 100755
+--- a/gcc/testsuite/gcc.dg/combine-maxmin.c
++++ b/gcc/testsuite/gcc.dg/combine-maxmin.c
+@@ -52,4 +52,4 @@ void hf (uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, uint8_t *src,
+ /* { dg-final { scan-assembler-times {[us]min\t} 6 } }  */
+ /* All of the vectorized patterns are expected to be matched.  */
+ /* { dg-final { scan-assembler-not {cmtst\t} } }  */
+-/* { dg-final { scan-assembler-times {uzp1\t} 5 } }  */
++/* { dg-final { scan-assembler-times {uzp1\t} 2 } }  */
+-- 
+2.33.0
+
diff --git a/0047-AES-Implement-AES-pattern-matching.patch b/0047-AES-Implement-AES-pattern-matching.patch
new file mode 100644
index 0000000..cd983bf
--- /dev/null
+++ b/0047-AES-Implement-AES-pattern-matching.patch
@@ -0,0 +1,3968 @@
+From 53d321d2fe08f69a29527be157d4bcaaefea04ab Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 00812787 
+Date: Wed, 6 Dec 2023 10:46:28 +0300
+Subject: [PATCH 15/18] [AES] Implement AES pattern matching
+
+---
+ gcc/Makefile.in                               |    1 +
+ gcc/common.opt                                |    4 +
+ gcc/config/aarch64/aarch64.cc                 |   24 +
+ gcc/crypto-accel.cc                           | 2415 +++++++++++++++++
+ gcc/doc/tm.texi                               |   29 +
+ gcc/doc/tm.texi.in                            |   12 +
+ gcc/passes.def                                |    1 +
+ gcc/rtl-matcher.h                             |  367 +++
+ gcc/target.def                                |   41 +
+ .../gcc.target/aarch64/aes-decrypt.c          |  478 ++++
+ .../gcc.target/aarch64/aes-encrypt.c          |  443 +++
+ gcc/timevar.def                               |    1 +
+ gcc/tree-pass.h                               |    1 +
+ 13 files changed, 3817 insertions(+)
+ create mode 100644 gcc/crypto-accel.cc
+ create mode 100644 gcc/rtl-matcher.h
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/aes-decrypt.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/aes-encrypt.c
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 45705c1f3..876000bda 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1332,6 +1332,7 @@ OBJS = \
+ 	cgraphunit.o \
+ 	cgraphclones.o \
+ 	combine.o \
++	crypto-accel.o \
+ 	combine-stack-adj.o \
+ 	compare-elim.o \
+ 	context.o \
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 3a5004271..1eb62ada5 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1129,6 +1129,10 @@ Common Var(flag_array_widen_compare) Optimization
+ Extends types for pointers to arrays to improve array comparsion performance.
+ In some extreme situations this may result in unsafe behavior.
+ 
++fcrypto-accel-aes
++Common Var(flag_crypto_accel_aes) Init(0) Optimization
++Perform crypto acceleration AES pattern matching.
++
+ fauto-inc-dec
+ Common Var(flag_auto_inc_dec) Init(1) Optimization
+ Generate auto-inc/dec instructions.
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index fa566dd80..9171d9d56 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -27569,6 +27569,30 @@ is_aarch64_stp_insn (int icode, bool *has_wb)
+ #undef TARGET_IS_STP_INSN
+ #define TARGET_IS_STP_INSN is_aarch64_stp_insn
+ 
++machine_mode
++aarch64_get_v16qi_mode ()
++{
++  return V16QImode;
++}
++
++#undef TARGET_GET_V16QI_MODE
++#define TARGET_GET_V16QI_MODE aarch64_get_v16qi_mode
++
++#undef TARGET_GEN_REV32V16QI
++#define TARGET_GEN_REV32V16QI gen_aarch64_rev32v16qi
++
++#undef TARGET_GEN_AESEV16QI
++#define TARGET_GEN_AESEV16QI gen_aarch64_crypto_aesev16qi
++
++#undef TARGET_GEN_AESDV16QI
++#define TARGET_GEN_AESDV16QI gen_aarch64_crypto_aesdv16qi
++
++#undef TARGET_GEN_AESMCV16QI
++#define TARGET_GEN_AESMCV16QI gen_aarch64_crypto_aesmcv16qi
++
++#undef TARGET_GEN_AESIMCV16QI
++#define TARGET_GEN_AESIMCV16QI gen_aarch64_crypto_aesimcv16qi
++
+ #undef TARGET_STACK_PROTECT_GUARD
+ #define TARGET_STACK_PROTECT_GUARD aarch64_stack_protect_guard
+ 
+diff --git a/gcc/crypto-accel.cc b/gcc/crypto-accel.cc
+new file mode 100644
+index 000000000..f4e810a6b
+--- /dev/null
++++ b/gcc/crypto-accel.cc
+@@ -0,0 +1,2415 @@
++/* Crypto-pattern optimizer.
++   Copyright (C) 2003-2023 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
++.  */
++
++#include "config.h"
++#define INCLUDE_VECTOR
++#define INCLUDE_MAP
++#define INCLUDE_SET
++#define INCLUDE_ALGORITHM
++#include "system.h"
++#include "coretypes.h"
++#include "backend.h"
++#include "target.h"
++#include "rtl.h"
++#include "tree.h"
++#include "df.h"
++#include "memmodel.h"
++#include "optabs.h"
++#include "regs.h"
++#include "emit-rtl.h"
++#include "recog.h"
++#include "cfgrtl.h"
++#include "cfgcleanup.h"
++#include "expr.h"
++#include "tree-pass.h"
++#include "rtl-matcher.h"
++
++/* Basic AES table descryption.  */
++struct aes_table
++{
++  /* Number of elements per table.  */
++  static const unsigned int table_nelts = 256;
++  /* Number of tables.  */
++  static const unsigned int basic_tables_num = 4;
++  /* Number of rounds.  */
++  static const unsigned int rounds_num = 4;
++  /* Common ID for wrong table.  */
++  static const unsigned int BAD_TABLE = -1;
++
++  typedef const unsigned int table_type[table_nelts];
++  typedef table_type *table_map[basic_tables_num];
++
++  template
++  static bool is_basic_table (tree ctor, const T ethalon[table_nelts])
++    {
++      if (TREE_CODE (ctor) != CONSTRUCTOR
++	  ||CONSTRUCTOR_NELTS (ctor) != table_nelts)
++	return false;
++
++      unsigned ix;
++      tree val;
++      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val)
++	if (TREE_INT_CST_LOW (val) != ethalon[ix])
++	  return false;
++      return true;
++    }
++
++  static unsigned check_table (tree ctor,
++			       table_map tables)
++    {
++      for (unsigned i = 0; i < 4; ++i)
++	if (is_basic_table (ctor, *tables[i]))
++	  return i;
++      return BAD_TABLE;
++    }
++};
++
++/* AES encryption info.  */
++struct aes_encrypt_table : aes_table
++{
++  typedef enum
++  {
++    TE0,
++    TE1,
++    TE2,
++    TE3,
++    BAD_TABLE = aes_table::BAD_TABLE
++  } table_entry;
++
++  static table_type Te0;
++  static table_type Te1;
++  static table_type Te2;
++  static table_type Te3;
++
++  static table_map tables;
++  static table_entry rounds[rounds_num];
++  static table_entry final_rounds[rounds_num];
++
++  static table_entry get_table_id (tree ctor)
++    {
++      return static_cast (check_table (ctor, tables));
++    }
++};
++
++/* AES decryption info.  */
++struct aes_decrypt_table : aes_table
++{
++  typedef enum
++  {
++    TD0,
++    TD1,
++    TD2,
++    TD3,
++    TD4,
++    BAD_TABLE = aes_table::BAD_TABLE
++  } table_entry;
++
++  static table_type Td0;
++  static table_type Td1;
++  static table_type Td2;
++  static table_type Td3;
++
++  static table_map tables;
++  static table_entry rounds[rounds_num];
++  static table_entry final_rounds[rounds_num];
++
++  static const unsigned char Td4[table_nelts];
++
++  /* TD4 requires special handler due to type shrinking optimizations.  */
++  static bool is_td4 (tree ctor)
++    {
++      if (is_basic_table (ctor, Td4))
++	return true;
++
++      if (TREE_CODE (ctor) != STRING_CST
++	  || TREE_STRING_LENGTH (ctor) != table_nelts)
++	return false;
++
++      const unsigned char *p
++	= (const unsigned char *) TREE_STRING_POINTER (ctor);
++      for (int i = 0; i < TREE_STRING_LENGTH (ctor); ++i)
++	if (p[i] != Td4[i])
++	  return false;
++
++      return true;
++    }
++
++  static table_entry get_table_id (tree ctor)
++    {
++      unsigned int res = check_table (ctor, tables);
++      if (res == aes_table::BAD_TABLE
++	  && is_td4 (ctor))
++	return TD4;
++      return static_cast (res);
++    }
++};
++
++/* Basic tables info.  */
++aes_encrypt_table::table_map aes_encrypt_table::tables
++  = { &Te0, &Te1, &Te2, &Te3 };
++aes_decrypt_table::table_map aes_decrypt_table::tables
++  = { &Td0, &Td1, &Td2, &Td3 };
++
++/* Round tables permutations info.  */
++aes_encrypt_table::table_entry aes_encrypt_table::rounds[]
++  = {TE0, TE1, TE2, TE3};
++aes_decrypt_table::table_entry aes_decrypt_table::rounds[]
++  = {TD0, TD1, TD2, TD3};
++aes_encrypt_table::table_entry aes_encrypt_table::final_rounds[]
++  = {TE2, TE3, TE0, TE1};
++aes_decrypt_table::table_entry aes_decrypt_table::final_rounds[]
++  = {TD4, TD4, TD4, TD4};
++
++aes_encrypt_table::table_type aes_encrypt_table::Te0 = {
++    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
++    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
++    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
++    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
++    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
++    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
++    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
++    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
++    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
++    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
++    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
++    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
++    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
++    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
++    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
++    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
++    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
++    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
++    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
++    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
++    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
++    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
++    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
++    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
++    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
++    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
++    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
++    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
++    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
++    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
++    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
++    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
++    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
++    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
++    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
++    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
++    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
++    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
++    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
++    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
++    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
++    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
++    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
++    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
++    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
++    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
++    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
++    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
++    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
++    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
++    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
++    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
++    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
++    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
++    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
++    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
++    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
++    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
++    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
++    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
++    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
++    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
++    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
++    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
++};
++
++aes_encrypt_table::table_type aes_encrypt_table::Te1 = {
++    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
++    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
++    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
++    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
++    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
++    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
++    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
++    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
++    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
++    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
++    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
++    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
++    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
++    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
++    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
++    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
++    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
++    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
++    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
++    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
++    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
++    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
++    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
++    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
++    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
++    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
++    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
++    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
++    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
++    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
++    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
++    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
++    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
++    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
++    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
++    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
++    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
++    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
++    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
++    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
++    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
++    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
++    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
++    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
++    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
++    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
++    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
++    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
++    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
++    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
++    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
++    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
++    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
++    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
++    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
++    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
++    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
++    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
++    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
++    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
++    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
++    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
++    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
++    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
++};
++
++aes_encrypt_table::table_type aes_encrypt_table::Te2 = {
++    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
++    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
++    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
++    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
++    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
++    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
++    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
++    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
++    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
++    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
++    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
++    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
++    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
++    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
++    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
++    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
++    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
++    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
++    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
++    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
++    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
++    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
++    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
++    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
++    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
++    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
++    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
++    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
++    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
++    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
++    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
++    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
++    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
++    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
++    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
++    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
++    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
++    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
++    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
++    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
++    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
++    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
++    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
++    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
++    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
++    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
++    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
++    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
++    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
++    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
++    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
++    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
++    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
++    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
++    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
++    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
++    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
++    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
++    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
++    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
++    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
++    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
++    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
++    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
++};
++
++aes_encrypt_table::table_type aes_encrypt_table::Te3 = {
++    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
++    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
++    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
++    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
++    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
++    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
++    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
++    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
++    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
++    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
++    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
++    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
++    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
++    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
++    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
++    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
++    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
++    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
++    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
++    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
++    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
++    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
++    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
++    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
++    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
++    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
++    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
++    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
++    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
++    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
++    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
++    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
++    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
++    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
++    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
++    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
++    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
++    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
++    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
++    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
++    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
++    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
++    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
++    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
++    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
++    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
++    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
++    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
++    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
++    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
++    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
++    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
++    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
++    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
++    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
++    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
++    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
++    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
++    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
++    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
++    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
++    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
++    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
++    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
++};
++
++aes_decrypt_table::table_type aes_decrypt_table::Td0 = {
++    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
++    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
++    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
++    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
++    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
++    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
++    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
++    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
++    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
++    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
++    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
++    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
++    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
++    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
++    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
++    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
++    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
++    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
++    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
++    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
++    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
++    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
++    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
++    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
++    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
++    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
++    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
++    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
++    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
++    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
++    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
++    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
++    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
++    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
++    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
++    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
++    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
++    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
++    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
++    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
++    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
++    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
++    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
++    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
++    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
++    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
++    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
++    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
++    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
++    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
++    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
++    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
++    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
++    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
++    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
++    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
++    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
++    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
++    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
++    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
++    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
++    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
++    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
++    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
++};
++
++aes_decrypt_table::table_type aes_decrypt_table::Td1 = {
++    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
++    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
++    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
++    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
++    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
++    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
++    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
++    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
++    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
++    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
++    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
++    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
++    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
++    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
++    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
++    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
++    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
++    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
++    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
++    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
++    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
++    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
++    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
++    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
++    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
++    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
++    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
++    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
++    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
++    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
++    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
++    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
++    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
++    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
++    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
++    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
++    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
++    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
++    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
++    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
++    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
++    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
++    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
++    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
++    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
++    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
++    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
++    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
++    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
++    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
++    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
++    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
++    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
++    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
++    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
++    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
++    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
++    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
++    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
++    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
++    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
++    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
++    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
++    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
++};
++
++aes_decrypt_table::table_type aes_decrypt_table::Td2 = {
++    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
++    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
++    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
++    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
++    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
++    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
++    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
++    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
++    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
++    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
++    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
++    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
++    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
++    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
++    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
++    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
++    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
++    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
++    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
++    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
++    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
++    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
++    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
++    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
++    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
++    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
++    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
++    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
++    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
++    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
++    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
++    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
++    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
++    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
++    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
++    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
++    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
++    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
++    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
++    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
++    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
++    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
++    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
++    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
++    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
++    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
++    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
++    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
++    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
++    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
++    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
++    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
++    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
++    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
++    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
++    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
++    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
++    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
++    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
++    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
++    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
++    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
++    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
++    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
++};
++
++aes_decrypt_table::table_type aes_decrypt_table::Td3 = {
++    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
++    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
++    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
++    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
++    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
++    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
++    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
++    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
++    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
++    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
++    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
++    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
++    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
++    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
++    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
++    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
++    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
++    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
++    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
++    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
++    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
++    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
++    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
++    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
++    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
++    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
++    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
++    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
++    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
++    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
++    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
++    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
++    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
++    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
++    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
++    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
++    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
++    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
++    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
++    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
++    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
++    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
++    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
++    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
++    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
++    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
++    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
++    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
++    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
++    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
++    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
++    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
++    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
++    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
++    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
++    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
++    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
++    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
++    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
++    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
++    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
++    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
++    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
++    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
++};
++
++const unsigned char aes_decrypt_table::Td4[table_nelts] = {
++    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
++    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
++    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
++    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
++    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
++    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
++    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
++    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
++    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
++    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
++    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
++    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
++    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
++    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
++    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
++    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
++    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
++    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
++    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
++    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
++    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
++    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
++    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
++    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
++    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
++    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
++    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
++    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
++    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
++    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
++    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
++    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
++};
++
++/* In-round shifts info.  */
++static const unsigned HOST_WIDE_INT shift_csts[4] = {24, 16, 8, 0};
++
++/* Check if the pattern is plus-const.  Helper for memref analysis.  */
++static bool
++plus_const_int_p (rtx op)
++{
++  return GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1));
++}
++
++/* Obtain info about memory access.  */
++static bool
++decompose_mem (rtx mem, rtx &base, unsigned HOST_WIDE_INT &offset)
++{
++  address_info info;
++  decompose_mem_address (&info, mem);
++  if (!info.base)
++    return false;
++
++  base = *info.base;
++
++  rtx op = XEXP (mem, 0);
++  if (plus_const_int_p (op))
++    offset = UINTVAL (XEXP (op, 1));
++  /* TODO: WRONG IN GENERAL CASE: we cannot guarantee that the offsets were not
++     changed.  */
++  else if ((GET_CODE (op) == PRE_MODIFY && plus_const_int_p (XEXP (op, 1)))
++	   || REG_P (op))
++    offset = 0;
++  else
++    return false;
++
++  return true;
++}
++
++/* Check if the regs in stmt are same as the provided ones.  */
++static bool
++cmp_regs_in_stmt (rtx stmt, rtx lhs, rtx rhs)
++{
++  return (XEXP (stmt, 0) == lhs) && (XEXP (stmt, 1) == rhs);
++}
++
++/* AES key info.  Inhereted from mem_term_info to be used inside
++   matchers without any unnecessary casts.  */
++struct aes_key : mem_term_info
++{
++  aes_key ()
++    {}
++  aes_key (void *)
++    : mem_term_info (NULL, NULL_RTX)
++    {}
++  aes_key (const mem_term_info &m)
++    : mem_term_info (m)
++    {}
++
++  /* Check if the key has the same base pointer origin as another one.
++     This check is required due to some possible CSE optimizations applied on
++     pointers before this pass.  */
++  bool has_same_origin (const aes_key &other, rtx_insn *use_point) const
++    {
++      /* Simple case: the pointer is same.  */
++      if (src == other.src)
++	return true;
++
++      if (!use_point)
++	return false;
++
++      basic_block curr_bb = BLOCK_FOR_INSN (use_point);
++      if (!single_pred_p (curr_bb)
++	  || modified_between_p (src, BB_HEAD (curr_bb), use_point)
++	  || modified_between_p (other.src, BB_HEAD (curr_bb), use_point))
++	return false;
++
++      edge e = single_pred_edge (curr_bb);
++      rtx_insn *jump = BB_END (e->src);
++      if (!any_condjump_p (jump))
++	return false;
++
++      basic_block from_bb = BLOCK_FOR_INSN (jump);
++      if (EDGE_COUNT (from_bb->succs) != 2)
++	return false;
++
++      /* Need proof that the sources are equal: try to get it from
++	 terminating condition.  */
++      rtx cond = XEXP (SET_SRC (pc_set (jump)), 0);
++      rtx_code code = GET_CODE (cond);
++      if (!((code == EQ && EDGE_SUCC (from_bb, 0) == e)
++	    || (code == NE && EDGE_SUCC (from_bb, 1) == e)))
++	return false;
++
++      rtx arg1 = XEXP (cond, 0);
++      if (XEXP (cond, 1) != CONST0_RTX (GET_MODE (arg1))
++	  || COMPARISON_P (arg1))
++	return false;
++
++      rtx_insn *cmp_insn = get_single_def_insn (jump, arg1);
++      rtx cmp;
++      if (!cmp_insn || !(cmp = get_single_set_op (cmp_insn)))
++	return false;
++
++      if (!(cmp_regs_in_stmt (cmp, src, other.src)
++	    || cmp_regs_in_stmt (cmp, other.src, src)))
++	return false;
++
++      return true;
++    }
++};
++
++/* AES basic state input info.  Inhereted from mem_term_info
++   to use it in matchers without any unnecessary casts.  */
++struct state_input_info : mem_term_info
++{
++  state_input_info ()
++    {}
++  state_input_info (const aes_key &k)
++    : mem_term_info (k), is_key (true)
++    {}
++  state_input_info (const mem_term_info &m)
++    : mem_term_info (m), is_key (false)
++    {}
++
++  bool is_key;
++
++  bool verify (const state_input_info *prev) const
++    {
++      if (!prev)
++	return true;
++
++      return BLOCK_FOR_INSN (loc) == BLOCK_FOR_INSN (prev->loc);
++    }
++};
++
++/* Memory matcher to filter only suitable memory instructions.  */
++struct mem_matcher : matcher_term
++{
++  static bool match (rtx_insn *insn, holder_type &m)
++    {
++      rtx src = get_single_set_op (insn);
++      return src && match (src, insn, m);
++    }
++
++  static bool match (rtx src, rtx_insn *insn, holder_type &m)
++    {
++      if (!MEM_P (src))
++	return false;
++
++      mem_term_info info (NULL, NULL_RTX);
++      if (!decompose_mem (src, info.src, info.offset))
++	return false;
++
++      info.loc = insn;
++      m[0] = info;
++      return true;
++    }
++};
++
++/* AES entry input info.  Enhanced from state input due to ideological
++   similarities.  */
++struct input_info : state_input_info
++{
++  input_info ()
++    {}
++  input_info (const mem_term_info &m, unsigned HOST_WIDE_INT shift_cst)
++    : state_input_info (m), shift_cst (shift_cst)
++    {}
++  input_info (const aes_key &k)
++    : state_input_info (k)
++    {}
++
++  unsigned HOST_WIDE_INT shift_cst;
++
++  /* Input info is sorted by references offsets.  */
++  bool operator < (const input_info &rhs) const
++    {
++      return offset < rhs.offset;
++    }
++
++  std::pair input () const
++    {
++      return std::make_pair (src, offset);
++    }
++
++  bool verify (const input_info *prev, unsigned i) const
++    {
++      if (!state_input_info::verify (prev))
++	return false;
++
++      /* Previous state should reference the previous element
++	 of the same buffer.  */
++      if (prev && (src != prev->src || offset != prev->offset + 1))
++	return false;
++
++      /* State should use the corresponding shift constant.  */
++      return shift_csts[i] == shift_cst;
++    }
++
++  static bool finalize (rtx_insn *insn, input_info *m)
++    {
++      typedef unop_matcher zext_matcher;
++
++      zext_matcher::holder_type zext;
++      if (zext_matcher::match (insn, zext))
++	{
++	  *m = input_info (zext[0], 0);
++	  return true;
++	}
++
++      typedef binop_matcher >
++	shifted_variant;
++      shifted_variant::holder_type lsh;
++      if (!shifted_variant::match (insn, lsh))
++	return false;
++
++      gcc_assert (CONST_INT_P (lsh[1].src));
++      *m = input_info (lsh[0], UINTVAL (lsh[1].src));
++      return true;
++    }
++};
++
++/* Check if the corresponding constants combinations may be used for
++   AES table access.  */
++static bool
++verify_table_access (unsigned HOST_WIDE_INT shift_cst,
++		     unsigned HOST_WIDE_INT and_cst = 0xFF,
++		     bool and_present = true)
++{
++  if (and_cst != 0xFF)
++    return false;
++
++  switch (shift_cst)
++    {
++    case 0:
++    case 8:
++    case 16:
++      return and_present;
++    case 24:
++      return true;
++    default:
++      return false;
++    }
++}
++
++/* AES table reference description.  */
++template
++struct aes_table_ref
++{
++  rtx_insn *insn;
++  rtx_insn *output_insn;
++  unsigned HOST_WIDE_INT lsr_cst;
++  rtx reg;
++  rtx output;
++  typename TABLE_T::table_entry itable;
++  bool is_final;
++
++  bool verify (unsigned i) const
++    {
++      typename TABLE_T::table_entry (ðalon)[TABLE_T::rounds_num]
++	= is_final ? TABLE_T::final_rounds : TABLE_T::rounds;
++      return lsr_cst == shift_csts[i] && itable == ethalon[i];
++    }
++};
++
++/* Check the minimal requirements of the pattern to be a table reference
++   and wrap the table id getter function.  */
++template
++static typename T::table_entry
++check_table (rtx mem)
++{
++  tree expr = MEM_EXPR (mem);
++  if (!expr || TREE_CODE (expr) != ARRAY_REF)
++    return T::BAD_TABLE;
++
++  tree decl = TREE_OPERAND (expr, 0);
++  if (!decl || !DECL_P (decl) || !TREE_READONLY (decl))
++    return T::BAD_TABLE;
++
++  tree ctor = DECL_INITIAL (decl);
++  if (!ctor)
++    return T::BAD_TABLE;
++
++  return T::get_table_id (ctor);
++}
++
++/* Simplified memory info.  Used for simplier table ref analysis.  */
++struct simplified_mem_info
++{
++  rtx base_reg;
++  rtx index;
++};
++
++/* Try to obtain table reference info.  */
++static bool
++decompose_tref_mem_address (simplified_mem_info &info, rtx mem)
++{
++  address_info addr_info;
++  decompose_mem_address (&addr_info, mem);
++  if (!addr_info.base || !addr_info.index)
++    return false;
++
++  info.base_reg = *addr_info.base;
++  info.index = *addr_info.index;
++
++  if (!REG_P (info.base_reg))
++    return false;
++
++  if (addr_info.mode == SImode)
++    {
++      if (GET_CODE (info.index) != MULT)
++	return false;
++
++      rtx cst = XEXP (info.index, 1);
++      if (!CONST_INT_P (cst) || UINTVAL (cst) != 4)
++	return false;
++
++      info.index = XEXP (info.index, 0);
++      return true;
++    }
++
++  return (addr_info.mode == QImode);
++}
++
++/* Find the possible final output instruction.  */
++template
++static rtx_insn *
++get_possible_final_output (rtx_insn *insn, rtx reg,
++			   unsigned HOST_WIDE_INT shift_cst,
++			   typename TABLE_T::table_entry itable);
++
++/* Specialize the function for AES encryption.  The output is AND instruction
++   with propper constant.  */
++template<>
++rtx_insn *
++get_possible_final_output (rtx_insn *insn, rtx reg,
++					      unsigned HOST_WIDE_INT shift_cst,
++					      aes_encrypt_table::table_entry)
++{
++  rtx_insn *out = get_single_use_insn (insn, reg);
++  if (!out)
++    return NULL;
++
++  rtx cst_val = get_op_const_cst (out);
++  if (!cst_val)
++    return NULL;
++
++  unsigned HOST_WIDE_INT ethalon;
++  switch (shift_cst)
++    {
++    case 24:
++      ethalon = 0xffffffffff000000;
++      break;
++    case 16:
++      ethalon = 0xff0000;
++      break;
++    case 8:
++      ethalon = 0xff00;
++      break;
++    case 0:
++      ethalon = 0xff;
++      break;
++    default:
++      gcc_unreachable ();
++    }
++
++  return UINTVAL (cst_val) == ethalon ? out : NULL;
++}
++
++/* Specialize the function for AES decryption.  The output is ASHIFT instruction
++   with propper constant or direct reference to TD4 table.
++
++   TODO: TD4 check might be done here for all the cases.  However, now it is not
++   done here to make decryption and encryption matching
++   more general in common.  */
++template<>
++rtx_insn *
++get_possible_final_output (rtx_insn *insn, rtx reg,
++					      unsigned HOST_WIDE_INT shift_cst,
++					      aes_decrypt_table::table_entry it)
++{
++  rtx_insn *out = get_single_use_insn (insn, reg);
++  if (!out)
++    return NULL;
++
++  rtx cst_val = get_op_const_cst (out);
++  if (!cst_val)
++    // no shift case
++    return it == aes_decrypt_table::TD4 ? insn : NULL;
++
++  return UINTVAL (cst_val) == shift_cst ? out : NULL;
++}
++
++typedef arg_op_matcher reg_matcher;
++
++/* Helper that matches suitable AES table references.  */
++template
++class tref_matcher
++{
++  /* (reg >> cst) matcher.  Helper.  */
++  typedef binop_matcher > table_access;
++  /* zext (reg >> cst) matcher.  Used for TABLE[(val >> 24)] variant.  */
++  typedef unop_matcher direct;
++  /* zext ((reg >> cst1) & cst2) matcher.  Used for
++     TABLE[(val >> (16|8)) & 0xff] variant.  */
++  typedef unop_matcher > > shifted;
++  /* zext (reg & cst) matcher.  Used for TABLE[val & 0xff] variant.  */
++  typedef unop_matcher > > noshift;
++
++  std::map table_alias;
++
++  bool finalize (aes_table_ref &tref,
++		 minimal_term_info &input_info,
++		 minimal_term_info *shift_info = NULL,
++		 minimal_term_info *mask_info = NULL)
++    {
++      gcc_assert (REG_P (input_info.src));
++      gcc_assert (!shift_info || CONST_INT_P (shift_info->src));
++      gcc_assert (!mask_info || CONST_INT_P (mask_info->src));
++
++      unsigned HOST_WIDE_INT shift
++	= shift_info ? UINTVAL (shift_info->src) : 0;
++      unsigned HOST_WIDE_INT mask
++	= mask_info ? UINTVAL (mask_info->src) : 0xFF;
++      if (!verify_table_access (shift, mask, mask_info))
++	return false;
++
++      tref.insn = input_info.loc;
++      tref.reg = input_info.src;
++      tref.lsr_cst = shift;
++      return true;
++    }
++
++  bool match (rtx_insn *insn, rtx index, aes_table_ref &tref)
++    {
++      direct::holder_type direct_res;
++      if (direct::match (index, insn, direct_res))
++	return finalize (tref, direct_res[0], &direct_res[1]);
++
++      shifted::holder_type shifted_res;
++      if (shifted::match (index, insn, shifted_res))
++	return finalize (tref, shifted_res[0],
++			 &shifted_res[1], &shifted_res[2]);
++
++      noshift::holder_type noshift_res;
++      return noshift::match (index, insn, noshift_res)
++	&& finalize (tref, noshift_res[0], NULL, &noshift_res[1]);
++    }
++
++public:
++  bool match (rtx_insn *insn, aes_table_ref &tref)
++    {
++      rtx mem = get_single_set_op (insn);
++      if (!mem && (mem = get_single_set_op (insn)))
++	mem = XEXP (mem, 0);
++
++      rtx dst = get_single_set_dst (insn);
++      if (!mem || !MEM_P (mem) || !dst || GET_MODE (dst) != SImode)
++	return false;
++
++      simplified_mem_info info;
++      if (!decompose_tref_mem_address (info, mem)
++	  || !match (insn, info.index, tref))
++	return false;
++
++      typename TABLE_T::table_entry itable;
++      if (!table_alias.count (info.base_reg))
++	{
++	  itable = check_table (mem);
++	  if (itable == TABLE_T::BAD_TABLE)
++	    return false;
++	  table_alias[info.base_reg] = itable;
++	}
++      else
++	itable = table_alias.at (info.base_reg);
++
++      if (rtx_insn *out = get_possible_final_output (insn, dst,
++							      tref.lsr_cst,
++							      itable))
++	{
++	  tref.is_final = true;
++	  tref.output_insn = out;
++	  tref.output = NULL_RTX;
++	}
++      else
++	{
++	  tref.is_final = false;
++	  tref.output_insn = insn;
++	  tref.output = dst;
++	}
++
++      tref.itable = itable;
++      return true;
++    }
++};
++
++/* AES stage description.  Required for some specializations
++   for curtain rounds.  */
++typedef enum { INPUT, MIDDLE, FINAL } aes_stage;
++
++/* AES entity description.  It can be both round or state inside round.
++   It provides interface for unified analysis between blocks of 4 parts:
++   round -> 4 states -> 4 * 4 arguments.  */
++template
++struct aes_entity
++{
++  aes_key key;
++  std::set entries;
++  rtx_insn *loc;
++
++  aes_entity ()
++    : key (NULL), loc (NULL)
++    {}
++
++  /* Push new entry to the entity.  */
++  bool push_entry (const ENTRY_T &v)
++    {
++      if (entries.size () == 4)
++	return false;
++
++      entries.insert (v);
++      return true;
++    }
++
++  /* The entities are sorted by key offset.  */
++  bool operator < (const aes_entity &rhs) const
++    {
++      return key.offset < rhs.key.offset;
++    }
++
++  /* Verify that all of the entries are correct within their positions inside
++     the entity.  */
++  bool finalize ()
++    {
++      if (entries.size () != 4)
++	return false;
++
++      unsigned i = 0;
++      const ENTRY_T *prev = NULL;
++      for (typename std::set::iterator it = entries.begin ();
++	   it != entries.end (); prev = &*it++, ++i)
++	if (!it->verify (prev, i))
++	  return false;
++
++      loc = entries.begin ()->loc;
++      return true;
++    }
++};
++
++/* Check the correctness of input regs permutations.  */
++template
++static bool
++check_input_regs (const std::vector &curr,
++		  const std::vector &prev);
++
++/* Specialize the function for AES encryption.  */
++template<>
++bool
++check_input_regs (const std::vector &curr,
++				 const std::vector &prev)
++{
++  gcc_assert (curr.size () == 4 && prev.size () == 4);
++  unsigned idx[4] = { 1, 2, 3, 0 };
++  for (int i = 0; i < 4; ++i)
++    if (curr[i] != prev[idx[i]])
++      return false;
++  return true;
++}
++
++/* Specialize the function for AES decryption.  */
++template<>
++bool
++check_input_regs (const std::vector &curr,
++				 const std::vector &prev)
++{
++  gcc_assert (curr.size () == 4 && prev.size () == 4);
++  unsigned idx[4] = { 3, 0, 1, 2 };
++  for (int i = 0; i < 4; ++i)
++    if (curr[i] != prev[idx[i]])
++      return false;
++  return true;
++}
++
++/* Basic descryption of state input.  */
++template
++struct state_input
++{
++  typedef std::vector type;
++
++  static void finalize (type &in, rtx v)
++    {
++      in.push_back (v);
++    }
++
++  template
++  static bool verify (const type &lhs, const type &rhs)
++    {
++      return check_input_regs (lhs, rhs);
++    }
++};
++
++/* Input round state uses special input.  */
++template<>
++struct state_input
++{
++  typedef std::pair type;
++
++  static void finalize (type &in, const type &v)
++    {
++      in = v;
++      // Order is inverted
++      in.second -= 3;
++    }
++
++  template
++  static bool verify (const type &lhs, const type &rhs)
++    {
++      return lhs.first == rhs.first
++	&& lhs.second == rhs.second + 4;
++    }
++};
++
++/* Basic descryption of state output.  */
++template
++struct state_output
++{
++  typedef rtx type;
++
++  static bool verify (const type &, const type &)
++    {
++      return true;
++    }
++};
++
++/* Final round state generates special output.  */
++template<>
++struct state_output
++{
++  typedef std::pair type;
++
++  static bool verify (const type &lhs, const type &rhs)
++    {
++      return lhs.first == rhs.first
++	&& lhs.second == rhs.second + 4;
++    }
++};
++
++/* Basic descryption of round input.  */
++template
++struct round_input
++{
++  typedef std::vector type;
++};
++
++/* Input round uses special input just as its state.  */
++template<>
++struct round_input
++{
++  typedef std::pair type;
++};
++
++/* Basic descryption of round output.  */
++template
++struct round_output
++{
++  typedef std::vector type;
++
++  template
++  static void finalize (type &out, const T &v)
++    {
++      gcc_assert (v.size () == 4);
++      for (typename T::const_iterator it = v.begin (); it != v.end (); ++it)
++	out.push_back (it->output);
++    }
++
++  template
++  static void reorder (type &)
++    {}
++};
++
++/* Reorder output for AES decryption: the order is changed compared to
++   AES encryption.  */
++template<>
++template<>
++void round_output::reorder (type &out)
++{
++  gcc_assert (out.size () == 4);
++  std::swap (out[1], out[3]);
++}
++
++template<>
++template<>
++void round_output::reorder (type &out)
++{
++  round_output::reorder (out);
++}
++
++/* Final round generates special output.  */
++template<>
++struct round_output : state_output
++{
++  template
++  static void finalize (type &out, const T &v)
++    {
++      gcc_assert (v.size () == 4);
++      out = v.begin ()->output;
++    }
++
++  template
++  static void reorder (type &)
++    {}
++};
++
++/* AES state descryption.  */
++template
++struct aes_state : aes_entity
++{
++  typedef aes_entity base_entity;
++
++  typename state_input::type input;
++  typename state_output::type output;
++
++  aes_state ()
++    : base_entity ()
++    {}
++
++  void set_output (const typename state_output::type &o)
++    {
++      output = o;
++    }
++
++  bool push_entry (const ENTRY_T &v)
++    {
++      if (!v.is_key)
++	return base_entity::push_entry (v);
++
++      if (this->key.src)
++	return false;
++
++      this->key = v;
++      return true;
++    }
++
++  /* Verify if the state is correct within its position in round.  */
++  bool verify (const aes_state *prev, unsigned) const
++    {
++      if (!prev)
++	return true;
++
++      if (!this->key.has_same_origin (prev->key, this->loc)
++	  || this->key.offset != prev->key.offset + 4
++	  || BLOCK_FOR_INSN (this->loc) != BLOCK_FOR_INSN (prev->loc))
++	return false;
++
++      return state_input::template verify (input, prev->input)
++	&& state_output::verify (output, prev->output);
++    }
++
++  /* Check if the entries of the state are correct and finalize stored info.  */
++  bool finalize ()
++    {
++      if (!base_entity::finalize ())
++	return false;
++
++      for (typename std::set::iterator it = this->entries.begin ();
++	   it != this->entries.end (); ++it)
++	state_input::finalize (input, it->input ());
++
++      return true;
++    }
++};
++
++/* AES round descryption.  */
++template
++struct aes_round : aes_entity, STAGE, K>
++{
++  typedef aes_entity, STAGE, K> base_entity;
++
++  typename round_input::type input;
++  typename round_output::type output;
++
++  /* Check if the states are correct and finalize stored info.  */
++  bool finalize ()
++    {
++      if (!base_entity::finalize ())
++	return false;
++
++      input = this->entries.begin ()->input;
++      this->key = this->entries.begin ()->key;
++
++      round_output::finalize (output, this->entries);
++      round_output::template reorder (output);
++
++      return true;
++    }
++};
++
++template
++class aes_optimizer;
++
++/* AES round input info.  Used to find and store info about
++   table references.
++
++   Must be inited and finalized before and after usage.  */
++template
++struct round_input_info : state_input_info
++{
++  typedef typename aes_optimizer::table_ref_map tref_map;
++
++  round_input_info ()
++    {}
++  round_input_info (rtx_insn *insn, const aes_table_ref *tref)
++    : state_input_info (mem_term_info (insn, NULL_RTX)), tref (tref)
++    {}
++  round_input_info (const aes_key &k)
++    : state_input_info (k)
++    {}
++
++  rtx input () const
++    {
++      return tref->reg;
++    }
++
++  rtx output () const
++    {
++      return tref->output;
++    }
++
++  /* Table references are sorted by shift constants.
++     TODO: probably sort by key offset?  */
++  bool operator < (const round_input_info &rhs) const
++    {
++      return tref->lsr_cst > rhs.tref->lsr_cst;
++    }
++
++  bool verify (const round_input_info *prev, unsigned i) const
++    {
++      return state_input_info::verify (prev) && tref->verify (i);
++    }
++
++  static bool finalize (rtx_insn *insn, round_input_info *m)
++    {
++      if (checked_p->count (insn))
++	return false;
++
++      typename tref_map::const_iterator it = table_refs_p->find (insn);
++      if (it == table_refs_p->end ())
++	return false;
++
++      m[0] = round_input_info (insn, &it->second);
++      return true;
++    }
++
++  const aes_table_ref *tref;
++
++  static const tref_map *table_refs_p;
++  static const std::set *checked_p;
++
++  /* Store lookup table references.  */
++  static void init (const tref_map &t, const std::set &c)
++    {
++      gcc_assert (!table_refs_p && !checked_p);
++      table_refs_p = &t;
++      checked_p = &c;
++    }
++
++  /* Remove lookup table references.  */
++  static void fin ()
++    {
++      gcc_assert (table_refs_p && checked_p);
++      table_refs_p = NULL;
++      checked_p = NULL;
++    }
++};
++
++template
++const typename aes_optimizer::table_ref_map *
++round_input_info::table_refs_p = NULL;
++
++template
++const std::set *
++round_input_info::checked_p = NULL;
++
++/* AES encryption/decryption optimizer.  */
++template
++class aes_optimizer
++{
++public:
++  typedef std::map > table_ref_map;
++
++  /* AES states typedefs.  */
++  typedef aes_state aes_input_state;
++  typedef aes_state, MIDDLE, T> aes_body_state;
++  typedef aes_state, FINAL, T> aes_final_state;
++
++  /* AES rounds typedefs.  */
++  typedef aes_round aes_input_round;
++  typedef aes_round, MIDDLE, T> aes_body_round;
++  typedef aes_round, FINAL, T> aes_final_round;
++
++  bool run ();
++
++private:
++  bool collect_aes_lookup_tables ();
++  bool form_rounds ();
++  bool find_aes_init_round ();
++  bool collect_state (rtx_insn * insn, aes_body_state &state,
++		      std::set &checked);
++  bool find_aes_rounds ();
++  bool collect_final_round (rtx_insn *insn, aes_final_state &state,
++			    std::set &checked);
++  bool find_aes_final_round ();
++  bool check_aes_pattern ();
++  void erase_unused_rounds (std::set *> &used);
++
++  bool gen_aes_code ();
++  bool gen_init_round ();
++  bool gen_round (const aes_body_round &round);
++  bool gen_final_round ();
++
++  rtx gen_or_get_vreg (const std::vector &vec);
++  rtx get_vreg (const std::vector &vec);
++  rtx gen_vreg (const std::vector &vec);
++
++  table_ref_map table_refs;
++  table_ref_map final_table_refs;
++
++  aes_input_round input_round;
++  std::map, aes_body_round> rounds;
++  aes_final_round final_round;
++
++  std::map, rtx> vec_regs;
++  std::vector to_delete;
++};
++
++/* Find all the AES table references in function.  */
++template
++bool
++aes_optimizer::collect_aes_lookup_tables ()
++{
++  basic_block bb;
++  rtx_insn *insn;
++
++  tref_matcher m;
++  FOR_EACH_BB_FN (bb, cfun)
++    FOR_BB_INSNS (bb, insn)
++      {
++	aes_table_ref tref;
++	if (!m.match (insn, tref))
++	  continue;
++
++	if (!tref.is_final)
++	  table_refs[insn] = tref;
++	else
++	  final_table_refs[tref.output_insn] = tref;
++      }
++
++  return !table_refs.empty () && !final_table_refs.empty ();
++}
++
++/* Helper function to match all the permutations of five arg
++   calculations.  */
++template
++struct five_args_calc_matcher
++{
++  /* Helper for matching (op1 * op2).  */
++  typedef binop_matcher two_args_block;
++  /* Helper for matching (op1 * (op2 * op3)).  */
++  typedef binop_matcher three_args_block;
++  /* Helper for matching ((op1 * op2) * (op3 * op4)).  */
++  typedef binop_matcher opt_four_args_block;
++  /* Helper for matching (op1 * (op2 * (op3 * op4))).  */
++  typedef binop_matcher linear_four_args_block;
++
++  /* Match the (op1 * ((op2 * op3) * (op4 * op5))) variant.  */
++  typedef binop_matcher opt_op_term;
++  /* Match the ((op1 * op2) * (op3 * (op4 * op5))) variant.  */
++  typedef binop_matcher three_op_two;
++  /* Match the (op1 * (op2 * (op3 * (op4 * op5)))) variant.  */
++  typedef binop_matcher fully_linear;
++
++  static const int holder_size = fully_linear::holder_size;
++  static const int op_num = fully_linear::op_num;
++  typedef typename fully_linear::term_type term_type;
++  typedef typename fully_linear::holder_type holder_type;
++
++  static rtx_insn* match (rtx_insn *insn, holder_type &m, unsigned depth = 1)
++    {
++      for (rtx dst = get_single_set_dst (insn); depth && insn && dst;
++	   insn = get_single_use_insn (insn, dst),
++	   dst = insn ? get_single_set_dst (insn) : NULL_RTX,
++	   --depth)
++	if (opt_op_term::match (insn, m) || three_op_two::match (insn, m)
++	    || fully_linear::match (insn, m))
++	  return insn;
++      return NULL;
++    }
++};
++
++/* Match the AES key.  */
++struct key_matcher : matcher_term
++{
++  static bool match (rtx_insn *insn, holder_type &m)
++    {
++      mem_matcher::holder_type info;
++      if (!mem_matcher::match (insn, info))
++	return false;
++
++      m[0] = info[0];
++      return true;
++    }
++};
++
++/* Matcher term for state input.  */
++template
++struct state_input_term : matcher_term
++{
++  typedef typename matcher_term::holder_type holder_type;
++
++  static bool match (rtx, rtx_insn *, holder_type &)
++    {
++      return false;
++    }
++
++  static bool match (rtx_insn *insn, holder_type &m)
++    {
++      key_matcher::holder_type k;
++      if (key_matcher::match (insn, k))
++	{
++	  m[0] = k[0];
++	  return true;
++	}
++
++      return matcher_term::term_type::finalize (insn, m);
++    }
++};
++
++/* Fill state from args.  */
++template 
++static bool
++finalize_input (const T (&args)[5], STATE &state)
++{
++  for (unsigned i = 0; i < 5; ++i)
++    if (!state.push_entry (args[i]))
++      return false;
++
++  return state.finalize ();
++}
++
++/* Construct input state.  */
++template
++static bool
++form_input (rtx_insn *insn, T &state)
++{
++  typedef five_args_calc_matcher >
++    matcher;
++
++  matcher::holder_type m;
++  if (!matcher::match (insn, m) || !finalize_input (m, state))
++    return false;
++
++  /* TODO: probably should not be set here.  */
++  state.set_output (SET_DEST (single_set (insn)));
++  return true;
++}
++
++/* Get definitions chain for the reg being used in the insn.  */
++static df_link *
++get_defs (rtx_insn *insn, rtx reg)
++{
++  df_link *ref_chain = get_def_chain (insn, reg);
++  gcc_assert (ref_chain);
++
++  for (df_link *ref_link = ref_chain; ref_link; ref_link = ref_link->next)
++    if (!check_def_chain_ref (ref_link->ref, reg))
++      return NULL;
++
++  return ref_chain;
++}
++
++/* Find AES init round.  To do this, find the table references that depends on
++   two definitions.  One of them is our input.  */
++template
++bool
++aes_optimizer::find_aes_init_round ()
++{
++  std::set checked;
++
++  for (typename table_ref_map::iterator it = table_refs.begin (),
++       end = table_refs.end (); it != end; ++it)
++    for (df_link *def = get_defs (it->second.insn, it->second.reg);
++	 def; def = def->next)
++      {
++	rtx_insn *def_insn = DF_REF_INSN (def->ref);
++	if (checked.count (def_insn))
++	  continue;
++
++	aes_input_state input_state;
++	if (form_input (def_insn, input_state)
++	    && !input_round.push_entry (input_state))
++	  return false;
++
++	checked.insert (def_insn);
++      }
++
++  return input_round.finalize ();
++}
++
++/* Collect AES inner state.  */
++template
++bool
++aes_optimizer::collect_state (rtx_insn *insn, aes_body_state &state,
++				 std::set &checked)
++{
++  typedef round_input_info term_info;
++  typedef five_args_calc_matcher > matcher;
++
++  typename matcher::holder_type m;
++  term_info::init (table_refs, checked);
++  rtx_insn *match_entry = matcher::match (insn, m, 3);
++  term_info::fin ();
++
++  if (!match_entry || !finalize_input (m, state))
++    return false;
++
++  /* TODO: probably should not be set here.  */
++  state.set_output (SET_DEST (single_set (match_entry)));
++  for (unsigned i = 0; i < 5; ++i)
++    if (!m[i].is_key)
++      checked.insert (m[i].tref->output_insn);
++
++  return true;
++}
++
++/* Simple sorter to link rounds by their registers.  */
++struct reg_comp
++{
++  bool operator () (rtx lhs, rtx rhs) const
++    {
++      return REGNO (lhs) < REGNO (rhs);
++    }
++};
++
++/* Find AES inner rounds.  */
++template
++bool
++aes_optimizer::find_aes_rounds ()
++{
++  typedef std::set input_key;
++
++  std::set checked;
++  std::map candidate_rounds;
++  for (typename table_ref_map::iterator it = table_refs.begin (),
++       end = table_refs.end (); it != end; ++it)
++    {
++      rtx_insn *insn = it->first;
++      if (checked.count (insn))
++	continue;
++
++      rtx_insn *use = get_single_use_insn (insn, SET_DEST (single_set (insn)));
++      if (!use)
++	continue;
++
++      aes_body_state state;
++      if (!collect_state (use, state, checked))
++	continue;
++
++      /* Sort the input so we can found the corresponding state.  */
++      input_key input (state.input.begin (), state.input.end ());
++      candidate_rounds[input].push_entry (state);
++    }
++
++  for (typename std::map::iterator
++       it = candidate_rounds.begin ();
++       it != candidate_rounds.end (); ++it)
++    if (it->second.finalize ())
++      rounds[it->second.input] = it->second;
++
++  return !rounds.empty ();
++}
++
++template
++struct final_state_matcher;
++
++/* AES encrypt matcher requires additional check on key calculations
++   due to possible optimizations.  */
++template<>
++struct final_state_matcher
++{
++  typedef round_input_info term_info;
++  typedef five_args_calc_matcher, IOR, true>
++    matcher;
++  typedef typename matcher::term_type
++    holder_type[matcher::holder_size - matcher::op_num];
++
++  static rtx_insn *match (rtx_insn *insn, holder_type &m, unsigned depth)
++    {
++      matcher::holder_type inner_m;
++      rtx_insn *res = matcher::match (insn, inner_m, depth);
++      if (!res)
++	return NULL;
++
++      /* Run pre-order traversal of the operands to check the correctness
++	 of key usage.  */
++      gcc_assert (inner_m[0].is_op);
++      unsigned pos = 0;
++      if (!check_key_calculations (inner_m, pos))
++	return NULL;
++      gcc_assert (pos == (matcher::holder_size - 1));
++
++      unsigned idx = 0;
++      for (unsigned i = 0; i < matcher::holder_size; ++i)
++	if (!inner_m[i].is_op)
++	  m[idx++] = inner_m[i];
++
++      gcc_assert (idx == 5);
++      return res;
++    }
++
++  static bool check_key_calculations (const matcher::holder_type &m,
++				      unsigned &idx,
++				      bool failure_on_key = false)
++    {
++      gcc_assert (idx < matcher::holder_size);
++      if (!m[idx].is_op)
++	return !(failure_on_key && m[idx].is_key);
++
++      failure_on_key |= (GET_CODE (m[idx].src) == IOR);
++      return check_key_calculations (m, ++idx, failure_on_key)
++	&& check_key_calculations (m, ++idx, failure_on_key);
++    }
++};
++
++
++/* The final state is simple wrapper since no additional checks are required
++   here.  */
++template<>
++struct final_state_matcher
++{
++  typedef round_input_info term_info;
++  typedef five_args_calc_matcher > matcher;
++  typedef typename matcher::holder_type holder_type;
++
++  static rtx_insn *match (rtx_insn *insn, holder_type &m, unsigned depth)
++    {
++      return matcher::match (insn, m, depth);
++    }
++};
++
++/* Match the AES final state.  */
++template
++bool
++aes_optimizer::collect_final_round (rtx_insn *insn, aes_final_state &state,
++				       std::set &checked)
++{
++  typedef final_state_matcher matcher_wrapper;
++
++  typename matcher_wrapper::holder_type m;
++  matcher_wrapper::term_info::init (final_table_refs, checked);
++  rtx_insn *match_entry = matcher_wrapper::match (insn, m, 3);
++  matcher_wrapper::term_info::fin ();
++
++  rtx dst;
++  if (!match_entry || !(dst = get_single_set_dst (match_entry))
++      || !finalize_input (m, state))
++    return false;
++
++  rtx src;
++  if (!(match_entry = get_single_use_insn (match_entry, dst))
++      || !(check_simple_op (match_entry, src, dst))
++      || !dst)
++    return false;
++
++  std::pair output;
++  if (!(match_entry = get_single_use_insn (match_entry, dst))
++      || !(dst = get_single_set_dst (match_entry))
++      || !decompose_mem (dst, output.first, output.second))
++    return false;
++
++  to_delete.push_back (match_entry);
++  state.set_output (output);
++  for (unsigned i = 0; i < 5; ++i)
++    if (!m[i].is_key)
++      checked.insert (m[i].tref->output_insn);
++
++  return true;
++}
++
++/* Find the final round.  */
++template
++bool
++aes_optimizer::find_aes_final_round ()
++{
++  std::set checked;
++  for (typename table_ref_map::iterator it = final_table_refs.begin (),
++       end = final_table_refs.end (); it != end; ++it)
++    {
++      rtx_insn *insn = it->first;
++
++      if (checked.count (insn))
++	continue;
++
++      rtx_insn *use = get_single_use_insn (insn, SET_DEST (single_set (insn)));
++      if (!use)
++	continue;
++
++      aes_final_state state;
++      if (collect_final_round (use, state, checked))
++	final_round.push_entry (state);
++    }
++
++  return final_round.finalize ();
++}
++
++template
++bool
++aes_optimizer::form_rounds ()
++{
++  return find_aes_final_round ()
++    && find_aes_init_round ()
++    && find_aes_rounds ();
++}
++
++template
++void
++aes_optimizer::erase_unused_rounds (std::set *> &used)
++{
++  if (used.size () == rounds.size ())
++    return;
++
++  for (typename std::map, aes_body_round>::iterator
++       it = rounds.begin (), next = it,
++       end = rounds.end (); it != end; it = next)
++    {
++      ++next;
++      if (!used.count (&it->first))
++	rounds.erase (it);
++    }
++}
++
++/* Find round starts and link them together.  */
++template
++bool
++aes_optimizer::check_aes_pattern ()
++{
++  std::set *> checked;
++
++  typename std::map, aes_body_round>::iterator fit
++    = rounds.find (input_round.output);
++
++  bool to_final = false;
++  while (fit != rounds.end () && !checked.count (&fit->first))
++    {
++      checked.insert (&fit->first);
++
++      if (fit->second.output == final_round.input)
++	to_final = true;
++
++      fit = rounds.find (fit->second.output);
++    }
++
++  if (!to_final)
++    return false;
++
++  erase_unused_rounds (checked);
++
++  return true;
++}
++
++static bool
++gen_insns (const rtx patterns[4], rtx_insn *loc)
++{
++  start_sequence ();
++  for (unsigned i = 0; i < 4; ++i)
++    {
++      rtx_insn *insn = emit_insn (patterns[i]);
++      if (recog_memoized (insn) < 0)
++	{
++	  end_sequence ();
++	  return false;
++	}
++    }
++
++  rtx_insn *seq = get_insns ();
++  end_sequence ();
++  emit_insn_after (seq, loc);
++
++  return true;
++}
++
++static rtx
++gen_offset_access (rtx base, unsigned HOST_WIDE_INT offset)
++{
++  if (!offset)
++    return base;
++
++  machine_mode mode = GET_MODE (base);
++  return gen_rtx_PLUS (mode, base, gen_rtx_CONST_INT (mode, offset));
++}
++
++template
++rtx
++aes_optimizer::get_vreg (const std::vector &vec)
++{
++  std::map, rtx>::iterator fit = vec_regs.find (vec);
++  if (fit != vec_regs.end ())
++    return fit->second;
++
++  return 0;
++}
++
++template
++rtx
++aes_optimizer::gen_vreg (const std::vector &vec)
++{
++  machine_mode vmode = targetm.get_v16qi_mode ();
++  rtx vreg = gen_reg_rtx (vmode);
++  vec_regs.insert (std::make_pair (vec, vreg));
++
++  return vreg;
++}
++
++template
++rtx
++aes_optimizer::gen_or_get_vreg (const std::vector &vec)
++{
++  rtx vreg = get_vreg (vec);
++  if (!vreg)
++    vreg = gen_vreg (vec);
++
++  return vreg;
++}
++
++template
++static rtx
++gen_aes_single_round (rtx vout, rtx vreg, rtx vkey);
++template
++static rtx
++gen_aes_mix_columns (rtx vreg, rtx vin);
++
++template<>
++rtx
++gen_aes_single_round (rtx vout, rtx vreg, rtx vkey)
++{
++  return targetm.gen_aesev16qi (vout, vreg, vkey);
++}
++
++template<>
++rtx
++gen_aes_mix_columns (rtx vreg, rtx vin)
++{
++  return targetm.gen_aesmcv16qi (vreg, vin);
++}
++
++template<>
++rtx
++gen_aes_single_round (rtx vout, rtx vreg, rtx vkey)
++{
++  return targetm.gen_aesdv16qi (vout, vreg, vkey);
++}
++
++template<>
++rtx
++gen_aes_mix_columns (rtx vreg, rtx vin)
++{
++  return targetm.gen_aesimcv16qi (vreg, vin);
++}
++
++template
++bool
++aes_optimizer::gen_init_round ()
++{
++  rtx_insn *loc = input_round.loc;
++
++  machine_mode vmode = targetm.get_v16qi_mode ();
++
++  rtx vreg = gen_reg_rtx (vmode);
++  rtx vkey = gen_reg_rtx (vmode);
++  rtx vout = gen_vreg (input_round.output);
++
++  rtx buf = input_round.input.first;
++  rtx key = gen_offset_access (input_round.key.src, input_round.key.offset);
++
++  rtx vload_pat = gen_rtx_SET (vreg,
++			       gen_rtx_MEM (vmode, buf));
++  rtx vkey_load_pat = gen_rtx_SET (vkey,
++				   gen_rtx_MEM (vmode, key));
++  rtx vrev_pat = targetm.gen_rev32v16qi (vkey, vkey);
++  rtx vaes_pat = gen_aes_single_round (vout, vreg, vkey);
++
++  const rtx patterns[4] = {vload_pat, vkey_load_pat, vrev_pat, vaes_pat};
++
++  return gen_insns (patterns, loc);
++}
++
++template
++bool
++aes_optimizer::gen_round (const aes_body_round &round)
++{
++  rtx_insn *loc = round.loc;
++
++  machine_mode vmode = targetm.get_v16qi_mode ();
++
++  rtx vreg = gen_reg_rtx (vmode);
++  rtx vkey = gen_reg_rtx (vmode);
++  rtx vin  = gen_or_get_vreg (round.input);
++  rtx vout = gen_or_get_vreg (round.output);
++
++  rtx key = gen_offset_access (round.key.src, round.key.offset);
++
++  rtx vkey_load_pat = gen_rtx_SET (vkey,
++				   gen_rtx_MEM (vmode, key));
++  rtx vrev_pat = targetm.gen_rev32v16qi (vkey, vkey);
++  rtx vmix_pat = gen_aes_mix_columns (vreg, vin);
++  rtx vaes_pat = gen_aes_single_round (vout, vreg, vkey);
++
++  const rtx patterns[4] = {vkey_load_pat, vrev_pat, vmix_pat, vaes_pat};
++
++  return gen_insns (patterns, loc);
++}
++
++template
++bool
++aes_optimizer::gen_final_round ()
++{
++  rtx_insn *loc = final_round.loc;
++
++  machine_mode vmode = targetm.get_v16qi_mode ();
++
++  rtx vreg = gen_reg_rtx (vmode);
++  rtx vkey = gen_reg_rtx (vmode);
++  rtx vin = get_vreg (final_round.input);
++
++  gcc_assert (vin);
++
++  rtx buf = final_round.output.first;
++  rtx key = gen_offset_access (final_round.key.src, final_round.key.offset);
++
++  rtx vkey_load_pat = gen_rtx_SET (vkey,
++				   gen_rtx_MEM (vmode, key));
++  rtx vrev_pat = targetm.gen_rev32v16qi (vkey, vkey);
++  rtx vxor_pat = gen_rtx_SET (vreg, gen_rtx_XOR (vmode, vin, vkey));
++  rtx vstore_pat = gen_rtx_SET (gen_rtx_MEM (vmode, buf), vreg);
++
++  const rtx patterns[4] = {vkey_load_pat, vrev_pat, vxor_pat, vstore_pat};
++
++  return gen_insns (patterns, loc);
++}
++
++template
++bool
++aes_optimizer::gen_aes_code ()
++{
++  if (!gen_init_round ())
++    return false;
++
++  for (typename std::map, aes_body_round>::iterator
++       it = rounds.begin (), end = rounds.end (); it != end; ++it)
++    {
++      if (!gen_round (it->second))
++	return false;
++    }
++
++  if (!gen_final_round ())
++    return false;
++
++  for (std::vector::iterator it = to_delete.begin (),
++       end = to_delete.end (); it != end; ++it)
++    SET_INSN_DELETED (*it);
++
++  return true;
++}
++
++template
++bool
++aes_optimizer::run ()
++{
++  return collect_aes_lookup_tables ()
++    && form_rounds ()
++    && check_aes_pattern ()
++    && gen_aes_code ();
++}
++
++static unsigned int
++crypto_acceleration ()
++{
++  aes_optimizer enc;
++  aes_optimizer dec;
++  enc.run ();
++  dec.run ();
++
++  return 0;
++}
++
++static void
++init_df ()
++{
++  df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
++  df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
++  df_mir_add_problem ();
++  df_live_add_problem ();
++  df_live_set_all_dirty ();
++  df_analyze ();
++  df_set_flags (DF_DEFER_INSN_RESCAN);
++}
++
++namespace {
++
++const pass_data pass_data_crypto_accel =
++{
++  RTL_PASS,	   // type
++  "crypto_accel",  // name
++  OPTGROUP_NONE,   // optinfo_flags
++  TV_CRYPTO_ACCEL, // tv_id
++  PROP_cfglayout,  // properties_required
++  0,		   // properties_provided
++  0,		   // properties_destroyed
++  0,		   // todo_flags_start
++  TODO_df_finish,  // todo_flags_finish
++};
++
++class pass_crypto_accel : public rtl_opt_pass
++{
++public:
++  pass_crypto_accel (gcc::context *ctxt)
++    : rtl_opt_pass (pass_data_crypto_accel, ctxt)
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *)
++    {
++      if (flag_crypto_accel_aes <= 0)
++	return false;
++      return targetm.get_v16qi_mode
++	&& targetm.gen_rev32v16qi
++	&& targetm.gen_aesev16qi
++	&& targetm.gen_aesmcv16qi;
++    }
++
++  virtual unsigned int execute (function *)
++    {
++      init_df ();
++      return crypto_acceleration ();
++    }
++}; // class pass_crypto_accel
++
++} // anon namespace
++
++rtl_opt_pass *
++make_pass_crypto_accel (gcc::context *ctxt)
++{
++  return new pass_crypto_accel (ctxt);
++}
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 3b6e90bf2..2aba523bb 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -12125,6 +12125,35 @@ types.  If @var{has_wb} is not NULL then its value is set to true if STP
+ contains post-index or pre-index operation.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} machine_mode TARGET_GET_V16QI_MODE ()
++This function get the 16 byte elements vector mode if target supports this.
++@end deftypefn
++
++@deftypefn {Target Hook} rtx TARGET_GEN_REV32V16QI (rtx @var{dest}, rtx @var{src})
++This function generate the byte reverse instruction
++ of 16 byte elements vector if target supports this.
++@end deftypefn
++
++@deftypefn {Target Hook} rtx TARGET_GEN_AESEV16QI (rtx @var{dest}, rtx @var{src1}, rtx @var{src2})
++This function generate the AES encryption instruction
++ of 16 byte elements vector if target supports this.
++@end deftypefn
++
++@deftypefn {Target Hook} rtx TARGET_GEN_AESDV16QI (rtx @var{dest}, rtx @var{src1}, rtx @var{src2})
++This function generate the AES decryption instruction
++ of 16 byte elements vector if target supports this.
++@end deftypefn
++
++@deftypefn {Target Hook} rtx TARGET_GEN_AESMCV16QI (rtx @var{dest}, rtx @var{src})
++This function generate the AES mix columns instruction
++ of 16 byte elements vector if target supports this.
++@end deftypefn
++
++@deftypefn {Target Hook} rtx TARGET_GEN_AESIMCV16QI (rtx @var{dest}, rtx @var{src})
++This function generate the AES inversed mix columns instruction
++ of 16 byte elements vector if target supports this.
++@end deftypefn
++
+ @deftypefn {Target Hook} bool TARGET_CANNOT_MODIFY_JUMPS_P (void)
+ This target hook returns @code{true} past the point in which new jump
+ instructions could be created.  On machines that require a register for
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 6ff60e562..817d586ff 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -7981,6 +7981,18 @@ lists.
+ 
+ @hook TARGET_IS_STP_INSN
+ 
++@hook TARGET_GET_V16QI_MODE
++
++@hook TARGET_GEN_REV32V16QI
++
++@hook TARGET_GEN_AESEV16QI
++
++@hook TARGET_GEN_AESDV16QI
++
++@hook TARGET_GEN_AESMCV16QI
++
++@hook TARGET_GEN_AESIMCV16QI
++
+ @hook TARGET_CANNOT_MODIFY_JUMPS_P
+ 
+ @hook TARGET_HAVE_CONDITIONAL_EXECUTION
+diff --git a/gcc/passes.def b/gcc/passes.def
+index a30e05688..b7d4f7b4e 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -475,6 +475,7 @@ along with GCC; see the file COPYING3.  If not see
+       NEXT_PASS (pass_rtl_fwprop_addr);
+       NEXT_PASS (pass_inc_dec);
+       NEXT_PASS (pass_initialize_regs);
++      NEXT_PASS (pass_crypto_accel);
+       NEXT_PASS (pass_ud_rtl_dce);
+       NEXT_PASS (pass_combine);
+       NEXT_PASS (pass_if_after_combine);
+diff --git a/gcc/rtl-matcher.h b/gcc/rtl-matcher.h
+new file mode 100644
+index 000000000..6aed8d98d
+--- /dev/null
++++ b/gcc/rtl-matcher.h
+@@ -0,0 +1,367 @@
++/* Helpers for RTL pattern matchers.
++   Copyright (C) 2003-2023 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
++.  */
++
++#ifndef GCC_RTL_MATCHER_H
++#define GCC_RTL_MATCHER_H
++
++#include "config.h"
++#include "system.h"
++#include "rtl.h"
++#include "df.h"
++
++/* Get definitions chain for the reg being used in insn.  */
++static df_link *
++get_def_chain (rtx_insn *insn, rtx reg)
++{
++  df_ref use;
++  FOR_EACH_INSN_USE (use, insn)
++    {
++      rtx use_reg = DF_REF_REG (use);
++      if (GET_CODE (use_reg) == SUBREG)
++	{
++	  if (REGNO (SUBREG_REG (use_reg)) == REGNO (reg))
++	    return NULL;
++	}
++      else
++	{
++	  gcc_assert (REG_P (use_reg));
++	  if (REGNO (use_reg) == REGNO (reg))
++	    return DF_REF_CHAIN (use);
++	}
++    }
++
++  return NULL;
++}
++
++/* Check if the reg is not global and actually modified in the ref.  */
++static bool
++check_def_chain_ref (df_ref ref, rtx reg)
++{
++  if (!ref || !DF_REF_INSN_INFO (ref))
++    return false;
++
++  return !global_regs[REGNO (reg)]
++    || set_of (reg, DF_REF_INSN (ref));
++}
++
++/* Get the single def instruction of the reg being used in the insn.  */
++static rtx_insn *
++get_single_def_insn (rtx_insn *insn, rtx reg)
++{
++  if (!REG_P (reg))
++    return NULL;
++
++  df_link *ref_chain = get_def_chain (insn, reg);
++  gcc_assert (ref_chain);
++
++  if (!ref_chain || ref_chain->next
++      || !check_def_chain_ref (ref_chain->ref, reg))
++    return NULL;
++
++  return DF_REF_INSN (ref_chain->ref);
++}
++
++/* Get the single user instruction of the reg being set in the insn.  */
++static rtx_insn *
++get_single_use_insn (rtx_insn *insn, rtx reg)
++{
++  df_ref def;
++  struct df_link *ref_chain;
++
++  if (!REG_P (reg))
++    return NULL;
++
++  FOR_EACH_INSN_DEF (def, insn)
++    if (REGNO (DF_REF_REG (def)) == REGNO (reg))
++      break;
++
++  gcc_assert (def && "Broken def-use analysis chain.");
++
++  ref_chain = DF_REF_CHAIN (def);
++
++  if (!ref_chain || ref_chain->next || !ref_chain->ref)
++    return NULL;
++
++  return DF_REF_INSN (ref_chain->ref);
++}
++
++/* Get the rtx pattern of suitable opcode from single set instruction.  */
++template 
++static rtx
++get_single_set_op (rtx_insn *insn)
++{
++  rtx pat = single_set (insn);
++  if (!pat)
++    return NULL_RTX;
++
++  rtx src = SET_SRC (pat);
++  if (GET_CODE (src) != OP1 && GET_CODE (src) != OP2)
++    return NULL_RTX;
++
++  return src;
++}
++
++/* Get the rtx pattern of suitable opcode from single set instruction.  */
++template 
++static rtx
++get_single_set_op (rtx_insn *insn)
++{
++  return get_single_set_op (insn);
++}
++
++/* Get the rtx constant from single set instruction of suitable opcode.  */
++template
++static rtx
++get_op_const_cst (rtx_insn *insn)
++{
++  rtx src = get_single_set_op (insn);
++  if (!src)
++    return NULL_RTX;
++
++  rtx cst = XEXP (src, 1);
++  return CONST_INT_P (cst) ? cst : NULL_RTX;
++}
++
++/* Get the rtx destination from single set instruction of suitable opcode.  */
++template 
++static rtx
++get_single_set_dst (rtx_insn *insn)
++{
++  rtx pat = single_set (insn);
++  if (!pat)
++    return NULL_RTX;
++
++  rtx dst = SET_DEST (pat);
++  if (GET_CODE (dst) != OP)
++    return NULL_RTX;
++
++  return dst;
++}
++
++/* Get the rtx destination from single set instruction.  */
++static rtx
++get_single_set_dst (rtx_insn *insn)
++{
++  rtx pat = single_set (insn);
++  if (!pat)
++    return NULL_RTX;
++
++  return SET_DEST (pat);
++}
++
++/* Check if the instruction is single set of suitable opcode.
++   Also gather its source and destination patterns.  */
++template 
++static bool
++check_simple_op (rtx_insn *insn, rtx &src, rtx &dst)
++{
++  rtx pat = single_set (insn);
++  if (!pat)
++    return false;
++
++  src = SET_SRC (pat);
++  dst = SET_DEST (pat);
++
++  if (GET_CODE (src) != OP)
++    return false;
++
++  return true;
++}
++
++/* Minimal term info of the RTL matcher.  All of the custom matchers should
++   inherit from it.
++
++   It stores information about matched pattern, instruction
++   of its location and predicate if the matched term represents operator
++   inside the matched tree.  */
++struct minimal_term_info
++{
++  minimal_term_info ()
++    {}
++  minimal_term_info (rtx_insn *loc, rtx src, bool is_op = false)
++    : loc (loc), src (src), is_op (is_op)
++    {}
++
++  rtx_insn *loc;
++  rtx src;
++  bool is_op;
++};
++
++/* Term info for memory matcher.  */
++struct mem_term_info : minimal_term_info
++{
++  mem_term_info ()
++    {}
++  mem_term_info (rtx_insn *loc, rtx src, unsigned HOST_WIDE_INT offset = 0)
++    : minimal_term_info (loc, src), offset (offset)
++    {}
++
++  unsigned HOST_WIDE_INT offset;
++};
++
++/* A wrapper being used to turn a term into a matcher-like entity.  */
++template
++struct matcher_term
++{
++  /* Required storage size information of the matcher.  */
++  static const int holder_size = 1;
++  static const int op_num = 0;
++  typedef T term_type;
++  typedef term_type holder_type[holder_size];
++};
++
++/* Simple matcher of patterns of suitable opcode.  */
++template
++struct arg_op_matcher : matcher_term
++{
++  typedef typename matcher_term::holder_type holder_type;
++
++  static bool match (rtx_insn *, holder_type &)
++    {
++      return false;
++    }
++
++  static bool match (rtx src, rtx_insn *insn, holder_type &m)
++    {
++      if (GET_CODE (src) != ARGOP)
++	return false;
++
++      static_cast (m[0]) = minimal_term_info (insn, src);
++      return true;
++    }
++};
++
++/* Simple matcher of integer constants.  */
++template
++struct int_cst_matcher : arg_op_matcher 
++{};
++
++/* Unary operator matcher.  */
++template
++struct unop_matcher
++{
++  /* Required storage size information of the matcher.  */
++  static const int holder_size = ARG::holder_size + store_op;
++  static const int op_num = ARG::op_num + store_op;
++  typedef typename ARG::term_type term_type;
++  typedef term_type holder_type[holder_size];
++
++  static bool match (rtx_insn *insn, holder_type &m)
++    {
++      rtx src = get_single_set_op (insn);
++      return src && match (src, insn, m);
++    }
++
++  static bool match (rtx src, rtx_insn *insn, holder_type &m)
++    {
++      if (REG_P (src))
++	{
++	  insn = get_single_def_insn (insn, src);
++	  if (insn && (src = single_set (insn)))
++	    src = SET_SRC (src);
++	}
++
++      if (!src || !insn || (GET_CODE (src) != OP1 && GET_CODE (src) != OP2))
++	return false;
++
++      /* Store current operation if needed.  */
++      if (store_op)
++	static_cast (m[0]) = minimal_term_info (insn, src,
++								     true);
++
++      rtx op = XEXP (src, 0);
++      rtx_insn *def = get_single_def_insn (insn, op);
++      typename ARG::holder_type &m_arg
++	= (typename ARG::holder_type &) *(m + store_op);
++      return (def && ARG::match (def, m_arg)) || ARG::match (op, insn, m_arg);
++    }
++};
++
++/* Binary operator matcher.  */
++template
++struct binop_matcher
++{
++  /* Required storage size information of the matcher.  */
++  static const int holder_size = LHS::holder_size + RHS::holder_size + store_op;
++  static const int op_num = LHS::op_num + RHS::op_num + store_op;
++  typedef typename LHS::term_type term_type;
++  typedef term_type holder_type[holder_size];
++
++  static bool match (rtx_insn *insn, holder_type &m)
++    {
++      rtx src = get_single_set_op (insn);
++      return src && match (src, insn, m);
++    }
++
++  static bool match (rtx src, rtx_insn *insn, holder_type &m)
++    {
++      if (GET_CODE (src) != OP1 && GET_CODE (src) != OP2)
++	return false;
++
++      /* Store current operation if needed.  */
++      if (store_op)
++	static_cast (m[0]) = minimal_term_info (insn, src,
++								     true);
++
++      rtx lhs_op = XEXP (src, 0);
++      rtx rhs_op = XEXP (src, 1);
++      rtx_insn *lhs_def = get_single_def_insn (insn, lhs_op);
++      rtx_insn *rhs_def = get_single_def_insn (insn, rhs_op);
++
++      return match (lhs_def, rhs_def, lhs_op, rhs_op, insn, m)
++	|| (COMMUTATIVE && match (rhs_def, lhs_def, rhs_op, lhs_op, insn, m));
++    }
++
++private:
++  static bool match (rtx_insn *lhs_def, rtx_insn *rhs_def,
++		     rtx lhs_op, rtx rhs_op, rtx_insn *insn,
++		     holder_type &m)
++    {
++      /* Force template instantiation error on non-matching types.  */
++      gcc_assert ((typename LHS::term_type *) NULL
++		  == (typename RHS::term_type *) NULL);
++
++      /* Obtain locations in the storage.  */
++      typename LHS::holder_type &m_lhs
++	= (typename LHS::holder_type &) *(m + store_op);
++      typename RHS::holder_type &m_rhs
++	= (typename RHS::holder_type &) *(m + store_op
++					  + LHS::holder_size);
++
++      /* Try match both instructions.  */
++      if (lhs_def && rhs_def && LHS::match (lhs_def, m_lhs)
++	  && RHS::match (rhs_def, m_rhs))
++	return true;
++      /* Try match instruction and pattern.  */
++      else if (lhs_def && LHS::match (lhs_def, m_lhs)
++	       && RHS::match (rhs_op, insn, m_rhs))
++	return true;
++      /* Try match pattern and instruction.  */
++      else if (rhs_def && LHS::match (lhs_op, insn, m_lhs)
++	       && RHS::match (rhs_def, m_rhs))
++	return true;
++      /* Try match both patterns.  */
++      else
++	return LHS::match (lhs_op, insn, m_lhs)
++	  && RHS::match (rhs_op, insn, m_rhs);
++    }
++};
++
++#endif // GCC_RTL_MATCHER_H
+diff --git a/gcc/target.def b/gcc/target.def
+index 8797a21d5..c9bb2b4c2 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -2693,6 +2693,47 @@ contains post-index or pre-index operation.",
+   bool, (int icode, bool *has_wb),
+   NULL)
+ 
++DEFHOOK
++(get_v16qi_mode,
++ "This function get the 16 byte elements vector mode if target supports this.",
++ machine_mode, (),
++ NULL)
++
++DEFHOOK
++(gen_rev32v16qi,
++ "This function generate the byte reverse instruction\n\
++ of 16 byte elements vector if target supports this.",
++ rtx, (rtx dest, rtx src),
++ NULL)
++
++DEFHOOK
++(gen_aesev16qi,
++ "This function generate the AES encryption instruction\n\
++ of 16 byte elements vector if target supports this.",
++ rtx, (rtx dest, rtx src1, rtx src2),
++ NULL)
++
++DEFHOOK
++(gen_aesdv16qi,
++ "This function generate the AES decryption instruction\n\
++ of 16 byte elements vector if target supports this.",
++ rtx, (rtx dest, rtx src1, rtx src2),
++ NULL)
++
++DEFHOOK
++(gen_aesmcv16qi,
++ "This function generate the AES mix columns instruction\n\
++ of 16 byte elements vector if target supports this.",
++ rtx, (rtx dest, rtx src),
++ NULL)
++
++DEFHOOK
++(gen_aesimcv16qi,
++ "This function generate the AES inversed mix columns instruction\n\
++ of 16 byte elements vector if target supports this.",
++ rtx, (rtx dest, rtx src),
++ NULL)
++
+ DEFHOOK
+ (gen_ccmp_first,
+  "This function prepares to emit a comparison insn for the first compare in a\n\
+diff --git a/gcc/testsuite/gcc.target/aarch64/aes-decrypt.c b/gcc/testsuite/gcc.target/aarch64/aes-decrypt.c
+new file mode 100644
+index 000000000..966ec5532
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/aes-decrypt.c
+@@ -0,0 +1,478 @@
++/* { dg-do run } */
++/* { dg-options "-O3 -fno-inline --save-temps -fcrypto-accel-aes -march=armv8.2-a+lse+crypto" } */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++typedef uint8_t u8;
++typedef uint32_t u32;
++
++static const u32 Td0[256] = {
++    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
++    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
++    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
++    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
++    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
++    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
++    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
++    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
++    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
++    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
++    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
++    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
++    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
++    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
++    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
++    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
++    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
++    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
++    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
++    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
++    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
++    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
++    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
++    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
++    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
++    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
++    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
++    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
++    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
++    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
++    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
++    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
++    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
++    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
++    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
++    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
++    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
++    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
++    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
++    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
++    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
++    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
++    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
++    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
++    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
++    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
++    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
++    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
++    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
++    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
++    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
++    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
++    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
++    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
++    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
++    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
++    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
++    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
++    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
++    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
++    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
++    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
++    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
++    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
++};
++
++static const u32 Td1[256] = {
++    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
++    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
++    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
++    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
++    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
++    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
++    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
++    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
++    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
++    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
++    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
++    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
++    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
++    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
++    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
++    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
++    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
++    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
++    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
++    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
++    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
++    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
++    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
++    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
++    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
++    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
++    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
++    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
++    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
++    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
++    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
++    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
++    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
++    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
++    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
++    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
++    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
++    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
++    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
++    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
++    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
++    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
++    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
++    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
++    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
++    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
++    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
++    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
++    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
++    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
++    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
++    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
++    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
++    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
++    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
++    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
++    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
++    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
++    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
++    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
++    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
++    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
++    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
++    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
++};
++
++static const u32 Td2[256] = {
++    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
++    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
++    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
++    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
++    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
++    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
++    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
++    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
++    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
++    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
++    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
++    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
++    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
++    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
++    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
++    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
++    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
++    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
++    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
++    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
++    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
++    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
++    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
++    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
++    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
++    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
++    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
++    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
++    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
++    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
++    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
++    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
++    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
++    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
++    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
++    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
++    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
++    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
++    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
++    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
++    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
++    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
++    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
++    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
++    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
++    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
++    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
++    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
++    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
++    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
++    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
++    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
++    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
++    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
++    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
++    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
++    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
++    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
++    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
++    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
++    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
++    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
++    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
++    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
++};
++
++static const u32 Td3[256] = {
++    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
++    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
++    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
++    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
++    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
++    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
++    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
++    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
++    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
++    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
++    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
++    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
++    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
++    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
++    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
++    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
++    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
++    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
++    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
++    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
++    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
++    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
++    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
++    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
++    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
++    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
++    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
++    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
++    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
++    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
++    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
++    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
++    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
++    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
++    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
++    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
++    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
++    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
++    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
++    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
++    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
++    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
++    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
++    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
++    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
++    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
++    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
++    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
++    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
++    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
++    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
++    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
++    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
++    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
++    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
++    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
++    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
++    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
++    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
++    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
++    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
++    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
++    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
++    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
++};
++
++static const u8 Td4[256] = {
++    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
++    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
++    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
++    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
++    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
++    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
++    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
++    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
++    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
++    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
++    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
++    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
++    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
++    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
++    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
++    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
++    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
++    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
++    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
++    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
++    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
++    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
++    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
++    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
++    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
++    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
++    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
++    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
++    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
++    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
++    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
++    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
++};
++
++#define GETU32(pt)	   \
++  (			   \
++    ((u32)(pt)[0] << 24)   \
++    ^ ((u32)(pt)[1] << 16) \
++    ^ ((u32)(pt)[2] <<  8) \
++    ^ ((u32)(pt)[3])       \
++  )
++
++#define PUTU32(ct, st)		\
++  {				\
++    (ct)[0] = (u8)((st) >> 24); \
++    (ct)[1] = (u8)((st) >> 16); \
++    (ct)[2] = (u8)((st) >>  8); \
++    (ct)[3] = (u8)(st);		\
++  }
++
++void
++aes_decrypt (const unsigned char *in, unsigned char *out,
++	     const u32 *rk, int nr)
++{
++  u32 s0, s1, s2, s3, t0, t1, t2, t3;
++
++  int r = nr >> 1;
++
++  s0 = GETU32 (in     ) ^ rk[0];
++  s1 = GETU32 (in +  4) ^ rk[1];
++  s2 = GETU32 (in +  8) ^ rk[2];
++  s3 = GETU32 (in + 12) ^ rk[3];
++
++  for (;;) {
++      t0 =
++	Td0[(s0 >> 24)       ] ^
++	Td1[(s3 >> 16) & 0xff] ^
++	Td2[(s2 >>  8) & 0xff] ^
++	Td3[(s1      ) & 0xff] ^
++	rk[4];
++      t1 =
++	Td0[(s1 >> 24)       ] ^
++	Td1[(s0 >> 16) & 0xff] ^
++	Td2[(s3 >>  8) & 0xff] ^
++	Td3[(s2      ) & 0xff] ^
++	rk[5];
++      t2 =
++	Td0[(s2 >> 24)       ] ^
++	Td1[(s1 >> 16) & 0xff] ^
++	Td2[(s0 >>  8) & 0xff] ^
++	Td3[(s3      ) & 0xff] ^
++	rk[6];
++      t3 =
++	Td0[(s3 >> 24)       ] ^
++	Td1[(s2 >> 16) & 0xff] ^
++	Td2[(s1 >>  8) & 0xff] ^
++	Td3[(s0      ) & 0xff] ^
++	rk[7];
++
++      rk += 8;
++      if (--r == 0) {
++	  break;
++      }
++
++      s0 =
++	Td0[(t0 >> 24)       ] ^
++	Td1[(t3 >> 16) & 0xff] ^
++	Td2[(t2 >>  8) & 0xff] ^
++	Td3[(t1      ) & 0xff] ^
++	rk[0];
++      s1 =
++	Td0[(t1 >> 24)       ] ^
++	Td1[(t0 >> 16) & 0xff] ^
++	Td2[(t3 >>  8) & 0xff] ^
++	Td3[(t2      ) & 0xff] ^
++	rk[1];
++      s2 =
++	Td0[(t2 >> 24)       ] ^
++	Td1[(t1 >> 16) & 0xff] ^
++	Td2[(t0 >>  8) & 0xff] ^
++	Td3[(t3      ) & 0xff] ^
++	rk[2];
++      s3 =
++	Td0[(t3 >> 24)       ] ^
++	Td1[(t2 >> 16) & 0xff] ^
++	Td2[(t1 >>  8) & 0xff] ^
++	Td3[(t0      ) & 0xff] ^
++	rk[3];
++    }
++
++    s0 =
++	((u32)Td4[(t0 >> 24)       ] << 24) ^
++	((u32)Td4[(t3 >> 16) & 0xff] << 16) ^
++	((u32)Td4[(t2 >>  8) & 0xff] <<  8) ^
++	((u32)Td4[(t1      ) & 0xff])       ^
++	rk[0];
++    PUTU32 (out     , s0);
++
++    s1 =
++	((u32)Td4[(t1 >> 24)       ] << 24) ^
++	((u32)Td4[(t0 >> 16) & 0xff] << 16) ^
++	((u32)Td4[(t3 >>  8) & 0xff] <<  8) ^
++	((u32)Td4[(t2      ) & 0xff])       ^
++	rk[1];
++    PUTU32 (out +  4, s1);
++
++    s2 =
++	((u32)Td4[(t2 >> 24)       ] << 24) ^
++	((u32)Td4[(t1 >> 16) & 0xff] << 16) ^
++	((u32)Td4[(t0 >>  8) & 0xff] <<  8) ^
++	((u32)Td4[(t3      ) & 0xff])       ^
++	rk[2];
++    PUTU32 (out +  8, s2);
++
++    s3 =
++	((u32)Td4[(t3 >> 24)       ] << 24) ^
++	((u32)Td4[(t2 >> 16) & 0xff] << 16) ^
++	((u32)Td4[(t1 >>  8) & 0xff] <<  8) ^
++	((u32)Td4[(t0      ) & 0xff])       ^
++	rk[3];
++    PUTU32 (out + 12, s3);
++}
++
++int main ()
++{
++  const u8 input[16] = { 0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb,
++			 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32 };
++
++  const u8 expected[16] = { 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
++			    0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 };
++
++  const u8 key[] = { 0xa8, 0xf9, 0x14, 0xd0, 0x89, 0x25, 0xee, 0xc9,
++		     0xc8, 0x0c, 0x3f, 0xe1, 0xa6, 0x0c, 0x63, 0xb6,
++      		     0x63, 0x5a, 0x7b, 0x0c, 0xfe, 0xea, 0x19, 0x13,
++      		     0x90, 0x88, 0x39, 0xb0, 0xb4, 0xfb, 0x4c, 0x66,
++      		     0x5a, 0x92, 0x7d, 0xdf, 0x9d, 0xb0, 0x62, 0x1f,
++      		     0x6e, 0x62, 0x20, 0xa3, 0x24, 0x73, 0x75, 0xd6,
++      		     0x47, 0x76, 0xc0, 0x12, 0xc7, 0x22, 0x1f, 0xc0,
++      		     0xf3, 0xd2, 0x42, 0xbc, 0x4a, 0x11, 0x55, 0x75,
++      		     0x76, 0xd8, 0xfc, 0x6e, 0x80, 0x54, 0xdf, 0xd2,
++      		     0x34, 0xf0, 0x5d, 0x7c, 0xb9, 0xc3, 0x17, 0xc9,
++      		     0xfc, 0x0a, 0xa3, 0x6e, 0xf6, 0x8c, 0x23, 0xbc,
++      		     0xb4, 0xa4, 0x82, 0xae, 0x8d, 0x33, 0x4a, 0xb5,
++      		     0x13, 0x44, 0x88, 0x90, 0x0a, 0x86, 0x80, 0xd2,
++      		     0x42, 0x28, 0xa1, 0x12, 0x39, 0x97, 0xc8, 0x1b,
++      		     0xf7, 0x13, 0x1f, 0x7c, 0x19, 0xc2, 0x08, 0x42,
++      		     0x48, 0xae, 0x21, 0xc0, 0x7b, 0xbf, 0x69, 0x09,
++      		     0xeb, 0x05, 0x75, 0xcc, 0xee, 0xd1, 0x17, 0x3e,
++      		     0x51, 0x6c, 0x29, 0x82, 0x33, 0x11, 0x48, 0xc9,
++      		     0xa7, 0x08, 0x37, 0x2b, 0x05, 0xd4, 0x62, 0xf2,
++      		     0xbf, 0xbd, 0x3e, 0xbc, 0x62, 0x7d, 0x61, 0x4b,
++      		     0x16, 0x15, 0x7e, 0x2b, 0xa6, 0xd2, 0xae, 0x28,
++      		     0x88, 0x15, 0xf7, 0xab, 0x3c, 0x4f, 0xcf, 0x09 };
++
++  u8 output[16] = { 0 };
++
++  aes_decrypt (input, output, (u32*) key, 10);
++
++  if (memcmp (output, expected, 16) != 0)
++    abort ();
++
++  return 0;
++}
++
++/* { dg-final { scan-assembler "rev32" } } */
++/* { dg-final { scan-assembler "aesimc" } } */
++/* { dg-final { scan-assembler "aesd" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/aes-encrypt.c b/gcc/testsuite/gcc.target/aarch64/aes-encrypt.c
+new file mode 100644
+index 000000000..e3f3c446f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/aes-encrypt.c
+@@ -0,0 +1,443 @@
++/* { dg-do run } */
++/* { dg-options "-O3 -fno-inline --save-temps -fcrypto-accel-aes -march=armv8.2-a+lse+crypto" } */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++
++typedef uint8_t u8;
++typedef uint32_t u32;
++
++static const u32 Te0[256] = {
++    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
++    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
++    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
++    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
++    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
++    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
++    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
++    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
++    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
++    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
++    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
++    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
++    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
++    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
++    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
++    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
++    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
++    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
++    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
++    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
++    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
++    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
++    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
++    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
++    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
++    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
++    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
++    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
++    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
++    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
++    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
++    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
++    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
++    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
++    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
++    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
++    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
++    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
++    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
++    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
++    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
++    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
++    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
++    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
++    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
++    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
++    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
++    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
++    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
++    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
++    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
++    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
++    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
++    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
++    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
++    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
++    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
++    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
++    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
++    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
++    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
++    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
++    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
++    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
++};
++
++static const u32 Te1[256] = {
++    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
++    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
++    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
++    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
++    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
++    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
++    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
++    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
++    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
++    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
++    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
++    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
++    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
++    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
++    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
++    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
++    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
++    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
++    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
++    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
++    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
++    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
++    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
++    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
++    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
++    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
++    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
++    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
++    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
++    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
++    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
++    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
++    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
++    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
++    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
++    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
++    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
++    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
++    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
++    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
++    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
++    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
++    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
++    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
++    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
++    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
++    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
++    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
++    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
++    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
++    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
++    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
++    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
++    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
++    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
++    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
++    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
++    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
++    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
++    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
++    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
++    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
++    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
++    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
++};
++
++static const u32 Te2[256] = {
++    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
++    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
++    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
++    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
++    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
++    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
++    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
++    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
++    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
++    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
++    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
++    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
++    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
++    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
++    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
++    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
++    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
++    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
++    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
++    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
++    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
++    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
++    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
++    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
++    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
++    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
++    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
++    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
++    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
++    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
++    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
++    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
++    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
++    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
++    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
++    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
++    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
++    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
++    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
++    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
++    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
++    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
++    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
++    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
++    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
++    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
++    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
++    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
++    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
++    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
++    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
++    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
++    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
++    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
++    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
++    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
++    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
++    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
++    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
++    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
++    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
++    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
++    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
++    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
++};
++
++static const u32 Te3[256] = {
++    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
++    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
++    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
++    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
++    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
++    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
++    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
++    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
++    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
++    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
++    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
++    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
++    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
++    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
++    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
++    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
++    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
++    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
++    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
++    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
++    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
++    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
++    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
++    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
++    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
++    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
++    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
++    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
++    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
++    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
++    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
++    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
++    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
++    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
++    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
++    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
++    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
++    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
++    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
++    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
++    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
++    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
++    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
++    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
++    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
++    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
++    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
++    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
++    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
++    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
++    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
++    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
++    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
++    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
++    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
++    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
++    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
++    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
++    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
++    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
++    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
++    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
++    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
++    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
++};
++
++#define GETU32(pt)	   \
++  (			   \
++    ((u32)(pt)[0] << 24)   \
++    ^ ((u32)(pt)[1] << 16) \
++    ^ ((u32)(pt)[2] <<  8) \
++    ^ ((u32)(pt)[3])       \
++  )
++
++#define PUTU32(ct, st)		\
++  {				\
++    (ct)[0] = (u8)((st) >> 24); \
++    (ct)[1] = (u8)((st) >> 16); \
++    (ct)[2] = (u8)((st) >>  8); \
++    (ct)[3] = (u8)(st);		\
++  }
++
++void
++aes_encrypt (const unsigned char *in, unsigned char *out,
++	     const u32 *rk, int nr)
++{
++  u32 s0, s1, s2, s3, t0, t1, t2, t3;
++
++  int r = nr >> 1;
++
++  s0 = GETU32 (in     ) ^ rk[0];
++  s1 = GETU32 (in +  4) ^ rk[1];
++  s2 = GETU32 (in +  8) ^ rk[2];
++  s3 = GETU32 (in + 12) ^ rk[3];
++
++  for (;;) {
++    t0 =
++	Te0[(s0 >> 24)       ] ^
++	Te1[(s1 >> 16) & 0xff] ^
++	Te2[(s2 >>  8) & 0xff] ^
++	Te3[(s3      ) & 0xff] ^
++	rk[4];
++    t1 =
++	Te0[(s1 >> 24)       ] ^
++	Te1[(s2 >> 16) & 0xff] ^
++	Te2[(s3 >>  8) & 0xff] ^
++	Te3[(s0      ) & 0xff] ^
++	rk[5];
++    t2 =
++	Te0[(s2 >> 24)       ] ^
++	Te1[(s3 >> 16) & 0xff] ^
++	Te2[(s0 >>  8) & 0xff] ^
++	Te3[(s1      ) & 0xff] ^
++	rk[6];
++    t3 =
++	Te0[(s3 >> 24)       ] ^
++	Te1[(s0 >> 16) & 0xff] ^
++	Te2[(s1 >>  8) & 0xff] ^
++	Te3[(s2      ) & 0xff] ^
++	rk[7];
++
++    rk += 8;
++    if (--r == 0)
++	break;
++
++    s0 =
++	Te0[(t0 >> 24)       ] ^
++	Te1[(t1 >> 16) & 0xff] ^
++	Te2[(t2 >>  8) & 0xff] ^
++	Te3[(t3      ) & 0xff] ^
++	rk[0];
++    s1 =
++	Te0[(t1 >> 24)       ] ^
++	Te1[(t2 >> 16) & 0xff] ^
++	Te2[(t3 >>  8) & 0xff] ^
++	Te3[(t0      ) & 0xff] ^
++	rk[1];
++    s2 =
++	Te0[(t2 >> 24)       ] ^
++	Te1[(t3 >> 16) & 0xff] ^
++	Te2[(t0 >>  8) & 0xff] ^
++	Te3[(t1      ) & 0xff] ^
++	rk[2];
++    s3 =
++	Te0[(t3 >> 24)       ] ^
++	Te1[(t0 >> 16) & 0xff] ^
++	Te2[(t1 >>  8) & 0xff] ^
++	Te3[(t2      ) & 0xff] ^
++	rk[3];
++  }
++
++  s0 =
++      (Te2[(t0 >> 24)       ] & 0xff000000) ^
++      (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^
++      (Te0[(t2 >>  8) & 0xff] & 0x0000ff00) ^
++      (Te1[(t3      ) & 0xff] & 0x000000ff) ^
++      rk[0];
++  PUTU32 (out     , s0);
++
++  s1 =
++      (Te2[(t1 >> 24)       ] & 0xff000000) ^
++      (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^
++      (Te0[(t3 >>  8) & 0xff] & 0x0000ff00) ^
++      (Te1[(t0      ) & 0xff] & 0x000000ff) ^
++      rk[1];
++  PUTU32 (out +  4, s1);
++
++  s2 =
++      (Te2[(t2 >> 24)       ] & 0xff000000) ^
++      (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^
++      (Te0[(t0 >>  8) & 0xff] & 0x0000ff00) ^
++      (Te1[(t1      ) & 0xff] & 0x000000ff) ^
++      rk[2];
++  PUTU32 (out +  8, s2);
++
++  s3 =
++      (Te2[(t3 >> 24)       ] & 0xff000000) ^
++      (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^
++      (Te0[(t1 >>  8) & 0xff] & 0x0000ff00) ^
++      (Te1[(t2      ) & 0xff] & 0x000000ff) ^
++      rk[3];
++  PUTU32 (out + 12, s3);
++}
++
++
++int main ()
++{
++  const u8 input[16] = { 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
++			 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 };
++
++  const u8 expected[16] = { 0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb,
++			    0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32 };
++
++  const u8 key[] = { 0x16, 0x15, 0x7e, 0x2b, 0xa6, 0xd2, 0xae, 0x28,
++		     0x88, 0x15, 0xf7, 0xab, 0x3c, 0x4f, 0xcf, 0x09,
++		     0x17, 0xfe, 0xfa, 0xa0, 0xb1, 0x2c, 0x54, 0x88,
++		     0x39, 0x39, 0xa3, 0x23, 0x05, 0x76, 0x6c, 0x2a,
++		     0xf2, 0x95, 0xc2, 0xf2, 0x43, 0xb9, 0x96, 0x7a,
++		     0x7a, 0x80, 0x35, 0x59, 0x7f, 0xf6, 0x59, 0x73,
++		     0x7d, 0x47, 0x80, 0x3d, 0x3e, 0xfe, 0x16, 0x47,
++		     0x44, 0x7e, 0x23, 0x1e, 0x3b, 0x88, 0x7a, 0x6d,
++		     0x41, 0xa5, 0x44, 0xef, 0x7f, 0x5b, 0x52, 0xa8,
++		     0x3b, 0x25, 0x71, 0xb6, 0x00, 0xad, 0x0b, 0xdb,
++		     0xf8, 0xc6, 0xd1, 0xd4, 0x87, 0x9d, 0x83, 0x7c,
++		     0xbc, 0xb8, 0xf2, 0xca, 0xbc, 0x15, 0xf9, 0x11,
++		     0x7a, 0xa3, 0x88, 0x6d, 0xfd, 0x3e, 0x0b, 0x11,
++		     0x41, 0x86, 0xf9, 0xdb, 0xfd, 0x93, 0x00, 0xca,
++		     0x0e, 0xf7, 0x54, 0x4e, 0xf3, 0xc9, 0x5f, 0x5f,
++		     0xb2, 0x4f, 0xa6, 0x84, 0x4f, 0xdc, 0xa6, 0x4e,
++		     0x21, 0x73, 0xd2, 0xea, 0xd2, 0xba, 0x8d, 0xb5,
++		     0x60, 0xf5, 0x2b, 0x31, 0x2f, 0x29, 0x8d, 0x7f,
++		     0xf3, 0x66, 0x77, 0xac, 0x21, 0xdc, 0xfa, 0x19,
++		     0x41, 0x29, 0xd1, 0x28, 0x6e, 0x00, 0x5c, 0x57,
++		     0xa8, 0xf9, 0x14, 0xd0, 0x89, 0x25, 0xee, 0xc9,
++		     0xc8, 0x0c, 0x3f, 0xe1, 0xa6, 0x0c, 0x63, 0xb6 };
++
++  u8 output[16] = { 0 };
++
++  aes_encrypt (input, output, (u32*) key, 10);
++
++  if (memcmp (output, expected, 16) != 0)
++    abort ();
++
++  return 0;
++}
++
++/* { dg-final { scan-assembler "rev32" } } */
++/* { dg-final { scan-assembler "aesmc" } } */
++/* { dg-final { scan-assembler "aese" } } */
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 2ccecffb5..18a9f62cc 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -261,6 +261,7 @@ DEFTIMEVAR (TV_AUTO_INC_DEC          , "auto inc dec")
+ DEFTIMEVAR (TV_CSE2                  , "CSE 2")
+ DEFTIMEVAR (TV_BRANCH_PROB           , "branch prediction")
+ DEFTIMEVAR (TV_COMBINE               , "combiner")
++DEFTIMEVAR (TV_CRYPTO_ACCEL	     , "crypto accel")
+ DEFTIMEVAR (TV_IFCVT		     , "if-conversion")
+ DEFTIMEVAR (TV_MODE_SWITCH           , "mode switching")
+ DEFTIMEVAR (TV_SMS		     , "sms modulo scheduling")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 6daac7fc1..1733931c3 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -583,6 +583,7 @@ extern rtl_opt_pass *make_pass_cse2 (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_df_initialize_opt (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_df_initialize_no_opt (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_reginfo_init (gcc::context *ctxt);
++extern rtl_opt_pass *make_pass_crypto_accel (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_inc_dec (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_stack_ptr_mod (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_initialize_regs (gcc::context *ctxt);
+-- 
+2.33.0
+
diff --git a/0048-crypto-accel-add-optimization-level-requirement-to-t.patch b/0048-crypto-accel-add-optimization-level-requirement-to-t.patch
new file mode 100644
index 0000000..49dfc1d
--- /dev/null
+++ b/0048-crypto-accel-add-optimization-level-requirement-to-t.patch
@@ -0,0 +1,27 @@
+From 915d549b03c10ab403538888149facd417a02ebc Mon Sep 17 00:00:00 2001
+From: vchernon 
+Date: Wed, 27 Dec 2023 23:31:26 +0800
+Subject: [PATCH 16/18] [crypto-accel] add optimization level requirement to
+ the gate
+
+fix issue (src-openEuler/gcc: I8RRDW)
+---
+ gcc/crypto-accel.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/crypto-accel.cc b/gcc/crypto-accel.cc
+index f4e810a6b..e7766a585 100644
+--- a/gcc/crypto-accel.cc
++++ b/gcc/crypto-accel.cc
+@@ -2391,7 +2391,7 @@ public:
+   /* opt_pass methods: */
+   virtual bool gate (function *)
+     {
+-      if (flag_crypto_accel_aes <= 0)
++      if (flag_crypto_accel_aes <= 0 || optimize < 1)
+ 	return false;
+       return targetm.get_v16qi_mode
+ 	&& targetm.gen_rev32v16qi
+-- 
+2.33.0
+
diff --git a/0049-Add-more-flexible-check-for-pointer-aliasing-during-.patch b/0049-Add-more-flexible-check-for-pointer-aliasing-during-.patch
new file mode 100644
index 0000000..df88789
--- /dev/null
+++ b/0049-Add-more-flexible-check-for-pointer-aliasing-during-.patch
@@ -0,0 +1,239 @@
+From b5865aef36ebaac87ae30d51f08bfe081795ed67 Mon Sep 17 00:00:00 2001
+From: Chernonog Viacheslav 
+Date: Tue, 12 Mar 2024 23:30:56 +0800
+Subject: [PATCH 17/18] Add more flexible check for pointer aliasing during
+ vectorization It takes minimum between number of iteration and segment length
+ it helps to speed up loops with small number of iterations when only tail can
+ be vectorized
+
+---
+ gcc/params.opt                                |  5 ++
+ .../sve/var_stride_flexible_segment_len_1.c   | 23 +++++++
+ gcc/tree-data-ref.cc                          | 67 +++++++++++++------
+ gcc/tree-data-ref.h                           | 11 ++-
+ gcc/tree-vect-data-refs.cc                    | 14 +++-
+ 5 files changed, 95 insertions(+), 25 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/var_stride_flexible_segment_len_1.c
+
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 6176d4790..7e5c119cf 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1180,6 +1180,11 @@ Maximum number of loop peels to enhance alignment of data references in a loop.
+ Common Joined UInteger Var(param_vect_max_version_for_alias_checks) Init(10) Param Optimization
+ Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check.
+ 
++-param=vect-alias-flexible-segment-len=
++Common Joined UInteger Var(param_flexible_seg_len) Init(0) IntegerRange(0, 1) Param Optimization
++Use a minimum length of different segments.  Currenlty the minimum between
++iteration number and vectorization length is chosen by this param.
++
+ -param=vect-max-version-for-alignment-checks=
+ Common Joined UInteger Var(param_vect_max_version_for_alignment_checks) Init(6) Param Optimization
+ Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check.
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/var_stride_flexible_segment_len_1.c b/gcc/testsuite/gcc.target/aarch64/sve/var_stride_flexible_segment_len_1.c
+new file mode 100644
+index 000000000..894f075f3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/var_stride_flexible_segment_len_1.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -ftree-vectorize --param=vect-alias-flexible-segment-len=1" } */
++
++#define TYPE int
++#define SIZE 257
++
++void __attribute__ ((weak))
++f (TYPE *x, TYPE *y, unsigned short n, long m __attribute__((unused)))
++{
++  for (int i = 0; i < SIZE; ++i)
++    x[i * n] += y[i * n];
++}
++
++/* { dg-final { scan-assembler {\tld1w\tz[0-9]+} } } */
++/* { dg-final { scan-assembler {\tst1w\tz[0-9]+} } } */
++/* { dg-final { scan-assembler {\tldr\tw[0-9]+} } } */
++/* { dg-final { scan-assembler {\tstr\tw[0-9]+} } } */
++/* Should use a WAR check that multiplies by (VF-2)*4 rather than
++   an overlap check that multiplies by (257-1)*4.  */
++/* { dg-final { scan-assembler {\tcntb\t(x[0-9]+)\n.*\tsub\tx[0-9]+, \1, #8\n.*\tmul\tx[0-9]+,[^\n]*\1} } } */
++/* One range check and a check for n being zero.  */
++/* { dg-final { scan-assembler-times {\t(?:cmp|tst)\t} 2 } } */
++/* { dg-final { scan-assembler-times {\tccmp\t} 1 } } */
+diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
+index 397792c35..e6ae9e847 100644
+--- a/gcc/tree-data-ref.cc
++++ b/gcc/tree-data-ref.cc
+@@ -2329,31 +2329,15 @@ create_intersect_range_checks_index (class loop *loop, tree *cond_expr,
+    same arguments.  Try to optimize cases in which the second access
+    is a write and in which some overlap is valid.  */
+ 
+-static bool
+-create_waw_or_war_checks (tree *cond_expr,
++static void
++create_waw_or_war_checks2 (tree *cond_expr, tree seg_len_a,
+ 			  const dr_with_seg_len_pair_t &alias_pair)
+ {
+   const dr_with_seg_len& dr_a = alias_pair.first;
+   const dr_with_seg_len& dr_b = alias_pair.second;
+ 
+-  /* Check for cases in which:
+-
+-     (a) DR_B is always a write;
+-     (b) the accesses are well-ordered in both the original and new code
+-	 (see the comment above the DR_ALIAS_* flags for details); and
+-     (c) the DR_STEPs describe all access pairs covered by ALIAS_PAIR.  */
+-  if (alias_pair.flags & ~(DR_ALIAS_WAR | DR_ALIAS_WAW))
+-    return false;
+-
+-  /* Check for equal (but possibly variable) steps.  */
+   tree step = DR_STEP (dr_a.dr);
+-  if (!operand_equal_p (step, DR_STEP (dr_b.dr)))
+-    return false;
+-
+-  /* Make sure that we can operate on sizetype without loss of precision.  */
+   tree addr_type = TREE_TYPE (DR_BASE_ADDRESS (dr_a.dr));
+-  if (TYPE_PRECISION (addr_type) != TYPE_PRECISION (sizetype))
+-    return false;
+ 
+   /* All addresses involved are known to have a common alignment ALIGN.
+      We can therefore subtract ALIGN from an exclusive endpoint to get
+@@ -2370,9 +2354,6 @@ create_waw_or_war_checks (tree *cond_expr,
+ 			       fold_convert (ssizetype, indicator),
+ 			       ssize_int (0));
+ 
+-  /* Get lengths in sizetype.  */
+-  tree seg_len_a
+-    = fold_convert (sizetype, rewrite_to_non_trapping_overflow (dr_a.seg_len));
+   step = fold_convert (sizetype, rewrite_to_non_trapping_overflow (step));
+ 
+   /* Each access has the following pattern:
+@@ -2479,6 +2460,50 @@ create_waw_or_war_checks (tree *cond_expr,
+   *cond_expr = fold_build2 (GT_EXPR, boolean_type_node, subject, limit);
+   if (dump_enabled_p ())
+     dump_printf (MSG_NOTE, "using an address-based WAR/WAW test\n");
++}
++
++/* This is a wrapper function for create_waw_or_war_checks2.  */
++static bool
++create_waw_or_war_checks (tree *cond_expr,
++			  const dr_with_seg_len_pair_t &alias_pair)
++{
++  const dr_with_seg_len& dr_a = alias_pair.first;
++  const dr_with_seg_len& dr_b = alias_pair.second;
++
++  /* Check for cases in which:
++
++     (a) DR_B is always a write;
++     (b) the accesses are well-ordered in both the original and new code
++     (see the comment above the DR_ALIAS_* flags for details); and
++     (c) the DR_STEPs describe all access pairs covered by ALIAS_PAIR.  */
++  if (alias_pair.flags & ~(DR_ALIAS_WAR | DR_ALIAS_WAW))
++    return false;
++
++  /* Check for equal (but possibly variable) steps.  */
++  tree step = DR_STEP (dr_a.dr);
++  if (!operand_equal_p (step, DR_STEP (dr_b.dr)))
++    return false;
++
++  /* Make sure that we can operate on sizetype without loss of precision.  */
++  tree addr_type = TREE_TYPE (DR_BASE_ADDRESS (dr_a.dr));
++  if (TYPE_PRECISION (addr_type) != TYPE_PRECISION (sizetype))
++    return false;
++
++  /* Get lengths in sizetype.  */
++  tree seg_len_a
++    = fold_convert (sizetype,
++		    rewrite_to_non_trapping_overflow (dr_a.seg_len));
++  create_waw_or_war_checks2 (cond_expr, seg_len_a, alias_pair);
++  if (param_flexible_seg_len && dr_a.seg_len != dr_a.seg_len2)
++    {
++      tree seg_len2_a
++	= fold_convert (sizetype,
++			rewrite_to_non_trapping_overflow (dr_a.seg_len2));
++      tree cond_expr2;
++      create_waw_or_war_checks2 (&cond_expr2, seg_len2_a, alias_pair);
++      *cond_expr =  fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
++				 *cond_expr, cond_expr2);
++   }
+   return true;
+ }
+ 
+diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
+index f643a95b2..9bc5f16ee 100644
+--- a/gcc/tree-data-ref.h
++++ b/gcc/tree-data-ref.h
+@@ -213,12 +213,19 @@ class dr_with_seg_len
+ public:
+   dr_with_seg_len (data_reference_p d, tree len, unsigned HOST_WIDE_INT size,
+ 		   unsigned int a)
+-    : dr (d), seg_len (len), access_size (size), align (a) {}
+-
++    : dr (d), seg_len (len), seg_len2 (len), access_size (size), align (a)
++    {}
++  dr_with_seg_len (data_reference_p d, tree len, tree len2,
++		   unsigned HOST_WIDE_INT size, unsigned int a)
++    : dr (d), seg_len (len), seg_len2 (len2), access_size (size), align (a)
++    {}
+   data_reference_p dr;
+   /* The offset of the last access that needs to be checked minus
+      the offset of the first.  */
+   tree seg_len;
++  /* The second version of segment length.  Currently this is used to
++     soften checks for a small number of iterations.  */
++  tree seg_len2;
+   /* A value that, when added to abs (SEG_LEN), gives the total number of
+      bytes in the segment.  */
+   poly_uint64 access_size;
+diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
+index 4e615b80b..04e68f621 100644
+--- a/gcc/tree-vect-data-refs.cc
++++ b/gcc/tree-vect-data-refs.cc
+@@ -3646,6 +3646,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
+     {
+       poly_uint64 lower_bound;
+       tree segment_length_a, segment_length_b;
++      tree segment_length2_a, segment_length2_b;
+       unsigned HOST_WIDE_INT access_size_a, access_size_b;
+       unsigned int align_a, align_b;
+ 
+@@ -3751,6 +3752,8 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
+ 	{
+ 	  segment_length_a = size_zero_node;
+ 	  segment_length_b = size_zero_node;
++	  segment_length2_a = size_zero_node;
++	  segment_length2_b = size_zero_node;
+ 	}
+       else
+ 	{
+@@ -3759,8 +3762,15 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
+ 	    length_factor = scalar_loop_iters;
+ 	  else
+ 	    length_factor = size_int (vect_factor);
++	  /* In any case we should rememeber scalar_loop_iters
++	     this helps to create flexible aliasing check
++	     for small number of iterations.  */
+ 	  segment_length_a = vect_vfa_segment_size (dr_info_a, length_factor);
+ 	  segment_length_b = vect_vfa_segment_size (dr_info_b, length_factor);
++	  segment_length2_a
++	    = vect_vfa_segment_size (dr_info_a, scalar_loop_iters);
++	  segment_length2_b
++	    = vect_vfa_segment_size (dr_info_b, scalar_loop_iters);
+ 	}
+       access_size_a = vect_vfa_access_size (loop_vinfo, dr_info_a);
+       access_size_b = vect_vfa_access_size (loop_vinfo, dr_info_b);
+@@ -3805,9 +3815,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
+ 	}
+ 
+       dr_with_seg_len dr_a (dr_info_a->dr, segment_length_a,
+-			    access_size_a, align_a);
++			    segment_length2_a, access_size_a, align_a);
+       dr_with_seg_len dr_b (dr_info_b->dr, segment_length_b,
+-			    access_size_b, align_b);
++			    segment_length2_b, access_size_b, align_b);
+       /* Canonicalize the order to be the one that's needed for accurate
+ 	 RAW, WAR and WAW flags, in cases where the data references are
+ 	 well-ordered.  The order doesn't really matter otherwise,
+-- 
+2.33.0
+
diff --git a/0050-Port-IPA-prefetch-to-GCC-12.patch b/0050-Port-IPA-prefetch-to-GCC-12.patch
new file mode 100644
index 0000000..225a0c4
--- /dev/null
+++ b/0050-Port-IPA-prefetch-to-GCC-12.patch
@@ -0,0 +1,2071 @@
+From 7ee50ce44c652e21ca8ad33dc4e175f02b51b072 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Fri, 8 Mar 2024 06:50:39 +0800
+Subject: [PATCH 18/18] Port IPA prefetch to GCC 12
+
+---
+ gcc/Makefile.in     |    1 +
+ gcc/cgraph.cc       |    1 +
+ gcc/cgraph.h        |    2 +
+ gcc/common.opt      |    8 +
+ gcc/ipa-devirt.cc   |   54 +-
+ gcc/ipa-prefetch.cc | 1819 +++++++++++++++++++++++++++++++++++++++++++
+ gcc/ipa-sra.cc      |    8 +
+ gcc/params.opt      |    8 +
+ gcc/passes.def      |    1 +
+ gcc/timevar.def     |    1 +
+ gcc/tree-pass.h     |    1 +
+ 11 files changed, 1902 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/ipa-prefetch.cc
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 876000bda..10544e4a9 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1468,6 +1468,7 @@ OBJS = \
+ 	ipa-modref.o \
+ 	ipa-modref-tree.o \
+ 	ipa-predicate.o \
++	ipa-prefetch.o \
+ 	ipa-profile.o \
+ 	ipa-prop.o \
+ 	ipa-param-manipulation.o \
+diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
+index 3734c85db..7d738b891 100644
+--- a/gcc/cgraph.cc
++++ b/gcc/cgraph.cc
+@@ -998,6 +998,7 @@ cgraph_node::create_indirect_edge (gcall *call_stmt, int ecf_flags,
+   edge->indirect_info = cgraph_allocate_init_indirect_info ();
+   edge->indirect_info->ecf_flags = ecf_flags;
+   edge->indirect_info->vptr_changed = true;
++  edge->indirect_info->targets = NULL;
+ 
+   /* Record polymorphic call info.  */
+   if (!cloning_p
+diff --git a/gcc/cgraph.h b/gcc/cgraph.h
+index d96690326..b84ff2f98 100644
+--- a/gcc/cgraph.h
++++ b/gcc/cgraph.h
+@@ -1659,6 +1659,8 @@ public:
+   int param_index;
+   /* ECF flags determined from the caller.  */
+   int ecf_flags;
++  /* Vector of potential call targets determined by analysis.  */
++  vec *targets;
+ 
+   /* Number of speculative call targets, it's less than GCOV_TOPN_VALUES.  */
+   unsigned num_speculative_call_targets : 16;
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 1eb62ada5..e65a06af9 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1328,6 +1328,10 @@ fdevirtualize
+ Common Var(flag_devirtualize) Optimization
+ Try to convert virtual calls to direct ones.
+ 
++fipa-ic
++Common Var(flag_ipa_ic) Optimization Init(0)
++Perform interprocedural analysis of indirect calls.
++
+ ficp
+ Common Var(flag_icp) Optimization Init(0)
+ Try to promote indirect calls to direct ones.
+@@ -2367,6 +2371,10 @@ fprefetch-loop-arrays
+ Common Var(flag_prefetch_loop_arrays) Init(-1) Optimization
+ Generate prefetch instructions, if available, for arrays in loops.
+ 
++fipa-prefetch
++Common Var(flag_ipa_prefetch) Init(0) Optimization
++Generate prefetch instructions, if available, using IPA info.
++
+ fprofile
+ Common Var(profile_flag)
+ Enable basic program profiling code.
+diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
+index 318535d06..dd3562d56 100644
+--- a/gcc/ipa-devirt.cc
++++ b/gcc/ipa-devirt.cc
+@@ -5758,6 +5758,54 @@ merge_fs_map_for_ftype_aliases ()
+     }
+ }
+ 
++/* Save results of indirect call analysis for the next passes.  */
++
++static void
++save_analysis_results ()
++{
++  if (dump_file)
++    fprintf (dump_file, "\n\nSave results of indirect call analysis.\n");
++
++  struct cgraph_node *n;
++  FOR_EACH_FUNCTION (n)
++    {
++      cgraph_edge *e, *next;
++      for (e = n->indirect_calls; e; e = next)
++	{
++	  next = e->next_callee;
++	  if (e->indirect_info->polymorphic)
++	    continue;
++	  gcall *stmt = e->call_stmt;
++	  gcc_assert (stmt != NULL);
++	  tree call_fn = gimple_call_fn (stmt);
++	  tree call_fn_ty = TREE_TYPE (call_fn);
++	  if (!POINTER_TYPE_P (call_fn_ty))
++	    continue;
++
++	  tree ctype = TYPE_CANONICAL (TREE_TYPE (call_fn_ty));
++	  unsigned ctype_uid = ctype ? TYPE_UID (ctype) : 0;
++	  if (!ctype_uid || unsafe_types->count (ctype_uid)
++	      || !fs_map->count (ctype_uid))
++	    continue;
++	  /* TODO: cleanup noninterposable aliases.  */
++	  decl_set *decls = (*fs_map)[ctype_uid];
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "For call ");
++	      print_gimple_stmt (dump_file, stmt, 0);
++	    }
++	  vec_alloc (e->indirect_info->targets, decls->size ());
++	  for (decl_set::const_iterator it = decls->begin ();
++	       it != decls->end (); it++)
++	    {
++	      struct cgraph_node *target = cgraph_node::get (*it);
++	      /* TODO: maybe discard some targets.  */
++	      e->indirect_info->targets->quick_push (target);
++	    }
++	}
++    }
++}
++
+ /* Dump function types with set of functions corresponding to it.  */
+ 
+ static void
+@@ -5822,6 +5870,8 @@ collect_function_signatures ()
+ 	}
+     }
+   merge_fs_map_for_ftype_aliases ();
++  if (flag_ipa_ic)
++    save_analysis_results ();
+   if (dump_file)
+     dump_function_signature_sets ();
+ }
+@@ -6217,7 +6267,7 @@ ipa_icp (void)
+      optimize indirect calls.  */
+   collect_function_type_aliases ();
+   collect_function_signatures ();
+-  bool optimized = optimize_indirect_calls ();
++  bool optimized = flag_icp ? optimize_indirect_calls () : false;
+ 
+   remove_type_alias_map (ta_map);
+   remove_type_alias_map (fta_map);
+@@ -6264,7 +6314,7 @@ public:
+   /* opt_pass methods: */
+   virtual bool gate (function *)
+     {
+-      return (optimize && flag_icp && !seen_error ()
++      return (optimize && (flag_icp || flag_ipa_ic) && !seen_error ()
+ 	      && (in_lto_p || flag_whole_program));
+     }
+ 
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+new file mode 100644
+index 000000000..aeea51105
+--- /dev/null
++++ b/gcc/ipa-prefetch.cc
+@@ -0,0 +1,1819 @@
++/* IPA prefetch optimizations.
++   Copyright (C) 2023 Free Software Foundation, Inc.
++   Contributed by Ilia Diachkov.
++
++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
++.  */
++
++/* IPA prefetch is an interprocedural pass that detects cases of indirect
++   memory access potentially in loops and inserts prefetch instructions
++   to optimize cache usage during these indirect memory accesses.  */
++
++#include "config.h"
++#define INCLUDE_SET
++#define INCLUDE_MAP
++#include "system.h"
++#include "coretypes.h"
++#include "target.h"
++#include "tm.h"
++#include "tree.h"
++#include "tree-pass.h"
++#include "cgraph.h"
++#include "diagnostic-core.h"
++#include "function.h"
++#include "basic-block.h"
++#include "gimple.h"
++#include "vec.h"
++#include "tree-pretty-print.h"
++#include "gimple-pretty-print.h"
++#include "gimple-iterator.h"
++#include "gimple-walk.h"
++#include "cfg.h"
++#include "cfghooks.h"
++#include "ssa.h"
++#include "tree-dfa.h"
++#include "fold-const.h"
++#include "tree-inline.h"
++#include "stor-layout.h"
++#include "tree-into-ssa.h"
++#include "tree-cfg.h"
++#include "alloc-pool.h"
++#include "symbol-summary.h"
++#include "ipa-prop.h"
++#include "tree-eh.h"
++#include "bitmap.h"
++#include "cfgloop.h"
++#include "langhooks.h"
++#include "ipa-param-manipulation.h"
++#include "ipa-fnsummary.h"
++#include "tree-ssa-loop.h"
++#include "tree-ssa-loop-ivopts.h"
++#include "gimple-fold.h"
++#include "gimplify.h"
++
++namespace {
++
++/* Call graph analysis.  */
++
++typedef std::set edge_set;
++typedef std::set node_set;
++typedef std::map node_to_iedge_map;
++typedef std::map node_to_node_map;
++typedef std::map edge_in_loop;
++typedef std::map node_in_loop;
++
++static edge_in_loop *el_map = NULL;
++static node_in_loop *nl_map = NULL;
++static node_to_iedge_map *icn_map = NULL;
++/* Contains nodes which reachable from a given node.  */
++static node_to_node_map *nn_map = NULL;
++
++static bool
++can_be_optimized (cgraph_node *n)
++{
++  /* TODO: maybe check also inlined_to.  */
++  return opt_for_fn (n->decl, flag_ipa_prefetch) && n->has_gimple_body_p ();
++}
++
++static void
++analyze_cgraph_edge (cgraph_edge *e)
++{
++  gcall *stmt = e->call_stmt;
++  gcc_checking_assert (e && stmt);
++  basic_block bb = gimple_bb (stmt);
++  gcc_checking_assert (bb);
++  /* TODO: add the same check for indirect calls.  */
++  if (e->callee && !can_be_optimized (e->callee))
++    return;
++
++  if (dump_file)
++    {
++      if (e->callee)
++	fprintf (dump_file, "\t%*s%s %s%*s  ", 1, "",
++		 e->callee->dump_name (), !e->inline_failed ? "inlined" :
++		 cgraph_inline_failed_string (e->inline_failed), 1, "");
++      else
++	fprintf (dump_file, "\t%*s%s %s%*s  ", 1, "", "(indirect)",
++		 "n/a", 1, "");
++      fprintf (dump_file, "freq:%4.2f", e->sreal_frequency ().to_double ());
++
++      if (e->callee && cross_module_call_p (e))
++	fprintf (dump_file, " cross module");
++
++      class ipa_call_summary *es = ipa_call_summaries->get (e);
++      if (es)
++	fprintf (dump_file, " loop depth:%2i size:%2i time: %2i",
++		 es->loop_depth, es->call_stmt_size, es->call_stmt_time);
++
++      fprintf (dump_file, "\n");
++    }
++  if (e->indirect_info && dump_file)
++    {
++      fprintf (dump_file, "II: %p\n", (void *) e->indirect_info->targets);
++      unsigned i = 0;
++      cgraph_node *n;
++      if (e->indirect_info->targets)
++	for (i = 0; e->indirect_info->targets->iterate (i, &n); ++i)
++	  fprintf (dump_file, "\t%s\n", n->dump_name ());
++    }
++
++  if (bb_loop_depth (bb) == 0)
++    return;
++
++  if (dump_file)
++    {
++      if (e->callee)
++	fprintf (dump_file, "\tCall in loop (%d): ", bb_loop_depth (bb));
++      else
++	fprintf (dump_file, "\tICall in loop (%d): ", bb_loop_depth (bb));
++      print_gimple_stmt (dump_file, stmt, 0);
++    }
++  (*el_map)[e] = e->sreal_frequency ().to_double ();
++}
++
++/* Walk optimizible cgraph nodes and collect info for edges.  */
++
++static void
++analyse_cgraph ()
++{
++  cgraph_node *n;
++  cgraph_edge *e;
++  FOR_EACH_DEFINED_FUNCTION (n)
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "\n\nProcesing function %s\n", n->dump_name ());
++	  print_generic_expr (dump_file, n->decl);
++	  fprintf (dump_file, "\n");
++	}
++      if (!can_be_optimized (n))
++	{
++	  if (dump_file)
++	    fprintf (dump_file, "Skip the function\n");
++	  continue;
++	}
++
++      /* TODO: maybe remove loop info here.  */
++      push_cfun (DECL_STRUCT_FUNCTION (n->decl));
++      calculate_dominance_info (CDI_DOMINATORS);
++      loop_optimizer_init (LOOPS_NORMAL);
++
++      for (e = n->callees; e; e = e->next_callee)
++	analyze_cgraph_edge (e);
++      for (e = n->indirect_calls; e; e = e->next_callee)
++	analyze_cgraph_edge (e);
++
++      free_dominance_info (CDI_DOMINATORS);
++      loop_optimizer_finalize ();
++
++      pop_cfun ();
++    }
++}
++
++/* Save indirect call info to node:icall_target map.  */
++
++static void
++prepare_indirect_call_info ()
++{
++  cgraph_node *n, *n2;
++  cgraph_edge *e;
++  FOR_EACH_DEFINED_FUNCTION (n)
++    for (e = n->indirect_calls; e; e = e->next_callee)
++      {
++	if (!e->indirect_info->targets)
++	  continue;
++	for (unsigned i = 0; e->indirect_info->targets->iterate (i, &n2); ++i)
++	  {
++	    if (icn_map->count (n2) == 0)
++	      (*icn_map)[n2] = new edge_set;
++	    (*icn_map)[n2]->insert (e);
++	  }
++      }
++}
++
++static void
++collect_nn_info (struct cgraph_edge *e, struct cgraph_node *n)
++{
++  struct cgraph_node *n2 = e->caller;
++  if (nn_map->count (n2) == 0)
++    (*nn_map)[n2] = new node_set;
++  (*nn_map)[n2]->insert (n);
++  if (nn_map->count (n) != 0)
++    {
++      node_set *set = (*nn_map)[n];
++      for (node_set::const_iterator it = set->begin ();
++	   it != set->end (); it++)
++	(*nn_map)[n2]->insert (*it);
++    }
++}
++
++static bool
++check_loop_info_for_cgraph_edge (struct cgraph_edge *e, struct cgraph_node *n,
++				 bool &all_in_loop, double &rate)
++{
++  collect_nn_info (e, n);
++  if (el_map->count (e) == 0)
++    {
++      if (dump_file)
++	fprintf (dump_file, "not all: %s->%s\n",
++		 e->caller->dump_name (), n->dump_name ());
++      all_in_loop = false;
++      return false;
++    }
++  rate += (*el_map)[e];
++  return true;
++}
++
++static bool
++update_loop_info_for_cgraph_node (struct cgraph_node *n)
++{
++  bool changed = false, all_in_loop = true;
++  double rate = 0.0;
++  struct cgraph_edge *e;
++
++  /* Iterate all direct callers.  */
++  if (n->callers)
++    for (e = n->callers; e; e = e->next_caller)
++      if (!check_loop_info_for_cgraph_edge (e, n, all_in_loop, rate))
++	break;
++
++  /* Iterate all possible indirect callers.  */
++  edge_set *set = (*icn_map)[n];
++  if (set)
++    for (edge_set::const_iterator it = set->begin (); it != set->end (); it++)
++      if (!check_loop_info_for_cgraph_edge (*it, n, all_in_loop, rate))
++	break;
++
++  /* The node had 0 loop count but the rate is > 0,
++     so something is changed.  */
++  if (dump_file)
++    fprintf (dump_file, "%s: all=%d, nl->c=%lu, r=%4.2f\n", n->dump_name (),
++	     all_in_loop, nl_map->count (n), rate);
++
++  if (all_in_loop && nl_map->count (n) == 0 && rate > 0.0)
++    {
++      if (dump_file)
++	fprintf (dump_file, "%s: new rate %4.2f\n", n->dump_name (), rate);
++      changed = true;
++    }
++  if (all_in_loop)
++    {
++      (*nl_map)[n] = nl_map->count (n) ? (*nl_map)[n] + rate : rate;
++      for (e = n->callees; e; e = e->next_callee)
++	(*el_map)[e] = el_map->count (e) ? (*el_map)[e] + rate : rate;
++      for (e = n->indirect_calls; e; e = e->next_callee)
++	{
++	  (*el_map)[e] = el_map->count (e) ? (*el_map)[e] + rate : rate;
++	  if (dump_file)
++	    fprintf (dump_file, "%s: reset indirect e=%p to %4.2f\n",
++		     n->dump_name (), (void *) e, (*el_map)[e]);
++	}
++    }
++  return changed;
++}
++
++/* Propagate in_loop info over the call graph.  */
++
++static void
++propagate_loop_info_in_cgraph ()
++{
++  struct cgraph_node *n;
++  bool changed;
++  unsigned iteration = 0;
++  do
++    {
++      changed = false;
++      if (dump_file)
++	fprintf (dump_file, "\nIteration %u\n", iteration++);
++      FOR_EACH_DEFINED_FUNCTION (n)
++	{
++	  if (!n->callers && !(*icn_map)[n])
++	    continue;
++	  if (update_loop_info_for_cgraph_node (n))
++	    changed = true;
++	}
++  } while (changed);
++
++  if (dump_file)
++    {
++      fprintf (dump_file, "\nList of nodes in loops:\n");
++      FOR_EACH_DEFINED_FUNCTION (n)
++	if (nl_map->count (n) != 0)
++	  fprintf (dump_file, "%s: %4.2f\n", n->dump_name (), (*nl_map)[n]);
++      fprintf (dump_file, "\nList of callable nodes:\n");
++      FOR_EACH_DEFINED_FUNCTION (n)
++	if (nn_map->count (n) != 0)
++	  {
++	    node_set *set = (*nn_map)[n];
++	    fprintf (dump_file, "%s: ", n->dump_name ());
++	    for (node_set::const_iterator it = set->begin ();
++		 it != set->end (); it++)
++	      fprintf (dump_file, "%s ", (*it)->dump_name ());
++	    fprintf (dump_file, "\n");
++	  }
++    }
++}
++
++/* Analysis of memory references.  */
++
++typedef enum
++{
++  MR_NONE,
++  MR_SIMPLE,
++  MR_POLYNOMIAL,
++  MR_INDIRECT,
++  MR_UNSUPPORTED
++} mr_type;
++const char *mr_type_str[] =
++    {"none", "simple", "poly", "indirect", "unsuppoted"};
++
++struct memref_type;
++typedef std::set memref_set;
++
++static unsigned max_mr_id = 0;
++typedef struct memref_type
++{
++  unsigned mr_id = 0;
++  mr_type type = MR_NONE;
++  tree mem = NULL_TREE;
++  tree base = NULL_TREE;
++  tree offset = NULL_TREE;
++  vec stmts = vNULL;
++  memref_set used_mrs;
++  bool is_store = false;
++  bool is_incr = false;
++  tree step = NULL_TREE;
++} memref_t;
++
++typedef std::map tree_memref_map;
++typedef std::map > function_mrs_map;
++typedef std::map funct_mrs_map;
++typedef std::map memref_map;
++typedef std::map memref_tree_map;
++
++typedef std::set stmt_set;
++typedef std::map tree_map;
++
++tree_memref_map *tm_map;
++funct_mrs_map *fmrs_map;
++funct_mrs_map *optimize_mrs_map;
++memref_map *mr_candidate_map;
++tree_map *decl_map;
++
++static void analyse_mem_ref (gimple *stmt, tree mem, memref_t* mr);
++
++static memref_t*
++get_memref (gimple *stmt, tree mem, bool is_store)
++{
++  if (tm_map->count (mem))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Found mr %d for %p.\n",
++		 (*tm_map)[mem]->mr_id, (void *) mem);
++      return (*tm_map)[mem];
++    }
++
++  memref_t *mr = new memref_t;
++  mr->mr_id = ++max_mr_id;
++  mr->is_store = is_store;
++  mr->mem = mem;
++  (*tm_map)[mem] = mr;
++  if (dump_file)
++    fprintf (dump_file, "Create mr %d for %p.\n",
++	     mr->mr_id, (void *) mem);
++  analyse_mem_ref (stmt, mem, mr);
++  return mr;
++}
++
++static void
++print_mrs_ids (memref_set &mrs, const char *start)
++{
++  if (start)
++    fprintf (dump_file, "%s", start);
++  for (memref_set::const_iterator it = mrs.begin (); it != mrs.end (); it++)
++    fprintf (dump_file, "%d ", (*it)->mr_id);
++  fprintf (dump_file, "\n");
++}
++
++static void
++print_memref (memref_t *mr)
++{
++  fprintf (dump_file, "MR (%d) type: %s (%s) mem: ", mr->mr_id,
++	   mr_type_str[mr->type], mr->is_store ? "st" : "ld");
++  print_generic_expr (dump_file, mr->mem);
++  fprintf (dump_file, "\nbase: ");
++  if (mr->base)
++    print_generic_expr (dump_file, mr->base);
++  else
++    fprintf (dump_file, "null");
++  fprintf (dump_file, "\noffset: ");
++  if (mr->offset)
++    print_generic_expr (dump_file, mr->offset);
++  else
++    fprintf (dump_file, "null");
++  fprintf (dump_file, "\nstmts:\n");
++  for (unsigned int i = 0; i < mr->stmts.length (); i++)
++    print_gimple_stmt (dump_file, mr->stmts[i], 0);
++  print_mrs_ids (mr->used_mrs, "\tused memrefs: ");
++  if (mr->is_incr)
++    {
++      fprintf (dump_file, "\tis incremental with step: ");
++      print_generic_expr (dump_file, mr->step);
++    }
++  fprintf (dump_file, "\n");
++}
++
++/* If there is a simple load or store to a memory reference in STMT, returns
++   the location of the memory reference, and sets IS_STORE according to whether
++   it is a store or load.  Otherwise, returns NULL.
++   TODO: from gcc/tree-ssa-loop-im.c, maybe make it global.  */
++
++static tree *
++simple_mem_ref_in_stmt (gimple *stmt, bool *is_store)
++{
++  tree *lhs, *rhs;
++
++  /* Recognize SSA_NAME = MEM and MEM = (SSA_NAME | invariant) patterns.  */
++  if (!gimple_assign_single_p (stmt))
++    return NULL;
++
++  lhs = gimple_assign_lhs_ptr (stmt);
++  rhs = gimple_assign_rhs1_ptr (stmt);
++
++  if (TREE_CODE (*lhs) == SSA_NAME && gimple_vuse (stmt))
++    {
++      *is_store = false;
++      return rhs;
++    }
++  else if (gimple_vdef (stmt)
++	   && (TREE_CODE (*rhs) == SSA_NAME || is_gimple_min_invariant (*rhs)))
++    {
++      *is_store = true;
++      return lhs;
++    }
++  else
++    return NULL;
++}
++
++static void
++analyse_incremental (gimple *stmt, memref_t* mr)
++{
++  if (!gimple_assign_single_p (stmt))
++    return;
++  tree rhs1, rhs2;
++  /* TODO: maybe support other types of stmts.  */
++  while (stmt && is_gimple_assign (stmt))
++    {
++      enum tree_code def_code = gimple_assign_rhs_code (stmt);
++      gimple_rhs_class rhs_class = gimple_assign_rhs_class (stmt);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Incr: in assign (%s)\n",
++		   get_tree_code_name (def_code));
++	  print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++	}
++      gcc_assert (def_code != ERROR_MARK);
++      switch (rhs_class)
++	{
++	case GIMPLE_TERNARY_RHS:
++	  if (dump_file)
++	    fprintf (dump_file, "Incr: unsupported trinary rhs\n");
++	  stmt = NULL;
++	  break;
++	case GIMPLE_UNARY_RHS:
++	case GIMPLE_SINGLE_RHS:
++	  rhs1 = gimple_assign_rhs1 (stmt);
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Incr: (%s)",
++		       get_tree_code_name (TREE_CODE (rhs1)));
++	      print_generic_expr (dump_file, rhs1);
++	      fprintf (dump_file, "\n");
++	    }
++	  if (def_code == SSA_NAME)
++	    stmt = SSA_NAME_DEF_STMT (rhs1);
++	  else if (def_code == MEM_REF || def_code == COMPONENT_REF
++		   || def_code == ARRAY_REF)
++	    {
++	      /* If we have dereference in address evaluation,
++		 it's indirect memory access.  */
++	      if (dump_file)
++		{
++		  if (operand_equal_p (mr->mem, rhs1))
++		    fprintf (dump_file, "Incr: the same MEM\n");
++		  else
++		    fprintf (dump_file, "Incr: diff MEM\n");
++		  print_generic_expr (dump_file, rhs1);
++		  fprintf (dump_file, " ");
++		  print_generic_expr (dump_file, mr->mem);
++		  fprintf (dump_file, "\n");
++		}
++	      if (operand_equal_p (mr->mem, rhs1) && mr->step)
++		mr->is_incr = true;
++	      stmt = NULL;
++	    }
++	  else
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Incr: unsupported unary/single\n");
++	      stmt = NULL;
++	    }
++	  break;
++	case GIMPLE_BINARY_RHS:
++	  rhs1 = gimple_assign_rhs1 (stmt);
++	  rhs2 = gimple_assign_rhs2 (stmt);
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "(%s) (%s)",
++		       get_tree_code_name (TREE_CODE (rhs1)),
++		       get_tree_code_name (TREE_CODE (rhs2)));
++	      print_generic_expr (dump_file, rhs1);
++	      fprintf (dump_file, " ");
++	      print_generic_expr (dump_file, rhs2);
++	      fprintf (dump_file, "\n");
++	    }
++	  /* TODO: extend for other types of incrementation.  */
++	  if (TREE_CODE (rhs1) == SSA_NAME && TREE_CODE (rhs2) == INTEGER_CST)
++	    {
++	      stmt = SSA_NAME_DEF_STMT (rhs1);
++	      mr->step = rhs2;
++	      if (dump_file)
++		{
++		  fprintf (dump_file, "Incr: const increment stmt: ");
++		  print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++		}
++	    }
++	  else
++	    stmt = NULL;
++	  break;
++	default:
++	  gcc_unreachable ();
++      }
++    }
++  if ((mr->step && !mr->is_incr) || (!mr->step && mr->is_incr))
++    {
++      mr->step = NULL_TREE;
++      mr->is_incr = false;
++    }
++}
++
++static mr_type
++get_memref_type (memref_t *base, memref_t *used, enum tree_code code)
++{
++  /* TODO: improve memref type detection.  */
++  enum tree_code base_code = TREE_CODE (base->mem);
++  if (dump_file)
++    fprintf (dump_file, "get_memref_type: base=%d,%d used=%d,%d code=%s "
++	     "base_code=%s\n", base->mr_id, base->type,
++	     used ? used->mr_id : -1, used ? used->type : -1,
++	     get_tree_code_name (code), get_tree_code_name (base_code));
++  if (used)
++    {
++      if (base->type > used->type)
++	return base->type;
++      if (used->type == MR_SIMPLE)
++	return MR_POLYNOMIAL;
++      if (used->type == MR_POLYNOMIAL)
++	return base_code == ARRAY_REF ? MR_POLYNOMIAL : MR_INDIRECT;
++      if (used->type == MR_INDIRECT)
++	return MR_INDIRECT;
++      return MR_UNSUPPORTED;
++    }
++  if (code == MEM_REF || code == ARRAY_REF || code == COMPONENT_REF)
++    return base->type;
++  if (code == POINTER_PLUS_EXPR || code == PLUS_EXPR
++      || code == MINUS_EXPR || code == MULT_EXPR)
++    return base->type <= MR_POLYNOMIAL ? MR_POLYNOMIAL : base->type;
++  return base->type >= MR_INDIRECT ? base->type : MR_INDIRECT;
++}
++
++/* Recursively walk defs of src expression and record used stmts and other mrs.
++   Return a base address candidate if it's found.  */
++
++static tree
++analyse_addr_eval (tree src, memref_t* mr)
++{
++  if (TREE_CODE (src) != SSA_NAME)
++    return NULL_TREE;
++  gimple *stmt = SSA_NAME_DEF_STMT (src);
++  if (dump_file)
++    {
++      fprintf (dump_file, "Src_stmt: ");
++      print_gimple_stmt (dump_file, stmt, 0);
++    }
++  if (!is_gimple_assign (stmt))
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Is not assign, stop analysis: ");
++	  print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++	}
++      mr->type = MR_UNSUPPORTED;
++      mr->stmts.safe_push (stmt);
++      return NULL_TREE;
++    }
++  enum tree_code def_code = gimple_assign_rhs_code (stmt);
++  if (def_code != MEM_REF && def_code != COMPONENT_REF
++      && def_code != ARRAY_REF)
++    mr->stmts.safe_push (stmt);
++  gimple_rhs_class rhs_class = gimple_assign_rhs_class (stmt);
++  tree rhs1, rhs2, base;
++  if (dump_file)
++    fprintf (dump_file, "In assign (%s): ", get_tree_code_name (def_code));
++
++  switch (rhs_class)
++    {
++    case GIMPLE_TERNARY_RHS:
++      if (dump_file)
++	fprintf (dump_file, "Unsupported trinary rhs\n");
++      mr->type = MR_UNSUPPORTED;
++      return NULL_TREE;
++    case GIMPLE_UNARY_RHS:
++    case GIMPLE_SINGLE_RHS:
++      rhs1 = gimple_assign_rhs1 (stmt);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "(%s)",
++		   get_tree_code_name (TREE_CODE (rhs1)));
++	  print_generic_expr (dump_file, rhs1);
++	  fprintf (dump_file, "\n");
++	}
++      if (def_code == NOP_EXPR)
++	return analyse_addr_eval (rhs1, mr);
++      else if (def_code == MEM_REF || def_code == COMPONENT_REF
++	       || def_code == ARRAY_REF)
++	{
++	  memref_t *mr2 = get_memref (stmt, rhs1, false);
++	  mr->type = get_memref_type (mr, mr2, def_code);
++	  for (memref_set::const_iterator it = mr2->used_mrs.begin ();
++	       it != mr2->used_mrs.end (); it++)
++	    mr->used_mrs.insert (*it);
++	  mr->used_mrs.insert (mr2);
++	  return mr2->base;
++	}
++      else
++	{
++	  if (dump_file)
++	    fprintf (dump_file, "Unsupported unary/single\n");
++	  mr->type = MR_UNSUPPORTED;
++	}
++      return NULL_TREE;
++    case GIMPLE_BINARY_RHS:
++      rhs1 = gimple_assign_rhs1 (stmt);
++      rhs2 = gimple_assign_rhs2 (stmt);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "(%s) (%s)",
++		   get_tree_code_name (TREE_CODE (rhs1)),
++		   get_tree_code_name (TREE_CODE (rhs2)));
++	  print_generic_expr (dump_file, rhs1);
++	  fprintf (dump_file, " ");
++	  print_generic_expr (dump_file, rhs2);
++	  fprintf (dump_file, "\n");
++	}
++      base = analyse_addr_eval (rhs1, mr);
++      analyse_addr_eval (rhs2, mr);
++      mr->type = get_memref_type (mr, NULL, def_code);
++      return base;
++    default:
++      gcc_unreachable ();
++    }
++  return NULL_TREE;
++}
++
++static tree
++get_mem_ref_address_ssa_name (tree mem, tree base)
++{
++  gcc_assert (TREE_CODE (mem) == MEM_REF);
++  if (base == NULL_TREE)
++    base = get_base_address (mem);
++  tree base_addr = NULL_TREE;
++  if (TREE_CODE (base) == MEM_REF)
++    base_addr = TREE_OPERAND (base, 0);
++  if (base_addr != NULL_TREE && TREE_CODE (base_addr) == SSA_NAME)
++    return base_addr;
++  return NULL_TREE;
++}
++
++static void
++analyse_mem_ref (gimple *stmt, tree mem, memref_t* mr)
++{
++  tree base = get_base_address (mem);
++  if (dump_file)
++    fprintf (dump_file, "Codes: base = %s, mem = %s\n",
++	     base ? get_tree_code_name (TREE_CODE (base)) : "null",
++	     mem ? get_tree_code_name (TREE_CODE (mem)) : "null");
++
++  mr->stmts.safe_push (stmt);
++  mr->base = base;
++  switch (TREE_CODE (mem))
++    {
++    case COMPONENT_REF:
++      if (mr->is_store)
++	analyse_incremental (stmt, mr);
++      mr->type = MR_SIMPLE;
++      mr->offset = TREE_OPERAND (mem, 1);
++      return;
++    case ARRAY_REF:
++      analyse_addr_eval (TREE_OPERAND (mem, 1), mr);
++      return;
++    case MEM_REF:
++      {
++	tree base_addr = get_mem_ref_address_ssa_name (mem, base);
++	if (dump_file)
++	  {
++	    fprintf (dump_file, "Base addr (%s): ",
++		     base_addr ? get_tree_code_name (TREE_CODE (base_addr))
++			       : "null");
++	    if (base_addr)
++	      print_generic_expr (dump_file, base_addr);
++	    fprintf (dump_file, "\n");
++	  }
++	if (base_addr)
++	  {
++	    mr->base = analyse_addr_eval (base_addr, mr);
++	    return;
++	  }
++	break;
++      }
++    default:
++      break;
++    }
++  mr->type = MR_UNSUPPORTED;
++  mr->base = NULL_TREE;
++}
++
++static void
++analyse_stmt (gimple *stmt)
++{
++  bool is_store;
++  tree *mem = simple_mem_ref_in_stmt (stmt, &is_store);
++  if (!mem)
++    return;
++  if (dump_file)
++    {
++      fprintf (dump_file, "\n%s: mr is found in stmt (%s): ",
++	       function_name (cfun), is_store ? "store" : "load");
++      print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++    }
++  memref_t *mr = get_memref (stmt, *mem, is_store);
++  (*fmrs_map)[cfun]->insert (mr);
++  if (dump_file)
++    print_memref (mr);
++}
++
++/* Scan stmts for indirect stores/loads with bases passed as function args.  */
++
++static void
++collect_memrefs_for_cgraph_node (struct cgraph_node *n)
++{
++  if (dump_file)
++    fprintf (dump_file, "\nCollect indirect ptr info in %s\n", n->dump_name ());
++  n->get_body ();
++  function *fn = DECL_STRUCT_FUNCTION (n->decl);
++  gcc_assert (fn && n->has_gimple_body_p ());
++
++  push_cfun (fn);
++  basic_block bb;
++  gimple_stmt_iterator si;
++  (*fmrs_map)[fn] = new memref_set;
++  FOR_EACH_BB_FN (bb, fn)
++    for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
++      {
++	gimple *stmt = gsi_stmt (si);
++	analyse_stmt (stmt);
++      }
++  pop_cfun ();
++}
++
++/* Walk cgraph nodes and collect memory references info.  */
++
++static void
++collect_memory_references ()
++{
++  struct cgraph_node *n;
++  /* TODO: collect info only for loops and functions in loops.  */
++  FOR_EACH_DEFINED_FUNCTION (n)
++    if (nl_map->count (n) != 0 && n->has_gimple_body_p ())
++      collect_memrefs_for_cgraph_node (n);
++
++  if (dump_file)
++    {
++      fprintf (dump_file, "\n\nDump mem references:\n");
++      FOR_EACH_DEFINED_FUNCTION (n)
++	if (nl_map->count (n) != 0 && n->has_gimple_body_p ())
++	  {
++	    function *fn = DECL_STRUCT_FUNCTION (n->decl);
++	    fprintf (dump_file, "\nIn function %s (%s):\n", function_name (fn),
++		     nl_map->count (n) != 0 ? "in loop" : "");
++	    for (memref_set::const_iterator it = (*fmrs_map)[fn]->begin ();
++		 it != (*fmrs_map)[fn]->end (); it++)
++	      print_memref (*it);
++	  }
++    }
++}
++
++/* Analysis of loops.  */
++
++memref_set *current_incr_mrs;
++memref_set *current_indirect_mrs;
++
++static void
++collect_memref (memref_t *mr, class loop *loop, bool check_loop)
++{
++  gimple *stmt = mr->stmts[0];
++  gcc_assert (stmt);
++  if (check_loop && !flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
++    return;
++
++  /* TODO: Improve base invariant analysis for memrefs which are not local
++     (located in called functions).  */
++  bool is_base_inv = false;
++  if (mr->base)
++    is_base_inv = expr_invariant_in_loop_p (loop, mr->base);
++
++  if (dump_file && (mr->type == MR_INDIRECT || mr->is_incr))
++    {
++      fprintf (dump_file, "%s MR (%d): ", mr->is_incr ? "INCR" : "INDIRECT",
++	       mr->mr_id);
++      print_generic_expr (dump_file, mr->mem);
++      fprintf (dump_file, "\twith base: ");
++      if (mr->base)
++	print_generic_expr (dump_file, mr->base);
++      else
++	fprintf (dump_file, "null");
++      fprintf (dump_file, " (is_inv=%d)\n", is_base_inv);
++    }
++
++  if (!is_base_inv)
++    return;
++  if (mr->type == MR_INDIRECT)
++    current_indirect_mrs->insert (mr);
++  if (mr->is_incr)
++    current_incr_mrs->insert (mr);
++}
++
++static void
++analyse_callable_function (struct cgraph_node *n, class loop *loop)
++{
++  if (dump_file)
++    fprintf (dump_file, "Callable (%s):\n", n->dump_name ());
++
++  function *fn = DECL_STRUCT_FUNCTION (n->decl);
++  if (fmrs_map->count (fn))
++    for (memref_set::const_iterator it = (*fmrs_map)[fn]->begin ();
++	 it != (*fmrs_map)[fn]->end (); it++)
++      collect_memref (*it, loop, false);
++}
++
++static void
++insert_node_with_callable_nodes (node_set &s, struct cgraph_node *n)
++{
++  s.insert (n);
++  if (nn_map->count (n) == 0)
++    return;
++  node_set *set = (*nn_map)[n];
++  for (node_set::const_iterator it = set->begin (); it != set->end (); it++)
++    s.insert ((*it));
++}
++
++static bool
++compatible_memrefs_p (memref_t *mr1, memref_t *mr2, bool &compatible_offset)
++{
++  if (!mr1->base || !mr2->base || !mr2->offset)
++    return false;
++  tree base_type1 = TYPE_MAIN_VARIANT (TREE_TYPE (mr1->base));
++  tree base_type2 = TYPE_MAIN_VARIANT (TREE_TYPE (mr2->base));
++  if (base_type1 != base_type2)
++    return false;
++  if (mr1->offset && mr1->offset == mr2->offset)
++    compatible_offset = true;
++  else
++    compatible_offset = false;
++  return true;
++}
++
++static void
++compare_memrefs (memref_t* mr, memref_t* mr2)
++{
++  /* TODO: improve analysis of memrefs from different functions: take into
++     account data flow and context.  */
++  bool compatible_offset = false;
++  if (!compatible_memrefs_p (mr, mr2, compatible_offset))
++    return;
++  if (!compatible_offset)
++    {
++      for (memref_set::const_iterator it = mr->used_mrs.begin ();
++	   it != mr->used_mrs.end (); it++)
++	if ((*it)->offset && (*it)->offset == mr2->offset)
++	  {
++	    compatible_offset = true;
++	    if (dump_file)
++	      fprintf (dump_file, "Used MR (%d) and INC MR have "
++		       "the same offset\n", (*it)->mr_id);
++	    break;
++	  }
++    }
++  if (!compatible_offset)
++    return;
++  if (dump_file)
++    {
++      fprintf (dump_file, "MR (%d) is optimization candidate with offset: ",
++	       mr->mr_id);
++      print_generic_expr (dump_file, mr2->offset);
++      fprintf (dump_file, "\n");
++    }
++
++  if (!mr_candidate_map->count (mr))
++    {
++      (*mr_candidate_map)[mr] = mr2;
++      return;
++    }
++  /* TODO: support analysis with incrementation of different fields.  */
++  if ((*mr_candidate_map)[mr]->offset != mr2->offset)
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "It conflicts with previously found MR (%d) "
++		   "with offset ", (*mr_candidate_map)[mr]->mr_id);
++	  if ((*mr_candidate_map)[mr] != NULL)
++	    print_generic_expr (dump_file, (*mr_candidate_map)[mr]->offset);
++	  fprintf (dump_file, ", disable the optimization\n");
++	}
++      (*mr_candidate_map)[mr] = NULL;
++    }
++}
++
++/* In the given loop and all functions called from the loop, collect
++   indirect/incremental memrefs with invariant base address and inductive
++   offset.  */
++
++static void
++collect_memrefs_for_loop (class loop *loop, struct cgraph_node *n,
++			  function *fn)
++{
++  current_incr_mrs = new memref_set;
++  current_indirect_mrs = new memref_set;
++
++  if (dump_file)
++    fprintf (dump_file, "Loop %d\n", loop->num);
++  if (fmrs_map->count (fn))
++    for (memref_set::const_iterator it = (*fmrs_map)[fn]->begin ();
++	 it != (*fmrs_map)[fn]->end (); it++)
++      collect_memref (*it, loop, true);
++
++  /* Collect vector of functions called in the loop.  */
++  node_set set;
++  struct cgraph_edge *e;
++  struct cgraph_node *n2;
++  for (e = n->callees; e; e = e->next_callee)
++    {
++      gcall *stmt = e->call_stmt;
++      if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
++	continue;
++      insert_node_with_callable_nodes (set, e->callee);
++    }
++  for (e = n->indirect_calls; e; e = e->next_callee)
++    {
++      gcall *stmt = e->call_stmt;
++      if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt))
++	  || !e->indirect_info->targets)
++	continue;
++      for (unsigned i = 0; e->indirect_info->targets->iterate (i, &n2); ++i)
++	insert_node_with_callable_nodes (set, n2);
++    }
++  if (set.empty ())
++    return;
++  if (dump_file)
++    fprintf (dump_file, "Go inside all callables of %s\n", n->dump_name ());
++
++  for (node_set::const_iterator it = set.begin (); it != set.end (); it++)
++    analyse_callable_function (*it, loop);
++
++  if (!current_incr_mrs->empty () && !current_indirect_mrs->empty ())
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Loop has both incr and indirect memrefs\n"
++		   "Incr: ");
++	  for (memref_set::const_iterator it = current_incr_mrs->begin ();
++	       it != current_incr_mrs->end (); it++)
++	    fprintf (dump_file, "%d ", (*it)->mr_id);
++	  fprintf (dump_file, "\nIndirect: ");
++	  for (memref_set::const_iterator it = current_indirect_mrs->begin ();
++	       it != current_indirect_mrs->end (); it++)
++	    fprintf (dump_file, "%d ", (*it)->mr_id);
++	  fprintf (dump_file, "\n");
++	}
++      /* Check if indirect memref has a base address similar to one of
++	 incremental memref.  */
++      for (memref_set::const_iterator it = current_indirect_mrs->begin ();
++	   it != current_indirect_mrs->end (); it++)
++	for (memref_set::const_iterator it2 = current_incr_mrs->begin ();
++	   it2 != current_incr_mrs->end (); it2++)
++	  compare_memrefs (*it, *it2);
++    }
++
++  delete current_incr_mrs;
++  delete current_indirect_mrs;
++}
++
++static void
++analyse_loops_in_cgraph_node (struct cgraph_node *n)
++{
++  if (dump_file)
++    fprintf (dump_file, "\nAnalyse loops in %s\n", n->dump_name ());
++
++  n->get_body ();
++  function *fn = DECL_STRUCT_FUNCTION (n->decl);
++  gcc_assert (fn && n->has_gimple_body_p ());
++
++  push_cfun (fn);
++  calculate_dominance_info (CDI_DOMINATORS);
++  loop_optimizer_init (LOOPS_NORMAL);
++
++  for (auto loop : loops_list (cfun, 0))
++    {
++      class loop *outer = loop_outer (loop);
++      /* Walk only outermost loops.  */
++      if (outer->num != 0)
++	continue;
++      collect_memrefs_for_loop (loop, n, fn);
++    }
++
++  free_dominance_info (CDI_DOMINATORS);
++  loop_optimizer_finalize ();
++  pop_cfun ();
++}
++
++static void
++analyse_loops ()
++{
++  if (dump_file)
++    fprintf (dump_file, "\n\nLoops: procesing functions\n");
++  cgraph_node *n;
++  FOR_EACH_DEFINED_FUNCTION (n)
++    {
++      if (!can_be_optimized (n))
++	{
++	  if (dump_file)
++	    fprintf (dump_file, "Skip the function\n");
++	  continue;
++	}
++      analyse_loops_in_cgraph_node (n);
++    }
++
++  if (dump_file)
++    fprintf (dump_file, "\n\nList of optimization candidates:\n");
++
++  FOR_EACH_DEFINED_FUNCTION (n)
++    {
++      function *fn = DECL_STRUCT_FUNCTION (n->decl);
++      if (!can_be_optimized (n) || !fmrs_map->count (fn))
++	continue;
++      for (memref_map::iterator it = mr_candidate_map->begin ();
++	   it != mr_candidate_map->end (); ++it)
++	{
++	  memref_t *mr = it->first, *mr2 = it->second;
++	  if (mr2 == NULL || !(*fmrs_map)[fn]->count (mr))
++	    continue;
++	  if (!optimize_mrs_map->count (fn))
++	    (*optimize_mrs_map)[fn] = new memref_set;
++	  (*optimize_mrs_map)[fn]->insert (mr);
++	}
++      if (dump_file && optimize_mrs_map->count (fn))
++	{
++	  fprintf (dump_file, "Function %s\n", n->dump_name ());
++	  for (memref_set::const_iterator it
++		   = (*optimize_mrs_map)[fn]->begin ();
++	       it != (*optimize_mrs_map)[fn]->end (); it++)
++	    {
++	      memref_t *mr = *it, *mr2 = (*mr_candidate_map)[mr];
++	      fprintf (dump_file, "MRs %d,%d with incremental offset ",
++		       mr->mr_id, mr2->mr_id);
++	      print_generic_expr (dump_file, mr2->offset);
++	      fprintf (dump_file, "\n");
++	    }
++	}
++    }
++}
++
++/* Reduce the set filtering out memrefs with the same memory references,
++   return the result vector of memrefs.  */
++
++static void
++reduce_memref_set (memref_set *set, vec &vec)
++{
++  for (memref_set::const_iterator it = set->begin ();
++      it != set->end (); it++)
++    {
++      memref_t *mr1 = *it;
++      if (!vec.length ())
++	vec.safe_push (mr1);
++      else
++	{
++	  bool inserted = false;
++	  for (unsigned int i = 0; i < vec.length (); i++)
++	    {
++	      /* mr2 is less than current mr1.  */
++	      memref_t *mr2 = vec[i];
++	      if (operand_equal_p (mr1->mem, mr2->mem))
++		{
++		  if (dump_file)
++		    fprintf (dump_file, "The same mems in MRs %d and %d\n",
++			     mr1->mr_id, mr2->mr_id);
++		  /* TODO: maybe build new memref which include stmts of both
++		     mr1 and mr2.  */
++		  if ((mr1->is_store && !mr2->is_store)
++		       || mr1->stmts.length () > mr2->stmts.length ())
++		    {
++		      inserted = true;
++		      vec[i] = mr1;
++		    }
++		}
++	    }
++	  if (!inserted)
++	    vec.safe_push (mr1);
++	}
++    }
++  if (dump_file)
++    {
++      fprintf (dump_file, "MRs (%d) after filtering: ", vec.length ());
++      for (unsigned int i = 0; i < vec.length (); i++)
++	fprintf (dump_file, "%d ", vec[i]->mr_id);
++      fprintf (dump_file, "\n");
++    }
++}
++
++static void
++find_nearest_common_dominator (memref_t *mr, basic_block &dom)
++{
++  for (unsigned int i = 0; i < mr->stmts.length (); i++)
++    {
++      basic_block bb = gimple_bb (mr->stmts[i]);
++      gcc_assert (bb);
++      if (dom == bb)
++	continue;
++      if (dom)
++	dom = nearest_common_dominator (CDI_DOMINATORS, dom, bb);
++      else
++	dom = bb;
++    }
++}
++
++/* Return true if DECL is a parameter or a SSA_NAME for a parameter.
++   TODO: from gcc/tree-inline.c, maybe make it global.  */
++
++static bool
++is_parm (tree decl)
++{
++  if (TREE_CODE (decl) == SSA_NAME)
++    {
++      decl = SSA_NAME_VAR (decl);
++      if (!decl)
++	return false;
++    }
++
++  return (TREE_CODE (decl) == PARM_DECL);
++}
++
++/* TODO: the following functions are inspired by remap in gcc/tree-inline.c,
++   maybe we can share some functionality.  */
++
++static tree
++remap_name (tree name, gimple *stmt, bool is_lhs)
++{
++  tree new_tree = NULL_TREE;
++  if (decl_map->count (name))
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Find map: ");
++	  print_generic_expr (dump_file, name);
++	  fprintf (dump_file, " ");
++	  print_generic_expr (dump_file, (*decl_map)[name]);
++	  fprintf (dump_file, "\n");
++	}
++      return unshare_expr ((*decl_map)[name]);
++    }
++  if (!is_lhs)
++    return name;
++  if (TREE_CODE (name) == SSA_NAME)
++    {
++      /* Remap anonymous SSA names or SSA names of anonymous decls.  */
++      tree var = SSA_NAME_VAR (name);
++      if (!var
++	  || (!SSA_NAME_IS_DEFAULT_DEF (name)
++	      && VAR_P (var) && !VAR_DECL_IS_VIRTUAL_OPERAND (var)
++	      && DECL_ARTIFICIAL (var) && DECL_IGNORED_P (var)
++	      && !DECL_NAME (var)))
++	{
++	  new_tree = make_ssa_name (TREE_TYPE (name), stmt);
++	  if (!var && SSA_NAME_IDENTIFIER (name))
++	    SET_SSA_NAME_VAR_OR_IDENTIFIER (new_tree,
++					    SSA_NAME_IDENTIFIER (name));
++	  SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_tree)
++	      = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name);
++	  /* So can range-info.  */
++	  if (!POINTER_TYPE_P (TREE_TYPE (name))
++	      && SSA_NAME_RANGE_INFO (name))
++	    duplicate_ssa_name_range_info (new_tree,
++					   SSA_NAME_RANGE_TYPE (name),
++					   SSA_NAME_RANGE_INFO (name));
++	  /* TODO: maybe correct the insertion.  */
++	  (*decl_map)[name] = new_tree;
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "New map (no var): ");
++	      print_generic_expr (dump_file, name);
++	      fprintf (dump_file, " ");
++	      print_generic_expr (dump_file, new_tree);
++	      fprintf (dump_file, "\n");
++	    }
++	  return new_tree;
++	}
++      /* TODO: maybe remap_name or do the same as before for SSA_NAME_VAR.  */
++      new_tree = make_ssa_name (TREE_TYPE (name), stmt);
++      (*decl_map)[name] = new_tree;
++      if (dump_file)
++	{
++	  fprintf (dump_file, "New map: ");
++	  print_generic_expr (dump_file, name);
++	  fprintf (dump_file, " ");
++	  print_generic_expr (dump_file, new_tree);
++	  fprintf (dump_file, "\n");
++	}
++    }
++  else if (VAR_P (name) || TREE_CODE (name) == PARM_DECL)
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "VAR/PARM: ");
++	  print_generic_expr (dump_file, name);
++	  fprintf (dump_file, "\n");
++	}
++      return name;
++    }
++  else
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Unsupported: ");
++	  print_generic_expr (dump_file, name);
++	  fprintf (dump_file, "\n");
++	}
++      //gcc_unreachable ();
++      return name;
++    }
++  return new_tree;
++}
++
++/* Passed to walk_tree.  Copies the node pointed to, if appropriate.  */
++
++static tree
++ipa_copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
++{
++  enum tree_code code = TREE_CODE (*tp);
++  enum tree_code_class cl = TREE_CODE_CLASS (code);
++
++  /* We make copies of most nodes.  */
++  if (IS_EXPR_CODE_CLASS (cl)
++      || code == TREE_LIST
++      || code == TREE_VEC
++      || code == TYPE_DECL
++      || code == OMP_CLAUSE)
++    {
++      /* Because the chain gets clobbered when we make a copy, we save it
++	 here.  */
++      tree chain = NULL_TREE, new_tree;
++
++      if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
++	chain = TREE_CHAIN (*tp);
++
++      /* Copy the node.  */
++      new_tree = copy_node (*tp);
++
++      *tp = new_tree;
++
++      /* Now, restore the chain, if appropriate.  That will cause
++	 walk_tree to walk into the chain as well.  */
++      if (code == PARM_DECL
++	  || code == TREE_LIST
++	  || code == OMP_CLAUSE)
++	TREE_CHAIN (*tp) = chain;
++
++      /* For now, we don't update BLOCKs when we make copies.  So, we
++	 have to nullify all BIND_EXPRs.  */
++      if (TREE_CODE (*tp) == BIND_EXPR)
++	BIND_EXPR_BLOCK (*tp) = NULL_TREE;
++    }
++  else if (code == CONSTRUCTOR || code == STATEMENT_LIST)
++    gcc_unreachable ();
++  else if (TREE_CODE_CLASS (code) == tcc_type
++	   || TREE_CODE_CLASS (code) == tcc_declaration
++	   || TREE_CODE_CLASS (code) == tcc_constant)
++    *walk_subtrees = 0;
++  return NULL_TREE;
++}
++
++/* Remap the GIMPLE operand pointed to by *TP.  DATA is really a
++   'struct walk_stmt_info *'.  DATA->INFO is a 'gimple *'.
++   WALK_SUBTREES is used to indicate walk_gimple_op whether to keep
++   recursing into the children nodes of *TP.  */
++
++static tree
++remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
++{
++  struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
++  gimple *stmt = (gimple *) wi_p->info;
++
++  /* For recursive invocations this is no longer the LHS itself.  */
++  bool is_lhs = wi_p->is_lhs;
++  wi_p->is_lhs = false;
++
++  if (TREE_CODE (*tp) == SSA_NAME)
++    {
++      *tp = remap_name (*tp, stmt, is_lhs);
++      *walk_subtrees = 0;
++      if (is_lhs)
++	SSA_NAME_DEF_STMT (*tp) = wi_p->stmt;
++      return NULL;
++    }
++  else if (auto_var_in_fn_p (*tp, cfun->decl))
++    {
++      /* Local variables and labels need to be replaced by equivalent
++	 variables.  We don't want to copy static variables; there's
++	 only one of those, no matter how many times we inline the
++	 containing function.  Similarly for globals from an outer
++	 function.  */
++      tree new_decl;
++
++      /* Remap the declaration.  */
++      new_decl = remap_name (*tp, stmt, is_lhs);
++      gcc_assert (new_decl);
++      /* Replace this variable with the copy.  */
++      STRIP_TYPE_NOPS (new_decl);
++      /* ???  The C++ frontend uses void * pointer zero to initialize
++	 any other type.  This confuses the middle-end type verification.
++	 As cloned bodies do not go through gimplification again the fixup
++	 there doesn't trigger.  */
++      if (TREE_CODE (new_decl) == INTEGER_CST
++	  && !useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (new_decl)))
++	new_decl = fold_convert (TREE_TYPE (*tp), new_decl);
++      *tp = new_decl;
++      *walk_subtrees = 0;
++    }
++  else if (TREE_CODE (*tp) == STATEMENT_LIST || TREE_CODE (*tp) == SAVE_EXPR)
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Unexpected tree: ");
++	  print_generic_expr (dump_file, *tp);
++	  fprintf (dump_file, "\n");
++	}
++      gcc_unreachable ();
++    }
++  else
++    {
++      /* Otherwise, just copy the node.  Note that copy_tree_r already
++	 knows not to copy VAR_DECLs, etc., so this is safe.  */
++
++      if (TREE_CODE (*tp) == MEM_REF)
++	{
++	  /* We need to re-canonicalize MEM_REFs from inline substitutions
++	     that can happen when a pointer argument is an ADDR_EXPR.
++	     Recurse here manually to allow that.  */
++	  tree ptr = TREE_OPERAND (*tp, 0);
++	  tree type = TREE_TYPE (*tp);
++	  tree old = *tp;
++	  walk_tree (&ptr, remap_gimple_op_r, data, NULL);
++	  *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
++	  TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
++	  TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
++	  TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
++	  /* TODO: maybe support this case.  */
++	  gcc_assert (MR_DEPENDENCE_CLIQUE (old) == 0);
++	  /* We cannot propagate the TREE_THIS_NOTRAP flag if we have
++	     remapped a parameter as the property might be valid only
++	     for the parameter itself.  */
++	  if (TREE_THIS_NOTRAP (old) && (!is_parm (TREE_OPERAND (old, 0))))
++	    TREE_THIS_NOTRAP (*tp) = 1;
++	  REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old);
++	  *walk_subtrees = 0;
++	  return NULL;
++	}
++
++      /* Here is the "usual case".  Copy this tree node, and then
++	 tweak some special cases.  */
++      ipa_copy_tree_r (tp, walk_subtrees, NULL);
++      gcc_assert (!(TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3)));
++      if (TREE_CODE (*tp) == ADDR_EXPR)
++	{
++	  /* TODO: If this used to be invariant, but is not any longer,
++	     then regimplification is probably needed.  */
++	  walk_tree (&TREE_OPERAND (*tp, 0), remap_gimple_op_r, data, NULL);
++	  recompute_tree_invariant_for_addr_expr (*tp);
++	  *walk_subtrees = 0;
++	}
++    }
++  /* TODO: maybe we need to update TREE_BLOCK (*tp).  */
++
++  /* Keep iterating.  */
++  return NULL_TREE;
++}
++
++static void
++create_cgraph_edge (cgraph_node *n, gimple *stmt)
++{
++  gcall *call_stmt = dyn_cast  (stmt);
++  basic_block bb = gimple_bb (stmt);
++  tree decl = gimple_call_fndecl (call_stmt);
++  if (!decl)
++    return;
++  struct cgraph_edge *e = n->create_edge (cgraph_node::get_create (decl),
++					  call_stmt, bb->count);
++  /* TODO: maybe we need to store ipa_call_summary result.  */
++  ipa_call_summaries->get_create (e);
++}
++
++/* Insert prefetch intrinsics in this function, return nonzero on success.  */
++
++static int
++optimize_function (cgraph_node *n, function *fn)
++{
++  /* In a given function, optimize only indirect memrefs with
++     the same incremental memref.
++     TODO: implement the optimization for other cases.  */
++  bool different_incrementals = false;
++  memref_t *first_mr = NULL;
++  memref_set used_mrs;
++  for (memref_set::const_iterator it = (*optimize_mrs_map)[fn]->begin ();
++       it != (*optimize_mrs_map)[fn]->end (); it++)
++    {
++      memref_t *mr = *it;
++      if (!first_mr)
++	first_mr = mr;
++      else if ((*mr_candidate_map)[first_mr] != (*mr_candidate_map)[mr])
++	{
++	  different_incrementals = true;
++	  break;
++	}
++      for (memref_set::const_iterator it2 = mr->used_mrs.begin ();
++	   it2 != mr->used_mrs.end (); it2++)
++	used_mrs.insert (*it2);
++    }
++  if (different_incrementals)
++    {
++      if (dump_file)
++	fprintf (dump_file, "It contains memrefs with different "
++		 "incrementals.  Skip the case.\n");
++      return 0;
++    }
++  memref_t *inc_mr = (*mr_candidate_map)[first_mr];
++  if (!inc_mr->stmts[0] || !gimple_assign_single_p (inc_mr->stmts[0]))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Incremental MR with unexpected stmt.  "
++		 "Skip the case.\n");
++      return 0;
++    }
++  if (dump_file && !used_mrs.empty ())
++    print_mrs_ids (used_mrs, "Common list of used mrs:\n");
++
++  /* Find a memref in used mrs which corresponds to the found incremental
++     memref.  */
++  memref_t *comp_mr = NULL;
++  for (memref_set::const_iterator it = used_mrs.begin ();
++       it != used_mrs.end (); it++)
++    {
++    bool c_offset;
++    if ((*it)->type != MR_SIMPLE || inc_mr->type != MR_SIMPLE
++	|| !compatible_memrefs_p (*it, inc_mr, c_offset))
++      continue;
++    if (c_offset)
++      {
++	if (dump_file)
++	  fprintf (dump_file, "Found compatible used MR (%d) and "
++		   "incr MR (%d)\n", (*it)->mr_id, inc_mr->mr_id);
++	comp_mr = (*it);
++      }
++    }
++  if (!comp_mr || !comp_mr->stmts[0]
++      || !gimple_assign_single_p (comp_mr->stmts[0]))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Compatible MR in this function is not found "
++		 " or it has unexpected stmt.  Skip the case.\n");
++      return 0;
++    }
++
++  /* Filter out memrefs with the same memory references.
++     TODO: maybe do the same with used mrs.  */
++  vec vmrs = vNULL;
++  reduce_memref_set ((*optimize_mrs_map)[fn], vmrs);
++
++  /* Find insertion place.  Create new BB.  */
++  /* TODO: maybe it is useful to process also used_mrs.  */
++  basic_block dom_bb = NULL;
++  for (unsigned int i = 0; i < vmrs.length (); i++)
++    find_nearest_common_dominator (vmrs[i], dom_bb);
++
++  if (!dom_bb)
++    {
++      if (dump_file)
++	fprintf (dump_file, "Dominator bb for MRs is not found.  "
++		 "Skip the case.\n");
++      return 0;
++    }
++  else if (dump_file)
++    fprintf (dump_file, "Dominator bb %d for MRs\n", dom_bb->index);
++
++  split_block (dom_bb, (gimple *) NULL);
++  gimple_stmt_iterator gsi = gsi_last_bb (dom_bb);
++
++  /* Create new inc var.  Insert new_var = old_var + step * factor.  */
++  decl_map = new tree_map;
++  gcc_assert (comp_mr->stmts[0] && gimple_assign_single_p (comp_mr->stmts[0]));
++  tree inc_var = gimple_assign_lhs (comp_mr->stmts[0]);
++  gimple_seq stmts = NULL;
++  tree var_type = TREE_TYPE (inc_var);
++  enum tree_code inc_code;
++  if (TREE_CODE (var_type) == POINTER_TYPE)
++    inc_code = POINTER_PLUS_EXPR;
++  else
++    inc_code = PLUS_EXPR;
++  tree step = inc_mr->step;
++  unsigned dist_val = tree_to_uhwi (step) * param_ipa_prefetch_distance_factor;
++  tree dist = build_int_cst (TREE_TYPE (step), dist_val);
++  tree new_inc_var = gimple_build (&stmts, inc_code, var_type, inc_var, dist);
++  (*decl_map)[inc_var] = new_inc_var;
++
++  /* Create other new vars.  Insert new stmts.  */
++  struct walk_stmt_info wi;
++  stmt_set processed_stmts;
++  memref_tree_map mr_new_trees;
++  for (memref_set::const_iterator it = used_mrs.begin ();
++       it != used_mrs.end (); it++)
++    {
++      memref_t *mr = *it;
++      gimple *last_stmt = NULL;
++      if (mr == comp_mr)
++	continue;
++      for (int i = mr->stmts.length () - 1; i >= 0 ; i--)
++	{
++	  if (processed_stmts.count (mr->stmts[i]))
++	    continue;
++	  processed_stmts.insert (mr->stmts[i]);
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Copy stmt %d from used MR (%d):\n",
++		       i, mr->mr_id);
++	      print_gimple_stmt (dump_file, mr->stmts[i], 0);
++	    }
++	  /* Create a new copy of STMT and duplicate STMT's virtual
++	     operands.  */
++	  gimple *copy = gimple_copy (mr->stmts[i]);
++	  gcc_checking_assert (!is_gimple_debug (copy));
++
++	  /* Remap all the operands in COPY.  */
++	  memset (&wi, 0, sizeof (wi));
++	  last_stmt = copy;
++	  wi.info = copy;
++	  walk_gimple_op (copy, remap_gimple_op_r, &wi);
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Stmt %d after remap:\n",i);
++	      print_gimple_stmt (dump_file, copy, 0);
++	    }
++	  gimple_seq_add_stmt (&stmts, copy);
++	}
++      gcc_assert (last_stmt);
++      mr_new_trees[mr] = gimple_assign_lhs (last_stmt);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "MR (%d) new mem: ", mr->mr_id);
++	  print_generic_expr (dump_file, gimple_assign_lhs (last_stmt));
++	  fprintf (dump_file, "\n");
++	}
++    }
++  /* On new load check page fault.  */
++  /* Insert prefetch instructions.  */
++  if (dump_file)
++    fprintf (dump_file, "Evaluate addresses and insert prefetch insn.\n");
++
++  vec pcalls = vNULL;
++  tree local;
++  switch (param_ipa_prefetch_locality)
++    {
++    case 0:
++      local = integer_zero_node;
++      break;
++    case 1:
++      local = integer_one_node;
++      break;
++    case 2:
++      local = build_int_cst (integer_type_node, 2);
++      break;
++    default:
++    case 3:
++      local = integer_three_node;
++      break;
++    }
++  for (unsigned int j = 0; j < vmrs.length (); j++)
++    {
++      memref_t *mr = vmrs[j];
++      /* Don't need to copy the last stmt, since we insert prefetch insn
++	 instead of it.  */
++      for (int i = mr->stmts.length () - 1; i >= 1 ; i--)
++	{
++	  if (processed_stmts.count (mr->stmts[i]))
++	    continue;
++	  processed_stmts.insert (mr->stmts[i]);
++
++	  gimple *copy = gimple_copy (mr->stmts[i]);
++	  gcc_checking_assert (!is_gimple_debug (copy));
++
++	  /* Remap all the operands in COPY.  */
++	  memset (&wi, 0, sizeof (wi));
++	  wi.info = copy;
++	  walk_gimple_op (copy, remap_gimple_op_r, &wi);
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Stmt %d after remap:\n",i);
++	      print_gimple_stmt (dump_file, copy, 0);
++	    }
++	  gimple_seq_add_stmt (&stmts, copy);
++	}
++      gimple *last_stmt = mr->stmts[0];
++      gcc_assert (last_stmt);
++      mr_new_trees[mr] = gimple_assign_lhs (last_stmt);
++      tree write_p = mr->is_store ? integer_one_node : integer_zero_node;
++      tree addr = get_mem_ref_address_ssa_name (mr->mem, NULL_TREE);
++      if (decl_map->count (addr))
++	addr = (*decl_map)[addr];
++      last_stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_PREFETCH),
++				     3, addr, write_p, local);
++      pcalls.safe_push (last_stmt);
++      gimple_seq_add_stmt (&stmts, last_stmt);
++    }
++
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++  delete decl_map;
++
++  /* Modify cgraph inserting calls to prefetch intrinsics.  */
++  for (unsigned i = 0; i < pcalls.length (); i++)
++    create_cgraph_edge (n, pcalls[i]);
++  ipa_update_overall_fn_summary (n);
++
++  return 1;
++}
++
++static int
++insert_prefetch ()
++{
++  int res = 0;
++  cgraph_node *n;
++  FOR_EACH_DEFINED_FUNCTION (n)
++    {
++      function *fn = DECL_STRUCT_FUNCTION (n->decl);
++      if (!optimize_mrs_map->count (fn))
++	continue;
++      if (dump_file)
++	fprintf (dump_file, "Optimize function %s\n", n->dump_name ());
++      push_cfun (DECL_STRUCT_FUNCTION (n->decl));
++      calculate_dominance_info (CDI_DOMINATORS);
++      res |= optimize_function (n, fn);
++      free_dominance_info (CDI_DOMINATORS);
++      pop_cfun ();
++    }
++  return res;
++}
++
++static unsigned int
++ipa_prefetch (void)
++{
++  if (!targetm.have_prefetch ())
++    {
++      if (dump_file)
++	fprintf (dump_file, "Prefetch is not supported by the target.\n");
++      return 0;
++    }
++
++  unsigned int ret = 0;
++  el_map = new edge_in_loop;
++  nl_map = new node_in_loop;
++  icn_map = new node_to_iedge_map;
++  nn_map = new node_to_node_map;
++  tm_map = new tree_memref_map;
++  fmrs_map = new funct_mrs_map;
++  mr_candidate_map = new memref_map;
++  optimize_mrs_map = new funct_mrs_map;
++
++  max_mr_id = 0;
++  /* TODO: check if we really need this init.  */
++  if (!builtin_decl_explicit_p (BUILT_IN_PREFETCH))
++    {
++      tree type = build_function_type_list (void_type_node,
++					    const_ptr_type_node, NULL_TREE);
++      tree decl = add_builtin_function ("__builtin_prefetch", type,
++					BUILT_IN_PREFETCH, BUILT_IN_NORMAL,
++					NULL, NULL_TREE);
++      DECL_IS_NOVOPS (decl) = true;
++      set_builtin_decl (BUILT_IN_PREFETCH, decl, false);
++    }
++
++  analyse_cgraph ();
++  prepare_indirect_call_info ();
++  propagate_loop_info_in_cgraph ();
++  collect_memory_references ();
++  analyse_loops ();
++
++  /* TODO: implement some specific heuristics.  */
++  if (!optimize_mrs_map->empty ())
++    ret = insert_prefetch ();
++
++  delete el_map;
++  delete nl_map;
++  for (node_to_iedge_map::iterator it = icn_map->begin ();
++       it != icn_map->end (); ++it)
++    delete it->second;
++  delete icn_map;
++  for (node_to_node_map::iterator it = nn_map->begin ();
++       it != nn_map->end (); ++it)
++    delete it->second;
++  delete nn_map;
++  for (tree_memref_map::iterator it = tm_map->begin ();
++       it != tm_map->end (); ++it)
++    delete it->second;
++  delete tm_map;
++  for (funct_mrs_map::iterator it = fmrs_map->begin ();
++       it != fmrs_map->end (); ++it)
++    delete it->second;
++  delete fmrs_map;
++  delete mr_candidate_map;
++  delete optimize_mrs_map;
++
++  /* TODO: maybe add other todos.  */
++  return ret | TODO_verify_all;
++}
++
++const pass_data pass_data_ipa_prefetch =
++{
++  SIMPLE_IPA_PASS, // type
++  "ipa_prefetch", // name
++  OPTGROUP_NONE, // optinfo_flags
++  TV_IPA_PREFETCH, // tv_id
++  0, // properties_required
++  0, // properties_provided
++  0, // properties_destroyed
++  0, // todo_flags_start
++  0, // todo_flags_finish
++};
++
++class pass_ipa_prefetch : public simple_ipa_opt_pass
++{
++public:
++  pass_ipa_prefetch (gcc::context *ctxt)
++    : simple_ipa_opt_pass (pass_data_ipa_prefetch, ctxt)
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *);
++  virtual unsigned int execute (function *)
++  {
++    return ipa_prefetch ();
++  }
++}; // class pass_ipa_prefetch
++
++bool
++pass_ipa_prefetch::gate (function *)
++{
++  return (optimize >= 3
++	  && flag_ipa_prefetch
++	  /* Don't bother doing anything if the program has errors.  */
++	  && !seen_error ()
++	  && flag_lto_partition == LTO_PARTITION_ONE
++	  /* Only enable struct optimizations in lto or whole_program.  */
++	  && (in_lto_p || flag_whole_program));
++}
++
++} // anon namespace
++
++simple_ipa_opt_pass *
++make_pass_ipa_prefetch (gcc::context *ctxt)
++{
++  return new pass_ipa_prefetch (ctxt);
++}
+diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
+index 261a72085..5355cf2f4 100644
+--- a/gcc/ipa-sra.cc
++++ b/gcc/ipa-sra.cc
+@@ -3033,6 +3033,14 @@ process_edge_to_unknown_caller (cgraph_edge *cs)
+   gcc_checking_assert (from_ifs);
+   isra_call_summary *csum = call_sums->get (cs);
+ 
++  /* TODO: implement better support for call edges inserted after summary
++     collection but before sra wpa invocation.  */
++  if (!csum)
++    {
++      csum = call_sums->get_create (cs);
++      csum->m_return_ignored = true;
++    }
++
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file, "Processing an edge to an unknown caller from %s:\n",
+ 	     cs->caller->dump_name ());
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 7e5c119cf..5c07e3986 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -309,6 +309,14 @@ Maximum pieces that IPA-SRA tracks per formal parameter, as a consequence, also
+ Common Joined UInteger Var(param_ipa_sra_ptr_growth_factor) Init(2) Param Optimization
+ Maximum allowed growth of number and total size of new parameters that ipa-sra replaces a pointer to an aggregate with.
+ 
++-param=ipa-prefetch-distance-factor=
++Common Joined UInteger Var(param_ipa_prefetch_distance_factor) Init(4) Param Optimization
++The factor represents the number of inductive variable incrementations to evaluate an indirect memory address for IPA prefetch.
++
++-param=ipa-prefetch-locality=
++Common Joined UInteger Var(param_ipa_prefetch_locality) Init(3) Param Optimization
++The flag represents temporal locality values in the following way: 0:pstl1strm, 1:pstl3keep, 2:pstl2keep, 3:pstl1keep.
++
+ -param=ira-loop-reserved-regs=
+ Common Joined UInteger Var(param_ira_loop_reserved_regs) Init(2) Param Optimization
+ The number of registers in each class kept unused by loop invariant motion.
+diff --git a/gcc/passes.def b/gcc/passes.def
+index b7d4f7b4e..4c1436766 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -158,6 +158,7 @@ along with GCC; see the file COPYING3.  If not see
+   NEXT_PASS (pass_ipa_icf);
+   NEXT_PASS (pass_ipa_devirt);
+   NEXT_PASS (pass_ipa_icp);
++  NEXT_PASS (pass_ipa_prefetch);
+   NEXT_PASS (pass_ipa_cp);
+   NEXT_PASS (pass_ipa_sra);
+   NEXT_PASS (pass_ipa_cdtor_merge);
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 18a9f62cc..810ae20fd 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -81,6 +81,7 @@ DEFTIMEVAR (TV_IPA_CONSTANT_PROP     , "ipa cp")
+ DEFTIMEVAR (TV_IPA_INLINING          , "ipa inlining heuristics")
+ DEFTIMEVAR (TV_IPA_FNSPLIT           , "ipa function splitting")
+ DEFTIMEVAR (TV_IPA_COMDATS	     , "ipa comdats")
++DEFTIMEVAR (TV_IPA_PREFETCH	     , "ipa prefetch")
+ DEFTIMEVAR (TV_IPA_STRUCT_REORG      , "ipa struct reorg optimization")
+ DEFTIMEVAR (TV_IPA_OPT		     , "ipa various optimizations")
+ DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS    , "lto stream decompression")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 1733931c3..63f1192ae 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -529,6 +529,7 @@ extern ipa_opt_pass_d *make_pass_ipa_icp (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt);
++extern simple_ipa_opt_pass *make_pass_ipa_prefetch (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt);
+-- 
+2.33.0
+
diff --git a/0051-Port-fixes-for-IPA-prefetch-to-GCC-12.patch b/0051-Port-fixes-for-IPA-prefetch-to-GCC-12.patch
new file mode 100644
index 0000000..dae19fa
--- /dev/null
+++ b/0051-Port-fixes-for-IPA-prefetch-to-GCC-12.patch
@@ -0,0 +1,2216 @@
+From 4c262af8e178ac7c81b32be5b159b4d09a5841c9 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Fri, 8 Mar 2024 07:07:50 +0800
+Subject: [PATCH 1/2] Port fixes for IPA prefetch to GCC 12
+
+---
+ gcc/ipa-devirt.cc                          |    9 +-
+ gcc/ipa-prefetch.cc                        |  174 +-
+ gcc/ipa-sra.cc                             |    7 +
+ gcc/params.opt                             |    4 +-
+ gcc/testsuite/gcc.dg/completion-1.c        |    1 +
+ gcc/testsuite/gcc.dg/ipa/ipa-prefetch-xz.c | 1843 ++++++++++++++++++++
+ 6 files changed, 1974 insertions(+), 64 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-prefetch-xz.c
+
+diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc
+index dd3562d56..dd000b401 100644
+--- a/gcc/ipa-devirt.cc
++++ b/gcc/ipa-devirt.cc
+@@ -5029,9 +5029,12 @@ analyze_assign_stmt (gimple *stmt)
+ 	}
+       else
+ 	{
+-	  fprintf (dump_file, "\nUnsupported rhs type %s in assign stmt: ",
+-		   get_tree_code_name (TREE_CODE (rhs)));
+-	  print_gimple_stmt (dump_file, stmt, 0);
++	  if (dump_file && (dump_flags & TDF_DETAILS))
++	    {
++	      fprintf (dump_file, "\nUnsupported rhs type %s in assign stmt: ",
++		       get_tree_code_name (TREE_CODE (rhs)));
++	      print_gimple_stmt (dump_file, stmt, 0);
++	    }
+ 	  gcc_unreachable ();
+ 	}
+     }
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index aeea51105..9537e4835 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -167,6 +167,7 @@ analyse_cgraph ()
+ 	}
+ 
+       /* TODO: maybe remove loop info here.  */
++      n->get_body ();
+       push_cfun (DECL_STRUCT_FUNCTION (n->decl));
+       calculate_dominance_info (CDI_DOMINATORS);
+       loop_optimizer_init (LOOPS_NORMAL);
+@@ -942,6 +943,9 @@ compare_memrefs (memref_t* mr, memref_t* mr2)
+       (*mr_candidate_map)[mr] = mr2;
+       return;
+     }
++  /* Probably we shouldn't leave nulls in the map.  */
++  if ((*mr_candidate_map)[mr] == NULL)
++    return;
+   /* TODO: support analysis with incrementation of different fields.  */
+   if ((*mr_candidate_map)[mr]->offset != mr2->offset)
+     {
+@@ -1090,6 +1094,15 @@ analyse_loops ()
+ 	  memref_t *mr = it->first, *mr2 = it->second;
+ 	  if (mr2 == NULL || !(*fmrs_map)[fn]->count (mr))
+ 	    continue;
++	  /* For now optimize only MRs that mem is MEM_REF.
++	     TODO: support other MR types.  */
++	  if (TREE_CODE (mr->mem) != MEM_REF)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "Skip MR %d: unsupported tree code = %s\n",
++			 mr->mr_id, get_tree_code_name (TREE_CODE (mr->mem)));
++	      continue;
++	    }
+ 	  if (!optimize_mrs_map->count (fn))
+ 	    (*optimize_mrs_map)[fn] = new memref_set;
+ 	  (*optimize_mrs_map)[fn]->insert (mr);
+@@ -1102,7 +1115,7 @@ analyse_loops ()
+ 	       it != (*optimize_mrs_map)[fn]->end (); it++)
+ 	    {
+ 	      memref_t *mr = *it, *mr2 = (*mr_candidate_map)[mr];
+-	      fprintf (dump_file, "MRs %d,%d with incremental offset ",
++	      fprintf (dump_file, "MRs %d, %d with incremental offset ",
+ 		       mr->mr_id, mr2->mr_id);
+ 	      print_generic_expr (dump_file, mr2->offset);
+ 	      fprintf (dump_file, "\n");
+@@ -1435,6 +1448,52 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
+   return NULL_TREE;
+ }
+ 
++/* Copy stmt and remap its operands.  */
++
++static gimple *
++gimple_copy_and_remap (gimple *stmt)
++{
++  gimple *copy = gimple_copy (stmt);
++  gcc_checking_assert (!is_gimple_debug (copy));
++
++  /* Remap all the operands in COPY.  */
++  struct walk_stmt_info wi;
++  memset (&wi, 0, sizeof (wi));
++  wi.info = copy;
++  walk_gimple_op (copy, remap_gimple_op_r, &wi);
++  if (dump_file)
++    {
++      fprintf (dump_file, "Stmt copy after remap:\n");
++      print_gimple_stmt (dump_file, copy, 0);
++    }
++  return copy;
++}
++
++/* Copy and remap stmts listed in MR in reverse order to last_idx, skipping
++   processed ones.  Insert new stmts to the sequence.  */
++
++static gimple *
++gimple_copy_and_remap_memref_stmts (memref_t *mr, gimple_seq &stmts,
++				    int last_idx, stmt_set &processed)
++{
++  gimple *last_stmt = NULL;
++  for (int i = mr->stmts.length () - 1; i >= last_idx ; i--)
++    {
++      if (processed.count (mr->stmts[i]))
++	continue;
++      processed.insert (mr->stmts[i]);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Copy stmt %d from used MR (%d):\n",
++		   i, mr->mr_id);
++	  print_gimple_stmt (dump_file, mr->stmts[i], 0);
++	}
++      last_stmt = gimple_copy_and_remap (mr->stmts[i]);
++      gimple_seq_add_stmt (&stmts, last_stmt);
++  }
++  return last_stmt;
++}
++
+ static void
+ create_cgraph_edge (cgraph_node *n, gimple *stmt)
+ {
+@@ -1490,6 +1549,13 @@ optimize_function (cgraph_node *n, function *fn)
+ 		 "Skip the case.\n");
+       return 0;
+     }
++  if (!tree_fits_shwi_p (inc_mr->step))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Cannot represent incremental MR's step as "
++		 "integer.  Skip the case.\n");
++      return 0;
++    }
+   if (dump_file && !used_mrs.empty ())
+     print_mrs_ids (used_mrs, "Common list of used mrs:\n");
+ 
+@@ -1539,16 +1605,44 @@ optimize_function (cgraph_node *n, function *fn)
+       return 0;
+     }
+   else if (dump_file)
+-    fprintf (dump_file, "Dominator bb %d for MRs\n", dom_bb->index);
++    {
++      fprintf (dump_file, "Dominator bb %d for MRs:\n", dom_bb->index);
++      gimple_dump_bb (dump_file, dom_bb, 0, dump_flags);
++      fprintf (dump_file, "\n");
++    }
+ 
+-  split_block (dom_bb, (gimple *) NULL);
++  /* Try to find comp_mr's stmt in the dominator bb.  */
++  gimple *last_used = NULL;
++  for (gimple_stmt_iterator si = gsi_last_bb (dom_bb); !gsi_end_p (si);
++       gsi_prev (&si))
++    if (comp_mr->stmts[0] == gsi_stmt (si))
++      {
++	last_used = gsi_stmt (si);
++	if (dump_file)
++	  {
++	    fprintf (dump_file, "Last used stmt in dominator bb:\n");
++	    print_gimple_stmt (dump_file, last_used, 0);
++	  }
++	break;
++      }
++
++  split_block (dom_bb, last_used);
+   gimple_stmt_iterator gsi = gsi_last_bb (dom_bb);
+ 
+   /* Create new inc var.  Insert new_var = old_var + step * factor.  */
+   decl_map = new tree_map;
+   gcc_assert (comp_mr->stmts[0] && gimple_assign_single_p (comp_mr->stmts[0]));
+   tree inc_var = gimple_assign_lhs (comp_mr->stmts[0]);
++  /* If old_var definition dominates the current use, just use it, otherwise
++     evaluate it just before new inc var evaluation.  */
+   gimple_seq stmts = NULL;
++  stmt_set processed_stmts;
++  if (!dominated_by_p (CDI_DOMINATORS, dom_bb, gimple_bb (comp_mr->stmts[0])))
++    {
++      gimple *tmp = gimple_copy_and_remap_memref_stmts (comp_mr, stmts, 0,
++							processed_stmts);
++      inc_var = gimple_assign_lhs (tmp);
++    }
+   tree var_type = TREE_TYPE (inc_var);
+   enum tree_code inc_code;
+   if (TREE_CODE (var_type) == POINTER_TYPE)
+@@ -1556,52 +1650,28 @@ optimize_function (cgraph_node *n, function *fn)
+   else
+     inc_code = PLUS_EXPR;
+   tree step = inc_mr->step;
+-  unsigned dist_val = tree_to_uhwi (step) * param_ipa_prefetch_distance_factor;
++  HOST_WIDE_INT dist_val = tree_to_shwi (step)
++			   * param_ipa_prefetch_distance_factor;
+   tree dist = build_int_cst (TREE_TYPE (step), dist_val);
+   tree new_inc_var = gimple_build (&stmts, inc_code, var_type, inc_var, dist);
+   (*decl_map)[inc_var] = new_inc_var;
++  if (dump_file)
++    {
++      fprintf (dump_file, "New distance value: %ld, new inc var: ", dist_val);
++      print_generic_expr (dump_file, new_inc_var);
++      fprintf (dump_file, "\n");
++    }
+ 
+   /* Create other new vars.  Insert new stmts.  */
+-  struct walk_stmt_info wi;
+-  stmt_set processed_stmts;
+-  memref_tree_map mr_new_trees;
+   for (memref_set::const_iterator it = used_mrs.begin ();
+        it != used_mrs.end (); it++)
+     {
+       memref_t *mr = *it;
+-      gimple *last_stmt = NULL;
+       if (mr == comp_mr)
+ 	continue;
+-      for (int i = mr->stmts.length () - 1; i >= 0 ; i--)
+-	{
+-	  if (processed_stmts.count (mr->stmts[i]))
+-	    continue;
+-	  processed_stmts.insert (mr->stmts[i]);
+-	  if (dump_file)
+-	    {
+-	      fprintf (dump_file, "Copy stmt %d from used MR (%d):\n",
+-		       i, mr->mr_id);
+-	      print_gimple_stmt (dump_file, mr->stmts[i], 0);
+-	    }
+-	  /* Create a new copy of STMT and duplicate STMT's virtual
+-	     operands.  */
+-	  gimple *copy = gimple_copy (mr->stmts[i]);
+-	  gcc_checking_assert (!is_gimple_debug (copy));
+-
+-	  /* Remap all the operands in COPY.  */
+-	  memset (&wi, 0, sizeof (wi));
+-	  last_stmt = copy;
+-	  wi.info = copy;
+-	  walk_gimple_op (copy, remap_gimple_op_r, &wi);
+-	  if (dump_file)
+-	    {
+-	      fprintf (dump_file, "Stmt %d after remap:\n",i);
+-	      print_gimple_stmt (dump_file, copy, 0);
+-	    }
+-	  gimple_seq_add_stmt (&stmts, copy);
+-	}
++      gimple *last_stmt = gimple_copy_and_remap_memref_stmts (mr, stmts, 0,
++							      processed_stmts);
+       gcc_assert (last_stmt);
+-      mr_new_trees[mr] = gimple_assign_lhs (last_stmt);
+       if (dump_file)
+ 	{
+ 	  fprintf (dump_file, "MR (%d) new mem: ", mr->mr_id);
+@@ -1637,29 +1707,9 @@ optimize_function (cgraph_node *n, function *fn)
+       memref_t *mr = vmrs[j];
+       /* Don't need to copy the last stmt, since we insert prefetch insn
+ 	 instead of it.  */
+-      for (int i = mr->stmts.length () - 1; i >= 1 ; i--)
+-	{
+-	  if (processed_stmts.count (mr->stmts[i]))
+-	    continue;
+-	  processed_stmts.insert (mr->stmts[i]);
+-
+-	  gimple *copy = gimple_copy (mr->stmts[i]);
+-	  gcc_checking_assert (!is_gimple_debug (copy));
+-
+-	  /* Remap all the operands in COPY.  */
+-	  memset (&wi, 0, sizeof (wi));
+-	  wi.info = copy;
+-	  walk_gimple_op (copy, remap_gimple_op_r, &wi);
+-	  if (dump_file)
+-	    {
+-	      fprintf (dump_file, "Stmt %d after remap:\n",i);
+-	      print_gimple_stmt (dump_file, copy, 0);
+-	    }
+-	  gimple_seq_add_stmt (&stmts, copy);
+-	}
++      gimple_copy_and_remap_memref_stmts (mr, stmts, 1, processed_stmts);
+       gimple *last_stmt = mr->stmts[0];
+       gcc_assert (last_stmt);
+-      mr_new_trees[mr] = gimple_assign_lhs (last_stmt);
+       tree write_p = mr->is_store ? integer_one_node : integer_zero_node;
+       tree addr = get_mem_ref_address_ssa_name (mr->mem, NULL_TREE);
+       if (decl_map->count (addr))
+@@ -1668,6 +1718,11 @@ optimize_function (cgraph_node *n, function *fn)
+ 				     3, addr, write_p, local);
+       pcalls.safe_push (last_stmt);
+       gimple_seq_add_stmt (&stmts, last_stmt);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Insert %d prefetch stmt:\n", j);
++	  print_gimple_stmt (dump_file, last_stmt, 0);
++	}
+     }
+ 
+   gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
+@@ -1677,6 +1732,7 @@ optimize_function (cgraph_node *n, function *fn)
+   for (unsigned i = 0; i < pcalls.length (); i++)
+     create_cgraph_edge (n, pcalls[i]);
+   ipa_update_overall_fn_summary (n);
++  renumber_gimple_stmt_uids (DECL_STRUCT_FUNCTION (n->decl));
+ 
+   return 1;
+ }
+@@ -1806,7 +1862,7 @@ pass_ipa_prefetch::gate (function *)
+ 	  /* Don't bother doing anything if the program has errors.  */
+ 	  && !seen_error ()
+ 	  && flag_lto_partition == LTO_PARTITION_ONE
+-	  /* Only enable struct optimizations in lto or whole_program.  */
++	  /* Only enable prefetch optimizations in lto or whole_program.  */
+ 	  && (in_lto_p || flag_whole_program));
+ }
+ 
+diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
+index 5355cf2f4..471b3927c 100644
+--- a/gcc/ipa-sra.cc
++++ b/gcc/ipa-sra.cc
+@@ -3393,6 +3393,13 @@ param_splitting_across_edge (cgraph_edge *cs)
+   gcc_checking_assert (from_ifs && from_ifs->m_parameters);
+ 
+   isra_call_summary *csum = call_sums->get (cs);
++  /* TODO: implement better support for call edges inserted after summary
++     collection but before sra wpa invocation.  */
++  if (!csum)
++    {
++      csum = call_sums->get_create (cs);
++      csum->m_return_ignored = true;
++    }
+   gcc_checking_assert (csum);
+   unsigned args_count = csum->m_arg_flow.length ();
+   isra_func_summary *to_ifs = func_sums->get (callee);
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 5c07e3986..50385dfd7 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -314,8 +314,8 @@ Common Joined UInteger Var(param_ipa_prefetch_distance_factor) Init(4) Param Opt
+ The factor represents the number of inductive variable incrementations to evaluate an indirect memory address for IPA prefetch.
+ 
+ -param=ipa-prefetch-locality=
+-Common Joined UInteger Var(param_ipa_prefetch_locality) Init(3) Param Optimization
+-The flag represents temporal locality values in the following way: 0:pstl1strm, 1:pstl3keep, 2:pstl2keep, 3:pstl1keep.
++Common Joined UInteger Var(param_ipa_prefetch_locality) Init(3) IntegerRange(0, 3) Param Optimization
++The flag represents temporal locality value between 0 and 3, the higher value means the higher temporal locality in the data.
+ 
+ -param=ira-loop-reserved-regs=
+ Common Joined UInteger Var(param_ira_loop_reserved_regs) Init(2) Param Optimization
+diff --git a/gcc/testsuite/gcc.dg/completion-1.c b/gcc/testsuite/gcc.dg/completion-1.c
+index 64da64f1c..df2319c76 100644
+--- a/gcc/testsuite/gcc.dg/completion-1.c
++++ b/gcc/testsuite/gcc.dg/completion-1.c
+@@ -2,6 +2,7 @@
+ /* { dg-options "--completion=-fipa-ic" } */
+ 
+ /* { dg-begin-multiline-output "" }
++-fipa-ic
+ -fipa-icf
+ -fipa-icf-functions
+ -fipa-icf-variables
+diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-prefetch-xz.c b/gcc/testsuite/gcc.dg/ipa/ipa-prefetch-xz.c
+new file mode 100644
+index 000000000..bd4fb2bdc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/ipa/ipa-prefetch-xz.c
+@@ -0,0 +1,1843 @@
++/* { dg-do link } */
++/* { dg-options "-O3 -fipa-ic -fipa-prefetch -flto -flto-partition=one -fdump-ipa-ipa_prefetch -fdump-ipa-icp" } */
++/* { dg-require-effective-target lto } */
++
++/* Based on opensource xz code.  */
++
++#include 
++#include 
++
++typedef long int ptrdiff_t;
++typedef long unsigned int size_t;
++typedef unsigned int wchar_t;
++
++typedef unsigned char __u_char;
++typedef unsigned short int __u_short;
++typedef unsigned int __u_int;
++typedef unsigned long int __u_long;
++
++typedef signed char __int8_t;
++typedef unsigned char __uint8_t;
++typedef signed short int __int16_t;
++typedef unsigned short int __uint16_t;
++typedef signed int __int32_t;
++typedef unsigned int __uint32_t;
++
++typedef signed long int __int64_t;
++typedef unsigned long int __uint64_t;
++
++typedef __int8_t __int_least8_t;
++typedef __uint8_t __uint_least8_t;
++typedef __int16_t __int_least16_t;
++typedef __uint16_t __uint_least16_t;
++typedef __int32_t __int_least32_t;
++typedef __uint32_t __uint_least32_t;
++typedef __int64_t __int_least64_t;
++typedef __uint64_t __uint_least64_t;
++
++typedef __int8_t int8_t;
++typedef __int16_t int16_t;
++typedef __int32_t int32_t;
++typedef __int64_t int64_t;
++
++typedef __uint8_t uint8_t;
++typedef __uint16_t uint16_t;
++typedef __uint32_t uint32_t;
++typedef __uint64_t uint64_t;
++
++typedef long int intptr_t;
++typedef unsigned long int uintptr_t;
++
++static inline uint16_t
++read16ne(const uint8_t *buf)
++{
++ uint16_t num;
++ memcpy(&num, buf, sizeof(num));
++ return num;
++}
++
++static inline uint32_t
++read32ne(const uint8_t *buf)
++{
++ uint32_t num;
++ memcpy(&num, buf, sizeof(num));
++ return num;
++}
++
++static inline uint16_t
++aligned_read16ne(const uint8_t *buf)
++{
++ uint16_t num;
++ memcpy(&num, __builtin_assume_aligned(buf, sizeof(num)), sizeof(num));
++ return num;
++}
++
++
++static inline uint32_t
++aligned_read32ne(const uint8_t *buf)
++{
++ uint32_t num;
++ memcpy(&num, __builtin_assume_aligned(buf, sizeof(num)), sizeof(num));
++ return num;
++}
++
++static inline uint64_t
++aligned_read64ne(const uint8_t *buf)
++{
++ uint64_t num;
++ memcpy(&num, __builtin_assume_aligned(buf, sizeof(num)), sizeof(num));
++ return num;
++}
++
++typedef unsigned char lzma_bool;
++
++typedef enum {
++ LZMA_RESERVED_ENUM = 0
++} lzma_reserved_enum;
++
++typedef enum {
++ LZMA_OK = 0,
++ LZMA_STREAM_END = 1,
++ LZMA_NO_CHECK = 2,
++ LZMA_UNSUPPORTED_CHECK = 3,
++ LZMA_GET_CHECK = 4,
++ LZMA_MEM_ERROR = 5,
++ LZMA_MEMLIMIT_ERROR = 6,
++ LZMA_FORMAT_ERROR = 7,
++ LZMA_OPTIONS_ERROR = 8,
++ LZMA_DATA_ERROR = 9,
++ LZMA_BUF_ERROR = 10,
++ LZMA_PROG_ERROR = 11,
++} lzma_ret;
++
++typedef enum {
++ LZMA_RUN = 0,
++ LZMA_SYNC_FLUSH = 1,
++ LZMA_FULL_FLUSH = 2,
++ LZMA_FULL_BARRIER = 4,
++ LZMA_FINISH = 3
++} lzma_action;
++
++typedef struct {
++ void *( *alloc)(void *opaque, size_t nmemb, size_t size);
++
++ void ( *free)(void *opaque, void *ptr);
++
++ void *opaque;
++} lzma_allocator;
++
++typedef uint64_t lzma_vli;
++
++typedef enum {
++ LZMA_CHECK_NONE = 0,
++ LZMA_CHECK_CRC32 = 1,
++ LZMA_CHECK_CRC64 = 4,
++ LZMA_CHECK_SHA256 = 10
++} lzma_check;
++
++typedef struct {
++ lzma_vli id;
++ void *options;
++} lzma_filter;
++
++typedef enum {
++ LZMA_MF_HC3 = 0x03,
++ LZMA_MF_HC4 = 0x04,
++ LZMA_MF_BT2 = 0x12,
++ LZMA_MF_BT3 = 0x13,
++ LZMA_MF_BT4 = 0x14
++} lzma_match_finder;
++
++typedef struct lzma_next_coder_s lzma_next_coder;
++
++typedef struct lzma_filter_info_s lzma_filter_info;
++
++typedef lzma_ret (*lzma_init_function)(
++  lzma_next_coder *next, const lzma_allocator *allocator,
++  const lzma_filter_info *filters);
++
++typedef lzma_ret (*lzma_code_function)(
++  void *coder, const lzma_allocator *allocator,
++  const uint8_t *restrict in, size_t *restrict in_pos,
++  size_t in_size, uint8_t *restrict out,
++  size_t *restrict out_pos, size_t out_size,
++  lzma_action action);
++
++typedef void (*lzma_end_function)(
++  void *coder, const lzma_allocator *allocator);
++
++struct lzma_filter_info_s {
++ lzma_vli id;
++ lzma_init_function init;
++ void *options;
++};
++
++struct lzma_next_coder_s {
++ void *coder;
++ lzma_vli id;
++ uintptr_t init;
++
++ lzma_code_function code;
++ lzma_end_function end;
++ void (*get_progress)(void *coder,
++   uint64_t *progress_in, uint64_t *progress_out);
++
++ lzma_check (*get_check)(const void *coder);
++ lzma_ret (*memconfig)(void *coder, uint64_t *memusage,
++   uint64_t *old_memlimit, uint64_t new_memlimit);
++ lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
++   const lzma_filter *filters, const lzma_filter *reversed_filters);
++};
++
++typedef struct {
++ uint32_t len;
++ uint32_t dist;
++} lzma_match;
++
++typedef struct lzma_mf_s lzma_mf;
++struct lzma_mf_s {
++ uint8_t *buffer;
++ uint32_t size;
++ uint32_t keep_size_before;
++ uint32_t keep_size_after;
++ uint32_t offset;
++ uint32_t read_pos;
++ uint32_t read_ahead;
++ uint32_t read_limit;
++ uint32_t write_pos;
++ uint32_t pending;
++ uint32_t (*find)(lzma_mf *mf, lzma_match *matches);
++ void (*skip)(lzma_mf *mf, uint32_t num);
++ uint32_t *hash;
++ uint32_t *son;
++ uint32_t cyclic_pos;
++ uint32_t cyclic_size;
++ uint32_t hash_mask;
++ uint32_t depth;
++ uint32_t nice_len;
++ uint32_t match_len_max;
++ lzma_action action;
++ uint32_t hash_count;
++ uint32_t sons_count;
++};
++
++typedef struct {
++ size_t before_size;
++ size_t dict_size;
++ size_t after_size;
++ size_t match_len_max;
++ size_t nice_len;
++ lzma_match_finder match_finder;
++ uint32_t depth;
++ const uint8_t *preset_dict;
++ uint32_t preset_dict_size;
++} lzma_lz_options;
++
++typedef struct {
++ void *coder;
++ lzma_ret (*code)(void *coder,
++   lzma_mf *restrict mf, uint8_t *restrict out,
++   size_t *restrict out_pos, size_t out_size);
++ void (*end)(void *coder, const lzma_allocator *allocator);
++ lzma_ret (*options_update)(void *coder, const lzma_filter *filter);
++} lzma_lz_encoder;
++
++static inline const uint8_t *
++mf_ptr(const lzma_mf *mf)
++{
++ return mf->buffer + mf->read_pos;
++}
++
++static inline uint32_t
++mf_avail(const lzma_mf *mf)
++{
++ return mf->write_pos - mf->read_pos;
++}
++
++typedef struct {
++ uint32_t state[8];
++ uint64_t size;
++} lzma_sha256_state;
++
++typedef struct {
++ union {
++  uint8_t u8[64];
++  uint32_t u32[16];
++  uint64_t u64[8];
++ } buffer;
++ union {
++  uint32_t crc32;
++  uint64_t crc64;
++  lzma_sha256_state sha256;
++ } state;
++} lzma_check_state;
++
++// The table is constantly initialized in the original code.
++// Skip it in the test.
++const uint32_t lzma_crc32_table[8][256];
++
++static inline uint32_t __attribute__((__always_inline__))
++lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
++  uint32_t len, uint32_t limit)
++{
++ while (len < limit) {
++  uint32_t x = read32ne(buf1 + len) - read32ne(buf2 + len);
++  if (x != 0) {
++   if ((x & 0xFFFF) == 0) {
++    len += 2;
++    x >>= 16;
++   }
++
++   if ((x & 0xFF) == 0)
++    ++len;
++
++   return ((len) < (limit) ? (len) : (limit));
++  }
++
++  len += 4;
++ }
++
++ return limit;
++}
++
++extern uint32_t
++lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
++{
++ const uint32_t count = mf->find(mf, matches);
++ uint32_t len_best = 0;
++
++ if (count > 0) {
++  len_best = matches[count - 1].len;
++  if (len_best == mf->nice_len) {
++   uint32_t limit = mf_avail(mf) + 1;
++   if (limit > mf->match_len_max)
++    limit = mf->match_len_max;
++   const uint8_t *p1 = mf_ptr(mf) - 1;
++   const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
++   len_best = lzma_memcmplen(p1, p2, len_best, limit);
++  }
++ }
++
++ *count_ptr = count;
++ ++mf->read_ahead;
++
++ return len_best;
++}
++
++static void
++normalize(lzma_mf *mf)
++{
++ const uint32_t subvalue = ((4294967295U) - mf->cyclic_size);
++
++ for (uint32_t i = 0; i < mf->hash_count; ++i) {
++  if (mf->hash[i] <= subvalue)
++   mf->hash[i] = 0;
++  else
++   mf->hash[i] -= subvalue;
++ }
++
++ for (uint32_t i = 0; i < mf->sons_count; ++i) {
++  if (mf->son[i] <= subvalue)
++   mf->son[i] = 0;
++  else
++   mf->son[i] -= subvalue;
++ }
++
++ mf->offset -= subvalue;
++ return;
++}
++
++static void
++move_pos(lzma_mf *mf)
++{
++ if (++mf->cyclic_pos == mf->cyclic_size)
++  mf->cyclic_pos = 0;
++ ++mf->read_pos;
++ if (__builtin_expect(mf->read_pos + mf->offset == (4294967295U), 0 ))
++  normalize(mf);
++}
++
++static void
++move_pending(lzma_mf *mf)
++{
++ ++mf->read_pos;
++ ++mf->pending;
++}
++
++static lzma_match *
++hc_find_func(
++  const uint32_t len_limit,
++  const uint32_t pos,
++  const uint8_t *const cur,
++  uint32_t cur_match,
++  uint32_t depth,
++  uint32_t *const son,
++  const uint32_t cyclic_pos,
++  const uint32_t cyclic_size,
++  lzma_match *matches,
++  uint32_t len_best)
++{
++ son[cyclic_pos] = cur_match;
++
++ while (1) {
++  const uint32_t delta = pos - cur_match;
++  if (depth-- == 0 || delta >= cyclic_size)
++   return matches;
++
++  const uint8_t *const pb = cur - delta;
++  cur_match = son[cyclic_pos - delta
++    + (delta > cyclic_pos ? cyclic_size : 0)];
++
++  if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
++   uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
++
++   if (len_best < len) {
++    len_best = len;
++    matches->len = len;
++    matches->dist = delta - 1;
++    ++matches;
++
++    if (len == len_limit)
++     return matches;
++   }
++  }
++ }
++}
++
++extern uint32_t
++lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
++{
++ uint32_t len_limit = mf_avail(mf);
++ if (mf->nice_len <= len_limit) {
++  len_limit = mf->nice_len;
++ } else if (len_limit < (3)) {
++  move_pending(mf);
++  return 0;
++ }
++ const uint8_t *cur = mf_ptr(mf);
++ const uint32_t pos = mf->read_pos + mf->offset;
++ uint32_t matches_count = 0;
++
++ const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++ const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++ const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask;
++
++ const uint32_t delta2 = pos - mf->hash[hash_2_value];
++ const uint32_t cur_match = mf->hash[((1U << 10)) + hash_value];
++
++ mf->hash[hash_2_value] = pos;
++ mf->hash[((1U << 10)) + hash_value] = pos;
++
++ uint32_t len_best = 2;
++
++ if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
++  len_best = lzma_memcmplen(cur - delta2, cur, len_best, len_limit);
++
++  matches[0].len = len_best;
++  matches[0].dist = delta2 - 1;
++  matches_count = 1;
++
++  if (len_best == len_limit) {
++   mf->son[mf->cyclic_pos] = cur_match;
++   move_pos(mf);
++   return 1;
++  }
++ }
++
++ matches_count = hc_find_func(len_limit, pos, cur, cur_match, mf->depth,
++			      mf->son, mf->cyclic_pos, mf->cyclic_size,
++			      matches + matches_count, len_best) - matches;
++ move_pos(mf);
++ return matches_count;
++}
++
++extern void
++lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
++{
++ do {
++  if (mf_avail(mf) < 3) {
++   move_pending(mf);
++   continue;
++  }
++
++  const uint8_t *cur = mf_ptr(mf);
++  const uint32_t pos = mf->read_pos + mf->offset;
++
++  const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++  const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++  const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask;
++
++  const uint32_t cur_match
++    = mf->hash[((1U << 10)) + hash_value];
++
++  mf->hash[hash_2_value] = pos;
++  mf->hash[((1U << 10)) + hash_value] = pos;
++
++  do { mf->son[mf->cyclic_pos] = cur_match; move_pos(mf); } while (0);
++
++ } while (--amount != 0);
++}
++
++extern uint32_t
++lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
++{
++ uint32_t len_limit = mf_avail(mf);
++ if (mf->nice_len <= len_limit) {
++  len_limit = mf->nice_len;
++ } else if (len_limit < (4)) {
++  move_pending(mf);
++  return 0;
++ }
++ const uint8_t *cur = mf_ptr(mf);
++ const uint32_t pos = mf->read_pos + mf->offset;
++ uint32_t matches_count = 0;
++
++ const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++ const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++ const uint32_t hash_3_value = (temp ^ ((uint32_t)(cur[2]) << 8))
++				& ((1U << 16) - 1);
++ const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)
++				      ^ (lzma_crc32_table[0][cur[3]] << 5))
++			      & mf->hash_mask;
++ uint32_t delta2 = pos - mf->hash[hash_2_value];
++ const uint32_t delta3
++   = pos - mf->hash[((1U << 10)) + hash_3_value];
++ const uint32_t cur_match = mf->hash[((1U << 10) + (1U << 16)) + hash_value];
++
++ mf->hash[hash_2_value ] = pos;
++ mf->hash[((1U << 10)) + hash_3_value] = pos;
++ mf->hash[((1U << 10) + (1U << 16)) + hash_value] = pos;
++
++ uint32_t len_best = 1;
++
++ if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
++  len_best = 2;
++  matches[0].len = 2;
++  matches[0].dist = delta2 - 1;
++  matches_count = 1;
++ }
++
++ if (delta2 != delta3 && delta3 < mf->cyclic_size
++   && *(cur - delta3) == *cur) {
++  len_best = 3;
++  matches[matches_count++].dist = delta3 - 1;
++  delta2 = delta3;
++ }
++
++ if (matches_count != 0) {
++  len_best = lzma_memcmplen(cur - delta2, cur,
++    len_best, len_limit);
++
++  matches[matches_count - 1].len = len_best;
++
++  if (len_best == len_limit) {
++   mf->son[mf->cyclic_pos] = cur_match; move_pos(mf);
++   return matches_count;
++  }
++ }
++
++ if (len_best < 3)
++  len_best = 3;
++
++ matches_count = hc_find_func(len_limit, pos, cur, cur_match, mf->depth,
++			      mf->son, mf->cyclic_pos, mf->cyclic_size,
++			      matches + matches_count, len_best) - matches;
++ move_pos(mf);
++ return matches_count;
++}
++
++extern void
++lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
++{
++ do {
++  if (mf_avail(mf) < 4) {
++   move_pending(mf);
++   continue;
++  }
++
++  const uint8_t *cur = mf_ptr(mf);
++  const uint32_t pos = mf->read_pos + mf->offset;
++
++  const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++  const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++  const uint32_t hash_3_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & ((1U << 16) - 1);
++  const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)
++				       ^ (lzma_crc32_table[0][cur[3]] << 5))
++			       & mf->hash_mask;
++
++  const uint32_t cur_match
++    = mf->hash[((1U << 10) + (1U << 16)) + hash_value];
++
++  mf->hash[hash_2_value] = pos;
++  mf->hash[((1U << 10)) + hash_3_value] = pos;
++  mf->hash[((1U << 10) + (1U << 16)) + hash_value] = pos;
++
++  mf->son[mf->cyclic_pos] = cur_match;
++  move_pos(mf);
++ } while (--amount != 0);
++}
++
++static lzma_match *
++bt_find_func(
++  const uint32_t len_limit,
++  const uint32_t pos,
++  const uint8_t *const cur,
++  uint32_t cur_match,
++  uint32_t depth,
++  uint32_t *const son,
++  const uint32_t cyclic_pos,
++  const uint32_t cyclic_size,
++  lzma_match *matches,
++  uint32_t len_best)
++{
++ uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
++ uint32_t *ptr1 = son + (cyclic_pos << 1);
++
++ uint32_t len0 = 0;
++ uint32_t len1 = 0;
++
++ while (1) {
++  const uint32_t delta = pos - cur_match;
++  if (depth-- == 0 || delta >= cyclic_size) {
++   *ptr0 = 0;
++   *ptr1 = 0;
++   return matches;
++  }
++
++  uint32_t *const pair = son + ((cyclic_pos - delta
++    + (delta > cyclic_pos ? cyclic_size : 0))
++    << 1);
++
++  const uint8_t *const pb = cur - delta;
++  uint32_t len = ((len0) < (len1) ? (len0) : (len1));
++
++  if (pb[len] == cur[len]) {
++   len = lzma_memcmplen(pb, cur, len + 1, len_limit);
++
++   if (len_best < len) {
++    len_best = len;
++    matches->len = len;
++    matches->dist = delta - 1;
++    ++matches;
++
++    if (len == len_limit) {
++     *ptr1 = pair[0];
++     *ptr0 = pair[1];
++     return matches;
++    }
++   }
++  }
++
++  if (pb[len] < cur[len]) {
++   *ptr1 = cur_match;
++   ptr1 = pair + 1;
++   cur_match = *ptr1;
++   len1 = len;
++  } else {
++   *ptr0 = cur_match;
++   ptr0 = pair;
++   cur_match = *ptr0;
++   len0 = len;
++  }
++ }
++}
++
++
++static void
++bt_skip_func(
++  const uint32_t len_limit,
++  const uint32_t pos,
++  const uint8_t *const cur,
++  uint32_t cur_match,
++  uint32_t depth,
++  uint32_t *const son,
++  const uint32_t cyclic_pos,
++  const uint32_t cyclic_size)
++{
++ uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
++ uint32_t *ptr1 = son + (cyclic_pos << 1);
++
++ uint32_t len0 = 0;
++ uint32_t len1 = 0;
++
++ while (1) {
++  const uint32_t delta = pos - cur_match;
++  if (depth-- == 0 || delta >= cyclic_size) {
++   *ptr0 = 0;
++   *ptr1 = 0;
++   return;
++  }
++
++  uint32_t *pair = son + ((cyclic_pos - delta
++    + (delta > cyclic_pos ? cyclic_size : 0))
++    << 1);
++  const uint8_t *pb = cur - delta;
++  uint32_t len = ((len0) < (len1) ? (len0) : (len1));
++
++  if (pb[len] == cur[len]) {
++   len = lzma_memcmplen(pb, cur, len + 1, len_limit);
++
++   if (len == len_limit) {
++    *ptr1 = pair[0];
++    *ptr0 = pair[1];
++    return;
++   }
++  }
++
++  if (pb[len] < cur[len]) {
++   *ptr1 = cur_match;
++   ptr1 = pair + 1;
++   cur_match = *ptr1;
++   len1 = len;
++  } else {
++   *ptr0 = cur_match;
++   ptr0 = pair;
++   cur_match = *ptr0;
++   len0 = len;
++  }
++ }
++}
++
++extern uint32_t
++lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
++{
++ uint32_t len_limit = mf_avail(mf);
++ if (mf->nice_len <= len_limit) {
++  len_limit = mf->nice_len;
++ } else if (len_limit < (2) || (mf->action == LZMA_SYNC_FLUSH)) {
++  move_pending(mf);
++  return 0;
++ }
++ const uint8_t *cur = mf_ptr(mf);
++ const uint32_t pos = mf->read_pos + mf->offset;
++ uint32_t matches_count = 0;
++ const uint32_t hash_value = read16ne(cur);
++ const uint32_t cur_match = mf->hash[hash_value];
++ mf->hash[hash_value] = pos;
++
++ matches_count = bt_find_func(len_limit, pos, cur, cur_match, mf->depth,
++                              mf->son, mf->cyclic_pos, mf->cyclic_size,
++                              matches + matches_count, 1) - matches;
++ move_pos(mf);
++ return matches_count;
++}
++
++extern void
++lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
++{
++ do {
++  uint32_t len_limit = mf_avail(mf);
++  if (mf->nice_len <= len_limit) {
++   len_limit = mf->nice_len;
++  } else if (len_limit < (2) || (mf->action == LZMA_SYNC_FLUSH)) { 
++   move_pending(mf);
++   continue;
++  }
++  const uint8_t *cur = mf_ptr(mf);
++  const uint32_t pos = mf->read_pos + mf->offset;
++
++  const uint32_t hash_value = read16ne(cur);
++  const uint32_t cur_match = mf->hash[hash_value];
++  mf->hash[hash_value] = pos;
++
++  bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, mf->son,
++	       mf->cyclic_pos, mf->cyclic_size);
++  move_pos(mf);
++ } while (--amount != 0);
++}
++
++extern uint32_t
++lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
++{
++ uint32_t len_limit = mf_avail(mf);
++ if (mf->nice_len <= len_limit) {
++  len_limit = mf->nice_len;
++ } else if (len_limit < (3) || (1 && mf->action == LZMA_SYNC_FLUSH)) { 
++  move_pending(mf);
++  return 0;
++ }
++ const uint8_t *cur = mf_ptr(mf);
++ const uint32_t pos = mf->read_pos + mf->offset;
++ uint32_t matches_count = 0;
++
++ const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++ const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++ const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask;
++
++ const uint32_t delta2 = pos - mf->hash[hash_2_value];
++ const uint32_t cur_match = mf->hash[((1U << 10)) + hash_value];
++
++ mf->hash[hash_2_value] = pos;
++ mf->hash[((1U << 10)) + hash_value] = pos;
++
++ uint32_t len_best = 2;
++
++ if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
++  len_best = lzma_memcmplen(
++    cur, cur - delta2, len_best, len_limit);
++
++  matches[0].len = len_best;
++  matches[0].dist = delta2 - 1;
++  matches_count = 1;
++
++  if (len_best == len_limit) {
++   bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, mf->son,
++		mf->cyclic_pos, mf->cyclic_size);
++   move_pos(mf);
++   return 1;
++  }
++ }
++
++ matches_count = bt_find_func(len_limit, pos, cur, cur_match, mf->depth,
++			      mf->son, mf->cyclic_pos, mf->cyclic_size,
++			      matches + matches_count, len_best) - matches;
++ move_pos(mf);
++ return matches_count;
++}
++
++
++extern void
++lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
++{
++ do {
++  uint32_t len_limit = mf_avail(mf);
++  if (mf->nice_len <= len_limit) {
++    len_limit = mf->nice_len; }
++  else if (len_limit < (3) || (1 && mf->action == LZMA_SYNC_FLUSH)) { 
++    move_pending(mf);
++    continue;
++  }
++  const uint8_t *cur = mf_ptr(mf);
++  const uint32_t pos = mf->read_pos + mf->offset;
++
++  const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++  const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++  const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask;
++
++  const uint32_t cur_match = mf->hash[((1U << 10)) + hash_value];
++
++  mf->hash[hash_2_value] = pos;
++  mf->hash[((1U << 10)) + hash_value] = pos;
++
++  bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, mf->son,
++	       mf->cyclic_pos, mf->cyclic_size); 
++  move_pos(mf);
++ } while (--amount != 0);
++}
++
++extern uint32_t
++lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
++{
++ uint32_t len_limit = mf->write_pos - mf->read_pos;
++ if (mf->nice_len <= len_limit) {
++  len_limit = mf->nice_len;
++ } else if (len_limit < (4) || (mf->action == LZMA_SYNC_FLUSH)) {
++  ++mf->read_pos;
++  ++mf->pending;
++  return 0;
++ }
++
++ const uint8_t *cur = mf->buffer + mf->read_pos;
++ const uint32_t pos = mf->read_pos + mf->offset;
++ uint32_t matches_count = 0;
++
++ const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++ const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++ const uint32_t hash_3_value = (temp ^ ((uint32_t)(cur[2]) << 8)) & ((1U << 16) - 1);
++ const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)
++				      ^ (lzma_crc32_table[0][cur[3]] << 5))
++			      & mf->hash_mask;
++
++ uint32_t delta2 = pos - mf->hash[hash_2_value];
++ const uint32_t delta3 = pos - mf->hash[((1U << 10)) + hash_3_value];
++ const uint32_t cur_match = mf->hash[((1U << 10) + (1U << 16)) + hash_value];
++
++ mf->hash[hash_2_value] = pos;
++ mf->hash[((1U << 10)) + hash_3_value] = pos;
++ mf->hash[((1U << 10) + (1U << 16)) + hash_value] = pos;
++
++ uint32_t len_best = 1;
++
++ if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
++  len_best = 2;
++  matches[0].len = 2;
++  matches[0].dist = delta2 - 1;
++  matches_count = 1;
++ }
++
++ if (delta2 != delta3 && delta3 < mf->cyclic_size && *(cur - delta3) == *cur) {
++  len_best = 3;
++  matches[matches_count++].dist = delta3 - 1;
++  delta2 = delta3;
++ }
++
++ if (matches_count != 0) {
++  len_best = lzma_memcmplen(cur, cur - delta2, len_best, len_limit);
++
++  matches[matches_count - 1].len = len_best;
++
++  if (len_best == len_limit) {
++    bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, mf->son,
++		 mf->cyclic_pos, mf->cyclic_size);
++    move_pos(mf);
++    return matches_count;
++  }
++ }
++
++ if (len_best < 3)
++  len_best = 3;
++
++ matches_count = bt_find_func(len_limit, pos, cur, cur_match, mf->depth, mf->son,
++                              mf->cyclic_pos, mf->cyclic_size,
++                              matches + matches_count, len_best) - matches;
++ move_pos(mf);
++ return matches_count;
++}
++
++extern void
++lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
++{
++ do {
++  uint32_t len_limit = mf_avail(mf);
++  if (mf->nice_len <= len_limit) {
++   len_limit = mf->nice_len;
++  } else if (len_limit < (4) || (mf->action == LZMA_SYNC_FLUSH)) {
++   move_pending(mf);
++   continue;
++  }
++
++  const uint8_t *cur = mf->buffer + mf->read_pos;
++  const uint32_t pos = mf->read_pos + mf->offset;
++
++  const uint32_t temp = lzma_crc32_table[0][cur[0]] ^ cur[1];
++  const uint32_t hash_2_value = temp & ((1U << 10) - 1);
++  const uint32_t hash_3_value = (temp ^ ((uint32_t)(cur[2]) << 8))
++				& ((1U << 16) - 1);
++  const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8)
++				       ^ (lzma_crc32_table[0][cur[3]] << 5))
++			       & mf->hash_mask;
++
++  const uint32_t cur_match = mf->hash[((1U << 10) + (1U << 16)) + hash_value];
++
++  mf->hash[hash_2_value] = pos;
++  mf->hash[((1U << 10)) + hash_3_value] = pos;
++  mf->hash[((1U << 10) + (1U << 16)) + hash_value] = pos;
++
++  bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, mf->son,
++	       mf->cyclic_pos, mf->cyclic_size);
++  move_pos(mf);
++ } while (--amount != 0);
++}
++
++static inline void
++mf_skip(lzma_mf *mf, uint32_t amount)
++{
++ if (amount != 0) {
++  mf->skip(mf, amount);
++  mf->read_ahead += amount;
++ }
++}
++
++typedef struct lzma_lzma1_encoder_s lzma_lzma1_encoder;
++typedef uint16_t probability;
++
++typedef struct {
++ probability choice;
++ probability choice2;
++ probability low[(1 << 4)][(1 << 3)];
++ probability mid[(1 << 4)][(1 << 3)];
++ probability high[(1 << 8)];
++ uint32_t prices[(1 << 4)][((1 << 3) + (1 << 3) + (1 << 8))];
++ uint32_t table_size;
++ uint32_t counters[(1 << 4)];
++} lzma_length_encoder;
++
++typedef struct {
++ uint64_t low;
++ uint64_t cache_size;
++ uint32_t range;
++ uint8_t cache;
++ size_t count;
++ size_t pos;
++
++ enum {
++  RC_BIT_0,
++  RC_BIT_1,
++  RC_DIRECT_0,
++  RC_DIRECT_1,
++  RC_FLUSH,
++ } symbols[58];
++
++ probability *probs[58];
++} lzma_range_encoder;
++
++
++typedef enum {
++ STATE_LIT_LIT,
++ STATE_MATCH_LIT_LIT,
++ STATE_REP_LIT_LIT,
++ STATE_SHORTREP_LIT_LIT,
++ STATE_MATCH_LIT,
++ STATE_REP_LIT,
++ STATE_SHORTREP_LIT,
++ STATE_LIT_MATCH,
++ STATE_LIT_LONGREP,
++ STATE_LIT_SHORTREP,
++ STATE_NONLIT_MATCH,
++ STATE_NONLIT_REP,
++} lzma_lzma_state;
++
++typedef struct {
++ lzma_lzma_state state;
++ _Bool prev_1_is_literal;
++ _Bool prev_2;
++
++ uint32_t pos_prev_2;
++ uint32_t back_prev_2;
++
++ uint32_t price;
++ uint32_t pos_prev;
++ uint32_t back_prev;
++
++ uint32_t backs[4];
++} lzma_optimal;
++
++struct lzma_lzma1_encoder_s {
++ lzma_range_encoder rc;
++ lzma_lzma_state state;
++ uint32_t reps[4];
++ lzma_match matches[(2 + ((1 << 3) + (1 << 3) + (1 << 8)) - 1) + 1];
++ uint32_t matches_count;
++ uint32_t longest_match_length;
++ _Bool fast_mode;
++ _Bool is_initialized;
++ _Bool is_flushed;
++ uint32_t pos_mask;
++ uint32_t literal_context_bits;
++ uint32_t literal_pos_mask;
++
++ probability literal[(1 << 4)][0x300];
++ probability is_match[12][(1 << 4)];
++ probability is_rep[12];
++ probability is_rep0[12];
++ probability is_rep1[12];
++ probability is_rep2[12];
++ probability is_rep0_long[12][(1 << 4)];
++ probability dist_slot[4][(1 << 6)];
++ probability dist_special[(1 << (14 / 2)) - 14];
++ probability dist_align[(1 << 4)];
++
++ lzma_length_encoder match_len_encoder;
++ lzma_length_encoder rep_len_encoder;
++
++ uint32_t dist_slot_prices[4][(1 << 6)];
++ uint32_t dist_prices[4][(1 << (14 / 2))];
++ uint32_t dist_table_size;
++ uint32_t match_price_count;
++
++ uint32_t align_prices[(1 << 4)];
++ uint32_t align_price_count;
++ uint32_t opts_end_index;
++ uint32_t opts_current_index;
++ lzma_optimal opts[(1 << 12)];
++};
++
++extern void
++lzma_lzma_optimum_fast(lzma_lzma1_encoder *restrict coder,
++  lzma_mf *restrict mf,
++  uint32_t *restrict back_res, uint32_t *restrict len_res)
++{
++ const uint32_t nice_len = mf->nice_len;
++
++ uint32_t len_main;
++ uint32_t matches_count;
++ if (mf->read_ahead == 0) {
++  len_main = lzma_mf_find(mf, &matches_count, coder->matches);
++ } else {
++  len_main = coder->longest_match_length;
++  matches_count = coder->matches_count;
++ }
++
++ const uint8_t *buf = mf_ptr(mf) - 1;
++ const uint32_t buf_avail
++   = ((mf_avail(mf) + 1) < ((2 + ((1 << 3) + (1 << 3) + (1 << 8)) - 1))
++      ? (mf_avail(mf) + 1) : ((2 + ((1 << 3) + (1 << 3) + (1 << 8)) - 1)));
++
++ if (buf_avail < 2) {
++  *back_res = (4294967295U);
++  *len_res = 1;
++  return;
++ }
++
++ uint32_t rep_len = 0;
++ uint32_t rep_index = 0;
++
++ for (uint32_t i = 0; i < 4; ++i) {
++  const uint8_t *const buf_back = buf - coder->reps[i] - 1;
++  if ((read16ne(buf) != read16ne(buf_back)))
++   continue;
++  const uint32_t len = lzma_memcmplen(buf, buf_back, 2, buf_avail);
++  if (len >= nice_len) {
++   *back_res = i;
++   *len_res = len;
++   mf_skip(mf, len - 1);
++   return;
++  }
++  if (len > rep_len) {
++   rep_index = i;
++   rep_len = len;
++  }
++ }
++ if (len_main >= nice_len) {
++  *back_res = coder->matches[matches_count - 1].dist + 4;
++  *len_res = len_main;
++  mf_skip(mf, len_main - 1);
++  return;
++ }
++
++ uint32_t back_main = 0;
++ if (len_main >= 2) {
++  back_main = coder->matches[matches_count - 1].dist;
++  while (matches_count > 1 && len_main ==
++    coder->matches[matches_count - 2].len + 1) {
++   if (!(((back_main) >> 7) > (coder->matches[ matches_count - 2].dist)))
++    break;
++   --matches_count;
++   len_main = coder->matches[matches_count - 1].len;
++   back_main = coder->matches[matches_count - 1].dist;
++  }
++  if (len_main == 2 && back_main >= 0x80)
++   len_main = 1;
++ }
++
++ if (rep_len >= 2) {
++  if (rep_len + 1 >= len_main
++    || (rep_len + 2 >= len_main
++     && back_main > (1U << 9))
++    || (rep_len + 3 >= len_main
++     && back_main > (1U << 15))) {
++   *back_res = rep_index;
++   *len_res = rep_len;
++   mf_skip(mf, rep_len - 1);
++   return;
++  }
++ }
++
++ if (len_main < 2 || buf_avail <= 2) {
++  *back_res = (4294967295U);
++  *len_res = 1;
++  return;
++ }
++
++ coder->longest_match_length = lzma_mf_find(mf,
++   &coder->matches_count, coder->matches);
++
++ if (coder->longest_match_length >= 2) {
++  const uint32_t new_dist = coder->matches[
++    coder->matches_count - 1].dist;
++
++  if ((coder->longest_match_length >= len_main
++     && new_dist < back_main)
++    || (coder->longest_match_length == len_main + 1
++     && !(((new_dist) >> 7) > (back_main)))
++    || (coder->longest_match_length > len_main + 1)
++    || (coder->longest_match_length + 1 >= len_main
++     && len_main >= 3
++     && (((back_main) >> 7) > (new_dist)))) {
++   *back_res = (4294967295U);
++   *len_res = 1;
++   return;
++  }
++ }
++ ++buf;
++ const uint32_t limit = ((2) > (len_main - 1) ? (2) : (len_main - 1));
++ for (uint32_t i = 0; i < 4; ++i) {
++  if (memcmp(buf, buf - coder->reps[i] - 1, limit) == 0) {
++   *back_res = (4294967295U);
++   *len_res = 1;
++   return;
++  }
++ }
++
++ *back_res = back_main + 4;
++ *len_res = len_main;
++ mf_skip(mf, len_main - 2);
++ return;
++}
++
++static inline void
++rc_bit(lzma_range_encoder *rc, probability *prob, uint32_t bit)
++{
++ rc->symbols[rc->count] = bit;
++ rc->probs[rc->count] = prob;
++ ++rc->count;
++}
++
++static inline void
++rc_bittree(lzma_range_encoder *rc, probability *probs,
++  uint32_t bit_count, uint32_t symbol)
++{
++ uint32_t model_index = 1;
++
++ do {
++  const uint32_t bit = (symbol >> --bit_count) & 1;
++  rc_bit(rc, &probs[model_index], bit);
++  model_index = (model_index << 1) + bit;
++ } while (bit_count != 0);
++}
++
++static _Bool
++encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf)
++{
++ if (mf->read_pos == mf->read_limit) {
++  if (mf->action == LZMA_RUN)
++   return 0;
++ } else {
++  mf_skip(mf, 1);
++  mf->read_ahead = 0;
++  rc_bit(&coder->rc, &coder->is_match[0][0], 0);
++  rc_bittree(&coder->rc, coder->literal[0], 8, mf->buffer[0]);
++ }
++
++ coder->is_initialized = 1;
++
++ return 1;
++}
++
++static inline uint32_t
++mf_position(const lzma_mf *mf)
++{
++ return mf->read_pos - mf->read_ahead;
++}
++
++static inline _Bool
++rc_shift_low(lzma_range_encoder *rc,
++  uint8_t *out, size_t *out_pos, size_t out_size)
++{
++ if ((uint32_t)(rc->low) < (uint32_t)(0xFF000000)
++   || (uint32_t)(rc->low >> 32) != 0) {
++  do {
++   if (*out_pos == out_size)
++    return 1;
++
++   out[*out_pos] = rc->cache + (uint8_t)(rc->low >> 32);
++   ++*out_pos;
++   rc->cache = 0xFF;
++  } while (--rc->cache_size != 0);
++  rc->cache = (rc->low >> 24) & 0xFF;
++ }
++
++ ++rc->cache_size;
++ rc->low = (rc->low & 0x00FFFFFF) << 8;
++ return 0;
++}
++
++static inline void
++rc_reset(lzma_range_encoder *rc)
++{
++ rc->low = 0;
++ rc->cache_size = 1;
++ rc->range = (4294967295U);
++ rc->cache = 0;
++ rc->count = 0;
++ rc->pos = 0;
++}
++
++static inline _Bool
++rc_encode(lzma_range_encoder *rc,
++  uint8_t *out, size_t *out_pos, size_t out_size)
++{
++ while (rc->pos < rc->count) {
++  if (rc->range < (1U << 24)) {
++   if (rc_shift_low(rc, out, out_pos, out_size))
++    return 1;
++   rc->range <<= 8;
++  }
++
++  switch (rc->symbols[rc->pos]) {
++  case RC_BIT_0: {
++   probability prob = *rc->probs[rc->pos];
++   rc->range = (rc->range >> 11)
++     * prob;
++   prob += ((1U << 11) - prob) >> 5;
++   *rc->probs[rc->pos] = prob;
++   break;
++  }
++
++  case RC_BIT_1: {
++   probability prob = *rc->probs[rc->pos];
++   const uint32_t bound = prob * (rc->range
++     >> 11);
++   rc->low += bound;
++   rc->range -= bound;
++   prob -= prob >> 5;
++   *rc->probs[rc->pos] = prob;
++   break;
++  }
++
++  case RC_DIRECT_0:
++   rc->range >>= 1;
++   break;
++
++  case RC_DIRECT_1:
++   rc->range >>= 1;
++   rc->low += rc->range;
++   break;
++
++  case RC_FLUSH:
++   rc->range = (4294967295U);
++   do {
++    if (rc_shift_low(rc, out, out_pos, out_size))
++     return 1;
++   } while (++rc->pos < rc->count);
++
++   rc_reset(rc);
++   return 0;
++
++  default:
++   break;
++  }
++  ++rc->pos;
++ }
++
++ rc->count = 0;
++ rc->pos = 0;
++ return 0;
++}
++
++static inline uint64_t
++rc_pending(const lzma_range_encoder *rc)
++{
++ return rc->cache_size + 5 - 1;
++}
++
++static inline void
++literal_matched(lzma_range_encoder *rc, probability *subcoder,
++  uint32_t match_byte, uint32_t symbol)
++{
++ uint32_t offset = 0x100;
++ symbol += 1U << 8;
++
++ do {
++  match_byte <<= 1;
++  const uint32_t match_bit = match_byte & offset;
++  const uint32_t subcoder_index
++    = offset + match_bit + (symbol >> 8);
++  const uint32_t bit = (symbol >> 7) & 1;
++  rc_bit(rc, &subcoder[subcoder_index], bit);
++
++  symbol <<= 1;
++  offset &= ~(match_byte ^ symbol);
++
++ } while (symbol < (1U << 16));
++}
++
++static inline void
++literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position)
++{
++ const uint8_t cur_byte = mf->buffer[mf->read_pos - mf->read_ahead];
++ probability *subcoder  = ((coder->literal)[
++   (((position) & (coder->literal_pos_mask))
++    << (coder->literal_context_bits))
++   + ((uint32_t)(mf->buffer[mf->read_pos - mf->read_ahead - 1])
++   >> (8U - (coder->literal_context_bits)))]);
++
++ if (((coder->state) < 7)) {
++  rc_bittree(&coder->rc, subcoder, 8, cur_byte);
++ } else {
++  const uint8_t match_byte
++    = mf->buffer[mf->read_pos - coder->reps[0] - 1 - mf->read_ahead];
++  literal_matched(&coder->rc, subcoder, match_byte, cur_byte);
++ }
++ coder->state
++   = ((coder->state) <= STATE_SHORTREP_LIT_LIT
++      ? STATE_LIT_LIT : ((coder->state) <= STATE_LIT_SHORTREP
++			 ? (coder->state) - 3 : (coder->state) - 6));
++}
++
++const uint8_t lzma_rc_prices[] = {
++         128, 103,  91,  84,  78,  73,  69,  66,
++          63,  61,  58,  56,  54,  52,  51,  49,
++          48,  46,  45,  44,  43,  42,  41,  40,
++          39,  38,  37,  36,  35,  34,  34,  33,
++          32,  31,  31,  30,  29,  29,  28,  28,
++          27,  26,  26,  25,  25,  24,  24,  23,
++          23,  22,  22,  22,  21,  21,  20,  20,
++          19,  19,  19,  18,  18,  17,  17,  17,
++          16,  16,  16,  15,  15,  15,  14,  14,
++          14,  13,  13,  13,  12,  12,  12,  11,
++          11,  11,  11,  10,  10,  10,  10,   9,
++           9,   9,   9,   8,   8,   8,   8,   7,
++           7,   7,   7,   6,   6,   6,   6,   5,
++           5,   5,   5,   5,   4,   4,   4,   4,
++           3,   3,   3,   3,   3,   2,   2,   2,
++           2,   2,   2,   1,   1,   1,   1,   1
++};
++
++static inline uint32_t
++rc_bit_price(const probability prob, const uint32_t bit)
++{
++ return lzma_rc_prices[(prob ^ ((0U - bit)
++   & ((1U << 11) - 1))) >> 4];
++}
++
++static inline uint32_t
++rc_bit_0_price(const probability prob)
++{
++ return lzma_rc_prices[prob >> 4];
++}
++
++static inline uint32_t
++rc_bit_1_price(const probability prob)
++{
++ return lzma_rc_prices[(prob ^ ((1U << 11) - 1))
++   >> 4];
++}
++
++static inline uint32_t
++rc_bittree_price(const probability *const probs,
++  const uint32_t bit_levels, uint32_t symbol)
++{
++ uint32_t price = 0;
++ symbol += 1U << bit_levels;
++
++ do {
++  const uint32_t bit = symbol & 1;
++  symbol >>= 1;
++  price += rc_bit_price(probs[symbol], bit);
++ } while (symbol != 1);
++
++ return price;
++}
++
++static void
++length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state)
++{
++ const uint32_t table_size = lc->table_size;
++ lc->counters[pos_state] = table_size;
++
++ const uint32_t a0 = rc_bit_0_price(lc->choice);
++ const uint32_t a1 = rc_bit_1_price(lc->choice);
++ const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2);
++ const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2);
++ uint32_t *const prices = lc->prices[pos_state];
++
++ uint32_t i;
++ for (i = 0; i < table_size && i < (1 << 3); ++i)
++  prices[i] = a0 + rc_bittree_price(lc->low[pos_state],
++    3, i);
++
++ for (; i < table_size && i < (1 << 3) + (1 << 3); ++i)
++  prices[i] = b0 + rc_bittree_price(lc->mid[pos_state],
++    3, i - (1 << 3));
++
++ for (; i < table_size; ++i)
++  prices[i] = b1 + rc_bittree_price(lc->high, 8,
++    i - (1 << 3) - (1 << 3));
++
++ return;
++}
++
++static inline void
++length(lzma_range_encoder *rc, lzma_length_encoder *lc,
++  const uint32_t pos_state, uint32_t len, const _Bool fast_mode)
++{
++ len -= 2;
++
++ if (len < (1 << 3)) {
++  rc_bit(rc, &lc->choice, 0);
++  rc_bittree(rc, lc->low[pos_state], 3, len);
++ } else {
++  rc_bit(rc, &lc->choice, 1);
++  len -= (1 << 3);
++
++  if (len < (1 << 3)) {
++   rc_bit(rc, &lc->choice2, 0);
++   rc_bittree(rc, lc->mid[pos_state], 3, len);
++  } else {
++   rc_bit(rc, &lc->choice2, 1);
++   len -= (1 << 3);
++   rc_bittree(rc, lc->high, 8, len);
++  }
++ }
++
++ if (!fast_mode)
++  if (--lc->counters[pos_state] == 0)
++   length_update_prices(lc, pos_state);
++}
++
++static inline void
++rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
++  const uint32_t rep, const uint32_t len)
++{
++ if (rep == 0) {
++  rc_bit(&coder->rc, &coder->is_rep0[coder->state], 0);
++  rc_bit(&coder->rc,
++    &coder->is_rep0_long[coder->state][pos_state],
++    len != 1);
++ } else {
++  const uint32_t distance = coder->reps[rep];
++  rc_bit(&coder->rc, &coder->is_rep0[coder->state], 1);
++
++  if (rep == 1) {
++   rc_bit(&coder->rc, &coder->is_rep1[coder->state], 0);
++  } else {
++   rc_bit(&coder->rc, &coder->is_rep1[coder->state], 1);
++   rc_bit(&coder->rc, &coder->is_rep2[coder->state],
++     rep - 2);
++
++   if (rep == 3)
++    coder->reps[3] = coder->reps[2];
++
++   coder->reps[2] = coder->reps[1];
++  }
++
++  coder->reps[1] = coder->reps[0];
++  coder->reps[0] = distance;
++ }
++
++ if (len == 1) {
++  coder->state = ((coder->state) < 7 ? STATE_LIT_SHORTREP : STATE_NONLIT_REP);
++ } else {
++  length(&coder->rc, &coder->rep_len_encoder, pos_state, len,
++    coder->fast_mode);
++  coder->state = ((coder->state) < 7 ? STATE_LIT_LONGREP : STATE_NONLIT_REP);
++ }
++}
++
++// This array is constantly initialized in the original code. It's quite big
++// so we skip it.
++const uint8_t lzma_fastpos[1 << 13];
++
++static inline uint32_t
++get_dist_slot(uint32_t dist)
++{
++ if (dist < (1U << (13 + ((0) + (0) * (13 - 1)))))
++  return lzma_fastpos[dist];
++
++ if (dist < (1U << (13 + ((0) + (1) * (13 - 1)))))
++  return (uint32_t)(lzma_fastpos[(dist) >> ((0) + (1) * (13 - 1))]) + 2 * ((0) + (1) * (13 - 1));
++
++ return (uint32_t)(lzma_fastpos[(dist) >> ((0) + (2) * (13 - 1))]) + 2 * ((0) + (2) * (13 - 1));
++}
++
++static inline void
++rc_bittree_reverse(lzma_range_encoder *rc, probability *probs,
++  uint32_t bit_count, uint32_t symbol)
++{
++ uint32_t model_index = 1;
++ do {
++  const uint32_t bit = symbol & 1;
++  symbol >>= 1;
++  rc_bit(rc, &probs[model_index], bit);
++  model_index = (model_index << 1) + bit;
++ } while (--bit_count != 0);
++}
++
++static inline void
++rc_direct(lzma_range_encoder *rc, uint32_t value, uint32_t bit_count)
++{
++ do {
++  rc->symbols[rc->count++]
++    = RC_DIRECT_0 + ((value >> --bit_count) & 1);
++ } while (bit_count != 0);
++}
++
++static inline void
++match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
++      const uint32_t distance, const uint32_t len)
++{
++ coder->state = ((coder->state) < 7 ? STATE_LIT_MATCH : STATE_NONLIT_MATCH);
++
++ length(&coder->rc, &coder->match_len_encoder, pos_state, len,
++	coder->fast_mode);
++
++ const uint32_t dist_slot = get_dist_slot(distance);
++ const uint32_t dist_state = ((len) < 4 + 2 ? (len) - 2 : 4 - 1);
++ rc_bittree(&coder->rc, coder->dist_slot[dist_state], 6, dist_slot);
++
++ if (dist_slot >= 4) {
++  const uint32_t footer_bits = (dist_slot >> 1) - 1;
++  const uint32_t base = (2 | (dist_slot & 1)) << footer_bits;
++  const uint32_t dist_reduced = distance - base;
++
++  if (dist_slot < 14) {
++   rc_bittree_reverse(&coder->rc, coder->dist_special + base - dist_slot - 1,
++		     footer_bits, dist_reduced);
++  } else {
++   rc_direct(&coder->rc, dist_reduced >> 4,
++     footer_bits - 4);
++   rc_bittree_reverse(
++     &coder->rc, coder->dist_align,
++     4, dist_reduced & ((1 << 4) - 1));
++   ++coder->align_price_count;
++  }
++ }
++
++ coder->reps[3] = coder->reps[2];
++ coder->reps[2] = coder->reps[1];
++ coder->reps[1] = coder->reps[0];
++ coder->reps[0] = distance;
++ ++coder->match_price_count;
++}
++
++static void
++encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf,
++  uint32_t back, uint32_t len, uint32_t position)
++{
++ const uint32_t pos_state = position & coder->pos_mask;
++
++ if (back == (4294967295U)) {
++  rc_bit(&coder->rc,
++    &coder->is_match[coder->state][pos_state], 0);
++  literal(coder, mf, position);
++ } else {
++  rc_bit(&coder->rc,
++   &coder->is_match[coder->state][pos_state], 1);
++
++  if (back < 4) {
++   rc_bit(&coder->rc, &coder->is_rep[coder->state], 1);
++   rep_match(coder, pos_state, back, len);
++  } else {
++   rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
++   match(coder, pos_state, back - 4, len);
++  }
++ }
++ mf->read_ahead -= len;
++}
++
++static void
++encode_eopm(lzma_lzma1_encoder *coder, uint32_t position)
++{
++ const uint32_t pos_state = position & coder->pos_mask;
++ rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1);
++ rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
++ match(coder, pos_state, (4294967295U), 2);
++}
++
++static inline void
++rc_flush(lzma_range_encoder *rc)
++{
++ for (size_t i = 0; i < 5; ++i)
++  rc->symbols[rc->count++] = RC_FLUSH;
++}
++
++extern void exit (int __status)
++ __attribute__ ((__nothrow__ , __leaf__ , __noreturn__));
++
++extern lzma_ret
++lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
++  uint8_t *restrict out, size_t *restrict out_pos,
++  size_t out_size, uint32_t limit)
++{
++
++ if (!coder->is_initialized && !encode_init(coder, mf))
++  return LZMA_OK;
++
++ uint32_t position = mf_position(mf);
++
++ while (1) {
++  if (rc_encode(&coder->rc, out, out_pos, out_size)) {
++   return LZMA_OK;
++  }
++
++  if (limit != (4294967295U)
++      && (mf->read_pos - mf->read_ahead >= limit
++	 || *out_pos + rc_pending(&coder->rc)
++	    >= (1U << 16) - ((1 << 12) + 1)))
++   break;
++
++  if (mf->read_pos >= mf->read_limit) {
++   if (mf->action == LZMA_RUN)
++    return LZMA_OK;
++
++
++   if (mf->read_ahead == 0)
++    break;
++  }
++  uint32_t len;
++  uint32_t back;
++
++  if (coder->fast_mode)
++   lzma_lzma_optimum_fast(coder, mf, &back, &len);
++  else
++   // The original code contains the  call to
++   // lzma_lzma_optimum_normal(coder, mf, &back, &len, position);
++   exit (-1);
++
++  encode_symbol(coder, mf, back, len, position);
++
++  position += len;
++ }
++
++ if (!coder->is_flushed) {
++  coder->is_flushed = 1;
++  if (limit == (4294967295U))
++   encode_eopm(coder, position);
++
++  rc_flush(&coder->rc);
++
++  if (rc_encode(&coder->rc, out, out_pos, out_size)) {
++   return LZMA_OK;
++  }
++ }
++
++ coder->is_flushed = 0;
++ return LZMA_STREAM_END;
++}
++
++extern void
++lzma_free(void *ptr, const lzma_allocator *allocator)
++{
++ if (allocator != ((void *)0) && allocator->free != ((void *)0))
++  allocator->free(allocator->opaque, ptr);
++ else
++  free(ptr);
++ return;
++}
++
++static _Bool
++lz_encoder_prepare(lzma_mf *mf, const lzma_allocator *allocator,
++  const lzma_lz_options *lz_options)
++{
++ if (lz_options->dict_size < 4096U
++   || lz_options->dict_size
++    > (1U << 30) + (1U << 29)
++   || lz_options->nice_len > lz_options->match_len_max)
++  return 1;
++
++ mf->keep_size_before = lz_options->before_size + lz_options->dict_size;
++ mf->keep_size_after = lz_options->after_size
++   + lz_options->match_len_max;
++ uint32_t reserve = lz_options->dict_size / 2;
++ if (reserve > (1U << 30))
++  reserve /= 2;
++
++ reserve += (lz_options->before_size + lz_options->match_len_max
++   + lz_options->after_size) / 2 + (1U << 19);
++
++ const uint32_t old_size = mf->size;
++ mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
++
++ if ((mf->buffer != ((void *)0)) && old_size != mf->size) {
++  lzma_free(mf->buffer, allocator);
++  mf->buffer = ((void *)0);
++ }
++
++ mf->match_len_max = lz_options->match_len_max;
++ mf->nice_len = lz_options->nice_len;
++ mf->cyclic_size = lz_options->dict_size + 1;
++
++ switch (lz_options->match_finder) {
++ case LZMA_MF_HC3:
++  mf->find = &lzma_mf_hc3_find;
++  mf->skip = &lzma_mf_hc3_skip;
++  break;
++
++ case LZMA_MF_HC4:
++  mf->find = &lzma_mf_hc4_find;
++  mf->skip = &lzma_mf_hc4_skip;
++  break;
++
++ case LZMA_MF_BT2:
++  mf->find = &lzma_mf_bt2_find;
++  mf->skip = &lzma_mf_bt2_skip;
++  break;
++
++ case LZMA_MF_BT3:
++  mf->find = &lzma_mf_bt3_find;
++  mf->skip = &lzma_mf_bt3_skip;
++  break;
++
++ case LZMA_MF_BT4:
++  mf->find = &lzma_mf_bt4_find;
++  mf->skip = &lzma_mf_bt4_skip;
++  break;
++
++ default:
++  return 1;
++ }
++
++ const uint32_t hash_bytes = lz_options->match_finder & 0x0F;
++ if (hash_bytes > mf->nice_len)
++  return 1;
++
++ const _Bool is_bt = (lz_options->match_finder & 0x10) != 0;
++ uint32_t hs;
++
++ if (hash_bytes == 2) {
++  hs = 0xFFFF;
++ } else {
++  hs = lz_options->dict_size - 1;
++  hs |= hs >> 1;
++  hs |= hs >> 2;
++  hs |= hs >> 4;
++  hs |= hs >> 8;
++  hs >>= 1;
++  hs |= 0xFFFF;
++
++  if (hs > (1U << 24)) {
++   if (hash_bytes == 3)
++    hs = (1U << 24) - 1;
++   else
++    hs >>= 1;
++  }
++ }
++
++ mf->hash_mask = hs;
++
++ ++hs;
++ if (hash_bytes > 2)
++  hs += (1U << 10);
++ if (hash_bytes > 3)
++  hs += (1U << 16);
++
++ const uint32_t old_hash_count = mf->hash_count;
++ const uint32_t old_sons_count = mf->sons_count;
++ mf->hash_count = hs;
++ mf->sons_count = mf->cyclic_size;
++ if (is_bt)
++  mf->sons_count *= 2;
++
++ if (old_hash_count != mf->hash_count
++   || old_sons_count != mf->sons_count) {
++  lzma_free(mf->hash, allocator);
++  mf->hash = ((void *)0);
++
++  lzma_free(mf->son, allocator);
++  mf->son = ((void *)0);
++ }
++
++ mf->depth = lz_options->depth;
++ if (mf->depth == 0) {
++  if (is_bt)
++   mf->depth = 16 + mf->nice_len / 2;
++  else
++   mf->depth = 4 + mf->nice_len / 4;
++ }
++
++ return 0;
++}
++
++int
++main ()
++{
++  lzma_mf mf;
++  lzma_allocator allocator;
++  lzma_lz_options lz_options;
++
++  void *coder;
++  uint8_t *restrict out;
++  size_t *restrict out_pos;
++  size_t out_size;
++
++  lz_encoder_prepare(&mf, &allocator, &lz_options);
++  return (int) lzma_lzma_encode(coder, &mf, out, out_pos, out_size, (4294967295U));
++}
++
++
++/* { dg-final { scan-wpa-ipa-dump "Save results of indirect call analysis." "icp"} } */
++/* { dg-final { scan-wpa-ipa-dump-times "For call" 2 "icp"} } */
++/* { dg-final { scan-wpa-ipa-dump-times "Insert 0 prefetch stmt:" 5 "ipa_prefetch"} } */
++/* { dg-final { scan-wpa-ipa-dump-times "Insert 1 prefetch stmt:" 4 "ipa_prefetch"} } */
++/* { dg-final { scan-wpa-ipa-dump-times "Insert 2 prefetch stmt:" 2 "ipa_prefetch"} } */
+-- 
+2.33.0
+
diff --git a/0052-Fix-fails-in-IPA-prefetch-src-openEuler-gcc-I96ID7.patch b/0052-Fix-fails-in-IPA-prefetch-src-openEuler-gcc-I96ID7.patch
new file mode 100644
index 0000000..e50c9b2
--- /dev/null
+++ b/0052-Fix-fails-in-IPA-prefetch-src-openEuler-gcc-I96ID7.patch
@@ -0,0 +1,94 @@
+From 0263daa1312d0cdcdf9c770bcf5d982a2d4fc16b Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Fri, 29 Mar 2024 17:15:41 +0800
+Subject: [PATCH 2/2] Fix fails in IPA prefetch (src-openEuler/gcc: I96ID7)
+
+---
+ gcc/ipa-prefetch.cc | 28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index 9537e4835..1ceb5137f 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -366,6 +366,7 @@ typedef std::map memref_map;
+ typedef std::map memref_tree_map;
+ 
+ typedef std::set stmt_set;
++typedef std::set tree_set;
+ typedef std::map tree_map;
+ 
+ tree_memref_map *tm_map;
+@@ -1124,8 +1125,21 @@ analyse_loops ()
+     }
+ }
+ 
++/* Compare memrefs by IDs; helper for qsort.  */
++
++static int
++memref_id_cmp (const void *p1, const void *p2)
++{
++  const memref_t *mr1 = *(const memref_t **) p1;
++  const memref_t *mr2 = *(const memref_t **) p2;
++
++  if ((unsigned) mr1->mr_id > (unsigned) mr2->mr_id)
++    return 1;
++  return -1;
++}
++
+ /* Reduce the set filtering out memrefs with the same memory references,
+-   return the result vector of memrefs.  */
++   sort and return the result vector of memrefs.  */
+ 
+ static void
+ reduce_memref_set (memref_set *set, vec &vec)
+@@ -1162,6 +1176,7 @@ reduce_memref_set (memref_set *set, vec &vec)
+ 	    vec.safe_push (mr1);
+ 	}
+     }
++  vec.qsort (memref_id_cmp);
+   if (dump_file)
+     {
+       fprintf (dump_file, "MRs (%d) after filtering: ", vec.length ());
+@@ -1663,10 +1678,15 @@ optimize_function (cgraph_node *n, function *fn)
+     }
+ 
+   /* Create other new vars.  Insert new stmts.  */
++  vec used_mr_vec = vNULL;
+   for (memref_set::const_iterator it = used_mrs.begin ();
+        it != used_mrs.end (); it++)
++    used_mr_vec.safe_push (*it);
++  used_mr_vec.qsort (memref_id_cmp);
++
++  for (unsigned int j = 0; j < used_mr_vec.length (); j++)
+     {
+-      memref_t *mr = *it;
++      memref_t *mr = used_mr_vec[j];
+       if (mr == comp_mr)
+ 	continue;
+       gimple *last_stmt = gimple_copy_and_remap_memref_stmts (mr, stmts, 0,
+@@ -1702,6 +1722,7 @@ optimize_function (cgraph_node *n, function *fn)
+       local = integer_three_node;
+       break;
+     }
++  tree_set prefetched_addrs;
+   for (unsigned int j = 0; j < vmrs.length (); j++)
+     {
+       memref_t *mr = vmrs[j];
+@@ -1714,10 +1735,13 @@ optimize_function (cgraph_node *n, function *fn)
+       tree addr = get_mem_ref_address_ssa_name (mr->mem, NULL_TREE);
+       if (decl_map->count (addr))
+ 	addr = (*decl_map)[addr];
++      if (prefetched_addrs.count (addr))
++	continue;
+       last_stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_PREFETCH),
+ 				     3, addr, write_p, local);
+       pcalls.safe_push (last_stmt);
+       gimple_seq_add_stmt (&stmts, last_stmt);
++      prefetched_addrs.insert (addr);
+       if (dump_file)
+ 	{
+ 	  fprintf (dump_file, "Insert %d prefetch stmt:\n", j);
+-- 
+2.33.0
+
diff --git a/0053-struct-reorg-Add-Semi-Relayout.patch b/0053-struct-reorg-Add-Semi-Relayout.patch
new file mode 100644
index 0000000..f687164
--- /dev/null
+++ b/0053-struct-reorg-Add-Semi-Relayout.patch
@@ -0,0 +1,1366 @@
+From c2a0dcc565e0f6274f26644bd389337db8f2940c Mon Sep 17 00:00:00 2001
+From: tiancheng-bao 
+Date: Sat, 30 Mar 2024 11:04:23 +0800
+Subject: [PATCH] [struct-reorg] Add Semi Relayout
+
+---
+ gcc/common.opt                                |   6 +-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc      | 975 +++++++++++++++++-
+ gcc/ipa-struct-reorg/ipa-struct-reorg.h       |   8 +
+ gcc/params.opt                                |   5 +
+ .../gcc.dg/struct/semi_relayout_rewrite.c     |  86 ++
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |   4 +
+ 6 files changed, 1040 insertions(+), 44 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/semi_relayout_rewrite.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 38f1e457d..9484df5ad 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2010,9 +2010,9 @@ Common Var(flag_ipa_struct_reorg) Init(0) Optimization
+ Perform structure layout optimizations.
+ 
+ fipa-struct-reorg=
+-Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 5)
+--fipa-struct-reorg=[0,1,2,3,4,5] adding none, struct-reorg, reorder-fields,
+-dfe, safe-pointer-compression, unsafe-pointer-compression optimizations.
++Common RejectNegative Joined UInteger Var(struct_layout_optimize_level) Init(0) IntegerRange(0, 6)
++-fipa-struct-reorg=[0,1,2,3,4,5,6] adding none, struct-reorg, reorder-fields,
++dfe, safe-pointer-compression, unsafe-pointer-compression, semi-relayout optimizations.
+ 
+ fipa-vrp
+ Common Var(flag_ipa_vrp) Optimization
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index 3922873f3..6a202b4bd 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -294,7 +294,8 @@ enum struct_layout_opt_level
+   STRUCT_REORDER_FIELDS = 1 << 2,
+   DEAD_FIELD_ELIMINATION = 1 << 3,
+   POINTER_COMPRESSION_SAFE = 1 << 4,
+-  POINTER_COMPRESSION_UNSAFE = 1 << 5
++  POINTER_COMPRESSION_UNSAFE = 1 << 5,
++  SEMI_RELAYOUT = 1 << 6
+ };
+ 
+ /* Defines the target pointer size of compressed pointer, which should be 8,
+@@ -308,6 +309,7 @@ void get_base (tree &base, tree expr);
+ 
+ static unsigned int current_layout_opt_level;
+ hash_map replace_type_map;
++hash_map semi_relayout_map;
+ 
+ /* Return true if one of these types is created by struct-reorg.  */
+ 
+@@ -426,7 +428,9 @@ srtype::srtype (tree type)
+     visited (false),
+     pc_candidate (false),
+     has_legal_alloc_num (false),
+-    has_alloc_array (0)
++    has_alloc_array (0),
++    semi_relayout (false),
++    bucket_parts (0)
+ {
+   for (int i = 0; i < max_split; i++)
+     newtype[i] = NULL_TREE;
+@@ -891,6 +895,66 @@ srfield::create_new_reorder_fields (tree newtype[max_split],
+   newfield[0] = field;
+ }
+ 
++/* Given a struct s whose fields has already reordered by size, we try to
++   combine fields less than 8 bytes together to 8 bytes.  Example:
++   struct s {
++     uint64_t a,
++     uint32_t b,
++     uint32_t c,
++     uint32_t d,
++     uint16_t e,
++     uint8_t f
++   }
++
++   We allocate memory for arrays of struct S, before semi-relayout, their
++   layout in memory is shown as below:
++   [a,b,c,d,e,f,padding;a,b,c,d,e,f,padding;...]
++
++   During semi-relayout, we put a number of structs into a same region called
++   bucket.  The number is determined by param realyout-bucket-capacity-level.
++   Using 1024 here as example.  After semi-relayout, the layout in a bucket is
++   shown as below:
++   part1 [a;a;a...]
++   part2 [b,c;b,c;b,c;...]
++   part3 [d,e,f,pad;d,e,f,pad;d,e,f,pad;...]
++
++   In the last bucket, if the amount of rest structs is less than the capacity
++   of a bucket, the rest of allcated memory will be wasted as padding.  */
++
++unsigned
++srtype::calculate_bucket_size ()
++{
++  unsigned parts = 0;
++  unsigned bit_sum = 0;
++  unsigned relayout_offset = 0;
++  /* Currently, limit each 8 bytes with less than 2 fields.  */
++  unsigned curr_part_num = 0;
++  unsigned field_num = 0;
++  for (tree f = TYPE_FIELDS (newtype[0]); f; f = DECL_CHAIN (f))
++    {
++      unsigned size = TYPE_PRECISION (TREE_TYPE (f));
++      bit_sum += size;
++      field_num++;
++      if (++curr_part_num > 2 || bit_sum > 64)
++	{
++	  bit_sum = size;
++	  parts++;
++	  relayout_offset = relayout_part_size * parts;
++	  curr_part_num = 1;
++	}
++      else
++	{
++	  relayout_offset = relayout_part_size * parts + (bit_sum - size) / 8;
++	}
++      new_field_offsets.put (f, relayout_offset);
++    }
++  /* Donnot relayout a struct with only one field after DFE.  */
++  if (field_num == 1)
++    return 0;
++  bucket_parts = ++parts;
++  return parts * relayout_part_size;
++}
++
+ /* Create the new TYPE corresponding to THIS type.  */
+ 
+ bool
+@@ -1001,6 +1065,15 @@ srtype::create_new_type (void)
+   if (pc_candidate && pc_gptr == NULL_TREE)
+     create_global_ptr_for_pc ();
+ 
++  if (semi_relayout)
++    {
++      bucket_size = calculate_bucket_size ();
++      if (bucket_size == 0)
++	return false;
++      if (semi_relayout_map.get (this->newtype[0]) == NULL)
++	semi_relayout_map.put (this->newtype[0], this->type);
++    }
++
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "Created %d types:\n", maxclusters);
+@@ -1393,7 +1466,7 @@ public:
+ 		       bool should_create = false, bool can_escape = false);
+   bool wholeaccess (tree expr, tree base, tree accesstype, srtype *t);
+ 
+-  void check_alloc_num (gimple *stmt, srtype *type);
++  void check_alloc_num (gimple *stmt, srtype *type, bool ptrptr);
+   void check_definition_assign (srdecl *decl, vec &worklist);
+   void check_definition_call (srdecl *decl, vec &worklist);
+   void check_definition (srdecl *decl, vec &);
+@@ -1442,6 +1515,33 @@ public:
+ 						  tree &);
+   basic_block create_bb_for_compress_nullptr (basic_block, tree &);
+   basic_block create_bb_for_decompress_nullptr (basic_block, tree, tree &);
++
++   // Semi-relayout methods:
++  bool is_semi_relayout_candidate (tree);
++  srtype *get_semi_relayout_candidate_type (tree);
++  void check_and_prune_struct_for_semi_relayout (void);
++  tree rewrite_pointer_diff (gimple_stmt_iterator *, tree, tree, srtype *);
++  tree rewrite_pointer_plus_integer (gimple *, gimple_stmt_iterator *, tree,
++				     tree, srtype *);
++  tree build_div_expr (gimple_stmt_iterator *, tree, tree);
++  tree get_true_pointer_base (gimple_stmt_iterator *, tree, srtype *);
++  tree get_real_allocated_ptr (tree, gimple_stmt_iterator *);
++  tree set_ptr_for_use (tree, gimple_stmt_iterator *);
++  void record_allocated_size (tree, gimple_stmt_iterator *, tree);
++  tree read_allocated_size (tree, gimple_stmt_iterator *);
++  gimple *create_aligned_alloc (gimple_stmt_iterator *, srtype *, tree,
++				tree &);
++  void create_memset_zero (tree, gimple_stmt_iterator *, tree);
++  void create_memcpy (tree, tree, tree, gimple_stmt_iterator *);
++  void create_free (tree, gimple_stmt_iterator *);
++  void copy_to_lhs (tree, tree, gimple_stmt_iterator *);
++  srtype *get_relayout_candidate_type (tree);
++  long unsigned int get_true_field_offset (srfield *, srtype *);
++  tree rewrite_address (tree, srfield *, srtype *, gimple_stmt_iterator *);
++  bool check_sr_copy (gimple *);
++  void relayout_field_copy (gimple_stmt_iterator *, gimple *, tree, tree,
++			    tree&, tree &);
++  bool do_semi_relayout (gimple_stmt_iterator *, gimple *, tree &, tree &);
+ };
+ 
+ struct ipa_struct_relayout
+@@ -4355,7 +4455,7 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
+ }
+ 
+ void
+-ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type)
++ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type, bool ptrptr)
+ {
+   if (current_layout_opt_level >= COMPLETE_STRUCT_RELAYOUT
+       && handled_allocation_stmt (stmt))
+@@ -4363,13 +4463,28 @@ ipa_struct_reorg::check_alloc_num (gimple *stmt, srtype *type)
+       tree arg0 = gimple_call_arg (stmt, 0);
+       basic_block bb = gimple_bb (stmt);
+       cgraph_node *node = current_function->node;
++      if (!ptrptr && current_layout_opt_level >= SEMI_RELAYOUT
++	  && gimple_call_builtin_p (stmt, BUILT_IN_MALLOC))
++	{
++	  /* Malloc is commonly used for allocations of
++	  a single struct and semi-relayout will waste
++	  a mess of memory, so we skip it.  */
++	  type->has_alloc_array = -4;
++	  return;
++	}
+       if (integer_onep (arg0))
+ 	/* Actually NOT an array, but may ruin other array.  */
+ 	type->has_alloc_array = -1;
+       else if (bb->loop_father != NULL
+ 	       && loop_outer (bb->loop_father) != NULL)
+-	/* The allocation is in a loop.  */
+-	type->has_alloc_array = -2;
++	{
++	  /* For semi-relayout, do not escape realloc.  */
++	  if (current_layout_opt_level & SEMI_RELAYOUT
++	      && gimple_call_builtin_p (stmt, BUILT_IN_REALLOC))
++	    return;
++	  /* The allocation is in a loop.  */
++	  type->has_alloc_array = -2;
++	}
+       else if (node->callers != NULL)
+ 	type->has_alloc_array = -3;
+       else
+@@ -4448,6 +4563,13 @@ ipa_struct_reorg::check_definition_assign (srdecl *decl,
+       return;
+     }
+ 
++  if (semi_relayout_map.get (type->type) != NULL)
++    {
++      if (current_layout_opt_level != COMPLETE_STRUCT_RELAYOUT)
++	type->mark_escape (escape_unhandled_rewrite, stmt);
++      return;
++    }
++
+   /* d) if the name is from a cast/assignment, make sure it is used as
+ 	that type or void*
+ 	i) If void* then push the ssa_name into worklist.  */
+@@ -4484,7 +4606,8 @@ ipa_struct_reorg::check_definition_call (srdecl *decl, vec &worklist)
+ 	type->mark_escape (escape_return, stmt);
+     }
+ 
+-  check_alloc_num (stmt, type);
++  bool ptrptr = isptrptr (decl->orig_type);
++  check_alloc_num (stmt, type, ptrptr);
+   return;
+ }
+ 
+@@ -6038,6 +6161,55 @@ ipa_struct_reorg::pc_candidate_tree_p (tree xhs)
+   return false;
+ }
+ 
++srtype *
++ipa_struct_reorg::get_semi_relayout_candidate_type (tree xhs)
++{
++  if (xhs == NULL)
++    return NULL;
++  if (TREE_CODE (xhs) == SSA_NAME || TREE_CODE (xhs) == COMPONENT_REF)
++    {
++      srtype *access_type = find_type (inner_type (TREE_TYPE (xhs)));
++      if (access_type != NULL && access_type->semi_relayout)
++	return access_type;
++    }
++  return NULL;
++}
++
++bool
++ipa_struct_reorg::is_semi_relayout_candidate (tree xhs)
++{
++  if (xhs == NULL)
++    return false;
++
++  if (TREE_CODE (xhs) == SSA_NAME)
++    xhs = TREE_TYPE (xhs);
++
++  if (TREE_CODE (xhs) == POINTER_TYPE)
++    {
++      srtype *var_type = find_type (TREE_TYPE (xhs));
++      if (!var_type || var_type->has_escaped ())
++	return false;
++      if (var_type->semi_relayout)
++	return true;
++    }
++
++  if (TREE_CODE (xhs) == COMPONENT_REF)
++    {
++      tree mem = TREE_OPERAND (xhs, 0);
++      if (TREE_CODE (mem) == MEM_REF)
++	{
++	  tree type = TREE_TYPE (mem);
++	  srtype *old_type = get_relayout_candidate_type (type);
++	  if (!old_type)
++	    return false;
++	  if (types_compatible_p (type, old_type->type)
++	      && old_type->semi_relayout)
++	    return true;
++  	}
++    }
++  return false;
++}
++
+ /* True if xhs is a component_ref that base has escaped but uses a compression
+    candidate type.  */
+ 
+@@ -6388,7 +6560,7 @@ ipa_struct_reorg::decompress_candidate_without_check (gimple_stmt_iterator *gsi,
+ 		}
+ 	    }
+ 	  /* -> _1 = t->s
+-	        _2 = _1->s
++		_2 = _1->s
+ 	     In this case, _1 might not be nullptr, so decompress it without
+ 	     check.  */
+ 	  else if (TREE_CODE (next_rhs) == COMPONENT_REF)
+@@ -6582,6 +6754,426 @@ ipa_struct_reorg::try_rewrite_with_pointer_compression (gassign *stmt,
+     }
+ }
+ 
++tree
++ipa_struct_reorg::rewrite_pointer_diff (gimple_stmt_iterator *gsi, tree ptr1,
++					tree ptr2, srtype *type)
++{
++  tree shifts = build_int_cst (long_integer_type_node, semi_relayout_align);
++  tree pointer_type = build_pointer_type (unsigned_char_type_node);
++  // tree pointer_type = build_pointer_type (long_integer_type_node);
++  tree intptr_type = signed_type_for (pointer_type);
++
++  /* addr_high_1 = (intptr_t)ptr1 >> shifts  */
++  tree ptr1_cvt = fold_convert (intptr_type, ptr1);
++  tree addr_high_1 = gimplify_build2 (gsi, RSHIFT_EXPR, intptr_type,
++				      ptr1_cvt, shifts);
++  /* addr_high_2 = (intptr_t)ptr2 >> shifts  */
++  tree ptr2_cvt = fold_convert (intptr_type, ptr2);
++  tree addr_high_2 = gimplify_build2 (gsi, RSHIFT_EXPR, intptr_type,
++				      ptr2_cvt, shifts);
++  /* off1 = (intptr_t)ptr1 - (addr_high_1 << shifts)  */
++  tree bucket_start_1 = gimplify_build2 (gsi, LSHIFT_EXPR, intptr_type,
++					 addr_high_1, shifts);
++  tree off1 = gimplify_build2 (gsi, MINUS_EXPR, intptr_type,
++			       ptr1_cvt, bucket_start_1);
++  /* off2 = (intptr_t)ptr2 - (addr_high_2 << shifts)  */
++  tree bucket_start_2 = gimplify_build2 (gsi, LSHIFT_EXPR, intptr_type,
++					 addr_high_2, shifts);
++  tree off2 = gimplify_build2 (gsi, MINUS_EXPR, intptr_type,
++			       ptr2_cvt, bucket_start_2);
++  /* group_diff = (addr_high_1 - addr_high_2) / bucket_parts  */
++  tree bucket_sub = gimplify_build2 (gsi, MINUS_EXPR, intptr_type,
++				     addr_high_1, addr_high_2);
++  tree bucket_parts = build_int_cst (intptr_type,
++				     type->bucket_parts);
++  tree group_diff = gimplify_build2 (gsi, TRUNC_DIV_EXPR,
++				     intptr_type,
++				     bucket_sub, bucket_parts);
++  /* off_addr_diff = off1 - off2  */
++  tree off_addr_diff = gimplify_build2 (gsi, MINUS_EXPR, intptr_type,
++					off1, off2);
++  /* res = group_diff * bucket_capacity + off_diff / 8  */
++  tree capacity = build_int_cst (long_integer_type_node,
++				 relayout_part_size / 8);
++  tree unit_size = build_int_cst (long_integer_type_node, 8);
++  tree bucket_index_diff = gimplify_build2 (gsi, MULT_EXPR,
++					    intptr_type,
++					    group_diff, capacity);
++  tree off_index = gimplify_build2 (gsi, TRUNC_DIV_EXPR,
++				    long_integer_type_node,
++				    off_addr_diff, unit_size);
++  tree res = gimplify_build2 (gsi, PLUS_EXPR, intptr_type,
++			      bucket_index_diff, off_index);
++  return res;
++}
++
++basic_block
++create_bb_for_group_diff_eq_0 (basic_block last_bb, tree phi, tree new_granule)
++{
++  basic_block new_bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (new_bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  /* Emit res = new_granule;  */
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  gimple *new_stmt = gimple_build_assign (phi, new_granule);
++  gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
++  return new_bb;
++}
++
++basic_block
++create_bb_for_group_diff_ne_0 (basic_block new_bb, tree &phi, tree ptr,
++			       tree group_diff, tree off_times_8, srtype *type)
++{
++  tree intptr_type = signed_type_for (long_unsigned_type_node);
++  tree shifts = build_int_cst (intptr_type, semi_relayout_align);
++  gimple_stmt_iterator gsi = gsi_last_bb (new_bb);
++  gsi_insert_after (&gsi, gimple_build_nop (), GSI_NEW_STMT);
++  tree ptr_cvt = fold_convert (intptr_type, ptr);
++  /* curr_group_start = (ptr >> shifts) << shifts;  */
++  tree ptr_r_1 = gimplify_build2 (&gsi, RSHIFT_EXPR, intptr_type,
++				  ptr_cvt, shifts);
++  tree curr_group_start = gimplify_build2 (&gsi, LSHIFT_EXPR, intptr_type,
++					   ptr_r_1, shifts);
++  /* curr_off_from_group = ptr - curr_group_start;  */
++  tree curr_off_from_group = gimplify_build2 (&gsi, MINUS_EXPR,
++					      intptr_type,
++					      ptr_cvt, curr_group_start);
++  /* res = curr_group_start + ((group_diff * parts) << shifts)
++	   + ((curr_off_from_group + off_times_8) % shifts);  */
++  tree step1 = gimplify_build2 (&gsi, MULT_EXPR, long_integer_type_node,
++				group_diff, build_int_cst (
++				long_integer_type_node, type->bucket_parts));
++  tree step1_cvt = fold_convert (intptr_type, step1);
++  tree step2 = gimplify_build2 (&gsi, LSHIFT_EXPR, intptr_type,
++				step1_cvt, shifts);
++  tree off_times_8_cvt = fold_convert (intptr_type, off_times_8);
++  tree step3 = gimplify_build2 (&gsi, PLUS_EXPR, intptr_type,
++				curr_off_from_group, off_times_8_cvt);
++  tree step4 = gimplify_build2 (&gsi, TRUNC_MOD_EXPR, intptr_type,
++				step3, build_int_cst (intptr_type,
++				relayout_part_size));
++  tree step5 = gimplify_build2 (&gsi, PLUS_EXPR, intptr_type,
++				step2, step4);
++  tree res_phi1 = gimplify_build2 (&gsi, PLUS_EXPR, long_integer_type_node,
++				   curr_group_start, step5);
++  /* if (group_diff < 0)  */
++  gcond *cond = gimple_build_cond (LT_EXPR, group_diff,
++				   build_int_cst (long_integer_type_node, 0),
++				   NULL_TREE, NULL_TREE);
++  gsi_insert_before (&gsi, cond, GSI_SAME_STMT);
++  /* remove nop  */
++  gsi_remove (&gsi, true);
++  /* res += shifts  */
++  basic_block true_bb = create_empty_bb (new_bb);
++  if (new_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (true_bb, new_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  gimple_stmt_iterator true_gsi = gsi_last_bb (true_bb);
++  tree res_phi2 = make_ssa_name (long_integer_type_node);
++  gimple *new_stmt
++		= gimple_build_assign (res_phi2, PLUS_EXPR, res_phi1,
++				       build_int_cst (long_integer_type_node,
++				       relayout_part_size));
++  gsi_insert_after (&true_gsi, new_stmt, GSI_NEW_STMT);
++  /* create phi bb  */
++  basic_block res_bb = create_empty_bb (true_bb);
++  if (new_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (res_bb, new_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  /* rebuild cfg  */
++  edge etrue = make_edge (new_bb, true_bb, EDGE_TRUE_VALUE);
++  etrue->probability = profile_probability::unlikely ();
++  true_bb->count = etrue->count ();
++
++  edge efalse = make_edge (new_bb, res_bb, EDGE_FALSE_VALUE);
++  efalse->probability = profile_probability::likely ();
++  res_bb->count = efalse->count ();
++
++  edge efall = make_single_succ_edge (true_bb, res_bb, EDGE_FALLTHRU);
++
++  phi = make_ssa_name (long_integer_type_node);
++  gphi *phi_node = create_phi_node (phi, res_bb);
++  add_phi_arg (phi_node, res_phi2, efall, UNKNOWN_LOCATION);
++  add_phi_arg (phi_node, res_phi1, efalse, UNKNOWN_LOCATION);
++
++  if (dom_info_available_p (CDI_DOMINATORS))
++    {
++      set_immediate_dominator (CDI_DOMINATORS, true_bb, new_bb);
++      set_immediate_dominator (CDI_DOMINATORS, res_bb, new_bb);
++    }
++  return res_bb;
++}
++
++tree
++ipa_struct_reorg::rewrite_pointer_plus_integer (gimple *stmt,
++						gimple_stmt_iterator *gsi,
++						tree ptr, tree offset,
++						srtype *type)
++{
++  gcc_assert (type->semi_relayout);
++  tree off = fold_convert (long_integer_type_node, offset);
++  tree num_8 = build_int_cst (long_integer_type_node, 8);
++  tree shifts = build_int_cst (long_integer_type_node, semi_relayout_align);
++  // tree shifts = build_int_cst (integer_type_node, semi_relayout_align);
++  /* off_times_8 = off * 8;  */
++  tree off_times_8 = gimplify_build2 (gsi, MULT_EXPR, long_integer_type_node,
++				      off, num_8);
++  /* new_granule = ptr + off * 8;  */
++  tree ptr_int = fold_convert (long_integer_type_node, ptr);
++  tree new_granule = gimplify_build2 (gsi, PLUS_EXPR, long_integer_type_node,
++				      ptr_int, off_times_8);
++  /* group_diff = (new_granule >> shifts) - (ptr >> shifts);  */
++  tree group_diff_rhs_1 = gimplify_build2 (gsi, RSHIFT_EXPR,
++					   long_integer_type_node,
++					   new_granule, shifts);
++  tree group_diff_rhs_2 = gimplify_build2 (gsi, RSHIFT_EXPR,
++					   long_integer_type_node,
++					   ptr_int, shifts);
++  tree group_diff = gimplify_build2 (gsi, MINUS_EXPR, long_integer_type_node,
++				     group_diff_rhs_1, group_diff_rhs_2);
++  /* if (group_diff == 0)  */
++  gcond *cond = gimple_build_cond (EQ_EXPR, group_diff,
++				   build_int_cst (long_integer_type_node, 0),
++				   NULL_TREE, NULL_TREE);
++  gimple_set_location (cond, UNKNOWN_LOCATION);
++  gsi_insert_before (gsi, cond, GSI_SAME_STMT);
++
++  edge e = split_block (cond->bb, cond);
++  basic_block split_src_bb = e->src;
++  basic_block split_dst_bb = e->dest;
++  remove_edge_raw (e);
++  /* if (group_diff == 0)
++       res = new_granule;  */
++  tree res_phi_1 = make_ssa_name (long_integer_type_node);
++  basic_block true_bb = create_bb_for_group_diff_eq_0 (split_src_bb, res_phi_1,
++						       new_granule);
++  /* else  */
++  tree res_phi_2 = NULL_TREE;
++  basic_block false_bb = create_empty_bb (split_src_bb);
++  if (split_src_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (false_bb, split_src_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++
++  edge etrue = make_edge (split_src_bb, true_bb, EDGE_TRUE_VALUE);
++  etrue->probability = profile_probability::very_likely ();
++  true_bb->count = etrue->count ();
++
++  edge efalse = make_edge (split_src_bb, false_bb, EDGE_FALSE_VALUE);
++  efalse->probability = profile_probability::unlikely ();
++  false_bb->count = efalse->count ();
++  basic_block res_bb = create_bb_for_group_diff_ne_0 (false_bb, res_phi_2,
++						      ptr_int, group_diff,
++						      off_times_8, type);
++  /* rebuild cfg  */
++  edge e_true_fall = make_single_succ_edge (true_bb, split_dst_bb,
++					    EDGE_FALLTHRU);
++  edge e_false_fall = make_single_succ_edge (res_bb, split_dst_bb,
++					     EDGE_FALLTHRU);
++  tree res_int = make_ssa_name (long_integer_type_node);
++  gphi *phi_node = create_phi_node (res_int, split_dst_bb);
++  add_phi_arg (phi_node, res_phi_1, e_true_fall, UNKNOWN_LOCATION);
++  add_phi_arg (phi_node, res_phi_2, e_false_fall, UNKNOWN_LOCATION);
++  if (dom_info_available_p (CDI_DOMINATORS))
++    {
++      set_immediate_dominator (CDI_DOMINATORS, split_dst_bb, split_src_bb);
++      set_immediate_dominator (CDI_DOMINATORS, true_bb, split_src_bb);
++      set_immediate_dominator (CDI_DOMINATORS, false_bb, split_src_bb);
++    }
++  *gsi = gsi_start_bb (split_dst_bb);
++  tree pointer_type = build_pointer_type (unsigned_char_type_node);
++  tree res = gimplify_build1 (gsi, NOP_EXPR, pointer_type, res_int);
++  return res;
++}
++
++tree
++ipa_struct_reorg::build_div_expr (gimple_stmt_iterator *gsi,
++				  tree expr, tree orig_size)
++{
++  tree div_expr = build2 (TRUNC_DIV_EXPR, long_unsigned_type_node,
++			  expr, orig_size);
++  tree num = make_ssa_name (long_unsigned_type_node);
++  gimple *g = gimple_build_assign (num, div_expr);
++  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++  return num;
++}
++
++srtype *
++ipa_struct_reorg::get_relayout_candidate_type (tree type)
++{
++  if (type == NULL)
++    return NULL;
++  if (TREE_CODE (type) != RECORD_TYPE)
++    return NULL;
++  return find_type (inner_type (type));
++}
++
++long unsigned int
++ipa_struct_reorg::get_true_field_offset (srfield *field, srtype *type)
++{
++  unsigned HOST_WIDE_INT new_offset;
++  new_offset = *(type->new_field_offsets.get (field->newfield[0]));
++  return new_offset;
++}
++
++tree
++ipa_struct_reorg::get_true_pointer_base (gimple_stmt_iterator *gsi,
++					 tree mem_ref, srtype *type)
++{
++  tree ptr = TREE_OPERAND (mem_ref, 0);
++  tree off_bytes = TREE_OPERAND (mem_ref, 1);
++  unsigned num = tree_to_shwi (off_bytes);
++  if (num == 0)
++    return ptr;
++  tree orig_size = TYPE_SIZE_UNIT (TREE_TYPE (mem_ref));
++  tree off = build_int_cst (long_integer_type_node,
++			    num / tree_to_uhwi (orig_size));
++  gimple *stmt = gsi_stmt (*gsi);
++  tree new_pointer_base = rewrite_pointer_plus_integer (stmt, gsi, ptr,
++							off, type);
++  return new_pointer_base;
++}
++
++tree
++ipa_struct_reorg::rewrite_address (tree pointer_base, srfield *field,
++				   srtype *type, gimple_stmt_iterator *gsi)
++{
++  unsigned HOST_WIDE_INT field_offset = get_true_field_offset (field, type);
++
++  tree pointer_ssa = fold_convert (long_unsigned_type_node, pointer_base);
++  tree step1 = gimplify_build1 (gsi, NOP_EXPR, long_unsigned_type_node,
++				pointer_ssa);
++  tree new_offset_ssa = build_int_cst (long_unsigned_type_node, field_offset);
++  tree step2 = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node, step1,
++				new_offset_ssa);
++  tree field_ssa = fold_convert (
++		   build_pointer_type (TREE_TYPE (field->newfield[0])), step2);
++  tree step3 = gimplify_build1 (gsi, NOP_EXPR,
++				TREE_TYPE (field_ssa), field_ssa);
++
++  tree new_mem_ref = fold_build2 (MEM_REF, TREE_TYPE (field->newfield[0]),
++				  step3, build_int_cst (
++				  TREE_TYPE (field_ssa), 0));
++  return new_mem_ref;
++}
++
++bool
++ipa_struct_reorg::check_sr_copy (gimple *stmt)
++{
++  tree lhs = gimple_assign_lhs (stmt);
++  tree rhs = gimple_assign_rhs1 (stmt);
++
++  if (TREE_CODE (lhs) != MEM_REF || TREE_CODE (rhs) != MEM_REF)
++    return false;
++  srtype *t1 = get_relayout_candidate_type (TREE_TYPE (lhs));
++  srtype *t2 = get_relayout_candidate_type (TREE_TYPE (rhs));
++  if (!t1 || !t2 || !t1->semi_relayout || !t2->semi_relayout || t1 != t2)
++    return false;
++  tree pointer1 = TREE_OPERAND (lhs, 0);
++  tree pointer2 = TREE_OPERAND (rhs, 0);
++  if (TREE_CODE (TREE_TYPE (pointer1)) != POINTER_TYPE
++      || TREE_CODE (TREE_TYPE (pointer2)) != POINTER_TYPE)
++    return false;
++
++  tree type1 = TREE_TYPE (TREE_TYPE (pointer1));
++  tree type2 = TREE_TYPE (TREE_TYPE (pointer2));
++
++  srtype *t3 = get_relayout_candidate_type (type1);
++  srtype *t4 = get_relayout_candidate_type (type2);
++
++  if (t3 != t4 || t3 != t1)
++    return false;
++
++  return true;
++}
++
++void
++ipa_struct_reorg::relayout_field_copy (gimple_stmt_iterator *gsi,
++				       gimple *stmt ATTRIBUTE_UNUSED,
++				       tree lhs, tree rhs ATTRIBUTE_UNUSED,
++				       tree &newlhs, tree &newrhs)
++{
++  srtype *type = get_relayout_candidate_type (TREE_TYPE (lhs));
++  tree lhs_base_pointer = get_true_pointer_base (gsi, newlhs, type);
++  tree rhs_base_pointer = get_true_pointer_base (gsi, newrhs, type);
++  tree new_l_mem_ref = NULL_TREE;
++  tree new_r_mem_ref = NULL_TREE;
++  srfield *field = NULL;
++  unsigned i = 0;
++  FOR_EACH_VEC_ELT (type->fields, i, field)
++    {
++      if (!field->newfield[0])
++	continue;
++      new_l_mem_ref = rewrite_address (lhs_base_pointer, field, type, gsi);
++      new_r_mem_ref = rewrite_address (rhs_base_pointer, field, type, gsi);
++      if (!is_gimple_reg (new_l_mem_ref))
++	{
++	  tree tmp_reg = create_tmp_reg (TREE_TYPE(new_l_mem_ref));
++	  gimple *copy_stmt = gimple_build_assign (tmp_reg, new_r_mem_ref);
++	  gsi_insert_before (gsi, copy_stmt, GSI_SAME_STMT);
++	  new_r_mem_ref = tmp_reg;
++	}
++      gimple *new_stmt = gimple_build_assign (new_l_mem_ref, new_r_mem_ref);
++      gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
++    }
++  gcc_assert (new_l_mem_ref != NULL_TREE && new_r_mem_ref != NULL_TREE);
++  newlhs = new_l_mem_ref;
++  newrhs = new_r_mem_ref;
++}
++
++bool
++ipa_struct_reorg::do_semi_relayout (gimple_stmt_iterator *gsi, gimple *stmt,
++				    tree &newlhs, tree &newrhs)
++{
++  tree lhs = gimple_assign_lhs (stmt);
++  tree rhs = gimple_assign_rhs1 (stmt);
++
++  bool l = TREE_CODE (lhs) == COMPONENT_REF ? is_semi_relayout_candidate (lhs)
++					    : false;
++  bool r = TREE_CODE (rhs) == COMPONENT_REF ? is_semi_relayout_candidate (rhs)
++					    : false;
++
++  gcc_assert (!(l && r));
++
++  if (!l && !r)
++    {
++      if (check_sr_copy (stmt))
++	{
++	  relayout_field_copy (gsi, stmt, lhs, rhs, newlhs, newrhs);
++	  return true;
++	}
++    }
++  else if (l)
++    {
++      srtype *type = get_relayout_candidate_type (
++				TREE_TYPE (TREE_OPERAND (lhs, 0)));
++      srfield *new_field = type->find_field (
++				int_byte_position (TREE_OPERAND (lhs, 1)));
++      tree pointer_base = get_true_pointer_base (
++				gsi, TREE_OPERAND (newlhs, 0), type);
++      newlhs = rewrite_address (pointer_base, new_field, type, gsi);
++    }
++  else if (r)
++    {
++      srtype *type = get_relayout_candidate_type (
++				TREE_TYPE (TREE_OPERAND (rhs, 0)));
++      srfield *new_field = type->find_field (
++				int_byte_position (TREE_OPERAND (rhs, 1)));
++      tree pointer_base = get_true_pointer_base (
++				gsi, TREE_OPERAND (newrhs, 0), type);
++      newrhs = rewrite_address (pointer_base, new_field, type, gsi);
++    }
++  return false;
++}
++
+ bool
+ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ {
+@@ -6677,7 +7269,8 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+       tree size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (lhs)));
+       tree num;
+       /* Check if rhs2 is a multiplication of the size of the type.  */
+-      if (!is_result_of_mult (rhs2, &num, size))
++      if (!is_result_of_mult (rhs2, &num, size)
++	  && !(current_layout_opt_level & SEMI_RELAYOUT))
+ 	internal_error (
+ 	  "The rhs of pointer is not a multiplicate and it slips through");
+ 
+@@ -6698,12 +7291,39 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	      tree newsize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (newlhs[i])));
+ 	      newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype, num,
+ 					 newsize);
++	      if (current_layout_opt_level >= SEMI_RELAYOUT)
++		{
++		  if (is_semi_relayout_candidate (lhs))
++		    {
++		      srtype *type = get_semi_relayout_candidate_type (lhs);
++		      newrhs[i] = rewrite_pointer_plus_integer (stmt, gsi,
++								newrhs[i],
++								num, type);
++		      newsize = build_int_cst (long_unsigned_type_node, 0);
++		    }
++		}
+ 	      new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR,
+ 					      newrhs[i], newsize);
+ 	    }
+ 	  else
+-	    new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR,
+-					    newrhs[i], rhs2);
++	    {
++	      /* rhs2 is not a const integer  */
++	      if (current_layout_opt_level >= SEMI_RELAYOUT)
++		{
++		  if (is_semi_relayout_candidate (lhs))
++		    {
++		      num = build_div_expr (gsi, rhs2,
++					    build_int_cst (
++					    long_unsigned_type_node, 1));
++		      srtype *type = get_semi_relayout_candidate_type (lhs);
++		      newrhs[i] = rewrite_pointer_plus_integer (stmt,
++								gsi, newrhs[i], num, type);
++		      rhs2 = build_int_cst (long_unsigned_type_node, 0);
++		    }
++		}
++	      new_stmt = gimple_build_assign (newlhs[i], POINTER_PLUS_EXPR,
++					      newrhs[i], rhs2);
++	    }
+ 	  gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
+ 	  remove = true;
+ 	}
+@@ -6744,13 +7364,34 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	return false;
+ 
+       /* The two operands always have pointer/reference type.  */
+-      for (unsigned i = 0; i < max_split && newrhs1[i] && newrhs2[i]; i++)
++      if (current_layout_opt_level >= SEMI_RELAYOUT
++	  && (is_semi_relayout_candidate (rhs1) || is_semi_relayout_candidate (rhs2)))
+ 	{
+-	  gimple_assign_set_rhs1 (stmt, newrhs1[i]);
+-	  gimple_assign_set_rhs2 (stmt, newrhs2[i]);
+-	  update_stmt (stmt);
++	  for (unsigned i = 0; i < max_split && newrhs1[i] &&newrhs2[i]; i++)
++	    {
++	      srtype *type = get_semi_relayout_candidate_type (rhs1);
++	      if (!type)
++		{
++		  type = get_semi_relayout_candidate_type (rhs2);
++		}
++	      gcc_assert (type != NULL);
++	      tree res = rewrite_pointer_diff (gsi, newrhs1[i],
++					       newrhs2[i], type);
++	      gimple *g = gimple_build_assign (gimple_assign_lhs (stmt),
++					       res);
++	      gsi_insert_before (gsi, g, GSI_SAME_STMT);
++	    }
++	  remove = true;
++	} 
++      else 
++	{
++	  for (unsigned i = 0; i < max_split && newrhs1[i] && newrhs2[i]; i++)
++	    {
++	      gimple_assign_set_rhs1 (stmt, newrhs1[i]);
++	      gimple_assign_set_rhs2 (stmt, newrhs2[i]);
++	      update_stmt (stmt);
++	    }
+ 	}
+-      remove = false;
+       return remove;
+     }
+ 
+@@ -6777,18 +7418,24 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	fprintf (dump_file, "\nreplaced with:\n");
+       for (unsigned i = 0; i < max_split && (newlhs[i] || newrhs[i]); i++)
+ 	{
++	  bool fields_copied = false;
++	  if (current_layout_opt_level & SEMI_RELAYOUT)
++	    fields_copied = do_semi_relayout (gsi, stmt, newlhs[i], newrhs[i]);
+ 	  if (current_layout_opt_level >= POINTER_COMPRESSION_SAFE)
+ 	    try_rewrite_with_pointer_compression (stmt, gsi, lhs, rhs,
+ 						  newlhs[i], newrhs[i]);
+-	  gimple *newstmt = gimple_build_assign (newlhs[i] ? newlhs[i] : lhs,
+-						 newrhs[i] ? newrhs[i] : rhs);
++	  remove = true;
++	  if (fields_copied)
++	    continue;
++	  tree lhs_expr = newlhs[i] ? newlhs[i] : lhs;
++	  tree rhs_expr = newrhs[i] ? newrhs[i] : rhs;
++	  gimple *newstmt = gimple_build_assign (lhs_expr, rhs_expr);
+ 	  if (dump_file && (dump_flags & TDF_DETAILS))
+ 	    {
+ 	      print_gimple_stmt (dump_file, newstmt, 0);
+ 	      fprintf (dump_file, "\n");
+ 	    }
+ 	  gsi_insert_before (gsi, newstmt, GSI_SAME_STMT);
+-	  remove = true;
+ 	}
+       return remove;
+     }
+@@ -6796,6 +7443,110 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+   return remove;
+ }
+ 
++tree
++ipa_struct_reorg::get_real_allocated_ptr (tree ptr, gimple_stmt_iterator *gsi)
++{
++  tree ptr_to_int = fold_convert (long_unsigned_type_node, ptr);
++  tree align = build_int_cst (long_unsigned_type_node, relayout_part_size);
++  tree real_addr = gimplify_build2 (gsi, MINUS_EXPR, long_unsigned_type_node,
++				    ptr_to_int, align);
++  tree res = gimplify_build1 (gsi, NOP_EXPR,
++			      build_pointer_type (long_unsigned_type_node),
++			      real_addr);
++  return res;
++}
++
++tree
++ipa_struct_reorg::set_ptr_for_use (tree ptr, gimple_stmt_iterator *gsi)
++{
++  tree ptr_to_int = fold_convert (long_unsigned_type_node, ptr);
++  tree align = build_int_cst (long_unsigned_type_node, relayout_part_size);
++  tree ptr_int = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node,
++				  ptr_to_int, align);
++  tree res = gimplify_build1 (gsi, NOP_EXPR,
++			      build_pointer_type (long_unsigned_type_node),
++			      ptr_int);
++  return res;
++}
++
++void
++ipa_struct_reorg::record_allocated_size (tree ptr, gimple_stmt_iterator *gsi,
++					 tree size)
++{
++  tree lhs = fold_build2 (MEM_REF, long_unsigned_type_node, ptr,
++			  build_int_cst (build_pointer_type (
++			  long_unsigned_type_node), 0));
++  gimple *stmt = gimple_build_assign (lhs, size);
++  gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
++}
++
++tree
++ipa_struct_reorg::read_allocated_size (tree ptr, gimple_stmt_iterator *gsi)
++{
++  tree to_type = build_pointer_type (long_unsigned_type_node);
++  tree off = build_int_cst (to_type, 0);
++  tree size = gimplify_build2 (gsi, MEM_REF, long_unsigned_type_node,
++			       ptr, off);
++  return size;
++}
++
++gimple *
++ipa_struct_reorg::create_aligned_alloc (gimple_stmt_iterator *gsi,
++					srtype *type, tree num, tree &size)
++{
++  tree fn = builtin_decl_implicit (BUILT_IN_ALIGNED_ALLOC);
++
++  tree align = build_int_cst (long_unsigned_type_node, relayout_part_size);
++  unsigned bucket_size = type->bucket_size;
++
++  tree nbuckets = gimplify_build2 (gsi, CEIL_DIV_EXPR, long_unsigned_type_node,
++				   num, build_int_cst (long_unsigned_type_node,
++				   relayout_part_size / 8));
++  tree use_size = gimplify_build2 (gsi, MULT_EXPR, long_unsigned_type_node,
++				   nbuckets, build_int_cst (
++				   long_unsigned_type_node, bucket_size));
++  size = gimplify_build2 (gsi, PLUS_EXPR, long_unsigned_type_node,
++			  use_size, align);
++  gimple *g = gimple_build_call (fn, 2, align, size);
++  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++  return g;
++}
++
++void
++ipa_struct_reorg::create_memset_zero (tree ptr, gimple_stmt_iterator *gsi,
++				      tree size)
++{
++  tree fn = builtin_decl_implicit (BUILT_IN_MEMSET);
++  tree val = build_int_cst (long_unsigned_type_node, 0);
++  gimple *g = gimple_build_call (fn, 3, ptr, val, size);
++  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++}
++
++void
++ipa_struct_reorg::create_memcpy (tree src, tree dst, tree size,
++				 gimple_stmt_iterator *gsi)
++{
++  tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
++  gimple *g = gimple_build_call (fn, 3, dst, src, size);
++  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++}
++
++void
++ipa_struct_reorg::create_free (tree ptr, gimple_stmt_iterator *gsi)
++{
++  tree fn = builtin_decl_implicit (BUILT_IN_FREE);
++  gimple *g = gimple_build_call (fn, 1, ptr);
++  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++}
++
++void
++ipa_struct_reorg::copy_to_lhs (tree lhs, tree new_lhs,
++			       gimple_stmt_iterator *gsi)
++{
++  gimple *g = gimple_build_assign (lhs, new_lhs);
++  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++}
++
+ /* Rewrite function call statement STMT.  Return TRUE if the statement
+    is to be removed.  */
+ 
+@@ -6837,25 +7588,74 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi)
+ 			 ? TYPE_SIZE_UNIT (decl->orig_type)
+ 			 : TYPE_SIZE_UNIT (type->newtype[i]);
+ 	  gimple *g;
+-	  /* Every allocation except for calloc needs
+-	     the size multiplied out.  */
+-	  if (!gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
+-	    newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype, num, newsize);
+-
+-	  if (gimple_call_builtin_p (stmt, BUILT_IN_MALLOC)
+-	      || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA))
+-	    g = gimple_build_call (gimple_call_fndecl (stmt),
+-				   1, newsize);
+-	  else if (gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
+-	    g = gimple_build_call (gimple_call_fndecl (stmt),
+-				   2, num, newsize);
+-	  else if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC))
+-	    g = gimple_build_call (gimple_call_fndecl (stmt),
+-				   2, newrhs1[i], newsize);
+-	  else
+-	    gcc_assert (false);
+-	  gimple_call_set_lhs (g, decl->newdecl[i]);
+-	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
++	  bool rewrite = false;
++	  if (current_layout_opt_level >= SEMI_RELAYOUT
++	      && type->semi_relayout)
++	    {
++	      if (gimple_call_builtin_p (stmt, BUILT_IN_MALLOC))
++		;
++	      else if (gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
++		{
++		  tree rhs2 = gimple_call_arg (stmt, 1);
++		  if (tree_to_uhwi (rhs2) == tree_to_uhwi (TYPE_SIZE_UNIT (type->type)))
++		    {
++		      rewrite = true;
++		      tree size = NULL_TREE;
++		      g = create_aligned_alloc (gsi, type, num, size);
++		      tree real_ptr = make_ssa_name (build_pointer_type (unsigned_char_type_node));
++		      gimple_set_lhs (g, real_ptr);
++		      create_memset_zero (real_ptr, gsi, size);
++		      record_allocated_size (real_ptr, gsi, size);
++		      tree lhs_use = set_ptr_for_use (real_ptr, gsi);
++		      copy_to_lhs (decl->newdecl[i], lhs_use, gsi);
++		    }
++		}
++	      else if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC))
++		{
++		  rewrite = true;
++		  tree size = NULL_TREE;
++		  g = create_aligned_alloc (gsi, type, num, size);
++		  tree real_ptr = make_ssa_name (build_pointer_type (unsigned_char_type_node));
++		  gimple_set_lhs (g, real_ptr);
++		  create_memset_zero (real_ptr, gsi, size);
++		  tree src = get_real_allocated_ptr (newrhs1[i], gsi);
++		  tree old_size = read_allocated_size (src, gsi);
++		  create_memcpy (src, real_ptr, old_size, gsi);
++		  record_allocated_size (real_ptr, gsi, size);
++		  tree lhs_use = set_ptr_for_use (real_ptr, gsi);
++		  create_free (src, gsi);
++		  copy_to_lhs (decl->newdecl[i], lhs_use, gsi);
++		}
++	      else
++		{
++		  gcc_assert (false);
++		  internal_error ("supported type for semi-relayout.");
++		}
++	    }
++	  if (!rewrite
++	      && (current_layout_opt_level >= STRUCT_REORDER_FIELDS
++		  || current_layout_opt_level == STRUCT_SPLIT))
++	    {
++	      /* Every allocation except for calloc needs the size multiplied out.  */
++	      if (!gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
++		newsize = gimplify_build2 (gsi, MULT_EXPR, sizetype,
++					   num, newsize);
++	      if (gimple_call_builtin_p (stmt, BUILT_IN_MALLOC)
++		  || gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA))
++		g = gimple_build_call (gimple_call_fndecl (stmt), 1, newsize);
++	      else if (gimple_call_builtin_p (stmt, BUILT_IN_CALLOC))
++		g = gimple_build_call (gimple_call_fndecl (stmt), 2,
++				       num, newsize);
++	      else if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC))
++		g = gimple_build_call (gimple_call_fndecl (stmt), 2,
++				       newrhs1[i], newsize);
++	      else
++		gcc_assert (false);
++	      gimple_call_set_lhs (g, decl->newdecl[i]);
++	      gsi_insert_before (gsi, g, GSI_SAME_STMT);
++	    }
++
++
+ 	  if (type->pc_candidate)
+ 	    {
+ 	      /* Init global header for pointer compression.  */
+@@ -6875,11 +7675,14 @@ ipa_struct_reorg::rewrite_call (gcall *stmt, gimple_stmt_iterator *gsi)
+       if (!rewrite_expr (expr, newexpr))
+ 	return false;
+ 
++      srtype *t = find_type (TREE_TYPE (TREE_TYPE (expr)));
+       if (newexpr[1] == NULL)
+ 	{
+-	  gimple_call_set_arg (stmt, 0, newexpr[0]);
+-	  update_stmt (stmt);
+-	  return false;
++	  if (t && t->semi_relayout)
++	    newexpr[0] = get_real_allocated_ptr (newexpr[0], gsi);
++	    gimple_call_set_arg (stmt, 0, newexpr[0]);
++	    update_stmt (stmt);
++	    return false;
+ 	}
+ 
+       for (unsigned i = 0; i < max_split && newexpr[i]; i++)
+@@ -7571,6 +8374,86 @@ ipa_struct_reorg::check_and_prune_struct_for_pointer_compression (void)
+     }
+ }
+ 
++void
++ipa_struct_reorg::check_and_prune_struct_for_semi_relayout (void)
++{
++  unsigned relayout_transform = 0;
++  for (unsigned i = 0; i < types.length (); i++)
++    {
++      srtype *type = types[i];
++      if (dump_file)
++	{
++	  print_generic_expr (dump_file, type->type);
++	}
++      if (type->has_escaped ())
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, " has escaped by %s, "
++				  "skip relayout.\n", type->escape_reason());
++	    }
++	  continue;
++	}
++      if (TYPE_FIELDS (type->type) == NULL)
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, " has zero field, skip relayout.\n");
++	    }
++	  continue;
++	}
++      if (type->chain_type)
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, " is chain_type, skip relayout.\n");
++	    }
++	    continue;
++	}
++      if (type->has_alloc_array == 0 || type->has_alloc_array == 1
++	  || type->has_alloc_array == -1 || type->has_alloc_array == -3
++	  || type->has_alloc_array == -4)
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, " has alloc number: %d,"
++				  " skip relayout.\n", type->has_alloc_array);
++	    }
++	  continue;
++	}
++      if (get_type_name (type->type) == NULL)
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, " has empty struct name,"
++				  " skip relayout.\n");
++	    }
++	  continue;
++	}
++      relayout_transform++;
++      type->semi_relayout = true;
++      if (dump_file)
++	{
++	  fprintf (dump_file, " attempts to do semi-relayout.\n");
++	}
++    }
++
++  if (dump_file)
++    {
++      if (relayout_transform)
++	{
++	  fprintf (dump_file, "\nNumber of structures to transform in "
++			      "semi-relayout is %d\n", relayout_transform);
++	}
++      else
++	{
++	  fprintf (dump_file, "\nNo structures to transform in "
++			      "semi-relayout.\n");
++	}
++    }
++}
++
++
+ /* Init pointer size from parameter param_pointer_compression_size.  */
+ 
+ static void
+@@ -7612,6 +8495,8 @@ ipa_struct_reorg::execute (unsigned int opt)
+ 
+       if (opt >= POINTER_COMPRESSION_SAFE)
+ 	check_and_prune_struct_for_pointer_compression ();
++      if (opt >= SEMI_RELAYOUT)
++	check_and_prune_struct_for_semi_relayout ();
+       ret = rewrite_functions ();
+     }
+   else
+@@ -7659,6 +8544,8 @@ public:
+     unsigned int level = 0;
+     switch (struct_layout_optimize_level)
+       {
++	case 6: level |= SEMI_RELAYOUT;
++	// FALLTHRU
+ 	case 5: level |= POINTER_COMPRESSION_UNSAFE;
+ 	// FALLTHRU
+ 	case 4: level |= POINTER_COMPRESSION_SAFE;
+@@ -7678,6 +8565,12 @@ public:
+     if (level & POINTER_COMPRESSION_SAFE)
+       init_pointer_size_for_pointer_compression ();
+ 
++    if (level & SEMI_RELAYOUT)
++      {
++	semi_relayout_align = semi_relayout_level;
++	relayout_part_size = 1 << semi_relayout_level;
++      }
++
+     /* Preserved for backward compatibility, reorder fields needs run before
+        struct split and complete struct relayout.  */
+     if (flag_ipa_reorder_fields && level < STRUCT_REORDER_FIELDS)
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.h b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+index 6c4469597..e3e6d7afb 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.h
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.h
+@@ -25,6 +25,9 @@ namespace struct_reorg {
+ 
+ const int max_split = 2;
+ 
++unsigned semi_relayout_align = semi_relayout_level;
++unsigned relayout_part_size = 1 << semi_relayout_level;
++
+ template 
+ struct auto_vec_del : auto_vec
+ {
+@@ -128,6 +131,10 @@ public:
+   /* Negative number means it has illegal allocated arrays
+      that we do not optimize.  */
+   int has_alloc_array;
++  bool semi_relayout;
++  hash_map new_field_offsets;
++  unsigned bucket_parts;
++  unsigned bucket_size;
+ 
+   // Constructors
+   srtype (tree type);
+@@ -149,6 +156,7 @@ public:
+   bool has_dead_field (void);
+   void mark_escape (escape_type, gimple *stmt);
+   void create_global_ptr_for_pc ();
++  unsigned calculate_bucket_size ();
+   bool has_escaped (void)
+   {
+     return escapes != does_not_escape;
+diff --git a/gcc/params.opt b/gcc/params.opt
+index bb5d82471..82a3d92c5 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1221,4 +1221,9 @@ Target size of compressed pointer, which should be 8, 16 or 32.
+ -param=param-ldp-dependency-search-range=
+ Common Joined UInteger Var(param_ldp_dependency_search_range) Init(16) IntegerRange(1, 32) Param Optimization
+ Range for depended ldp search in split-ldp-stp path.
++
++-param=semi-relayout-level=
++Common Joined UInteger Var(semi_relayout_level) Init(13) IntegerRange(11, 15) Param Optimization
++Set capacity of each bucket to semi-relayout to (1 << semi-relayout-level) / 8 .
++
+ ; This comment is to ensure we retain the blank line above.
+diff --git a/gcc/testsuite/gcc.dg/struct/semi_relayout_rewrite.c b/gcc/testsuite/gcc.dg/struct/semi_relayout_rewrite.c
+new file mode 100644
+index 000000000..aca8400ca
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/semi_relayout_rewrite.c
+@@ -0,0 +1,86 @@
++// Check simplify rewrite chance for semi-relayout
++/* { dg-do compile } */
++
++#include 
++#include 
++
++typedef struct node node_t;
++typedef struct node *node_p;
++
++typedef struct arc arc_t;
++typedef struct arc *arc_p;
++
++typedef struct network
++{
++  arc_p arcs;
++  arc_p sorted_arcs;
++  int x;
++  node_p nodes;
++  node_p stop_nodes;
++} network_t;
++
++struct node
++{
++  int64_t potential;
++  int orientation;
++  node_p child;
++  node_p pred;
++  node_p sibling;
++  node_p sibling_prev;
++  arc_p basic_arc;
++  arc_p firstout;
++  arc_p firstin;
++  arc_p arc_tmp;
++  int64_t flow;
++  int64_t depth;
++  int number;
++  int time;
++};
++
++struct arc
++{
++  int id;
++  int64_t cost;
++  node_p tail;
++  node_p head;
++  short ident;
++  arc_p nextout;
++  arc_p nextin;
++  int64_t flow;
++  int64_t org_cost;
++  network_t* net_add;
++};
++
++
++const int MAX = 100;
++network_t* net;
++node_p node;
++arc_p arc;
++
++int
++main ()
++{
++  net = (network_t*) calloc (1, sizeof(network_t));
++  net->arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->sorted_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++  net->nodes = (node_p) calloc (MAX, sizeof (node_t));
++  net->arcs->id = 100;
++
++  node = net->nodes;
++  arc = net->arcs;
++
++  for (unsigned i = 0; i < MAX; i++)
++    {
++      arc->head = node;
++      arc->head->child = node;
++      node->potential = i + 1;
++      arc->cost = arc->head->potential;
++      arc->tail = node->sibling;
++      node = node + 1;
++      arc = arc + 1;
++    }
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "Number of structures to transform in semi-relayout is 1" "struct_reorg" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index c40474407..c5a955b00 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -55,6 +55,10 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \
+ 	"" "-fipa-struct-reorg=5 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
++# -fipa-struct-reorg=6
++gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/semi_relayout*.c]] \
++	"" "-fipa-struct-reorg=6 -fdump-ipa-all -flto-partition=one -fwhole-program"
++
+ # All done.
+ torture-finish
+ dg-finish
+-- 
+2.33.0
+
diff --git a/0054-Struct-Reorg-Bugfix-for-structure-pointer-compressio.patch b/0054-Struct-Reorg-Bugfix-for-structure-pointer-compressio.patch
new file mode 100644
index 0000000..54e93fc
--- /dev/null
+++ b/0054-Struct-Reorg-Bugfix-for-structure-pointer-compressio.patch
@@ -0,0 +1,28 @@
+From 9dc3df938b9ed2c27498c8548087fee1ce930366 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Tue, 2 Apr 2024 11:08:30 +0800
+Subject: [PATCH] [Struct Reorg] Bugfix for structure pointer compression
+
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index fa33f2d35..3922873f3 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -7541,9 +7541,11 @@ ipa_struct_reorg::check_and_prune_struct_for_pointer_compression (void)
+       if (!type->has_legal_alloc_num)
+ 	{
+ 	  if (current_layout_opt_level & POINTER_COMPRESSION_UNSAFE)
++	    {
+ 	    if (dump_file)
+ 	      fprintf (dump_file, " has unknown alloc size, but"
+ 				  " in unsafe mode, so");
++	    }
+ 	  else
+ 	    {
+ 	      if (dump_file)
+-- 
+2.33.0
+
diff --git a/0055-Struct-Reorg-Port-bugfixes-to-GCC-12.3.1.patch b/0055-Struct-Reorg-Port-bugfixes-to-GCC-12.3.1.patch
new file mode 100644
index 0000000..8f6b3b7
--- /dev/null
+++ b/0055-Struct-Reorg-Port-bugfixes-to-GCC-12.3.1.patch
@@ -0,0 +1,420 @@
+From 55c547748af36ffc3f2d5ed154a91fb3fcb8431c Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Thu, 11 Apr 2024 15:49:59 +0800
+Subject: [PATCH] [Struct Reorg] Port bugfixes to GCC 12.3.1
+
+Migrated from commits in GCC10.3.1:
+https://gitee.com/openeuler/gcc/commit/41af6d361a6d85ef4fce8a8438113d765596afdd
+https://gitee.com/openeuler/gcc/commit/25d74b98caeaae881e374924886ee664aa1af5bc
+https://gitee.com/openeuler/gcc/commit/b5a3bfe92f96cd0d2224d80ac4eaa80dab1bd6bf
+https://gitee.com/openeuler/gcc/commit/708ffe6f132ee39441b66b6ab6b98847d35916b7
+https://gitee.com/openeuler/gcc/commit/e875e4e7f3716aa268ffbbf55ee199ec82b6aeba
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc      | 97 ++++++++++---------
+ gcc/testsuite/gcc.dg/struct/dfe_escape.c      | 50 ++++++++++
+ gcc/testsuite/gcc.dg/struct/dfe_func_ptr.c    | 69 +++++++++++++
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |  2 +
+ gcc/testsuite/gcc.dg/struct/struct_reorg-10.c | 29 ++++++
+ gcc/testsuite/gcc.dg/struct/struct_reorg-11.c | 16 +++
+ gcc/testsuite/gcc.dg/struct/struct_reorg-12.c | 26 +++++
+ 7 files changed, 243 insertions(+), 46 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_escape.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/dfe_func_ptr.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-10.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-11.c
+ create mode 100644 gcc/testsuite/gcc.dg/struct/struct_reorg-12.c
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index 6a202b4bd..f03d1d875 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -466,10 +466,19 @@ srtype::has_dead_field (void)
+   unsigned i;
+   FOR_EACH_VEC_ELT (fields, i, this_field)
+     {
+-      if (!(this_field->field_access & READ_FIELD))
+-	{
+-	  may_dfe = true;
+-	  break;
++      /* Function pointer members are not processed, because DFE
++         does not currently support accurate analysis of function
++         pointers, and we have not identified specific use cases. */
++      if (!(this_field->field_access & READ_FIELD)
++	 && !FUNCTION_POINTER_TYPE_P (this_field->fieldtype))
++	{
++	  /* Fields with escape risks should not be processed. */
++	  if (this_field->type == NULL
++	      || (this_field->type->escapes == does_not_escape))
++	    {
++	      may_dfe = true;
++	      break;
++	    }
+ 	}
+     }
+   return may_dfe;
+@@ -1032,8 +1041,13 @@ srtype::create_new_type (void)
+     {
+       srfield *f = fields[i];
+       if (current_layout_opt_level & DEAD_FIELD_ELIMINATION
+-	  && !(f->field_access & READ_FIELD))
+-	continue;
++	  && !(f->field_access & READ_FIELD)
++	  && !FUNCTION_POINTER_TYPE_P (f->fieldtype))
++	{
++	  /* Fields with escape risks should not be processed. */
++	  if (f->type == NULL || (f->type->escapes == does_not_escape))
++	    continue;
++	}
+       f->create_new_fields (newtype, newfields, newlast);
+     }
+ 
+@@ -3815,9 +3829,17 @@ ipa_struct_reorg::maybe_mark_or_record_other_side (tree side, tree other,
+       if (VOID_POINTER_P (TREE_TYPE (side))
+ 	  && TREE_CODE (side) == SSA_NAME)
+ 	{
+-	  /* The type is other, the declaration is side.  */
+-	  current_function->record_decl (type, side, -1,
+-		isptrptr (TREE_TYPE (other)) ? TREE_TYPE (other) : NULL);
++	  tree inner = SSA_NAME_VAR (side);
++	  if (inner)
++	    {
++	      srdecl *in = find_decl (inner);
++	      if (in && !in->type->has_escaped ())
++		{
++		  /* The type is other, the declaration is side.  */
++		  current_function->record_decl (type, side, -1,
++			isptrptr (TREE_TYPE (other)) ? TREE_TYPE (other) : NULL);
++		}
++	     }
+ 	}
+       else
+ 	/* *_1 = &MEM[(void *)&x + 8B].  */
+@@ -3910,6 +3932,12 @@ ipa_struct_reorg::maybe_record_assign (cgraph_node *node, gassign *stmt)
+ 	maybe_mark_or_record_other_side (rhs, lhs, stmt);
+       if (TREE_CODE (lhs) == SSA_NAME)
+ 	maybe_mark_or_record_other_side (lhs, rhs, stmt);
++
++      /* Handle missing ARRAY_REF cases.  */
++      if (TREE_CODE (lhs) == ARRAY_REF)
++	mark_type_as_escape (TREE_TYPE (lhs), escape_array, stmt);
++      if (TREE_CODE (rhs) == ARRAY_REF)
++	mark_type_as_escape (TREE_TYPE (rhs), escape_array, stmt);
+     }
+ }
+ 
+@@ -5272,8 +5300,11 @@ ipa_struct_reorg::record_accesses (void)
+ 	record_function (cnode);
+       else
+ 	{
+-	  tree return_type = TREE_TYPE (TREE_TYPE (cnode->decl));
+-	  mark_type_as_escape (return_type, escape_return, NULL);
++	  if (cnode->externally_visible)
++	    {
++	      tree return_type = TREE_TYPE (TREE_TYPE (cnode->decl));
++	      mark_type_as_escape (return_type, escape_return, NULL);
++	    }
+ 	}
+ 
+     }
+@@ -5889,6 +5920,7 @@ ipa_struct_reorg::rewrite_expr (tree expr,
+   bool escape_from_base = false;
+ 
+   tree newbase[max_split];
++  memset (newbase, 0, sizeof (tree[max_split]));
+   memset (newexpr, 0, sizeof (tree[max_split]));
+ 
+   if (TREE_CODE (expr) == CONSTRUCTOR)
+@@ -6912,7 +6944,7 @@ create_bb_for_group_diff_ne_0 (basic_block new_bb, tree &phi, tree ptr,
+ }
+ 
+ tree
+-ipa_struct_reorg::rewrite_pointer_plus_integer (gimple *stmt,
++ipa_struct_reorg::rewrite_pointer_plus_integer (gimple *stmt ATTRIBUTE_UNUSED,
+ 						gimple_stmt_iterator *gsi,
+ 						tree ptr, tree offset,
+ 						srtype *type)
+@@ -7889,41 +7921,14 @@ ipa_struct_reorg::rewrite_cond (gcond *stmt,
+    should be removed.  */
+ 
+ bool
+-ipa_struct_reorg::rewrite_debug (gimple *stmt, gimple_stmt_iterator *)
++ipa_struct_reorg::rewrite_debug (gimple *, gimple_stmt_iterator *)
+ {
+-  if (current_layout_opt_level >= STRUCT_REORDER_FIELDS)
+-    /* Delete debug gimple now.  */
+-    return true;
+-  bool remove = false;
+-  if (gimple_debug_bind_p (stmt))
+-    {
+-      tree var = gimple_debug_bind_get_var (stmt);
+-      tree newvar[max_split];
+-      if (rewrite_expr (var, newvar, true))
+-	remove = true;
+-      if (gimple_debug_bind_has_value_p (stmt))
+-	{
+-	  var = gimple_debug_bind_get_value (stmt);
+-	  if (TREE_CODE (var) == POINTER_PLUS_EXPR)
+-	    var = TREE_OPERAND (var, 0);
+-	  if (rewrite_expr (var, newvar, true))
+-	    remove = true;
+-	}
+-    }
+-  else if (gimple_debug_source_bind_p (stmt))
+-    {
+-      tree var = gimple_debug_source_bind_get_var (stmt);
+-      tree newvar[max_split];
+-      if (rewrite_expr (var, newvar, true))
+-	remove = true;
+-      var = gimple_debug_source_bind_get_value (stmt);
+-      if (TREE_CODE (var) == POINTER_PLUS_EXPR)
+-	var = TREE_OPERAND (var, 0);
+-      if (rewrite_expr (var, newvar, true))
+-	remove = true;
+-    }
+-
+-  return remove;
++  /* In debug statements, there might be some statements that have
++     been optimized out in gimple but left in debug gimple.  Sometimes
++     these statements need to be analyzed to escape, but in rewrite
++     stage it shouldn't happen.  It needs to care a lot to handle these
++     cases but seems useless.  So now we just delete debug gimple.  */
++  return true;
+ }
+ 
+ /* Rewrite PHI nodes, return true if the PHI was replaced.  */
+diff --git a/gcc/testsuite/gcc.dg/struct/dfe_escape.c b/gcc/testsuite/gcc.dg/struct/dfe_escape.c
+new file mode 100644
+index 000000000..09efe8027
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/dfe_escape.c
+@@ -0,0 +1,50 @@
++/* { dg-do compile } */
++
++#include 
++#include 
++
++typedef struct arc arc_t;
++typedef struct arc *arc_p;
++
++typedef struct network
++{    
++  int x;
++} network_t;
++
++struct arc
++{
++  int flow;
++  network_t* net_add;
++};
++
++const int MAX = 100;
++
++/* let it escape_array, "Type is used in an array [not handled yet]".  */
++network_t* net[2];
++arc_p stop_arcs = NULL;
++
++int
++main ()
++{
++  net[0] = (network_t*) calloc (1, sizeof(network_t));
++  stop_arcs = (arc_p) calloc (MAX, sizeof (arc_t));
++
++  net[0]->x = 100;
++
++  for (unsigned i = 0; i < 3; i++)
++    {        
++      net[0]->x = net[0]->x + 2;
++      stop_arcs->flow = net[0]->x / 2;
++      stop_arcs->flow = stop_arcs->flow + 20;
++      stop_arcs->net_add = net[0];
++      stop_arcs++;
++    }
++
++  if( net[1] != 0 && stop_arcs != 0)
++    {
++      return -1;
++    }
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/dfe_func_ptr.c b/gcc/testsuite/gcc.dg/struct/dfe_func_ptr.c
+new file mode 100644
+index 000000000..74ea93bbc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/dfe_func_ptr.c
+@@ -0,0 +1,69 @@
++/* { dg-do compile } */
++/* { dg-do run } */
++
++#include 
++#include 
++
++#ifdef STACK_SIZE
++#if STACK_SIZE > 16000
++#define N 1000
++#else
++#define N (STACK_SIZE/16)
++#endif
++#else
++#define N 1000
++#endif
++
++int num;
++
++int (*foo)(int d);
++int f (int t);
++
++typedef struct str_t str_t1;
++struct str_t
++{
++   int a;
++   float b;
++   int (*foo)(int d);
++};
++
++int main ()
++{
++   int i, r;
++   r = rand ();
++   num = r > N ? N : r;
++   str_t1 * p1 = calloc (num, sizeof (str_t1));
++   if (p1 == NULL)
++      return 0;
++   for (i = 0; i < num; i++)
++     {
++       p1[i].foo = malloc (1 * sizeof (f));
++       p1[i].foo = f;
++       p1[i].foo (i);
++     }
++
++   for (i = 0; i < num; i++)
++      p1[i].a = 1;
++
++   for (i = 0; i < num; i++)
++      p1[i].b = 2;
++
++   for (i = 0; i < num; i++)
++      if (p1[i].a != 1)
++	 abort ();
++
++   for (i = 0; i < num; i++)
++      if (abs (p1[i].b - 2) > 0.0001)
++	 abort ();
++
++   return 0;
++}
++
++int f (int t)
++{
++   if ( t < 0)
++      abort ();
++   return 0;
++}
++
++/* { dg-final { scan-ipa-dump-times "Dead field elimination" 0 "struct_reorg" } } */
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index c5a955b00..687f6609f 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -46,6 +46,8 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \
+ # -fipa-struct-reorg=3
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \
+ 	"" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
++gcc-dg-runtest $srcdir/$subdir/struct_reorg-7.c \
++	"" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
+ # -fipa-struct-reorg=4
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pc*.c]] \
+diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-10.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-10.c
+new file mode 100644
+index 000000000..ec422f76f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-10.c
+@@ -0,0 +1,29 @@
++/* { dg-do compile } */
++/* { dg-options "-w -g -O3 -flto-partition=one -fipa-struct-reorg -fwhole-program -S" } */
++
++struct a {
++  int b;
++  char c;
++};
++struct {
++  double d;
++  _Bool e;
++} * f;
++struct g {
++  struct a h;
++} i;
++long j;
++void k();
++void l() { k(i); }
++void k(struct a m) {
++  f->e = 0;
++  for (;;)
++    l();
++}
++int main() {
++  for (; j; f = 0) {
++    struct g *n = 0;
++    char o = n->h.c;
++  }
++  l();
++}
+diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-11.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-11.c
+new file mode 100644
+index 000000000..3e42aa84a
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-11.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-options "-w -g -O3 -flto-partition=one -fipa-struct-reorg -fwhole-program -S" } */
++
++struct a {
++  int b;
++  double c;
++};
++struct d {
++  struct a e;
++};
++int f;
++int main() {
++  _Bool g;
++  struct d **h = 0;
++  g = *h += f;
++}
+diff --git a/gcc/testsuite/gcc.dg/struct/struct_reorg-12.c b/gcc/testsuite/gcc.dg/struct/struct_reorg-12.c
+new file mode 100644
+index 000000000..d434f9fe0
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/struct_reorg-12.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-options "-w -g -O3 -flto-partition=one -fipa-struct-reorg -fwhole-program -S" } */
++
++struct foo {
++  long element1;
++  long element2;
++};
++
++struct goo {
++  struct foo element_foo;
++};
++
++struct goo g1;
++
++void func () {
++  struct foo (*local)[] = 0;
++  long idx;
++  (g1).element_foo = (*local)[idx];
++}
++
++struct foo g2;
++int main () {
++  func ();
++  g2 = g1.element_foo;
++  return 0;
++}
+-- 
+2.33.0
+
diff --git a/0056-Fix-bug-that-verifying-gimple-failed-when-reorg-leve.patch b/0056-Fix-bug-that-verifying-gimple-failed-when-reorg-leve.patch
new file mode 100644
index 0000000..4bcaca8
--- /dev/null
+++ b/0056-Fix-bug-that-verifying-gimple-failed-when-reorg-leve.patch
@@ -0,0 +1,27 @@
+From fa6f80044dcebd28506e871e6e5d25e2dfd7e105 Mon Sep 17 00:00:00 2001
+From: tiancheng-bao 
+Date: Fri, 12 Apr 2024 15:09:28 +0800
+Subject: [PATCH 01/32] Fix bug that verifying gimple failed when reorg-level >
+ 5
+
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index f03d1d875..e08577c0c 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -7461,6 +7461,9 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	    continue;
+ 	  tree lhs_expr = newlhs[i] ? newlhs[i] : lhs;
+ 	  tree rhs_expr = newrhs[i] ? newrhs[i] : rhs;
++	  if (!useless_type_conversion_p (TREE_TYPE (lhs_expr),
++					  TREE_TYPE (rhs_expr)))
++	    rhs_expr = gimplify_build1 (gsi, NOP_EXPR, TREE_TYPE (lhs_expr), rhs_expr);  
+ 	  gimple *newstmt = gimple_build_assign (lhs_expr, rhs_expr);
+ 	  if (dump_file && (dump_flags & TDF_DETAILS))
+ 	    {
+-- 
+2.28.0.windows.1
+
diff --git a/0057-AutoFdo-Fix-memory-leaks-in-autofdo.patch b/0057-AutoFdo-Fix-memory-leaks-in-autofdo.patch
new file mode 100644
index 0000000..4d80606
--- /dev/null
+++ b/0057-AutoFdo-Fix-memory-leaks-in-autofdo.patch
@@ -0,0 +1,90 @@
+From 13e82fccba781b29e55a6e1934986514019b728d Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao 
+Date: Sun, 24 Mar 2024 20:42:27 +0800
+Subject: [PATCH 02/32] [AutoFdo] Fix memory leaks in autofdo
+
+---
+ gcc/final.cc | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/final.cc b/gcc/final.cc
+index d4c4fa08f..af4e529bb 100644
+--- a/gcc/final.cc
++++ b/gcc/final.cc
+@@ -4402,12 +4402,15 @@ get_fdo_count_quality (profile_count count)
+   return profile_quality[count.quality ()];
+ }
+ 
+-static const char *
++/* If the function is not public, return the function_name/file_name for
++   disambiguation of local symbols since there could be identical function
++   names coming from identical file names.  The caller needs to free memory.  */
++static char *
+ alias_local_functions (const char *fnname)
+ {
+   if (TREE_PUBLIC (cfun->decl))
+     {
+-      return fnname;
++      return concat (fnname, NULL);
+     }
+   return concat (fnname, "/", lbasename (dump_base_name), NULL);
+ }
+@@ -4457,12 +4460,13 @@ dump_direct_callee_info_to_asm (basic_block bb, gcov_type call_count)
+ 
+ 	  if (callee)
+ 	    {
++	      char *func_name =
++		      alias_local_functions (get_fnname_from_decl (callee));
+ 	      fprintf (asm_out_file, "\t.string \"%x\"\n",
+ 		       INSN_ADDRESSES (INSN_UID (insn)));
+ 
+ 	      fprintf (asm_out_file, "\t.string \"%s%s\"\n",
+-		       ASM_FDO_CALLEE_FLAG,
+-                       alias_local_functions (get_fnname_from_decl (callee)));
++		       ASM_FDO_CALLEE_FLAG, func_name);
+ 
+               fprintf (asm_out_file,
+                        "\t.string \"" HOST_WIDE_INT_PRINT_DEC "\"\n",
+@@ -4472,9 +4476,9 @@ dump_direct_callee_info_to_asm (basic_block bb, gcov_type call_count)
+                 {
+                   fprintf (dump_file, "call: %x --> %s \n",
+                            INSN_ADDRESSES (INSN_UID (insn)),
+-                           alias_local_functions
+-                           (get_fnname_from_decl (callee)));
++			   func_name);
+                 }
++	      free (func_name);
+             }
+         }
+      } 
+@@ -4547,8 +4551,9 @@ dump_bb_info_to_asm (basic_block bb, gcov_type bb_count)
+ static void 
+ dump_function_info_to_asm (const char *fnname)
+ {
++  char *func_name = alias_local_functions (fnname);
+   fprintf (asm_out_file, "\t.string \"%s%s\"\n",
+-           ASM_FDO_CALLER_FLAG, alias_local_functions (fnname));
++	   ASM_FDO_CALLER_FLAG, func_name);
+   fprintf (asm_out_file, "\t.string \"%s%d\"\n",
+            ASM_FDO_CALLER_SIZE_FLAG, get_function_end_addr ());
+   fprintf (asm_out_file, "\t.string \"%s%s\"\n",
+@@ -4557,7 +4562,7 @@ dump_function_info_to_asm (const char *fnname)
+   if (dump_file)
+     {
+       fprintf (dump_file, "\n FUNC_NAME: %s\n",
+-               alias_local_functions (fnname));
++	       func_name);
+       fprintf (dump_file, " file: %s\n",
+                dump_base_name);
+       fprintf (dump_file, "profile_status: %s\n",
+@@ -4567,6 +4572,7 @@ dump_function_info_to_asm (const char *fnname)
+       fprintf (dump_file, " function_bind: %s\n",
+                simple_get_function_bind ());
+     }
++  free (func_name);
+ }
+ 
+ /* Dump function profile into form AutoFDO or PGO to asm.    */
+-- 
+2.28.0.windows.1
+
diff --git a/0086-Modfify-cost-calculation-for-dealing-with-equivalenc.patch b/0086-Modfify-cost-calculation-for-dealing-with-equivalenc.patch
new file mode 100644
index 0000000..c87f3ec
--- /dev/null
+++ b/0086-Modfify-cost-calculation-for-dealing-with-equivalenc.patch
@@ -0,0 +1,321 @@
+From c546aad5d38165e2962456525a0f6a427e03583b Mon Sep 17 00:00:00 2001
+From: "Vladimir N. Makarov" 
+Date: Thu, 26 Oct 2023 09:50:40 -0400
+Subject: [PATCH 31/32] Modfify cost calculation for dealing with equivalences
+
+RISCV target developers reported that pseudos with equivalence used in
+a loop can be spilled.  Simple changes of heuristics of cost
+calculation of pseudos with equivalence or even ignoring equivalences
+resulted in numerous testsuite failures on different targets or worse
+spec2017 performance.  This patch implements more sophisticated cost
+calculations of pseudos with equivalences.  The patch does not change
+RA behaviour for targets still using the old reload pass instead of
+LRA.  The patch solves the reported problem and improves x86-64
+specint2017 a bit (specfp2017 performance stays the same).  The patch
+takes into account how the equivalence will be used: will it be
+integrated into the user insns or require an input reload insn.  It
+requires additional pass over insns.  To compensate RA slow down, the
+patch removes a pass over insns in the reload pass used by IRA before.
+This also decouples IRA from reload more and will help to remove the
+reload pass in the future if it ever happens.
+
+gcc/ChangeLog:
+
+	* dwarf2out.cc (reg_loc_descriptor): Use lra_eliminate_regs when
+	LRA is used.
+	* ira-costs.cc: Include regset.h.
+	(equiv_can_be_consumed_p, get_equiv_regno, calculate_equiv_gains):
+	New functions.
+	(find_costs_and_classes): Call calculate_equiv_gains and redefine
+	mem_cost of pseudos with equivs when LRA is used.
+	* var-tracking.cc: Include ira.h and lra.h.
+	(vt_initialize): Use lra_eliminate_regs when LRA is used.
+---
+ gcc/dwarf2out.cc    |   4 +-
+ gcc/ira-costs.cc    | 169 ++++++++++++++++++++++++++++++++++++++++++--
+ gcc/var-tracking.cc |  14 +++-
+ 3 files changed, 179 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
+index 0a5c081d8..f0f6f4fd4 100644
+--- a/gcc/dwarf2out.cc
++++ b/gcc/dwarf2out.cc
+@@ -14263,7 +14263,9 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
+      argument pointer and soft frame pointer rtx's.
+      Use DW_OP_fbreg offset DW_OP_stack_value in this case.  */
+   if ((rtl == arg_pointer_rtx || rtl == frame_pointer_rtx)
+-      && eliminate_regs (rtl, VOIDmode, NULL_RTX) != rtl)
++      && (ira_use_lra_p
++	  ? lra_eliminate_regs (rtl, VOIDmode, NULL_RTX)
++	  : eliminate_regs (rtl, VOIDmode, NULL_RTX)) != rtl)
+     {
+       dw_loc_descr_ref result = NULL;
+ 
+diff --git a/gcc/ira-costs.cc b/gcc/ira-costs.cc
+index 642fda529..c79311783 100644
+--- a/gcc/ira-costs.cc
++++ b/gcc/ira-costs.cc
+@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tm_p.h"
+ #include "insn-config.h"
+ #include "regs.h"
++#include "regset.h"
+ #include "ira.h"
+ #include "ira-int.h"
+ #include "addresses.h"
+@@ -1750,6 +1751,145 @@ process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node)
+     process_bb_for_costs (bb);
+ }
+ 
++/* Check that reg REGNO can be changed by TO in INSN.  Return true in case the
++   result insn would be valid one.  */
++static bool
++equiv_can_be_consumed_p (int regno, rtx to, rtx_insn *insn)
++{
++  validate_replace_src_group (regno_reg_rtx[regno], to, insn);
++  bool res = verify_changes (0);
++  cancel_changes (0);
++  return res;
++}
++
++/* Return true if X contains a pseudo with equivalence.  In this case also
++   return the pseudo through parameter REG.  If the pseudo is a part of subreg,
++   return the subreg through parameter SUBREG.  */
++
++static bool
++get_equiv_regno (rtx x, int ®no, rtx &subreg)
++{
++  subreg = NULL_RTX;
++  if (GET_CODE (x) == SUBREG)
++    {
++      subreg = x;
++      x = SUBREG_REG (x);
++    }
++  if (REG_P (x)
++      && (ira_reg_equiv[REGNO (x)].memory != NULL
++	  || ira_reg_equiv[REGNO (x)].constant != NULL))
++    {
++      regno = REGNO (x);
++      return true;
++    }
++  RTX_CODE code = GET_CODE (x);
++  const char *fmt = GET_RTX_FORMAT (code);
++
++  for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
++    if (fmt[i] == 'e')
++      {
++	if (get_equiv_regno (XEXP (x, i), regno, subreg))
++	  return true;
++      }
++    else if (fmt[i] == 'E')
++      {
++	for (int j = 0; j < XVECLEN (x, i); j++)
++	  if (get_equiv_regno (XVECEXP (x, i, j), regno, subreg))
++	    return true;
++      }
++  return false;
++}
++
++/* A pass through the current function insns.  Calculate costs of using
++   equivalences for pseudos and store them in regno_equiv_gains.  */
++
++static void
++calculate_equiv_gains (void)
++{
++  basic_block bb;
++  int regno, freq, cost;
++  rtx subreg;
++  rtx_insn *insn;
++  machine_mode mode;
++  enum reg_class rclass;
++  bitmap_head equiv_pseudos;
++
++  ira_assert (allocno_p);
++  bitmap_initialize (&equiv_pseudos, ®_obstack);
++  for (regno = max_reg_num () - 1; regno >= FIRST_PSEUDO_REGISTER; regno--)
++    if (ira_reg_equiv[regno].init_insns != NULL
++	&& (ira_reg_equiv[regno].memory != NULL
++	    || (ira_reg_equiv[regno].constant != NULL
++		/* Ignore complicated constants which probably will be placed
++		   in memory:  */
++		&& GET_CODE (ira_reg_equiv[regno].constant) != CONST_DOUBLE
++		&& GET_CODE (ira_reg_equiv[regno].constant) != CONST_VECTOR
++		&& GET_CODE (ira_reg_equiv[regno].constant) != LABEL_REF)))
++      {
++	rtx_insn_list *x;
++	for (x = ira_reg_equiv[regno].init_insns; x != NULL; x = x->next ())
++	  {
++	    insn = x->insn ();
++	    rtx set = single_set (insn);
++
++	    if (set == NULL_RTX || SET_DEST (set) != regno_reg_rtx[regno])
++	      break;
++	    bb = BLOCK_FOR_INSN (insn);
++	    ira_curr_regno_allocno_map
++	      = ira_bb_nodes[bb->index].parent->regno_allocno_map;
++	    mode = PSEUDO_REGNO_MODE (regno);
++	    rclass = pref[COST_INDEX (regno)];
++	    ira_init_register_move_cost_if_necessary (mode);
++	    if (ira_reg_equiv[regno].memory != NULL)
++	      cost = ira_memory_move_cost[mode][rclass][1];
++	    else
++	      cost = ira_register_move_cost[mode][rclass][rclass];
++	    freq = REG_FREQ_FROM_BB (bb);
++	    regno_equiv_gains[regno] += cost * freq;
++	  }
++	if (x != NULL)
++	  /* We found complicated equiv or reverse equiv mem=reg.  Ignore
++	     them.  */
++	  regno_equiv_gains[regno] = 0;
++	else
++	  bitmap_set_bit (&equiv_pseudos, regno);
++      }
++
++  FOR_EACH_BB_FN (bb, cfun)
++    {
++      freq = REG_FREQ_FROM_BB (bb);
++      ira_curr_regno_allocno_map
++	= ira_bb_nodes[bb->index].parent->regno_allocno_map;
++      FOR_BB_INSNS (bb, insn)
++	{
++	  if (!INSN_P (insn) || !get_equiv_regno (PATTERN (insn), regno, subreg)
++	      || !bitmap_bit_p (&equiv_pseudos, regno))
++	    continue;
++	  rtx subst = ira_reg_equiv[regno].memory;
++
++	  if (subst == NULL)
++	    subst = ira_reg_equiv[regno].constant;
++	  ira_assert (subst != NULL);
++	  mode = PSEUDO_REGNO_MODE (regno);
++	  ira_init_register_move_cost_if_necessary (mode);
++	  bool consumed_p = equiv_can_be_consumed_p (regno, subst, insn);
++
++	  rclass = pref[COST_INDEX (regno)];
++	  if (MEM_P (subst)
++	      /* If it is a change of constant into double for example, the
++		 result constant probably will be placed in memory.  */
++	      || (subreg != NULL_RTX && !INTEGRAL_MODE_P (GET_MODE (subreg))))
++	    cost = ira_memory_move_cost[mode][rclass][1] + (consumed_p ? 0 : 1);
++	  else if (consumed_p)
++	    continue;
++	  else
++	    cost = ira_register_move_cost[mode][rclass][rclass];
++	  regno_equiv_gains[regno] -= cost * freq;
++	}
++    }
++  bitmap_clear (&equiv_pseudos);
++}
++
+ /* Find costs of register classes and memory for allocnos or pseudos
+    and their best costs.  Set up preferred, alternative and allocno
+    classes for pseudos.  */
+@@ -1848,6 +1988,12 @@ find_costs_and_classes (FILE *dump_file)
+       if (pass == 0)
+ 	pref = pref_buffer;
+ 
++      if (ira_use_lra_p && allocno_p && pass == 1)
++	/* It is a pass through all insns.  So do it once and only for RA (not
++	   for insn scheduler) when we already found preferable pseudo register
++	   classes on the previous pass.  */
++	calculate_equiv_gains ();
++
+       /* Now for each allocno look at how desirable each class is and
+ 	 find which class is preferred.  */
+       for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
+@@ -1940,6 +2086,17 @@ find_costs_and_classes (FILE *dump_file)
+ 	    }
+ 	  if (i >= first_moveable_pseudo && i < last_moveable_pseudo)
+ 	    i_mem_cost = 0;
++	  else if (ira_use_lra_p)
++	    {
++	      if (equiv_savings > 0)
++		{
++		  i_mem_cost = 0;
++		  if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
++		    fprintf (ira_dump_file,
++			     "   Use MEM for r%d as the equiv savings is %d\n",
++			     i, equiv_savings);
++		}
++	    }
+ 	  else if (equiv_savings < 0)
+ 	    i_mem_cost = -equiv_savings;
+ 	  else if (equiv_savings > 0)
+@@ -2378,7 +2535,10 @@ ira_costs (void)
+   total_allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size
+ 						       * ira_allocnos_num);
+   initiate_regno_cost_classes ();
+-  calculate_elim_costs_all_insns ();
++  if (!ira_use_lra_p)
++    /* Process equivs in reload to update costs through hook
++       ira_adjust_equiv_reg_cost.  */
++    calculate_elim_costs_all_insns ();
+   find_costs_and_classes (ira_dump_file);
+   setup_allocno_class_and_costs ();
+   finish_regno_cost_classes ();
+@@ -2503,13 +2663,14 @@ ira_tune_allocno_costs (void)
+     }
+ }
+ 
+-/* Add COST to the estimated gain for eliminating REGNO with its
+-   equivalence.  If COST is zero, record that no such elimination is
+-   possible.  */
++/* A hook from the reload pass.  Add COST to the estimated gain for eliminating
++   REGNO with its equivalence.  If COST is zero, record that no such
++   elimination is possible.  */
+ 
+ void
+ ira_adjust_equiv_reg_cost (unsigned regno, int cost)
+ {
++  ira_assert (!ira_use_lra_p);
+   if (cost == 0)
+     regno_equiv_gains[regno] = 0;
+   else
+diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc
+index 7c3ad0a55..b10c8c1eb 100644
+--- a/gcc/var-tracking.cc
++++ b/gcc/var-tracking.cc
+@@ -107,6 +107,8 @@
+ #include "cfgrtl.h"
+ #include "cfganal.h"
+ #include "reload.h"
++#include "ira.h"
++#include "lra.h"
+ #include "calls.h"
+ #include "tree-dfa.h"
+ #include "tree-ssa.h"
+@@ -10133,7 +10135,9 @@ vt_initialize (void)
+ #else
+       reg = arg_pointer_rtx;
+ #endif
+-      elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
++      elim = (ira_use_lra_p
++	      ? lra_eliminate_regs (reg, VOIDmode, NULL_RTX)
++	      : eliminate_regs (reg, VOIDmode, NULL_RTX));
+       if (elim != reg)
+ 	{
+ 	  if (GET_CODE (elim) == PLUS)
+@@ -10153,7 +10157,9 @@ vt_initialize (void)
+       reg = arg_pointer_rtx;
+       fp_cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
+ #endif
+-      elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
++      elim = (ira_use_lra_p
++	      ? lra_eliminate_regs (reg, VOIDmode, NULL_RTX)
++	      : eliminate_regs (reg, VOIDmode, NULL_RTX));
+       if (elim != reg)
+ 	{
+ 	  if (GET_CODE (elim) == PLUS)
+@@ -10185,7 +10191,9 @@ vt_initialize (void)
+ #else
+       reg = arg_pointer_rtx;
+ #endif
+-      elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
++      elim = (ira_use_lra_p
++	      ? lra_eliminate_regs (reg, VOIDmode, NULL_RTX)
++	      : eliminate_regs (reg, VOIDmode, NULL_RTX));
+       if (elim != reg)
+ 	{
+ 	  if (GET_CODE (elim) == PLUS)
+-- 
+2.28.0.windows.1
+
diff --git a/0087-Add-cost-calculation-for-reg-equivalence-invariants.patch b/0087-Add-cost-calculation-for-reg-equivalence-invariants.patch
new file mode 100644
index 0000000..9315409
--- /dev/null
+++ b/0087-Add-cost-calculation-for-reg-equivalence-invariants.patch
@@ -0,0 +1,49 @@
+From 4965473a4211a9feb46a0d168180ab450cb18bcc Mon Sep 17 00:00:00 2001
+From: "Vladimir N. Makarov" 
+Date: Fri, 27 Oct 2023 08:28:24 -0400
+Subject: [PATCH 32/32] Add cost calculation for reg equivalence invariants
+
+My recent patch improving cost calculation for pseudos with equivalence
+resulted in failure of gcc.target/arm/eliminate.c on aarch64.  This patch
+fixes this failure.
+
+gcc/ChangeLog:
+
+	* ira-costs.cc: (get_equiv_regno, calculate_equiv_gains):
+	Process reg equivalence invariants.
+---
+ gcc/ira-costs.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/gcc/ira-costs.cc b/gcc/ira-costs.cc
+index c79311783..d33104a30 100644
+--- a/gcc/ira-costs.cc
++++ b/gcc/ira-costs.cc
+@@ -1777,6 +1777,7 @@ get_equiv_regno (rtx x, int ®no, rtx &subreg)
+     }
+   if (REG_P (x)
+       && (ira_reg_equiv[REGNO (x)].memory != NULL
++	  || ira_reg_equiv[REGNO (x)].invariant != NULL
+ 	  || ira_reg_equiv[REGNO (x)].constant != NULL))
+     {
+       regno = REGNO (x);
+@@ -1819,6 +1820,7 @@ calculate_equiv_gains (void)
+   for (regno = max_reg_num () - 1; regno >= FIRST_PSEUDO_REGISTER; regno--)
+     if (ira_reg_equiv[regno].init_insns != NULL
+ 	&& (ira_reg_equiv[regno].memory != NULL
++	    || ira_reg_equiv[regno].invariant != NULL
+ 	    || (ira_reg_equiv[regno].constant != NULL
+ 		/* Ignore complicated constants which probably will be placed
+ 		   in memory:  */
+@@ -1869,6 +1871,8 @@ calculate_equiv_gains (void)
+ 
+ 	  if (subst == NULL)
+ 	    subst = ira_reg_equiv[regno].constant;
++	  if (subst == NULL)
++	    subst = ira_reg_equiv[regno].invariant;
+ 	  ira_assert (subst != NULL);
+ 	  mode = PSEUDO_REGNO_MODE (regno);
+ 	  ira_init_register_move_cost_if_necessary (mode);
+-- 
+2.28.0.windows.1
+
diff --git a/0088-BUGFIX-Fix-the-configure-file-of-BOLT.patch b/0088-BUGFIX-Fix-the-configure-file-of-BOLT.patch
new file mode 100644
index 0000000..1d63246
--- /dev/null
+++ b/0088-BUGFIX-Fix-the-configure-file-of-BOLT.patch
@@ -0,0 +1,30102 @@
+From e245129ab722da21df3a2853474a9d4acf47fe67 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Fri, 26 Apr 2024 21:34:19 +0800
+Subject: [PATCH] [BUGFIX] Fix the configure file of BOLT
+
+---
+ Makefile.in             |  1319 +++++
+ bolt-plugin/Makefile.in |    34 +-
+ bolt-plugin/aclocal.m4  |  9169 +-----------------------------
+ bolt-plugin/config.h.in |   106 +-
+ bolt-plugin/configure   | 11313 +++++++++++++++-----------------------
+ 5 files changed, 5796 insertions(+), 16145 deletions(-)
+
+diff --git a/Makefile.in b/Makefile.in
+index 593495e16..7785b3d9a 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -1111,6 +1111,7 @@ configure-host:  \
+     maybe-configure-c++tools \
+     maybe-configure-gnattools \
+     maybe-configure-lto-plugin \
++    maybe-configure-bolt-plugin \
+     maybe-configure-libcc1 \
+     maybe-configure-gotools \
+     maybe-configure-libctf
+@@ -1288,6 +1289,9 @@ all-host: maybe-all-gnattools
+ @if lto-plugin-no-bootstrap
+ all-host: maybe-all-lto-plugin
+ @endif lto-plugin-no-bootstrap
++@if bolt-plugin-no-bootstrap
++all-host: maybe-all-bolt-plugin
++@endif bolt-plugin-no-bootstrap
+ all-host: maybe-all-libcc1
+ all-host: maybe-all-gotools
+ @if libctf-no-bootstrap
+@@ -1403,6 +1407,7 @@ info-host: maybe-info-utils
+ info-host: maybe-info-c++tools
+ info-host: maybe-info-gnattools
+ info-host: maybe-info-lto-plugin
++info-host: maybe-info-bolt-plugin
+ info-host: maybe-info-libcc1
+ info-host: maybe-info-gotools
+ info-host: maybe-info-libctf
+@@ -1493,6 +1498,7 @@ dvi-host: maybe-dvi-utils
+ dvi-host: maybe-dvi-c++tools
+ dvi-host: maybe-dvi-gnattools
+ dvi-host: maybe-dvi-lto-plugin
++dvi-host: maybe-dvi-bolt-plugin
+ dvi-host: maybe-dvi-libcc1
+ dvi-host: maybe-dvi-gotools
+ dvi-host: maybe-dvi-libctf
+@@ -1583,6 +1589,7 @@ pdf-host: maybe-pdf-utils
+ pdf-host: maybe-pdf-c++tools
+ pdf-host: maybe-pdf-gnattools
+ pdf-host: maybe-pdf-lto-plugin
++pdf-host: maybe-pdf-bolt-plugin
+ pdf-host: maybe-pdf-libcc1
+ pdf-host: maybe-pdf-gotools
+ pdf-host: maybe-pdf-libctf
+@@ -1673,6 +1680,7 @@ html-host: maybe-html-utils
+ html-host: maybe-html-c++tools
+ html-host: maybe-html-gnattools
+ html-host: maybe-html-lto-plugin
++html-host: maybe-html-bolt-plugin
+ html-host: maybe-html-libcc1
+ html-host: maybe-html-gotools
+ html-host: maybe-html-libctf
+@@ -1763,6 +1771,7 @@ TAGS-host: maybe-TAGS-utils
+ TAGS-host: maybe-TAGS-c++tools
+ TAGS-host: maybe-TAGS-gnattools
+ TAGS-host: maybe-TAGS-lto-plugin
++TAGS-host: maybe-TAGS-bolt-plugin
+ TAGS-host: maybe-TAGS-libcc1
+ TAGS-host: maybe-TAGS-gotools
+ TAGS-host: maybe-TAGS-libctf
+@@ -1853,6 +1862,7 @@ install-info-host: maybe-install-info-utils
+ install-info-host: maybe-install-info-c++tools
+ install-info-host: maybe-install-info-gnattools
+ install-info-host: maybe-install-info-lto-plugin
++install-info-host: maybe-install-info-bolt-plugin
+ install-info-host: maybe-install-info-libcc1
+ install-info-host: maybe-install-info-gotools
+ install-info-host: maybe-install-info-libctf
+@@ -1943,6 +1953,7 @@ install-dvi-host: maybe-install-dvi-utils
+ install-dvi-host: maybe-install-dvi-c++tools
+ install-dvi-host: maybe-install-dvi-gnattools
+ install-dvi-host: maybe-install-dvi-lto-plugin
++install-dvi-host: maybe-install-dvi-bolt-plugin
+ install-dvi-host: maybe-install-dvi-libcc1
+ install-dvi-host: maybe-install-dvi-gotools
+ install-dvi-host: maybe-install-dvi-libctf
+@@ -2033,6 +2044,7 @@ install-pdf-host: maybe-install-pdf-utils
+ install-pdf-host: maybe-install-pdf-c++tools
+ install-pdf-host: maybe-install-pdf-gnattools
+ install-pdf-host: maybe-install-pdf-lto-plugin
++install-pdf-host: maybe-install-pdf-bolt-plugin
+ install-pdf-host: maybe-install-pdf-libcc1
+ install-pdf-host: maybe-install-pdf-gotools
+ install-pdf-host: maybe-install-pdf-libctf
+@@ -2123,6 +2135,7 @@ install-html-host: maybe-install-html-utils
+ install-html-host: maybe-install-html-c++tools
+ install-html-host: maybe-install-html-gnattools
+ install-html-host: maybe-install-html-lto-plugin
++install-html-host: maybe-install-html-bolt-plugin
+ install-html-host: maybe-install-html-libcc1
+ install-html-host: maybe-install-html-gotools
+ install-html-host: maybe-install-html-libctf
+@@ -2213,6 +2226,7 @@ installcheck-host: maybe-installcheck-utils
+ installcheck-host: maybe-installcheck-c++tools
+ installcheck-host: maybe-installcheck-gnattools
+ installcheck-host: maybe-installcheck-lto-plugin
++installcheck-host: maybe-installcheck-bolt-plugin
+ installcheck-host: maybe-installcheck-libcc1
+ installcheck-host: maybe-installcheck-gotools
+ installcheck-host: maybe-installcheck-libctf
+@@ -2303,6 +2317,7 @@ mostlyclean-host: maybe-mostlyclean-utils
+ mostlyclean-host: maybe-mostlyclean-c++tools
+ mostlyclean-host: maybe-mostlyclean-gnattools
+ mostlyclean-host: maybe-mostlyclean-lto-plugin
++mostlyclean-host: maybe-mostlyclean-bolt-plugin
+ mostlyclean-host: maybe-mostlyclean-libcc1
+ mostlyclean-host: maybe-mostlyclean-gotools
+ mostlyclean-host: maybe-mostlyclean-libctf
+@@ -2393,6 +2408,7 @@ clean-host: maybe-clean-utils
+ clean-host: maybe-clean-c++tools
+ clean-host: maybe-clean-gnattools
+ clean-host: maybe-clean-lto-plugin
++clean-host: maybe-clean-bolt-plugin
+ clean-host: maybe-clean-libcc1
+ clean-host: maybe-clean-gotools
+ clean-host: maybe-clean-libctf
+@@ -2483,6 +2499,7 @@ distclean-host: maybe-distclean-utils
+ distclean-host: maybe-distclean-c++tools
+ distclean-host: maybe-distclean-gnattools
+ distclean-host: maybe-distclean-lto-plugin
++distclean-host: maybe-distclean-bolt-plugin
+ distclean-host: maybe-distclean-libcc1
+ distclean-host: maybe-distclean-gotools
+ distclean-host: maybe-distclean-libctf
+@@ -2573,6 +2590,7 @@ maintainer-clean-host: maybe-maintainer-clean-utils
+ maintainer-clean-host: maybe-maintainer-clean-c++tools
+ maintainer-clean-host: maybe-maintainer-clean-gnattools
+ maintainer-clean-host: maybe-maintainer-clean-lto-plugin
++maintainer-clean-host: maybe-maintainer-clean-bolt-plugin
+ maintainer-clean-host: maybe-maintainer-clean-libcc1
+ maintainer-clean-host: maybe-maintainer-clean-gotools
+ maintainer-clean-host: maybe-maintainer-clean-libctf
+@@ -2721,6 +2739,7 @@ check-host:  \
+     maybe-check-c++tools \
+     maybe-check-gnattools \
+     maybe-check-lto-plugin \
++    maybe-check-bolt-plugin \
+     maybe-check-libcc1 \
+     maybe-check-gotools \
+     maybe-check-libctf
+@@ -2858,6 +2877,7 @@ install-host-nogcc:  \
+     maybe-install-c++tools \
+     maybe-install-gnattools \
+     maybe-install-lto-plugin \
++    maybe-install-bolt-plugin \
+     maybe-install-libcc1 \
+     maybe-install-gotools \
+     maybe-install-libctf
+@@ -2913,6 +2933,7 @@ install-host:  \
+     maybe-install-c++tools \
+     maybe-install-gnattools \
+     maybe-install-lto-plugin \
++    maybe-install-bolt-plugin \
+     maybe-install-libcc1 \
+     maybe-install-gotools \
+     maybe-install-libctf
+@@ -3023,6 +3044,7 @@ install-strip-host:  \
+     maybe-install-strip-c++tools \
+     maybe-install-strip-gnattools \
+     maybe-install-strip-lto-plugin \
++    maybe-install-strip-bolt-plugin \
+     maybe-install-strip-libcc1 \
+     maybe-install-strip-gotools \
+     maybe-install-strip-libctf
+@@ -41493,6 +41515,1155 @@ maintainer-clean-lto-plugin:
+ 
+ 
+ 
++.PHONY: configure-bolt-plugin maybe-configure-bolt-plugin
++maybe-configure-bolt-plugin:
++@if gcc-bootstrap
++configure-bolt-plugin: stage_current
++@endif gcc-bootstrap
++@if bolt-plugin
++maybe-configure-bolt-plugin: configure-bolt-plugin
++configure-bolt-plugin: 
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	$(HOST_EXPORTS)  \
++	echo Configuring in $(HOST_SUBDIR)/bolt-plugin; \
++	cd "$(HOST_SUBDIR)/bolt-plugin" || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) \
++	  $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@ \
++	  || exit 1
++@endif bolt-plugin
++
++
++
++.PHONY: configure-stage1-bolt-plugin maybe-configure-stage1-bolt-plugin
++maybe-configure-stage1-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stage1-bolt-plugin: configure-stage1-bolt-plugin
++configure-stage1-bolt-plugin:
++	@[ $(current_stage) = stage1 ] || $(MAKE) stage1-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE1_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	CFLAGS="$(STAGE1_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGE1_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(LIBCFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage 1 in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	   \
++	  $(STAGE1_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stage2-bolt-plugin maybe-configure-stage2-bolt-plugin
++maybe-configure-stage2-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stage2-bolt-plugin: configure-stage2-bolt-plugin
++configure-stage2-bolt-plugin:
++	@[ $(current_stage) = stage2 ] || $(MAKE) stage2-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE2_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGE2_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGE2_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGE2_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage 2 in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGE2_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stage3-bolt-plugin maybe-configure-stage3-bolt-plugin
++maybe-configure-stage3-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stage3-bolt-plugin: configure-stage3-bolt-plugin
++configure-stage3-bolt-plugin:
++	@[ $(current_stage) = stage3 ] || $(MAKE) stage3-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE3_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGE3_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGE3_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGE3_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage 3 in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGE3_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stage4-bolt-plugin maybe-configure-stage4-bolt-plugin
++maybe-configure-stage4-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stage4-bolt-plugin: configure-stage4-bolt-plugin
++configure-stage4-bolt-plugin:
++	@[ $(current_stage) = stage4 ] || $(MAKE) stage4-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE4_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGE4_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGE4_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGE4_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage 4 in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGE4_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stageprofile-bolt-plugin maybe-configure-stageprofile-bolt-plugin
++maybe-configure-stageprofile-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stageprofile-bolt-plugin: configure-stageprofile-bolt-plugin
++configure-stageprofile-bolt-plugin:
++	@[ $(current_stage) = stageprofile ] || $(MAKE) stageprofile-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEprofile_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGEprofile_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGEprofile_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGEprofile_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage profile in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGEprofile_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stagetrain-bolt-plugin maybe-configure-stagetrain-bolt-plugin
++maybe-configure-stagetrain-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stagetrain-bolt-plugin: configure-stagetrain-bolt-plugin
++configure-stagetrain-bolt-plugin:
++	@[ $(current_stage) = stagetrain ] || $(MAKE) stagetrain-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEtrain_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGEtrain_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGEtrain_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGEtrain_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage train in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGEtrain_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stagefeedback-bolt-plugin maybe-configure-stagefeedback-bolt-plugin
++maybe-configure-stagefeedback-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stagefeedback-bolt-plugin: configure-stagefeedback-bolt-plugin
++configure-stagefeedback-bolt-plugin:
++	@[ $(current_stage) = stagefeedback ] || $(MAKE) stagefeedback-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEfeedback_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGEfeedback_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGEfeedback_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGEfeedback_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage feedback in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGEfeedback_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stageautoprofile-bolt-plugin maybe-configure-stageautoprofile-bolt-plugin
++maybe-configure-stageautoprofile-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stageautoprofile-bolt-plugin: configure-stageautoprofile-bolt-plugin
++configure-stageautoprofile-bolt-plugin:
++	@[ $(current_stage) = stageautoprofile ] || $(MAKE) stageautoprofile-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEautoprofile_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGEautoprofile_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGEautoprofile_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGEautoprofile_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage autoprofile in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGEautoprofile_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++.PHONY: configure-stageautofeedback-bolt-plugin maybe-configure-stageautofeedback-bolt-plugin
++maybe-configure-stageautofeedback-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-configure-stageautofeedback-bolt-plugin: configure-stageautofeedback-bolt-plugin
++configure-stageautofeedback-bolt-plugin:
++	@[ $(current_stage) = stageautofeedback ] || $(MAKE) stageautofeedback-start
++	@$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEautofeedback_TFLAGS)"; \
++	test ! -f $(HOST_SUBDIR)/bolt-plugin/Makefile || exit 0; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS) \
++	CFLAGS="$(STAGEautofeedback_CFLAGS)"; export CFLAGS; \
++	CXXFLAGS="$(STAGEautofeedback_CXXFLAGS)"; export CXXFLAGS; \
++	LIBCFLAGS="$(STAGEautofeedback_CFLAGS)"; export LIBCFLAGS;  \
++	echo Configuring stage autofeedback in $(HOST_SUBDIR)/bolt-plugin; \
++	$(SHELL) $(srcdir)/mkinstalldirs $(HOST_SUBDIR)/bolt-plugin; \
++	cd $(HOST_SUBDIR)/bolt-plugin || exit 1; \
++	case $(srcdir) in \
++	  /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
++	  *) topdir=`echo $(HOST_SUBDIR)/bolt-plugin/ | \
++		sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
++	esac; \
++	module_srcdir=bolt-plugin; \
++	$(SHELL) $$s/$$module_srcdir/configure \
++	  --srcdir=$${topdir}/$$module_srcdir \
++	  $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \
++	  --target=${target_alias} \
++	  --with-build-libsubdir=$(HOST_SUBDIR) \
++	  $(STAGEautofeedback_CONFIGURE_FLAGS) \
++	  --enable-shared @extra_linker_plugin_flags@ @extra_linker_plugin_configure_flags@
++@endif bolt-plugin-bootstrap
++
++
++
++
++
++.PHONY: all-bolt-plugin maybe-all-bolt-plugin
++maybe-all-bolt-plugin:
++@if gcc-bootstrap
++all-bolt-plugin: stage_current
++@endif gcc-bootstrap
++@if bolt-plugin
++TARGET-bolt-plugin=all
++maybe-all-bolt-plugin: all-bolt-plugin
++all-bolt-plugin: configure-bolt-plugin
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS)  \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS) $(STAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		$(TARGET-bolt-plugin))
++@endif bolt-plugin
++
++
++
++.PHONY: all-stage1-bolt-plugin maybe-all-stage1-bolt-plugin
++.PHONY: clean-stage1-bolt-plugin maybe-clean-stage1-bolt-plugin
++maybe-all-stage1-bolt-plugin:
++maybe-clean-stage1-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stage1-bolt-plugin: all-stage1-bolt-plugin
++all-stage1: all-stage1-bolt-plugin
++TARGET-stage1-bolt-plugin = $(TARGET-bolt-plugin)
++all-stage1-bolt-plugin: configure-stage1-bolt-plugin
++	@[ $(current_stage) = stage1 ] || $(MAKE) stage1-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE1_TFLAGS)"; \
++	$(HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGE1_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGE1_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGE1_CXXFLAGS)" \
++		LIBCFLAGS="$(LIBCFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS)  \
++		$(STAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGE1_TFLAGS)"  \
++		$(TARGET-stage1-bolt-plugin)
++
++maybe-clean-stage1-bolt-plugin: clean-stage1-bolt-plugin
++clean-stage1: clean-stage1-bolt-plugin
++clean-stage1-bolt-plugin:
++	@if [ $(current_stage) = stage1 ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stage1-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stage1-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS)  \
++	$(STAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stage2-bolt-plugin maybe-all-stage2-bolt-plugin
++.PHONY: clean-stage2-bolt-plugin maybe-clean-stage2-bolt-plugin
++maybe-all-stage2-bolt-plugin:
++maybe-clean-stage2-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stage2-bolt-plugin: all-stage2-bolt-plugin
++all-stage2: all-stage2-bolt-plugin
++TARGET-stage2-bolt-plugin = $(TARGET-bolt-plugin)
++all-stage2-bolt-plugin: configure-stage2-bolt-plugin
++	@[ $(current_stage) = stage2 ] || $(MAKE) stage2-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE2_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGE2_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGE2_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGE2_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGE2_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGE2_TFLAGS)"  \
++		$(TARGET-stage2-bolt-plugin)
++
++maybe-clean-stage2-bolt-plugin: clean-stage2-bolt-plugin
++clean-stage2: clean-stage2-bolt-plugin
++clean-stage2-bolt-plugin:
++	@if [ $(current_stage) = stage2 ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stage2-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stage2-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stage3-bolt-plugin maybe-all-stage3-bolt-plugin
++.PHONY: clean-stage3-bolt-plugin maybe-clean-stage3-bolt-plugin
++maybe-all-stage3-bolt-plugin:
++maybe-clean-stage3-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stage3-bolt-plugin: all-stage3-bolt-plugin
++all-stage3: all-stage3-bolt-plugin
++TARGET-stage3-bolt-plugin = $(TARGET-bolt-plugin)
++all-stage3-bolt-plugin: configure-stage3-bolt-plugin
++	@[ $(current_stage) = stage3 ] || $(MAKE) stage3-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE3_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGE3_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGE3_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGE3_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGE3_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGE3_TFLAGS)"  \
++		$(TARGET-stage3-bolt-plugin)
++
++maybe-clean-stage3-bolt-plugin: clean-stage3-bolt-plugin
++clean-stage3: clean-stage3-bolt-plugin
++clean-stage3-bolt-plugin:
++	@if [ $(current_stage) = stage3 ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stage3-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stage3-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stage4-bolt-plugin maybe-all-stage4-bolt-plugin
++.PHONY: clean-stage4-bolt-plugin maybe-clean-stage4-bolt-plugin
++maybe-all-stage4-bolt-plugin:
++maybe-clean-stage4-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stage4-bolt-plugin: all-stage4-bolt-plugin
++all-stage4: all-stage4-bolt-plugin
++TARGET-stage4-bolt-plugin = $(TARGET-bolt-plugin)
++all-stage4-bolt-plugin: configure-stage4-bolt-plugin
++	@[ $(current_stage) = stage4 ] || $(MAKE) stage4-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGE4_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGE4_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGE4_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGE4_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGE4_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGE4_TFLAGS)"  \
++		$(TARGET-stage4-bolt-plugin)
++
++maybe-clean-stage4-bolt-plugin: clean-stage4-bolt-plugin
++clean-stage4: clean-stage4-bolt-plugin
++clean-stage4-bolt-plugin:
++	@if [ $(current_stage) = stage4 ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stage4-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stage4-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stageprofile-bolt-plugin maybe-all-stageprofile-bolt-plugin
++.PHONY: clean-stageprofile-bolt-plugin maybe-clean-stageprofile-bolt-plugin
++maybe-all-stageprofile-bolt-plugin:
++maybe-clean-stageprofile-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stageprofile-bolt-plugin: all-stageprofile-bolt-plugin
++all-stageprofile: all-stageprofile-bolt-plugin
++TARGET-stageprofile-bolt-plugin = $(TARGET-bolt-plugin)
++all-stageprofile-bolt-plugin: configure-stageprofile-bolt-plugin
++	@[ $(current_stage) = stageprofile ] || $(MAKE) stageprofile-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEprofile_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGEprofile_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGEprofile_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGEprofile_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGEprofile_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGEprofile_TFLAGS)"  \
++		$(TARGET-stageprofile-bolt-plugin)
++
++maybe-clean-stageprofile-bolt-plugin: clean-stageprofile-bolt-plugin
++clean-stageprofile: clean-stageprofile-bolt-plugin
++clean-stageprofile-bolt-plugin:
++	@if [ $(current_stage) = stageprofile ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stageprofile-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stageprofile-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stagetrain-bolt-plugin maybe-all-stagetrain-bolt-plugin
++.PHONY: clean-stagetrain-bolt-plugin maybe-clean-stagetrain-bolt-plugin
++maybe-all-stagetrain-bolt-plugin:
++maybe-clean-stagetrain-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stagetrain-bolt-plugin: all-stagetrain-bolt-plugin
++all-stagetrain: all-stagetrain-bolt-plugin
++TARGET-stagetrain-bolt-plugin = $(TARGET-bolt-plugin)
++all-stagetrain-bolt-plugin: configure-stagetrain-bolt-plugin
++	@[ $(current_stage) = stagetrain ] || $(MAKE) stagetrain-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEtrain_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGEtrain_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGEtrain_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGEtrain_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGEtrain_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGEtrain_TFLAGS)"  \
++		$(TARGET-stagetrain-bolt-plugin)
++
++maybe-clean-stagetrain-bolt-plugin: clean-stagetrain-bolt-plugin
++clean-stagetrain: clean-stagetrain-bolt-plugin
++clean-stagetrain-bolt-plugin:
++	@if [ $(current_stage) = stagetrain ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stagetrain-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stagetrain-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stagefeedback-bolt-plugin maybe-all-stagefeedback-bolt-plugin
++.PHONY: clean-stagefeedback-bolt-plugin maybe-clean-stagefeedback-bolt-plugin
++maybe-all-stagefeedback-bolt-plugin:
++maybe-clean-stagefeedback-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stagefeedback-bolt-plugin: all-stagefeedback-bolt-plugin
++all-stagefeedback: all-stagefeedback-bolt-plugin
++TARGET-stagefeedback-bolt-plugin = $(TARGET-bolt-plugin)
++all-stagefeedback-bolt-plugin: configure-stagefeedback-bolt-plugin
++	@[ $(current_stage) = stagefeedback ] || $(MAKE) stagefeedback-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEfeedback_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGEfeedback_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGEfeedback_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGEfeedback_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGEfeedback_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGEfeedback_TFLAGS)"  \
++		$(TARGET-stagefeedback-bolt-plugin)
++
++maybe-clean-stagefeedback-bolt-plugin: clean-stagefeedback-bolt-plugin
++clean-stagefeedback: clean-stagefeedback-bolt-plugin
++clean-stagefeedback-bolt-plugin:
++	@if [ $(current_stage) = stagefeedback ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stagefeedback-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stagefeedback-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stageautoprofile-bolt-plugin maybe-all-stageautoprofile-bolt-plugin
++.PHONY: clean-stageautoprofile-bolt-plugin maybe-clean-stageautoprofile-bolt-plugin
++maybe-all-stageautoprofile-bolt-plugin:
++maybe-clean-stageautoprofile-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stageautoprofile-bolt-plugin: all-stageautoprofile-bolt-plugin
++all-stageautoprofile: all-stageautoprofile-bolt-plugin
++TARGET-stageautoprofile-bolt-plugin = $(TARGET-bolt-plugin)
++all-stageautoprofile-bolt-plugin: configure-stageautoprofile-bolt-plugin
++	@[ $(current_stage) = stageautoprofile ] || $(MAKE) stageautoprofile-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEautoprofile_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$$s/gcc/config/i386/$(AUTO_PROFILE) \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGEautoprofile_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGEautoprofile_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGEautoprofile_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGEautoprofile_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGEautoprofile_TFLAGS)"  \
++		$(TARGET-stageautoprofile-bolt-plugin)
++
++maybe-clean-stageautoprofile-bolt-plugin: clean-stageautoprofile-bolt-plugin
++clean-stageautoprofile: clean-stageautoprofile-bolt-plugin
++clean-stageautoprofile-bolt-plugin:
++	@if [ $(current_stage) = stageautoprofile ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stageautoprofile-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stageautoprofile-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++.PHONY: all-stageautofeedback-bolt-plugin maybe-all-stageautofeedback-bolt-plugin
++.PHONY: clean-stageautofeedback-bolt-plugin maybe-clean-stageautofeedback-bolt-plugin
++maybe-all-stageautofeedback-bolt-plugin:
++maybe-clean-stageautofeedback-bolt-plugin:
++@if bolt-plugin-bootstrap
++maybe-all-stageautofeedback-bolt-plugin: all-stageautofeedback-bolt-plugin
++all-stageautofeedback: all-stageautofeedback-bolt-plugin
++TARGET-stageautofeedback-bolt-plugin = $(TARGET-bolt-plugin)
++all-stageautofeedback-bolt-plugin: configure-stageautofeedback-bolt-plugin
++	@[ $(current_stage) = stageautofeedback ] || $(MAKE) stageautofeedback-start
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	TFLAGS="$(STAGEautofeedback_TFLAGS)"; \
++	$(HOST_EXPORTS) \
++	$(POSTSTAGE1_HOST_EXPORTS)  \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	 \
++	$(MAKE) $(BASE_FLAGS_TO_PASS) \
++		CFLAGS="$(STAGEautofeedback_CFLAGS)" \
++		GENERATOR_CFLAGS="$(STAGEautofeedback_GENERATOR_CFLAGS)" \
++		CXXFLAGS="$(STAGEautofeedback_CXXFLAGS)" \
++		LIBCFLAGS="$(STAGEautofeedback_CFLAGS)" \
++		CFLAGS_FOR_TARGET="$(CFLAGS_FOR_TARGET)" \
++		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
++		LIBCFLAGS_FOR_TARGET="$(LIBCFLAGS_FOR_TARGET)" \
++		$(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ \
++		TFLAGS="$(STAGEautofeedback_TFLAGS)" PERF_DATA=perf.data \
++		$(TARGET-stageautofeedback-bolt-plugin)
++
++maybe-clean-stageautofeedback-bolt-plugin: clean-stageautofeedback-bolt-plugin
++clean-stageautofeedback: clean-stageautofeedback-bolt-plugin
++clean-stageautofeedback-bolt-plugin:
++	@if [ $(current_stage) = stageautofeedback ]; then \
++	  [ -f $(HOST_SUBDIR)/bolt-plugin/Makefile ] || exit 0; \
++	else \
++	  [ -f $(HOST_SUBDIR)/stageautofeedback-bolt-plugin/Makefile ] || exit 0; \
++	  $(MAKE) stageautofeedback-start; \
++	fi; \
++	cd $(HOST_SUBDIR)/bolt-plugin && \
++	$(MAKE) $(EXTRA_HOST_FLAGS) $(POSTSTAGE1_FLAGS_TO_PASS) @extra_linker_plugin_flags@ clean
++@endif bolt-plugin-bootstrap
++
++
++
++
++
++.PHONY: check-bolt-plugin maybe-check-bolt-plugin
++maybe-check-bolt-plugin:
++@if bolt-plugin
++maybe-check-bolt-plugin: check-bolt-plugin
++
++check-bolt-plugin:
++	@: $(MAKE); $(unstage)
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(FLAGS_TO_PASS) @extra_linker_plugin_flags@ $(EXTRA_BOOTSTRAP_FLAGS) check)
++
++@endif bolt-plugin
++
++.PHONY: install-bolt-plugin maybe-install-bolt-plugin
++maybe-install-bolt-plugin:
++@if bolt-plugin
++maybe-install-bolt-plugin: install-bolt-plugin
++
++install-bolt-plugin: installdirs
++	@: $(MAKE); $(unstage)
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(FLAGS_TO_PASS) @extra_linker_plugin_flags@ install)
++
++@endif bolt-plugin
++
++.PHONY: install-strip-bolt-plugin maybe-install-strip-bolt-plugin
++maybe-install-strip-bolt-plugin:
++@if bolt-plugin
++maybe-install-strip-bolt-plugin: install-strip-bolt-plugin
++
++install-strip-bolt-plugin: installdirs
++	@: $(MAKE); $(unstage)
++	@r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(FLAGS_TO_PASS) @extra_linker_plugin_flags@ install-strip)
++
++@endif bolt-plugin
++
++# Other targets (info, dvi, pdf, etc.)
++
++.PHONY: maybe-info-bolt-plugin info-bolt-plugin
++maybe-info-bolt-plugin:
++@if bolt-plugin
++maybe-info-bolt-plugin: info-bolt-plugin
++
++info-bolt-plugin: \
++    configure-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing info in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          info) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-dvi-bolt-plugin dvi-bolt-plugin
++maybe-dvi-bolt-plugin:
++@if bolt-plugin
++maybe-dvi-bolt-plugin: dvi-bolt-plugin
++
++dvi-bolt-plugin: \
++    configure-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing dvi in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          dvi) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-pdf-bolt-plugin pdf-bolt-plugin
++maybe-pdf-bolt-plugin:
++@if bolt-plugin
++maybe-pdf-bolt-plugin: pdf-bolt-plugin
++
++pdf-bolt-plugin: \
++    configure-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing pdf in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          pdf) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-html-bolt-plugin html-bolt-plugin
++maybe-html-bolt-plugin:
++@if bolt-plugin
++maybe-html-bolt-plugin: html-bolt-plugin
++
++html-bolt-plugin: \
++    configure-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing html in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          html) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-TAGS-bolt-plugin TAGS-bolt-plugin
++maybe-TAGS-bolt-plugin:
++@if bolt-plugin
++maybe-TAGS-bolt-plugin: TAGS-bolt-plugin
++
++TAGS-bolt-plugin: \
++    configure-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing TAGS in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          TAGS) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-install-info-bolt-plugin install-info-bolt-plugin
++maybe-install-info-bolt-plugin:
++@if bolt-plugin
++maybe-install-info-bolt-plugin: install-info-bolt-plugin
++
++install-info-bolt-plugin: \
++    configure-bolt-plugin \
++    info-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing install-info in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          install-info) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-install-dvi-bolt-plugin install-dvi-bolt-plugin
++maybe-install-dvi-bolt-plugin:
++@if bolt-plugin
++maybe-install-dvi-bolt-plugin: install-dvi-bolt-plugin
++
++install-dvi-bolt-plugin: \
++    configure-bolt-plugin \
++    dvi-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing install-dvi in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          install-dvi) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-install-pdf-bolt-plugin install-pdf-bolt-plugin
++maybe-install-pdf-bolt-plugin:
++@if bolt-plugin
++maybe-install-pdf-bolt-plugin: install-pdf-bolt-plugin
++
++install-pdf-bolt-plugin: \
++    configure-bolt-plugin \
++    pdf-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing install-pdf in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          install-pdf) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-install-html-bolt-plugin install-html-bolt-plugin
++maybe-install-html-bolt-plugin:
++@if bolt-plugin
++maybe-install-html-bolt-plugin: install-html-bolt-plugin
++
++install-html-bolt-plugin: \
++    configure-bolt-plugin \
++    html-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing install-html in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          install-html) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-installcheck-bolt-plugin installcheck-bolt-plugin
++maybe-installcheck-bolt-plugin:
++@if bolt-plugin
++maybe-installcheck-bolt-plugin: installcheck-bolt-plugin
++
++installcheck-bolt-plugin: \
++    configure-bolt-plugin 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing installcheck in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          installcheck) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-mostlyclean-bolt-plugin mostlyclean-bolt-plugin
++maybe-mostlyclean-bolt-plugin:
++@if bolt-plugin
++maybe-mostlyclean-bolt-plugin: mostlyclean-bolt-plugin
++
++mostlyclean-bolt-plugin: 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing mostlyclean in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          mostlyclean) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-clean-bolt-plugin clean-bolt-plugin
++maybe-clean-bolt-plugin:
++@if bolt-plugin
++maybe-clean-bolt-plugin: clean-bolt-plugin
++
++clean-bolt-plugin: 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing clean in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          clean) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-distclean-bolt-plugin distclean-bolt-plugin
++maybe-distclean-bolt-plugin:
++@if bolt-plugin
++maybe-distclean-bolt-plugin: distclean-bolt-plugin
++
++distclean-bolt-plugin: 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing distclean in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          distclean) \
++	  || exit 1
++
++@endif bolt-plugin
++
++.PHONY: maybe-maintainer-clean-bolt-plugin maintainer-clean-bolt-plugin
++maybe-maintainer-clean-bolt-plugin:
++@if bolt-plugin
++maybe-maintainer-clean-bolt-plugin: maintainer-clean-bolt-plugin
++
++maintainer-clean-bolt-plugin: 
++	@[ -f ./bolt-plugin/Makefile ] || exit 0; \
++	r=`${PWD_COMMAND}`; export r; \
++	s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
++	$(HOST_EXPORTS) \
++	for flag in $(EXTRA_HOST_FLAGS) @extra_linker_plugin_flags@; do \
++	  eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
++	done; \
++	echo "Doing maintainer-clean in bolt-plugin"; \
++	(cd $(HOST_SUBDIR)/bolt-plugin && \
++	  $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
++	          "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
++	          "RANLIB=$${RANLIB}" \
++	          "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
++	          maintainer-clean) \
++	  || exit 1
++
++@endif bolt-plugin
++
++
++
+ .PHONY: configure-libcc1 maybe-configure-libcc1
+ maybe-configure-libcc1:
+ @if gcc-bootstrap
+@@ -61940,6 +63111,11 @@ stage1-start::
+ 	  mkdir stage1-lto-plugin; \
+ 	mv stage1-lto-plugin lto-plugin
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stage1-bolt-plugin ] || \
++	  mkdir stage1-bolt-plugin; \
++	mv stage1-bolt-plugin bolt-plugin
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stage1-libctf ] || \
+ 	  mkdir stage1-libctf; \
+@@ -62065,6 +63241,11 @@ stage1-end::
+ 	  cd $(HOST_SUBDIR); mv lto-plugin stage1-lto-plugin; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stage1-bolt-plugin; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stage1-libctf; \
+@@ -62256,6 +63437,12 @@ stage2-start::
+ 	mv stage2-lto-plugin lto-plugin; \
+ 	mv stage1-lto-plugin prev-lto-plugin || test -f stage1-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stage2-bolt-plugin ] || \
++	  mkdir stage2-bolt-plugin; \
++	mv stage2-bolt-plugin bolt-plugin; \
++	mv stage1-bolt-plugin prev-bolt-plugin || test -f stage1-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stage2-libctf ] || \
+ 	  mkdir stage2-libctf; \
+@@ -62406,6 +63593,12 @@ stage2-end::
+ 	  mv prev-lto-plugin stage1-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stage2-bolt-plugin; \
++	  mv prev-bolt-plugin stage1-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stage2-libctf; \
+@@ -62622,6 +63815,12 @@ stage3-start::
+ 	mv stage3-lto-plugin lto-plugin; \
+ 	mv stage2-lto-plugin prev-lto-plugin || test -f stage2-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stage3-bolt-plugin ] || \
++	  mkdir stage3-bolt-plugin; \
++	mv stage3-bolt-plugin bolt-plugin; \
++	mv stage2-bolt-plugin prev-bolt-plugin || test -f stage2-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stage3-libctf ] || \
+ 	  mkdir stage3-libctf; \
+@@ -62772,6 +63971,12 @@ stage3-end::
+ 	  mv prev-lto-plugin stage2-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stage3-bolt-plugin; \
++	  mv prev-bolt-plugin stage2-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stage3-libctf; \
+@@ -63044,6 +64249,12 @@ stage4-start::
+ 	mv stage4-lto-plugin lto-plugin; \
+ 	mv stage3-lto-plugin prev-lto-plugin || test -f stage3-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stage4-bolt-plugin ] || \
++	  mkdir stage4-bolt-plugin; \
++	mv stage4-bolt-plugin bolt-plugin; \
++	mv stage3-bolt-plugin prev-bolt-plugin || test -f stage3-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stage4-libctf ] || \
+ 	  mkdir stage4-libctf; \
+@@ -63194,6 +64405,12 @@ stage4-end::
+ 	  mv prev-lto-plugin stage3-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stage4-bolt-plugin; \
++	  mv prev-bolt-plugin stage3-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stage4-libctf; \
+@@ -63454,6 +64671,12 @@ stageprofile-start::
+ 	mv stageprofile-lto-plugin lto-plugin; \
+ 	mv stage1-lto-plugin prev-lto-plugin || test -f stage1-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stageprofile-bolt-plugin ] || \
++	  mkdir stageprofile-bolt-plugin; \
++	mv stageprofile-bolt-plugin bolt-plugin; \
++	mv stage1-bolt-plugin prev-bolt-plugin || test -f stage1-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stageprofile-libctf ] || \
+ 	  mkdir stageprofile-libctf; \
+@@ -63604,6 +64827,12 @@ stageprofile-end::
+ 	  mv prev-lto-plugin stage1-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stageprofile-bolt-plugin; \
++	  mv prev-bolt-plugin stage1-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stageprofile-libctf; \
+@@ -63797,6 +65026,12 @@ stagetrain-start::
+ 	mv stagetrain-lto-plugin lto-plugin; \
+ 	mv stageprofile-lto-plugin prev-lto-plugin || test -f stageprofile-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stagetrain-bolt-plugin ] || \
++	  mkdir stagetrain-bolt-plugin; \
++	mv stagetrain-bolt-plugin bolt-plugin; \
++	mv stageprofile-bolt-plugin prev-bolt-plugin || test -f stageprofile-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stagetrain-libctf ] || \
+ 	  mkdir stagetrain-libctf; \
+@@ -63947,6 +65182,12 @@ stagetrain-end::
+ 	  mv prev-lto-plugin stageprofile-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stagetrain-bolt-plugin; \
++	  mv prev-bolt-plugin stageprofile-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stagetrain-libctf; \
+@@ -64140,6 +65381,12 @@ stagefeedback-start::
+ 	mv stagefeedback-lto-plugin lto-plugin; \
+ 	mv stagetrain-lto-plugin prev-lto-plugin || test -f stagetrain-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stagefeedback-bolt-plugin ] || \
++	  mkdir stagefeedback-bolt-plugin; \
++	mv stagefeedback-bolt-plugin bolt-plugin; \
++	mv stagetrain-bolt-plugin prev-bolt-plugin || test -f stagetrain-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stagefeedback-libctf ] || \
+ 	  mkdir stagefeedback-libctf; \
+@@ -64290,6 +65537,12 @@ stagefeedback-end::
+ 	  mv prev-lto-plugin stagetrain-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stagefeedback-bolt-plugin; \
++	  mv prev-bolt-plugin stagetrain-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stagefeedback-libctf; \
+@@ -64506,6 +65759,12 @@ stageautoprofile-start::
+ 	mv stageautoprofile-lto-plugin lto-plugin; \
+ 	mv stage1-lto-plugin prev-lto-plugin || test -f stage1-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stageautoprofile-bolt-plugin ] || \
++	  mkdir stageautoprofile-bolt-plugin; \
++	mv stageautoprofile-bolt-plugin bolt-plugin; \
++	mv stage1-bolt-plugin prev-bolt-plugin || test -f stage1-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stageautoprofile-libctf ] || \
+ 	  mkdir stageautoprofile-libctf; \
+@@ -64656,6 +65915,12 @@ stageautoprofile-end::
+ 	  mv prev-lto-plugin stage1-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stageautoprofile-bolt-plugin; \
++	  mv prev-bolt-plugin stage1-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stageautoprofile-libctf; \
+@@ -64849,6 +66114,12 @@ stageautofeedback-start::
+ 	mv stageautofeedback-lto-plugin lto-plugin; \
+ 	mv stageautoprofile-lto-plugin prev-lto-plugin || test -f stageautoprofile-lean 
+ @endif lto-plugin
++@if bolt-plugin
++	@cd $(HOST_SUBDIR); [ -d stageautofeedback-bolt-plugin ] || \
++	  mkdir stageautofeedback-bolt-plugin; \
++	mv stageautofeedback-bolt-plugin bolt-plugin; \
++	mv stageautoprofile-bolt-plugin prev-bolt-plugin || test -f stageautoprofile-lean 
++@endif bolt-plugin
+ @if libctf
+ 	@cd $(HOST_SUBDIR); [ -d stageautofeedback-libctf ] || \
+ 	  mkdir stageautofeedback-libctf; \
+@@ -64999,6 +66270,12 @@ stageautofeedback-end::
+ 	  mv prev-lto-plugin stageautoprofile-lto-plugin; : ; \
+ 	fi
+ @endif lto-plugin
++@if bolt-plugin
++	@if test -d $(HOST_SUBDIR)/bolt-plugin; then \
++	  cd $(HOST_SUBDIR); mv bolt-plugin stageautofeedback-bolt-plugin; \
++	  mv prev-bolt-plugin stageautoprofile-bolt-plugin; : ; \
++	fi
++@endif bolt-plugin
+ @if libctf
+ 	@if test -d $(HOST_SUBDIR)/libctf; then \
+ 	  cd $(HOST_SUBDIR); mv libctf stageautofeedback-libctf; \
+@@ -65321,6 +66598,16 @@ configure-stagetrain-gcc: maybe-all-stagetrain-lto-plugin
+ configure-stagefeedback-gcc: maybe-all-stagefeedback-lto-plugin
+ configure-stageautoprofile-gcc: maybe-all-stageautoprofile-lto-plugin
+ configure-stageautofeedback-gcc: maybe-all-stageautofeedback-lto-plugin
++configure-gcc: maybe-all-bolt-plugin
++configure-stage1-gcc: maybe-all-stage1-bolt-plugin
++configure-stage2-gcc: maybe-all-stage2-bolt-plugin
++configure-stage3-gcc: maybe-all-stage3-bolt-plugin
++configure-stage4-gcc: maybe-all-stage4-bolt-plugin
++configure-stageprofile-gcc: maybe-all-stageprofile-bolt-plugin
++configure-stagetrain-gcc: maybe-all-stagetrain-bolt-plugin
++configure-stagefeedback-gcc: maybe-all-stagefeedback-bolt-plugin
++configure-stageautoprofile-gcc: maybe-all-stageautoprofile-bolt-plugin
++configure-stageautofeedback-gcc: maybe-all-stageautofeedback-bolt-plugin
+ configure-gcc: maybe-all-binutils
+ configure-stage1-gcc: maybe-all-stage1-binutils
+ configure-stage2-gcc: maybe-all-stage2-binutils
+@@ -65571,6 +66858,16 @@ all-stagetrain-gcc: maybe-all-stagetrain-lto-plugin
+ all-stagefeedback-gcc: maybe-all-stagefeedback-lto-plugin
+ all-stageautoprofile-gcc: maybe-all-stageautoprofile-lto-plugin
+ all-stageautofeedback-gcc: maybe-all-stageautofeedback-lto-plugin
++all-gcc: maybe-all-bolt-plugin
++all-stage1-gcc: maybe-all-stage1-bolt-plugin
++all-stage2-gcc: maybe-all-stage2-bolt-plugin
++all-stage3-gcc: maybe-all-stage3-bolt-plugin
++all-stage4-gcc: maybe-all-stage4-bolt-plugin
++all-stageprofile-gcc: maybe-all-stageprofile-bolt-plugin
++all-stagetrain-gcc: maybe-all-stagetrain-bolt-plugin
++all-stagefeedback-gcc: maybe-all-stagefeedback-bolt-plugin
++all-stageautoprofile-gcc: maybe-all-stageautoprofile-bolt-plugin
++all-stageautofeedback-gcc: maybe-all-stageautofeedback-bolt-plugin
+ all-gcc: maybe-all-libiconv
+ all-stage1-gcc: maybe-all-stage1-libiconv
+ all-stage2-gcc: maybe-all-stage2-libiconv
+@@ -65623,8 +66920,10 @@ html-stageautoprofile-gcc: maybe-all-build-libiberty
+ html-stageautofeedback-gcc: maybe-all-build-libiberty
+ install-gcc: maybe-install-fixincludes
+ install-gcc: maybe-install-lto-plugin
++install-gcc: maybe-install-bolt-plugin
+ install-strip-gcc: maybe-install-strip-fixincludes
+ install-strip-gcc: maybe-install-strip-lto-plugin
++install-strip-gcc: maybe-install-strip-bolt-plugin
+ configure-libcpp: configure-libiberty
+ configure-stage1-libcpp: configure-stage1-libiberty
+ configure-stage2-libcpp: configure-stage2-libiberty
+@@ -65716,6 +67015,26 @@ all-stagetrain-lto-plugin: maybe-all-stagetrain-libiberty-linker-plugin
+ all-stagefeedback-lto-plugin: maybe-all-stagefeedback-libiberty-linker-plugin
+ all-stageautoprofile-lto-plugin: maybe-all-stageautoprofile-libiberty-linker-plugin
+ all-stageautofeedback-lto-plugin: maybe-all-stageautofeedback-libiberty-linker-plugin
++all-bolt-plugin: maybe-all-libiberty
++all-stage1-bolt-plugin: maybe-all-stage1-libiberty
++all-stage2-bolt-plugin: maybe-all-stage2-libiberty
++all-stage3-bolt-plugin: maybe-all-stage3-libiberty
++all-stage4-bolt-plugin: maybe-all-stage4-libiberty
++all-stageprofile-bolt-plugin: maybe-all-stageprofile-libiberty
++all-stagetrain-bolt-plugin: maybe-all-stagetrain-libiberty
++all-stagefeedback-bolt-plugin: maybe-all-stagefeedback-libiberty
++all-stageautoprofile-bolt-plugin: maybe-all-stageautoprofile-libiberty
++all-stageautofeedback-bolt-plugin: maybe-all-stageautofeedback-libiberty
++all-bolt-plugin: maybe-all-libiberty-linker-plugin
++all-stage1-bolt-plugin: maybe-all-stage1-libiberty-linker-plugin
++all-stage2-bolt-plugin: maybe-all-stage2-libiberty-linker-plugin
++all-stage3-bolt-plugin: maybe-all-stage3-libiberty-linker-plugin
++all-stage4-bolt-plugin: maybe-all-stage4-libiberty-linker-plugin
++all-stageprofile-bolt-plugin: maybe-all-stageprofile-libiberty-linker-plugin
++all-stagetrain-bolt-plugin: maybe-all-stagetrain-libiberty-linker-plugin
++all-stagefeedback-bolt-plugin: maybe-all-stagefeedback-libiberty-linker-plugin
++all-stageautoprofile-bolt-plugin: maybe-all-stageautoprofile-libiberty-linker-plugin
++all-stageautofeedback-bolt-plugin: maybe-all-stageautofeedback-libiberty-linker-plugin
+ all-gotools: maybe-all-target-libgo
+ configure-intl: maybe-all-libiconv
+ configure-stage1-intl: maybe-all-stage1-libiconv
+diff --git a/bolt-plugin/Makefile.in b/bolt-plugin/Makefile.in
+index 11b59407e..0a58abc45 100644
+--- a/bolt-plugin/Makefile.in
++++ b/bolt-plugin/Makefile.in
+@@ -1,7 +1,7 @@
+-# Makefile.in generated by automake 1.16.5 from Makefile.am.
++# Makefile.in generated by automake 1.16.2 from Makefile.am.
+ # @configure_input@
+ 
+-# Copyright (C) 1994-2021 Free Software Foundation, Inc.
++# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+ 
+ # This Makefile.in is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -91,7 +91,15 @@ host_triplet = @host@
+ target_triplet = @target@
+ subdir = .
+ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/configure.ac
++am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
++	$(top_srcdir)/../config/depstand.m4 \
++	$(top_srcdir)/../config/lead-dot.m4 \
++	$(top_srcdir)/../config/lthostflags.m4 \
++	$(top_srcdir)/../config/override.m4 \
++	$(top_srcdir)/../config/warnings.m4 \
++	$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
++	$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
++	$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/configure.ac
+ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ 	$(ACLOCAL_M4)
+ DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+@@ -194,6 +202,9 @@ am__define_uniq_tagged_files = \
+   unique=`for i in $$list; do \
+     if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+   done | $(am__uniquify_input)`
++ETAGS = etags
++CTAGS = ctags
++CSCOPE = cscope
+ AM_RECURSIVE_TARGETS = cscope
+ ACLOCAL = @ACLOCAL@
+ AMTAR = @AMTAR@
+@@ -206,9 +217,8 @@ AWK = @AWK@
+ CC = @CC@
+ CCDEPMODE = @CCDEPMODE@
+ CFLAGS = @CFLAGS@
++CPP = @CPP@
+ CPPFLAGS = @CPPFLAGS@
+-CSCOPE = @CSCOPE@
+-CTAGS = @CTAGS@
+ CXX = @CXX@
+ CXXCPP = @CXXCPP@
+ CXXDEPMODE = @CXXDEPMODE@
+@@ -216,17 +226,14 @@ CXXFLAGS = @CXXFLAGS@
+ CYGPATH_W = @CYGPATH_W@
+ DEFS = @DEFS@
+ DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+ DSYMUTIL = @DSYMUTIL@
+ DUMPBIN = @DUMPBIN@
+ ECHO_C = @ECHO_C@
+ ECHO_N = @ECHO_N@
+ ECHO_T = @ECHO_T@
+ EGREP = @EGREP@
+-ETAGS = @ETAGS@
+ EXEEXT = @EXEEXT@
+ FGREP = @FGREP@
+-FILECMD = @FILECMD@
+ GREP = @GREP@
+ INSTALL = @INSTALL@
+ INSTALL_DATA = @INSTALL_DATA@
+@@ -241,10 +248,8 @@ LIBTOOL = @LIBTOOL@
+ LIPO = @LIPO@
+ LN_S = @LN_S@
+ LTLIBOBJS = @LTLIBOBJS@
+-LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+ MAINT = @MAINT@
+ MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+ MKDIR_P = @MKDIR_P@
+ NM = @NM@
+ NMEDIT = @NMEDIT@
+@@ -271,7 +276,7 @@ abs_srcdir = @abs_srcdir@
+ abs_top_builddir = @abs_top_builddir@
+ abs_top_srcdir = @abs_top_srcdir@
+ ac_bolt_plugin_ldflags = @ac_bolt_plugin_ldflags@
+-ac_ct_AR = @ac_ct_AR@
++ac_bolt_plugin_warn_cflags = @ac_bolt_plugin_warn_cflags@
+ ac_ct_CC = @ac_ct_CC@
+ ac_ct_CXX = @ac_ct_CXX@
+ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+@@ -285,7 +290,9 @@ bindir = @bindir@
+ build = @build@
+ build_alias = @build_alias@
+ build_cpu = @build_cpu@
++build_libsubdir = @build_libsubdir@
+ build_os = @build_os@
++build_subdir = @build_subdir@
+ build_vendor = @build_vendor@
+ builddir = @builddir@
+ datadir = @datadir@
+@@ -294,10 +301,12 @@ docdir = @docdir@
+ dvidir = @dvidir@
+ exec_prefix = @exec_prefix@
+ gcc_build_dir = @gcc_build_dir@
++get_gcc_base_ver = @get_gcc_base_ver@
+ host = @host@
+ host_alias = @host_alias@
+ host_cpu = @host_cpu@
+ host_os = @host_os@
++host_subdir = @host_subdir@
+ host_vendor = @host_vendor@
+ htmldir = @htmldir@
+ includedir = @includedir@
+@@ -307,6 +316,7 @@ libdir = @libdir@
+ libexecdir = @libexecdir@
+ localedir = @localedir@
+ localstatedir = @localstatedir@
++lt_host_flags = @lt_host_flags@
+ mandir = @mandir@
+ mkdir_p = @mkdir_p@
+ oldincludedir = @oldincludedir@
+@@ -315,7 +325,6 @@ prefix = @prefix@
+ program_transform_name = @program_transform_name@
+ psdir = @psdir@
+ real_target_noncanonical = @real_target_noncanonical@
+-runstatedir = @runstatedir@
+ sbindir = @sbindir@
+ sharedstatedir = @sharedstatedir@
+ srcdir = @srcdir@
+@@ -325,6 +334,7 @@ target_alias = @target_alias@
+ target_cpu = @target_cpu@
+ target_noncanonical := @target_noncanonical@
+ target_os = @target_os@
++target_subdir = @target_subdir@
+ target_vendor = @target_vendor@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+diff --git a/bolt-plugin/aclocal.m4 b/bolt-plugin/aclocal.m4
+index 679f2baa4..73bf7852c 100644
+--- a/bolt-plugin/aclocal.m4
++++ b/bolt-plugin/aclocal.m4
+@@ -1,6 +1,6 @@
+-# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
++# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
+ 
+-# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+ 
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -14,9077 +14,13 @@
+ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+ m4_ifndef([AC_AUTOCONF_VERSION],
+   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
+-[m4_warning([this file was generated for autoconf 2.71.
++m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
++[m4_warning([this file was generated for autoconf 2.69.
+ You have another version of autoconf.  It may work, but is not guaranteed to.
+ If you have problems, you may need to regenerate the build system entirely.
+ To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+ 
+-# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+-#
+-#   Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
+-#   Foundation, Inc.
+-#   Written by Gordon Matzigkeit, 1996
+-#
+-# This file is free software; the Free Software Foundation gives
+-# unlimited permission to copy and/or distribute it, with or without
+-# modifications, as long as this notice is preserved.
+-
+-m4_define([_LT_COPYING], [dnl
+-# Copyright (C) 2014 Free Software Foundation, Inc.
+-# This is free software; see the source for copying conditions.  There is NO
+-# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+-
+-# GNU Libtool 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 2 of of the License, or
+-# (at your option) any later version.
+-#
+-# As a special exception to the GNU General Public License, if you
+-# distribute this file as part of a program or library that is built
+-# using GNU Libtool, you may include this file under the  same
+-# distribution terms that you use for the rest of that program.
+-#
+-# GNU Libtool is distributed in the hope that it will be useful, but
+-# WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program.  If not, see .
+-])
+-
+-# serial 59 LT_INIT
+-
+-
+-# LT_PREREQ(VERSION)
+-# ------------------
+-# Complain and exit if this libtool version is less that VERSION.
+-m4_defun([LT_PREREQ],
+-[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+-       [m4_default([$3],
+-		   [m4_fatal([Libtool version $1 or higher is required],
+-		             63)])],
+-       [$2])])
+-
+-
+-# _LT_CHECK_BUILDDIR
+-# ------------------
+-# Complain if the absolute build directory name contains unusual characters
+-m4_defun([_LT_CHECK_BUILDDIR],
+-[case `pwd` in
+-  *\ * | *\	*)
+-    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+-esac
+-])
+-
+-
+-# LT_INIT([OPTIONS])
+-# ------------------
+-AC_DEFUN([LT_INIT],
+-[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+-AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+-AC_BEFORE([$0], [LT_LANG])dnl
+-AC_BEFORE([$0], [LT_OUTPUT])dnl
+-AC_BEFORE([$0], [LTDL_INIT])dnl
+-m4_require([_LT_CHECK_BUILDDIR])dnl
+-
+-dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+-m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+-m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+-dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+-dnl unless we require an AC_DEFUNed macro:
+-AC_REQUIRE([LTOPTIONS_VERSION])dnl
+-AC_REQUIRE([LTSUGAR_VERSION])dnl
+-AC_REQUIRE([LTVERSION_VERSION])dnl
+-AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+-m4_require([_LT_PROG_LTMAIN])dnl
+-
+-_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+-
+-dnl Parse OPTIONS
+-_LT_SET_OPTIONS([$0], [$1])
+-
+-# This can be used to rebuild libtool when needed
+-LIBTOOL_DEPS=$ltmain
+-
+-# Always use our own libtool.
+-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+-AC_SUBST(LIBTOOL)dnl
+-
+-_LT_SETUP
+-
+-# Only expand once:
+-m4_define([LT_INIT])
+-])# LT_INIT
+-
+-# Old names:
+-AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+-AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+-dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+-
+-
+-# _LT_PREPARE_CC_BASENAME
+-# -----------------------
+-m4_defun([_LT_PREPARE_CC_BASENAME], [
+-# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+-func_cc_basename ()
+-{
+-    for cc_temp in @S|@*""; do
+-      case $cc_temp in
+-        compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+-        distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+-        \-*) ;;
+-        *) break;;
+-      esac
+-    done
+-    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+-}
+-])# _LT_PREPARE_CC_BASENAME
+-
+-
+-# _LT_CC_BASENAME(CC)
+-# -------------------
+-# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+-# but that macro is also expanded into generated libtool script, which
+-# arranges for $SED and $ECHO to be set by different means.
+-m4_defun([_LT_CC_BASENAME],
+-[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+-AC_REQUIRE([_LT_DECL_SED])dnl
+-AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+-func_cc_basename $1
+-cc_basename=$func_cc_basename_result
+-])
+-
+-
+-# _LT_FILEUTILS_DEFAULTS
+-# ----------------------
+-# It is okay to use these file commands and assume they have been set
+-# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
+-m4_defun([_LT_FILEUTILS_DEFAULTS],
+-[: ${CP="cp -f"}
+-: ${MV="mv -f"}
+-: ${RM="rm -f"}
+-])# _LT_FILEUTILS_DEFAULTS
+-
+-
+-# _LT_SETUP
+-# ---------
+-m4_defun([_LT_SETUP],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+-AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+-AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+-
+-_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+-dnl
+-_LT_DECL([], [host_alias], [0], [The host system])dnl
+-_LT_DECL([], [host], [0])dnl
+-_LT_DECL([], [host_os], [0])dnl
+-dnl
+-_LT_DECL([], [build_alias], [0], [The build system])dnl
+-_LT_DECL([], [build], [0])dnl
+-_LT_DECL([], [build_os], [0])dnl
+-dnl
+-AC_REQUIRE([AC_PROG_CC])dnl
+-AC_REQUIRE([LT_PATH_LD])dnl
+-AC_REQUIRE([LT_PATH_NM])dnl
+-dnl
+-AC_REQUIRE([AC_PROG_LN_S])dnl
+-test -z "$LN_S" && LN_S="ln -s"
+-_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+-dnl
+-AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+-_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+-_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+-dnl
+-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+-m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+-m4_require([_LT_CMD_RELOAD])dnl
+-m4_require([_LT_DECL_FILECMD])dnl
+-m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+-m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+-m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+-m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+-m4_require([_LT_WITH_SYSROOT])dnl
+-m4_require([_LT_CMD_TRUNCATE])dnl
+-
+-_LT_CONFIG_LIBTOOL_INIT([
+-# See if we are running on zsh, and set the options that allow our
+-# commands through without removal of \ escapes INIT.
+-if test -n "\${ZSH_VERSION+set}"; then
+-   setopt NO_GLOB_SUBST
+-fi
+-])
+-if test -n "${ZSH_VERSION+set}"; then
+-   setopt NO_GLOB_SUBST
+-fi
+-
+-_LT_CHECK_OBJDIR
+-
+-m4_require([_LT_TAG_COMPILER])dnl
+-
+-case $host_os in
+-aix3*)
+-  # AIX sometimes has problems with the GCC collect2 program.  For some
+-  # reason, if we set the COLLECT_NAMES environment variable, the problems
+-  # vanish in a puff of smoke.
+-  if test set != "${COLLECT_NAMES+set}"; then
+-    COLLECT_NAMES=
+-    export COLLECT_NAMES
+-  fi
+-  ;;
+-esac
+-
+-# Global variables:
+-ofile=libtool
+-can_build_shared=yes
+-
+-# All known linkers require a '.a' archive for static linking (except MSVC and
+-# ICC, which need '.lib').
+-libext=a
+-
+-with_gnu_ld=$lt_cv_prog_gnu_ld
+-
+-old_CC=$CC
+-old_CFLAGS=$CFLAGS
+-
+-# Set sane defaults for various variables
+-test -z "$CC" && CC=cc
+-test -z "$LTCC" && LTCC=$CC
+-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+-test -z "$LD" && LD=ld
+-test -z "$ac_objext" && ac_objext=o
+-
+-_LT_CC_BASENAME([$compiler])
+-
+-# Only perform the check for file, if the check method requires it
+-test -z "$MAGIC_CMD" && MAGIC_CMD=file
+-case $deplibs_check_method in
+-file_magic*)
+-  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+-    _LT_PATH_MAGIC
+-  fi
+-  ;;
+-esac
+-
+-# Use C for the default configuration in the libtool script
+-LT_SUPPORTED_TAG([CC])
+-_LT_LANG_C_CONFIG
+-_LT_LANG_DEFAULT_CONFIG
+-_LT_CONFIG_COMMANDS
+-])# _LT_SETUP
+-
+-
+-# _LT_PREPARE_SED_QUOTE_VARS
+-# --------------------------
+-# Define a few sed substitution that help us do robust quoting.
+-m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+-[# Backslashify metacharacters that are still active within
+-# double-quoted strings.
+-sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+-
+-# Same as above, but do not quote variable references.
+-double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+-
+-# Sed substitution to delay expansion of an escaped shell variable in a
+-# double_quote_subst'ed string.
+-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+-
+-# Sed substitution to delay expansion of an escaped single quote.
+-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+-
+-# Sed substitution to avoid accidental globbing in evaled expressions
+-no_glob_subst='s/\*/\\\*/g'
+-])
+-
+-# _LT_PROG_LTMAIN
+-# ---------------
+-# Note that this code is called both from 'configure', and 'config.status'
+-# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+-# 'config.status' has no value for ac_aux_dir unless we are using Automake,
+-# so we pass a copy along to make sure it has a sensible value anyway.
+-m4_defun([_LT_PROG_LTMAIN],
+-[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+-_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+-ltmain=$ac_aux_dir/ltmain.sh
+-])# _LT_PROG_LTMAIN
+-
+-
+-
+-# So that we can recreate a full libtool script including additional
+-# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+-# in macros and then make a single call at the end using the 'libtool'
+-# label.
+-
+-
+-# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+-# ----------------------------------------
+-# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+-m4_define([_LT_CONFIG_LIBTOOL_INIT],
+-[m4_ifval([$1],
+-          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+-                     [$1
+-])])])
+-
+-# Initialize.
+-m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+-
+-
+-# _LT_CONFIG_LIBTOOL([COMMANDS])
+-# ------------------------------
+-# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+-m4_define([_LT_CONFIG_LIBTOOL],
+-[m4_ifval([$1],
+-          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+-                     [$1
+-])])])
+-
+-# Initialize.
+-m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+-
+-
+-# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+-# -----------------------------------------------------
+-m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+-[_LT_CONFIG_LIBTOOL([$1])
+-_LT_CONFIG_LIBTOOL_INIT([$2])
+-])
+-
+-
+-# _LT_FORMAT_COMMENT([COMMENT])
+-# -----------------------------
+-# Add leading comment marks to the start of each line, and a trailing
+-# full-stop to the whole comment if one is not present already.
+-m4_define([_LT_FORMAT_COMMENT],
+-[m4_ifval([$1], [
+-m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+-              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+-)])
+-
+-
+-
+-
+-
+-# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+-# -------------------------------------------------------------------
+-# CONFIGNAME is the name given to the value in the libtool script.
+-# VARNAME is the (base) name used in the configure script.
+-# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+-# VARNAME.  Any other value will be used directly.
+-m4_define([_LT_DECL],
+-[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+-    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+-	[m4_ifval([$1], [$1], [$2])])
+-    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+-    m4_ifval([$4],
+-	[lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+-    lt_dict_add_subkey([lt_decl_dict], [$2],
+-	[tagged?], [m4_ifval([$5], [yes], [no])])])
+-])
+-
+-
+-# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+-# --------------------------------------------------------
+-m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+-
+-
+-# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+-# ------------------------------------------------
+-m4_define([lt_decl_tag_varnames],
+-[_lt_decl_filter([tagged?], [yes], $@)])
+-
+-
+-# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+-# ---------------------------------------------------------
+-m4_define([_lt_decl_filter],
+-[m4_case([$#],
+-  [0], [m4_fatal([$0: too few arguments: $#])],
+-  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+-  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+-  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+-  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+-])
+-
+-
+-# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+-# --------------------------------------------------
+-m4_define([lt_decl_quote_varnames],
+-[_lt_decl_filter([value], [1], $@)])
+-
+-
+-# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+-# ---------------------------------------------------
+-m4_define([lt_decl_dquote_varnames],
+-[_lt_decl_filter([value], [2], $@)])
+-
+-
+-# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+-# ---------------------------------------------------
+-m4_define([lt_decl_varnames_tagged],
+-[m4_assert([$# <= 2])dnl
+-_$0(m4_quote(m4_default([$1], [[, ]])),
+-    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+-    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+-m4_define([_lt_decl_varnames_tagged],
+-[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+-
+-
+-# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+-# ------------------------------------------------
+-m4_define([lt_decl_all_varnames],
+-[_$0(m4_quote(m4_default([$1], [[, ]])),
+-     m4_if([$2], [],
+-	   m4_quote(lt_decl_varnames),
+-	m4_quote(m4_shift($@))))[]dnl
+-])
+-m4_define([_lt_decl_all_varnames],
+-[lt_join($@, lt_decl_varnames_tagged([$1],
+-			lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+-])
+-
+-
+-# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+-# ------------------------------------
+-# Quote a variable value, and forward it to 'config.status' so that its
+-# declaration there will have the same value as in 'configure'.  VARNAME
+-# must have a single quote delimited value for this to work.
+-m4_define([_LT_CONFIG_STATUS_DECLARE],
+-[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+-
+-
+-# _LT_CONFIG_STATUS_DECLARATIONS
+-# ------------------------------
+-# We delimit libtool config variables with single quotes, so when
+-# we write them to config.status, we have to be sure to quote all
+-# embedded single quotes properly.  In configure, this macro expands
+-# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+-#
+-#    ='`$ECHO "$" | $SED "$delay_single_quote_subst"`'
+-m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+-[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+-    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+-
+-
+-# _LT_LIBTOOL_TAGS
+-# ----------------
+-# Output comment and list of tags supported by the script
+-m4_defun([_LT_LIBTOOL_TAGS],
+-[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+-available_tags='_LT_TAGS'dnl
+-])
+-
+-
+-# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+-# -----------------------------------
+-# Extract the dictionary values for VARNAME (optionally with TAG) and
+-# expand to a commented shell variable setting:
+-#
+-#    # Some comment about what VAR is for.
+-#    visible_name=$lt_internal_name
+-m4_define([_LT_LIBTOOL_DECLARE],
+-[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+-					   [description])))[]dnl
+-m4_pushdef([_libtool_name],
+-    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+-m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+-    [0], [_libtool_name=[$]$1],
+-    [1], [_libtool_name=$lt_[]$1],
+-    [2], [_libtool_name=$lt_[]$1],
+-    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+-m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+-])
+-
+-
+-# _LT_LIBTOOL_CONFIG_VARS
+-# -----------------------
+-# Produce commented declarations of non-tagged libtool config variables
+-# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
+-# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+-# section) are produced by _LT_LIBTOOL_TAG_VARS.
+-m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+-[m4_foreach([_lt_var],
+-    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+-    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+-
+-
+-# _LT_LIBTOOL_TAG_VARS(TAG)
+-# -------------------------
+-m4_define([_LT_LIBTOOL_TAG_VARS],
+-[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+-    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+-
+-
+-# _LT_TAGVAR(VARNAME, [TAGNAME])
+-# ------------------------------
+-m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+-
+-
+-# _LT_CONFIG_COMMANDS
+-# -------------------
+-# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+-# variables for single and double quote escaping we saved from calls
+-# to _LT_DECL, we can put quote escaped variables declarations
+-# into 'config.status', and then the shell code to quote escape them in
+-# for loops in 'config.status'.  Finally, any additional code accumulated
+-# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+-m4_defun([_LT_CONFIG_COMMANDS],
+-[AC_PROVIDE_IFELSE([LT_OUTPUT],
+-	dnl If the libtool generation code has been placed in $CONFIG_LT,
+-	dnl instead of duplicating it all over again into config.status,
+-	dnl then we will have config.status run $CONFIG_LT later, so it
+-	dnl needs to know what name is stored there:
+-        [AC_CONFIG_COMMANDS([libtool],
+-            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+-    dnl If the libtool generation code is destined for config.status,
+-    dnl expand the accumulated commands and init code now:
+-    [AC_CONFIG_COMMANDS([libtool],
+-        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+-])#_LT_CONFIG_COMMANDS
+-
+-
+-# Initialize.
+-m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+-[
+-
+-# The HP-UX ksh and POSIX shell print the target directory to stdout
+-# if CDPATH is set.
+-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+-
+-sed_quote_subst='$sed_quote_subst'
+-double_quote_subst='$double_quote_subst'
+-delay_variable_subst='$delay_variable_subst'
+-_LT_CONFIG_STATUS_DECLARATIONS
+-LTCC='$LTCC'
+-LTCFLAGS='$LTCFLAGS'
+-compiler='$compiler_DEFAULT'
+-
+-# A function that is used when there is no print builtin or printf.
+-func_fallback_echo ()
+-{
+-  eval 'cat <<_LTECHO_EOF
+-\$[]1
+-_LTECHO_EOF'
+-}
+-
+-# Quote evaled strings.
+-for var in lt_decl_all_varnames([[ \
+-]], lt_decl_quote_varnames); do
+-    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+-    *[[\\\\\\\`\\"\\\$]]*)
+-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+-      ;;
+-    *)
+-      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+-      ;;
+-    esac
+-done
+-
+-# Double-quote double-evaled strings.
+-for var in lt_decl_all_varnames([[ \
+-]], lt_decl_dquote_varnames); do
+-    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+-    *[[\\\\\\\`\\"\\\$]]*)
+-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+-      ;;
+-    *)
+-      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+-      ;;
+-    esac
+-done
+-
+-_LT_OUTPUT_LIBTOOL_INIT
+-])
+-
+-# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+-# ------------------------------------
+-# Generate a child script FILE with all initialization necessary to
+-# reuse the environment learned by the parent script, and make the
+-# file executable.  If COMMENT is supplied, it is inserted after the
+-# '#!' sequence but before initialization text begins.  After this
+-# macro, additional text can be appended to FILE to form the body of
+-# the child script.  The macro ends with non-zero status if the
+-# file could not be fully written (such as if the disk is full).
+-m4_ifdef([AS_INIT_GENERATED],
+-[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+-[m4_defun([_LT_GENERATED_FILE_INIT],
+-[m4_require([AS_PREPARE])]dnl
+-[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+-[lt_write_fail=0
+-cat >$1 <<_ASEOF || lt_write_fail=1
+-#! $SHELL
+-# Generated by $as_me.
+-$2
+-SHELL=\${CONFIG_SHELL-$SHELL}
+-export SHELL
+-_ASEOF
+-cat >>$1 <<\_ASEOF || lt_write_fail=1
+-AS_SHELL_SANITIZE
+-_AS_PREPARE
+-exec AS_MESSAGE_FD>&1
+-_ASEOF
+-test 0 = "$lt_write_fail" && chmod +x $1[]dnl
+-m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+-
+-# LT_OUTPUT
+-# ---------
+-# This macro allows early generation of the libtool script (before
+-# AC_OUTPUT is called), incase it is used in configure for compilation
+-# tests.
+-AC_DEFUN([LT_OUTPUT],
+-[: ${CONFIG_LT=./config.lt}
+-AC_MSG_NOTICE([creating $CONFIG_LT])
+-_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+-[# Run this file to recreate a libtool stub with the current configuration.])
+-
+-cat >>"$CONFIG_LT" <<\_LTEOF
+-lt_cl_silent=false
+-exec AS_MESSAGE_LOG_FD>>config.log
+-{
+-  echo
+-  AS_BOX([Running $as_me.])
+-} >&AS_MESSAGE_LOG_FD
+-
+-lt_cl_help="\
+-'$as_me' creates a local libtool stub from the current configuration,
+-for use in further configure time tests before the real libtool is
+-generated.
+-
+-Usage: $[0] [[OPTIONS]]
+-
+-  -h, --help      print this help, then exit
+-  -V, --version   print version number, then exit
+-  -q, --quiet     do not print progress messages
+-  -d, --debug     don't remove temporary files
+-
+-Report bugs to ."
+-
+-lt_cl_version="\
+-m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+-m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+-configured by $[0], generated by m4_PACKAGE_STRING.
+-
+-Copyright (C) 2011 Free Software Foundation, Inc.
+-This config.lt script is free software; the Free Software Foundation
+-gives unlimited permision to copy, distribute and modify it."
+-
+-while test 0 != $[#]
+-do
+-  case $[1] in
+-    --version | --v* | -V )
+-      echo "$lt_cl_version"; exit 0 ;;
+-    --help | --h* | -h )
+-      echo "$lt_cl_help"; exit 0 ;;
+-    --debug | --d* | -d )
+-      debug=: ;;
+-    --quiet | --q* | --silent | --s* | -q )
+-      lt_cl_silent=: ;;
+-
+-    -*) AC_MSG_ERROR([unrecognized option: $[1]
+-Try '$[0] --help' for more information.]) ;;
+-
+-    *) AC_MSG_ERROR([unrecognized argument: $[1]
+-Try '$[0] --help' for more information.]) ;;
+-  esac
+-  shift
+-done
+-
+-if $lt_cl_silent; then
+-  exec AS_MESSAGE_FD>/dev/null
+-fi
+-_LTEOF
+-
+-cat >>"$CONFIG_LT" <<_LTEOF
+-_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+-_LTEOF
+-
+-cat >>"$CONFIG_LT" <<\_LTEOF
+-AC_MSG_NOTICE([creating $ofile])
+-_LT_OUTPUT_LIBTOOL_COMMANDS
+-AS_EXIT(0)
+-_LTEOF
+-chmod +x "$CONFIG_LT"
+-
+-# configure is writing to config.log, but config.lt does its own redirection,
+-# appending to config.log, which fails on DOS, as config.log is still kept
+-# open by configure.  Here we exec the FD to /dev/null, effectively closing
+-# config.log, so it can be properly (re)opened and appended to by config.lt.
+-lt_cl_success=:
+-test yes = "$silent" &&
+-  lt_config_lt_args="$lt_config_lt_args --quiet"
+-exec AS_MESSAGE_LOG_FD>/dev/null
+-$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+-exec AS_MESSAGE_LOG_FD>>config.log
+-$lt_cl_success || AS_EXIT(1)
+-])# LT_OUTPUT
+-
+-
+-# _LT_CONFIG(TAG)
+-# ---------------
+-# If TAG is the built-in tag, create an initial libtool script with a
+-# default configuration from the untagged config vars.  Otherwise add code
+-# to config.status for appending the configuration named by TAG from the
+-# matching tagged config vars.
+-m4_defun([_LT_CONFIG],
+-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-_LT_CONFIG_SAVE_COMMANDS([
+-  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+-  m4_if(_LT_TAG, [C], [
+-    # See if we are running on zsh, and set the options that allow our
+-    # commands through without removal of \ escapes.
+-    if test -n "${ZSH_VERSION+set}"; then
+-      setopt NO_GLOB_SUBST
+-    fi
+-
+-    cfgfile=${ofile}T
+-    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+-    $RM "$cfgfile"
+-
+-    cat <<_LT_EOF >> "$cfgfile"
+-#! $SHELL
+-# Generated automatically by $as_me ($PACKAGE) $VERSION
+-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+-
+-# Provide generalized library-building support services.
+-# Written by Gordon Matzigkeit, 1996
+-
+-_LT_COPYING
+-_LT_LIBTOOL_TAGS
+-
+-# Configured defaults for sys_lib_dlsearch_path munging.
+-: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+-
+-# ### BEGIN LIBTOOL CONFIG
+-_LT_LIBTOOL_CONFIG_VARS
+-_LT_LIBTOOL_TAG_VARS
+-# ### END LIBTOOL CONFIG
+-
+-_LT_EOF
+-
+-    cat <<'_LT_EOF' >> "$cfgfile"
+-
+-# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+-
+-_LT_PREPARE_MUNGE_PATH_LIST
+-_LT_PREPARE_CC_BASENAME
+-
+-# ### END FUNCTIONS SHARED WITH CONFIGURE
+-
+-_LT_EOF
+-
+-  case $host_os in
+-  aix3*)
+-    cat <<\_LT_EOF >> "$cfgfile"
+-# AIX sometimes has problems with the GCC collect2 program.  For some
+-# reason, if we set the COLLECT_NAMES environment variable, the problems
+-# vanish in a puff of smoke.
+-if test set != "${COLLECT_NAMES+set}"; then
+-  COLLECT_NAMES=
+-  export COLLECT_NAMES
+-fi
+-_LT_EOF
+-    ;;
+-  esac
+-
+-  _LT_PROG_LTMAIN
+-
+-  # We use sed instead of cat because bash on DJGPP gets confused if
+-  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+-  # text mode, it properly converts lines to CR/LF.  This bash problem
+-  # is reportedly fixed, but why not run on old versions too?
+-  $SED '$q' "$ltmain" >> "$cfgfile" \
+-     || (rm -f "$cfgfile"; exit 1)
+-
+-   mv -f "$cfgfile" "$ofile" ||
+-    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+-  chmod +x "$ofile"
+-],
+-[cat <<_LT_EOF >> "$ofile"
+-
+-dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+-dnl in a comment (ie after a #).
+-# ### BEGIN LIBTOOL TAG CONFIG: $1
+-_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+-# ### END LIBTOOL TAG CONFIG: $1
+-_LT_EOF
+-])dnl /m4_if
+-],
+-[m4_if([$1], [], [
+-    PACKAGE='$PACKAGE'
+-    VERSION='$VERSION'
+-    RM='$RM'
+-    ofile='$ofile'], [])
+-])dnl /_LT_CONFIG_SAVE_COMMANDS
+-])# _LT_CONFIG
+-
+-
+-# LT_SUPPORTED_TAG(TAG)
+-# ---------------------
+-# Trace this macro to discover what tags are supported by the libtool
+-# --tag option, using:
+-#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+-AC_DEFUN([LT_SUPPORTED_TAG], [])
+-
+-
+-# C support is built-in for now
+-m4_define([_LT_LANG_C_enabled], [])
+-m4_define([_LT_TAGS], [])
+-
+-
+-# LT_LANG(LANG)
+-# -------------
+-# Enable libtool support for the given language if not already enabled.
+-AC_DEFUN([LT_LANG],
+-[AC_BEFORE([$0], [LT_OUTPUT])dnl
+-m4_case([$1],
+-  [C],			[_LT_LANG(C)],
+-  [C++],		[_LT_LANG(CXX)],
+-  [Go],			[_LT_LANG(GO)],
+-  [Java],		[_LT_LANG(GCJ)],
+-  [Fortran 77],		[_LT_LANG(F77)],
+-  [Fortran],		[_LT_LANG(FC)],
+-  [Windows Resource],	[_LT_LANG(RC)],
+-  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+-    [_LT_LANG($1)],
+-    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+-])# LT_LANG
+-
+-
+-# _LT_LANG(LANGNAME)
+-# ------------------
+-m4_defun([_LT_LANG],
+-[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+-  [LT_SUPPORTED_TAG([$1])dnl
+-  m4_append([_LT_TAGS], [$1 ])dnl
+-  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+-  _LT_LANG_$1_CONFIG($1)])dnl
+-])# _LT_LANG
+-
+-
+-m4_ifndef([AC_PROG_GO], [
+-# NOTE: This macro has been submitted for inclusion into   #
+-#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
+-#  a released version of Autoconf we should remove this    #
+-#  macro and use it instead.                               #
+-m4_defun([AC_PROG_GO],
+-[AC_LANG_PUSH(Go)dnl
+-AC_ARG_VAR([GOC],     [Go compiler command])dnl
+-AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+-_AC_ARG_VAR_LDFLAGS()dnl
+-AC_CHECK_TOOL(GOC, gccgo)
+-if test -z "$GOC"; then
+-  if test -n "$ac_tool_prefix"; then
+-    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+-  fi
+-fi
+-if test -z "$GOC"; then
+-  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+-fi
+-])#m4_defun
+-])#m4_ifndef
+-
+-
+-# _LT_LANG_DEFAULT_CONFIG
+-# -----------------------
+-m4_defun([_LT_LANG_DEFAULT_CONFIG],
+-[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+-  [LT_LANG(CXX)],
+-  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+-
+-AC_PROVIDE_IFELSE([AC_PROG_F77],
+-  [LT_LANG(F77)],
+-  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+-
+-AC_PROVIDE_IFELSE([AC_PROG_FC],
+-  [LT_LANG(FC)],
+-  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+-
+-dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+-dnl pulling things in needlessly.
+-AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+-  [LT_LANG(GCJ)],
+-  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+-    [LT_LANG(GCJ)],
+-    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+-      [LT_LANG(GCJ)],
+-      [m4_ifdef([AC_PROG_GCJ],
+-	[m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+-       m4_ifdef([A][M_PROG_GCJ],
+-	[m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+-       m4_ifdef([LT_PROG_GCJ],
+-	[m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+-
+-AC_PROVIDE_IFELSE([AC_PROG_GO],
+-  [LT_LANG(GO)],
+-  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+-
+-AC_PROVIDE_IFELSE([LT_PROG_RC],
+-  [LT_LANG(RC)],
+-  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+-])# _LT_LANG_DEFAULT_CONFIG
+-
+-# Obsolete macros:
+-AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+-AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+-AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+-AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+-AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+-dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+-dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+-dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+-dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+-
+-
+-# _LT_TAG_COMPILER
+-# ----------------
+-m4_defun([_LT_TAG_COMPILER],
+-[AC_REQUIRE([AC_PROG_CC])dnl
+-
+-_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+-_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+-_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+-_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+-
+-# If no C compiler was specified, use CC.
+-LTCC=${LTCC-"$CC"}
+-
+-# If no C compiler flags were specified, use CFLAGS.
+-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+-
+-# Allow CC to be a program name with arguments.
+-compiler=$CC
+-])# _LT_TAG_COMPILER
+-
+-
+-# _LT_COMPILER_BOILERPLATE
+-# ------------------------
+-# Check for compiler boilerplate output or warnings with
+-# the simple compiler test code.
+-m4_defun([_LT_COMPILER_BOILERPLATE],
+-[m4_require([_LT_DECL_SED])dnl
+-ac_outfile=conftest.$ac_objext
+-echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+-_lt_compiler_boilerplate=`cat conftest.err`
+-$RM conftest*
+-])# _LT_COMPILER_BOILERPLATE
+-
+-
+-# _LT_LINKER_BOILERPLATE
+-# ----------------------
+-# Check for linker boilerplate output or warnings with
+-# the simple link test code.
+-m4_defun([_LT_LINKER_BOILERPLATE],
+-[m4_require([_LT_DECL_SED])dnl
+-ac_outfile=conftest.$ac_objext
+-echo "$lt_simple_link_test_code" >conftest.$ac_ext
+-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+-_lt_linker_boilerplate=`cat conftest.err`
+-$RM -r conftest*
+-])# _LT_LINKER_BOILERPLATE
+-
+-# _LT_REQUIRED_DARWIN_CHECKS
+-# -------------------------
+-m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+-  case $host_os in
+-    rhapsody* | darwin*)
+-    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+-    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+-    AC_CHECK_TOOL([LIPO], [lipo], [:])
+-    AC_CHECK_TOOL([OTOOL], [otool], [:])
+-    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+-    _LT_DECL([], [DSYMUTIL], [1],
+-      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+-    _LT_DECL([], [NMEDIT], [1],
+-      [Tool to change global to local symbols on Mac OS X])
+-    _LT_DECL([], [LIPO], [1],
+-      [Tool to manipulate fat objects and archives on Mac OS X])
+-    _LT_DECL([], [OTOOL], [1],
+-      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+-    _LT_DECL([], [OTOOL64], [1],
+-      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+-
+-    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+-      [lt_cv_apple_cc_single_mod=no
+-      if test -z "$LT_MULTI_MODULE"; then
+-	# By default we will add the -single_module flag. You can override
+-	# by either setting the environment variable LT_MULTI_MODULE
+-	# non-empty at configure time, or by adding -multi_module to the
+-	# link flags.
+-	rm -rf libconftest.dylib*
+-	echo "int foo(void){return 1;}" > conftest.c
+-	echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+--dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+-	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+-        _lt_result=$?
+-	# If there is a non-empty error log, and "single_module"
+-	# appears in it, assume the flag caused a linker warning
+-        if test -s conftest.err && $GREP single_module conftest.err; then
+-	  cat conftest.err >&AS_MESSAGE_LOG_FD
+-	# Otherwise, if the output was created with a 0 exit code from
+-	# the compiler, it worked.
+-	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+-	  lt_cv_apple_cc_single_mod=yes
+-	else
+-	  cat conftest.err >&AS_MESSAGE_LOG_FD
+-	fi
+-	rm -rf libconftest.dylib*
+-	rm -f conftest.*
+-      fi])
+-
+-    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+-      [lt_cv_ld_exported_symbols_list],
+-      [lt_cv_ld_exported_symbols_list=no
+-      save_LDFLAGS=$LDFLAGS
+-      echo "_main" > conftest.sym
+-      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+-      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+-	[lt_cv_ld_exported_symbols_list=yes],
+-	[lt_cv_ld_exported_symbols_list=no])
+-	LDFLAGS=$save_LDFLAGS
+-    ])
+-
+-    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+-      [lt_cv_ld_force_load=no
+-      cat > conftest.c << _LT_EOF
+-int forced_loaded() { return 2;}
+-_LT_EOF
+-      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+-      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+-      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+-      $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+-      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+-      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+-      cat > conftest.c << _LT_EOF
+-int main() { return 0;}
+-_LT_EOF
+-      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+-      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+-      _lt_result=$?
+-      if test -s conftest.err && $GREP force_load conftest.err; then
+-	cat conftest.err >&AS_MESSAGE_LOG_FD
+-      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+-	lt_cv_ld_force_load=yes
+-      else
+-	cat conftest.err >&AS_MESSAGE_LOG_FD
+-      fi
+-        rm -f conftest.err libconftest.a conftest conftest.c
+-        rm -rf conftest.dSYM
+-    ])
+-    case $host_os in
+-    rhapsody* | darwin1.[[012]])
+-      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+-    darwin1.*)
+-      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+-    darwin*)
+-      case $MACOSX_DEPLOYMENT_TARGET,$host in
+-        10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
+-          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+-        *)
+-          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+-      esac
+-    ;;
+-  esac
+-    if test yes = "$lt_cv_apple_cc_single_mod"; then
+-      _lt_dar_single_mod='$single_module'
+-    fi
+-    if test yes = "$lt_cv_ld_exported_symbols_list"; then
+-      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+-    else
+-      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+-    fi
+-    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+-      _lt_dsymutil='~$DSYMUTIL $lib || :'
+-    else
+-      _lt_dsymutil=
+-    fi
+-    ;;
+-  esac
+-])
+-
+-
+-# _LT_DARWIN_LINKER_FEATURES([TAG])
+-# ---------------------------------
+-# Checks for linker and compiler features on darwin
+-m4_defun([_LT_DARWIN_LINKER_FEATURES],
+-[
+-  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+-  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-  _LT_TAGVAR(hardcode_direct, $1)=no
+-  _LT_TAGVAR(hardcode_automatic, $1)=yes
+-  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+-  if test yes = "$lt_cv_ld_force_load"; then
+-    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+-    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+-                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+-  else
+-    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+-  fi
+-  _LT_TAGVAR(link_all_deplibs, $1)=yes
+-  _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
+-  case $cc_basename in
+-     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+-     *) _lt_dar_can_shared=$GCC ;;
+-  esac
+-  if test yes = "$_lt_dar_can_shared"; then
+-    output_verbose_link_cmd=func_echo_all
+-    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+-    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+-    _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+-    _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+-    m4_if([$1], [CXX],
+-[   if test yes != "$lt_cv_apple_cc_single_mod"; then
+-      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+-      _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+-    fi
+-],[])
+-  else
+-  _LT_TAGVAR(ld_shlibs, $1)=no
+-  fi
+-])
+-
+-# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+-# ----------------------------------
+-# Links a minimal program and checks the executable
+-# for the system default hardcoded library path. In most cases,
+-# this is /usr/lib:/lib, but when the MPI compilers are used
+-# the location of the communication and MPI libs are included too.
+-# If we don't find anything, use the default library path according
+-# to the aix ld manual.
+-# Store the results from the different compilers for each TAGNAME.
+-# Allow to override them for all tags through lt_cv_aix_libpath.
+-m4_defun([_LT_SYS_MODULE_PATH_AIX],
+-[m4_require([_LT_DECL_SED])dnl
+-if test set = "${lt_cv_aix_libpath+set}"; then
+-  aix_libpath=$lt_cv_aix_libpath
+-else
+-  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+-  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+-  lt_aix_libpath_sed='[
+-      /Import File Strings/,/^$/ {
+-	  /^0/ {
+-	      s/^0  *\([^ ]*\) *$/\1/
+-	      p
+-	  }
+-      }]'
+-  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  # Check for a 64-bit object if we didn't find anything.
+-  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+-    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  fi],[])
+-  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+-    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
+-  fi
+-  ])
+-  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+-fi
+-])# _LT_SYS_MODULE_PATH_AIX
+-
+-
+-# _LT_SHELL_INIT(ARG)
+-# -------------------
+-m4_define([_LT_SHELL_INIT],
+-[m4_divert_text([M4SH-INIT], [$1
+-])])# _LT_SHELL_INIT
+-
+-
+-
+-# _LT_PROG_ECHO_BACKSLASH
+-# -----------------------
+-# Find how we can fake an echo command that does not interpret backslash.
+-# In particular, with Autoconf 2.60 or later we add some code to the start
+-# of the generated configure script that will find a shell with a builtin
+-# printf (that we can use as an echo command).
+-m4_defun([_LT_PROG_ECHO_BACKSLASH],
+-[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+-
+-AC_MSG_CHECKING([how to print strings])
+-# Test print first, because it will be a builtin if present.
+-if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+-   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+-  ECHO='print -r --'
+-elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+-  ECHO='printf %s\n'
+-else
+-  # Use this function as a fallback that always works.
+-  func_fallback_echo ()
+-  {
+-    eval 'cat <<_LTECHO_EOF
+-$[]1
+-_LTECHO_EOF'
+-  }
+-  ECHO='func_fallback_echo'
+-fi
+-
+-# func_echo_all arg...
+-# Invoke $ECHO with all args, space-separated.
+-func_echo_all ()
+-{
+-    $ECHO "$*"
+-}
+-
+-case $ECHO in
+-  printf*) AC_MSG_RESULT([printf]) ;;
+-  print*) AC_MSG_RESULT([print -r]) ;;
+-  *) AC_MSG_RESULT([cat]) ;;
+-esac
+-
+-m4_ifdef([_AS_DETECT_SUGGESTED],
+-[_AS_DETECT_SUGGESTED([
+-  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+-    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+-    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+-    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+-    PATH=/empty FPATH=/empty; export PATH FPATH
+-    test "X`printf %s $ECHO`" = "X$ECHO" \
+-      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+-
+-_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+-_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+-])# _LT_PROG_ECHO_BACKSLASH
+-
+-
+-# _LT_WITH_SYSROOT
+-# ----------------
+-AC_DEFUN([_LT_WITH_SYSROOT],
+-[m4_require([_LT_DECL_SED])dnl
+-AC_MSG_CHECKING([for sysroot])
+-AC_ARG_WITH([sysroot],
+-[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
+-  [Search for dependent libraries within DIR (or the compiler's sysroot
+-   if not specified).])],
+-[], [with_sysroot=no])
+-
+-dnl lt_sysroot will always be passed unquoted.  We quote it here
+-dnl in case the user passed a directory name.
+-lt_sysroot=
+-case $with_sysroot in #(
+- yes)
+-   if test yes = "$GCC"; then
+-     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+-   fi
+-   ;; #(
+- /*)
+-   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+-   ;; #(
+- no|'')
+-   ;; #(
+- *)
+-   AC_MSG_RESULT([$with_sysroot])
+-   AC_MSG_ERROR([The sysroot must be an absolute path.])
+-   ;;
+-esac
+-
+- AC_MSG_RESULT([${lt_sysroot:-no}])
+-_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+-[dependent libraries, and where our libraries should be installed.])])
+-
+-# _LT_ENABLE_LOCK
+-# ---------------
+-m4_defun([_LT_ENABLE_LOCK],
+-[AC_ARG_ENABLE([libtool-lock],
+-  [AS_HELP_STRING([--disable-libtool-lock],
+-    [avoid locking (might break parallel builds)])])
+-test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+-
+-# Some flags need to be propagated to the compiler or linker for good
+-# libtool support.
+-case $host in
+-ia64-*-hpux*)
+-  # Find out what ABI is being produced by ac_compile, and set mode
+-  # options accordingly.
+-  echo 'int i;' > conftest.$ac_ext
+-  if AC_TRY_EVAL(ac_compile); then
+-    case `$FILECMD conftest.$ac_objext` in
+-      *ELF-32*)
+-	HPUX_IA64_MODE=32
+-	;;
+-      *ELF-64*)
+-	HPUX_IA64_MODE=64
+-	;;
+-    esac
+-  fi
+-  rm -rf conftest*
+-  ;;
+-*-*-irix6*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.
+-  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+-  if AC_TRY_EVAL(ac_compile); then
+-    if test yes = "$lt_cv_prog_gnu_ld"; then
+-      case `$FILECMD conftest.$ac_objext` in
+-	*32-bit*)
+-	  LD="${LD-ld} -melf32bsmip"
+-	  ;;
+-	*N32*)
+-	  LD="${LD-ld} -melf32bmipn32"
+-	  ;;
+-	*64-bit*)
+-	  LD="${LD-ld} -melf64bmip"
+-	;;
+-      esac
+-    else
+-      case `$FILECMD conftest.$ac_objext` in
+-	*32-bit*)
+-	  LD="${LD-ld} -32"
+-	  ;;
+-	*N32*)
+-	  LD="${LD-ld} -n32"
+-	  ;;
+-	*64-bit*)
+-	  LD="${LD-ld} -64"
+-	  ;;
+-      esac
+-    fi
+-  fi
+-  rm -rf conftest*
+-  ;;
+-
+-mips64*-*linux*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.
+-  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+-  if AC_TRY_EVAL(ac_compile); then
+-    emul=elf
+-    case `$FILECMD conftest.$ac_objext` in
+-      *32-bit*)
+-	emul="${emul}32"
+-	;;
+-      *64-bit*)
+-	emul="${emul}64"
+-	;;
+-    esac
+-    case `$FILECMD conftest.$ac_objext` in
+-      *MSB*)
+-	emul="${emul}btsmip"
+-	;;
+-      *LSB*)
+-	emul="${emul}ltsmip"
+-	;;
+-    esac
+-    case `$FILECMD conftest.$ac_objext` in
+-      *N32*)
+-	emul="${emul}n32"
+-	;;
+-    esac
+-    LD="${LD-ld} -m $emul"
+-  fi
+-  rm -rf conftest*
+-  ;;
+-
+-x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+-s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.  Note that the listed cases only cover the
+-  # situations where additional linker options are needed (such as when
+-  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+-  # vice versa); the common cases where no linker options are needed do
+-  # not appear in the list.
+-  echo 'int i;' > conftest.$ac_ext
+-  if AC_TRY_EVAL(ac_compile); then
+-    case `$FILECMD conftest.o` in
+-      *32-bit*)
+-	case $host in
+-	  x86_64-*kfreebsd*-gnu)
+-	    LD="${LD-ld} -m elf_i386_fbsd"
+-	    ;;
+-	  x86_64-*linux*)
+-	    case `$FILECMD conftest.o` in
+-	      *x86-64*)
+-		LD="${LD-ld} -m elf32_x86_64"
+-		;;
+-	      *)
+-		LD="${LD-ld} -m elf_i386"
+-		;;
+-	    esac
+-	    ;;
+-	  powerpc64le-*linux*)
+-	    LD="${LD-ld} -m elf32lppclinux"
+-	    ;;
+-	  powerpc64-*linux*)
+-	    LD="${LD-ld} -m elf32ppclinux"
+-	    ;;
+-	  s390x-*linux*)
+-	    LD="${LD-ld} -m elf_s390"
+-	    ;;
+-	  sparc64-*linux*)
+-	    LD="${LD-ld} -m elf32_sparc"
+-	    ;;
+-	esac
+-	;;
+-      *64-bit*)
+-	case $host in
+-	  x86_64-*kfreebsd*-gnu)
+-	    LD="${LD-ld} -m elf_x86_64_fbsd"
+-	    ;;
+-	  x86_64-*linux*)
+-	    LD="${LD-ld} -m elf_x86_64"
+-	    ;;
+-	  powerpcle-*linux*)
+-	    LD="${LD-ld} -m elf64lppc"
+-	    ;;
+-	  powerpc-*linux*)
+-	    LD="${LD-ld} -m elf64ppc"
+-	    ;;
+-	  s390*-*linux*|s390*-*tpf*)
+-	    LD="${LD-ld} -m elf64_s390"
+-	    ;;
+-	  sparc*-*linux*)
+-	    LD="${LD-ld} -m elf64_sparc"
+-	    ;;
+-	esac
+-	;;
+-    esac
+-  fi
+-  rm -rf conftest*
+-  ;;
+-
+-*-*-sco3.2v5*)
+-  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+-  SAVE_CFLAGS=$CFLAGS
+-  CFLAGS="$CFLAGS -belf"
+-  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+-    [AC_LANG_PUSH(C)
+-     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+-     AC_LANG_POP])
+-  if test yes != "$lt_cv_cc_needs_belf"; then
+-    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+-    CFLAGS=$SAVE_CFLAGS
+-  fi
+-  ;;
+-*-*solaris*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.
+-  echo 'int i;' > conftest.$ac_ext
+-  if AC_TRY_EVAL(ac_compile); then
+-    case `$FILECMD conftest.o` in
+-    *64-bit*)
+-      case $lt_cv_prog_gnu_ld in
+-      yes*)
+-        case $host in
+-        i?86-*-solaris*|x86_64-*-solaris*)
+-          LD="${LD-ld} -m elf_x86_64"
+-          ;;
+-        sparc*-*-solaris*)
+-          LD="${LD-ld} -m elf64_sparc"
+-          ;;
+-        esac
+-        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+-        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+-          LD=${LD-ld}_sol2
+-        fi
+-        ;;
+-      *)
+-	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+-	  LD="${LD-ld} -64"
+-	fi
+-	;;
+-      esac
+-      ;;
+-    esac
+-  fi
+-  rm -rf conftest*
+-  ;;
+-esac
+-
+-need_locks=$enable_libtool_lock
+-])# _LT_ENABLE_LOCK
+-
+-
+-# _LT_PROG_AR
+-# -----------
+-m4_defun([_LT_PROG_AR],
+-[AC_CHECK_TOOLS(AR, [ar], false)
+-: ${AR=ar}
+-_LT_DECL([], [AR], [1], [The archiver])
+-
+-# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+-# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+-# higher priority because thats what people were doing historically (setting
+-# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+-# variable obsoleted/removed.
+-
+-test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+-lt_ar_flags=$AR_FLAGS
+-_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
+-
+-# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+-# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+-_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
+-         [Flags to create an archive])
+-
+-AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+-  [lt_cv_ar_at_file=no
+-   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+-     [echo conftest.$ac_objext > conftest.lst
+-      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+-      AC_TRY_EVAL([lt_ar_try])
+-      if test 0 -eq "$ac_status"; then
+-	# Ensure the archiver fails upon bogus file names.
+-	rm -f conftest.$ac_objext libconftest.a
+-	AC_TRY_EVAL([lt_ar_try])
+-	if test 0 -ne "$ac_status"; then
+-          lt_cv_ar_at_file=@
+-        fi
+-      fi
+-      rm -f conftest.* libconftest.a
+-     ])
+-  ])
+-
+-if test no = "$lt_cv_ar_at_file"; then
+-  archiver_list_spec=
+-else
+-  archiver_list_spec=$lt_cv_ar_at_file
+-fi
+-_LT_DECL([], [archiver_list_spec], [1],
+-  [How to feed a file listing to the archiver])
+-])# _LT_PROG_AR
+-
+-
+-# _LT_CMD_OLD_ARCHIVE
+-# -------------------
+-m4_defun([_LT_CMD_OLD_ARCHIVE],
+-[_LT_PROG_AR
+-
+-AC_CHECK_TOOL(STRIP, strip, :)
+-test -z "$STRIP" && STRIP=:
+-_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+-
+-AC_CHECK_TOOL(RANLIB, ranlib, :)
+-test -z "$RANLIB" && RANLIB=:
+-_LT_DECL([], [RANLIB], [1],
+-    [Commands used to install an old-style archive])
+-
+-# Determine commands to create old-style static archives.
+-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+-old_postinstall_cmds='chmod 644 $oldlib'
+-old_postuninstall_cmds=
+-
+-if test -n "$RANLIB"; then
+-  case $host_os in
+-  bitrig* | openbsd*)
+-    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+-    ;;
+-  *)
+-    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+-    ;;
+-  esac
+-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+-fi
+-
+-case $host_os in
+-  darwin*)
+-    lock_old_archive_extraction=yes ;;
+-  *)
+-    lock_old_archive_extraction=no ;;
+-esac
+-_LT_DECL([], [old_postinstall_cmds], [2])
+-_LT_DECL([], [old_postuninstall_cmds], [2])
+-_LT_TAGDECL([], [old_archive_cmds], [2],
+-    [Commands used to build an old-style archive])
+-_LT_DECL([], [lock_old_archive_extraction], [0],
+-    [Whether to use a lock for old archive extraction])
+-])# _LT_CMD_OLD_ARCHIVE
+-
+-
+-# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+-#		[OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+-# ----------------------------------------------------------------
+-# Check whether the given compiler option works
+-AC_DEFUN([_LT_COMPILER_OPTION],
+-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_DECL_SED])dnl
+-AC_CACHE_CHECK([$1], [$2],
+-  [$2=no
+-   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+-   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+-   lt_compiler_flag="$3"  ## exclude from sc_useless_quotes_in_assignment
+-   # Insert the option either (1) after the last *FLAGS variable, or
+-   # (2) before a word containing "conftest.", or (3) at the end.
+-   # Note that $ac_compile itself does not contain backslashes and begins
+-   # with a dollar sign (not a hyphen), so the echo should work correctly.
+-   # The option is referenced via a variable to avoid confusing sed.
+-   lt_compile=`echo "$ac_compile" | $SED \
+-   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+-   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+-   -e 's:$: $lt_compiler_flag:'`
+-   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+-   (eval "$lt_compile" 2>conftest.err)
+-   ac_status=$?
+-   cat conftest.err >&AS_MESSAGE_LOG_FD
+-   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+-   if (exit $ac_status) && test -s "$ac_outfile"; then
+-     # The compiler can only warn and ignore the option if not recognized
+-     # So say no if there are warnings other than the usual output.
+-     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+-     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+-     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+-       $2=yes
+-     fi
+-   fi
+-   $RM conftest*
+-])
+-
+-if test yes = "[$]$2"; then
+-    m4_if([$5], , :, [$5])
+-else
+-    m4_if([$6], , :, [$6])
+-fi
+-])# _LT_COMPILER_OPTION
+-
+-# Old name:
+-AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+-
+-
+-# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+-#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+-# ----------------------------------------------------
+-# Check whether the given linker option works
+-AC_DEFUN([_LT_LINKER_OPTION],
+-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_DECL_SED])dnl
+-AC_CACHE_CHECK([$1], [$2],
+-  [$2=no
+-   save_LDFLAGS=$LDFLAGS
+-   LDFLAGS="$LDFLAGS $3"
+-   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+-   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+-     # The linker can only warn and ignore the option if not recognized
+-     # So say no if there are warnings
+-     if test -s conftest.err; then
+-       # Append any errors to the config.log.
+-       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+-       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+-       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+-       if diff conftest.exp conftest.er2 >/dev/null; then
+-         $2=yes
+-       fi
+-     else
+-       $2=yes
+-     fi
+-   fi
+-   $RM -r conftest*
+-   LDFLAGS=$save_LDFLAGS
+-])
+-
+-if test yes = "[$]$2"; then
+-    m4_if([$4], , :, [$4])
+-else
+-    m4_if([$5], , :, [$5])
+-fi
+-])# _LT_LINKER_OPTION
+-
+-# Old name:
+-AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+-
+-
+-# LT_CMD_MAX_LEN
+-#---------------
+-AC_DEFUN([LT_CMD_MAX_LEN],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-# find the maximum length of command line arguments
+-AC_MSG_CHECKING([the maximum length of command line arguments])
+-AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+-  i=0
+-  teststring=ABCD
+-
+-  case $build_os in
+-  msdosdjgpp*)
+-    # On DJGPP, this test can blow up pretty badly due to problems in libc
+-    # (any single argument exceeding 2000 bytes causes a buffer overrun
+-    # during glob expansion).  Even if it were fixed, the result of this
+-    # check would be larger than it should be.
+-    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+-    ;;
+-
+-  gnu*)
+-    # Under GNU Hurd, this test is not required because there is
+-    # no limit to the length of command line arguments.
+-    # Libtool will interpret -1 as no limit whatsoever
+-    lt_cv_sys_max_cmd_len=-1;
+-    ;;
+-
+-  cygwin* | mingw* | cegcc*)
+-    # On Win9x/ME, this test blows up -- it succeeds, but takes
+-    # about 5 minutes as the teststring grows exponentially.
+-    # Worse, since 9x/ME are not pre-emptively multitasking,
+-    # you end up with a "frozen" computer, even though with patience
+-    # the test eventually succeeds (with a max line length of 256k).
+-    # Instead, let's just punt: use the minimum linelength reported by
+-    # all of the supported platforms: 8192 (on NT/2K/XP).
+-    lt_cv_sys_max_cmd_len=8192;
+-    ;;
+-
+-  mint*)
+-    # On MiNT this can take a long time and run out of memory.
+-    lt_cv_sys_max_cmd_len=8192;
+-    ;;
+-
+-  amigaos*)
+-    # On AmigaOS with pdksh, this test takes hours, literally.
+-    # So we just punt and use a minimum line length of 8192.
+-    lt_cv_sys_max_cmd_len=8192;
+-    ;;
+-
+-  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+-    # This has been around since 386BSD, at least.  Likely further.
+-    if test -x /sbin/sysctl; then
+-      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+-    elif test -x /usr/sbin/sysctl; then
+-      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+-    else
+-      lt_cv_sys_max_cmd_len=65536	# usable default for all BSDs
+-    fi
+-    # And add a safety zone
+-    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+-    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+-    ;;
+-
+-  interix*)
+-    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+-    lt_cv_sys_max_cmd_len=196608
+-    ;;
+-
+-  os2*)
+-    # The test takes a long time on OS/2.
+-    lt_cv_sys_max_cmd_len=8192
+-    ;;
+-
+-  osf*)
+-    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+-    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+-    # nice to cause kernel panics so lets avoid the loop below.
+-    # First set a reasonable default.
+-    lt_cv_sys_max_cmd_len=16384
+-    #
+-    if test -x /sbin/sysconfig; then
+-      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+-        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+-      esac
+-    fi
+-    ;;
+-  sco3.2v5*)
+-    lt_cv_sys_max_cmd_len=102400
+-    ;;
+-  sysv5* | sco5v6* | sysv4.2uw2*)
+-    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+-    if test -n "$kargmax"; then
+-      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[	 ]]//'`
+-    else
+-      lt_cv_sys_max_cmd_len=32768
+-    fi
+-    ;;
+-  *)
+-    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+-    if test -n "$lt_cv_sys_max_cmd_len" && \
+-       test undefined != "$lt_cv_sys_max_cmd_len"; then
+-      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+-      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+-    else
+-      # Make teststring a little bigger before we do anything with it.
+-      # a 1K string should be a reasonable start.
+-      for i in 1 2 3 4 5 6 7 8; do
+-        teststring=$teststring$teststring
+-      done
+-      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+-      # If test is not a shell built-in, we'll probably end up computing a
+-      # maximum length that is only half of the actual maximum length, but
+-      # we can't tell.
+-      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+-	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+-	      test 17 != "$i" # 1/2 MB should be enough
+-      do
+-        i=`expr $i + 1`
+-        teststring=$teststring$teststring
+-      done
+-      # Only check the string length outside the loop.
+-      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+-      teststring=
+-      # Add a significant safety factor because C++ compilers can tack on
+-      # massive amounts of additional arguments before passing them to the
+-      # linker.  It appears as though 1/2 is a usable value.
+-      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+-    fi
+-    ;;
+-  esac
+-])
+-if test -n "$lt_cv_sys_max_cmd_len"; then
+-  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+-else
+-  AC_MSG_RESULT(none)
+-fi
+-max_cmd_len=$lt_cv_sys_max_cmd_len
+-_LT_DECL([], [max_cmd_len], [0],
+-    [What is the maximum length of a command?])
+-])# LT_CMD_MAX_LEN
+-
+-# Old name:
+-AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+-
+-
+-# _LT_HEADER_DLFCN
+-# ----------------
+-m4_defun([_LT_HEADER_DLFCN],
+-[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+-])# _LT_HEADER_DLFCN
+-
+-
+-# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+-#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+-# ----------------------------------------------------------------
+-m4_defun([_LT_TRY_DLOPEN_SELF],
+-[m4_require([_LT_HEADER_DLFCN])dnl
+-if test yes = "$cross_compiling"; then :
+-  [$4]
+-else
+-  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+-  lt_status=$lt_dlunknown
+-  cat > conftest.$ac_ext <<_LT_EOF
+-[#line $LINENO "configure"
+-#include "confdefs.h"
+-
+-#if HAVE_DLFCN_H
+-#include 
+-#endif
+-
+-#include 
+-
+-#ifdef RTLD_GLOBAL
+-#  define LT_DLGLOBAL		RTLD_GLOBAL
+-#else
+-#  ifdef DL_GLOBAL
+-#    define LT_DLGLOBAL		DL_GLOBAL
+-#  else
+-#    define LT_DLGLOBAL		0
+-#  endif
+-#endif
+-
+-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+-   find out it does not work in some platform. */
+-#ifndef LT_DLLAZY_OR_NOW
+-#  ifdef RTLD_LAZY
+-#    define LT_DLLAZY_OR_NOW		RTLD_LAZY
+-#  else
+-#    ifdef DL_LAZY
+-#      define LT_DLLAZY_OR_NOW		DL_LAZY
+-#    else
+-#      ifdef RTLD_NOW
+-#        define LT_DLLAZY_OR_NOW	RTLD_NOW
+-#      else
+-#        ifdef DL_NOW
+-#          define LT_DLLAZY_OR_NOW	DL_NOW
+-#        else
+-#          define LT_DLLAZY_OR_NOW	0
+-#        endif
+-#      endif
+-#    endif
+-#  endif
+-#endif
+-
+-/* When -fvisibility=hidden is used, assume the code has been annotated
+-   correspondingly for the symbols needed.  */
+-#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+-int fnord () __attribute__((visibility("default")));
+-#endif
+-
+-int fnord () { return 42; }
+-int main ()
+-{
+-  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+-  int status = $lt_dlunknown;
+-
+-  if (self)
+-    {
+-      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+-      else
+-        {
+-	  if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+-          else puts (dlerror ());
+-	}
+-      /* dlclose (self); */
+-    }
+-  else
+-    puts (dlerror ());
+-
+-  return status;
+-}]
+-_LT_EOF
+-  if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
+-    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+-    lt_status=$?
+-    case x$lt_status in
+-      x$lt_dlno_uscore) $1 ;;
+-      x$lt_dlneed_uscore) $2 ;;
+-      x$lt_dlunknown|x*) $3 ;;
+-    esac
+-  else :
+-    # compilation failed
+-    $3
+-  fi
+-fi
+-rm -fr conftest*
+-])# _LT_TRY_DLOPEN_SELF
+-
+-
+-# LT_SYS_DLOPEN_SELF
+-# ------------------
+-AC_DEFUN([LT_SYS_DLOPEN_SELF],
+-[m4_require([_LT_HEADER_DLFCN])dnl
+-if test yes != "$enable_dlopen"; then
+-  enable_dlopen=unknown
+-  enable_dlopen_self=unknown
+-  enable_dlopen_self_static=unknown
+-else
+-  lt_cv_dlopen=no
+-  lt_cv_dlopen_libs=
+-
+-  case $host_os in
+-  beos*)
+-    lt_cv_dlopen=load_add_on
+-    lt_cv_dlopen_libs=
+-    lt_cv_dlopen_self=yes
+-    ;;
+-
+-  mingw* | pw32* | cegcc*)
+-    lt_cv_dlopen=LoadLibrary
+-    lt_cv_dlopen_libs=
+-    ;;
+-
+-  cygwin*)
+-    lt_cv_dlopen=dlopen
+-    lt_cv_dlopen_libs=
+-    ;;
+-
+-  darwin*)
+-    # if libdl is installed we need to link against it
+-    AC_CHECK_LIB([dl], [dlopen],
+-		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
+-    lt_cv_dlopen=dyld
+-    lt_cv_dlopen_libs=
+-    lt_cv_dlopen_self=yes
+-    ])
+-    ;;
+-
+-  tpf*)
+-    # Don't try to run any link tests for TPF.  We know it's impossible
+-    # because TPF is a cross-compiler, and we know how we open DSOs.
+-    lt_cv_dlopen=dlopen
+-    lt_cv_dlopen_libs=
+-    lt_cv_dlopen_self=no
+-    ;;
+-
+-  *)
+-    AC_CHECK_FUNC([shl_load],
+-	  [lt_cv_dlopen=shl_load],
+-      [AC_CHECK_LIB([dld], [shl_load],
+-	    [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
+-	[AC_CHECK_FUNC([dlopen],
+-	      [lt_cv_dlopen=dlopen],
+-	  [AC_CHECK_LIB([dl], [dlopen],
+-		[lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
+-	    [AC_CHECK_LIB([svld], [dlopen],
+-		  [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
+-	      [AC_CHECK_LIB([dld], [dld_link],
+-		    [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
+-	      ])
+-	    ])
+-	  ])
+-	])
+-      ])
+-    ;;
+-  esac
+-
+-  if test no = "$lt_cv_dlopen"; then
+-    enable_dlopen=no
+-  else
+-    enable_dlopen=yes
+-  fi
+-
+-  case $lt_cv_dlopen in
+-  dlopen)
+-    save_CPPFLAGS=$CPPFLAGS
+-    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+-
+-    save_LDFLAGS=$LDFLAGS
+-    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+-
+-    save_LIBS=$LIBS
+-    LIBS="$lt_cv_dlopen_libs $LIBS"
+-
+-    AC_CACHE_CHECK([whether a program can dlopen itself],
+-	  lt_cv_dlopen_self, [dnl
+-	  _LT_TRY_DLOPEN_SELF(
+-	    lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+-	    lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+-    ])
+-
+-    if test yes = "$lt_cv_dlopen_self"; then
+-      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+-      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+-	  lt_cv_dlopen_self_static, [dnl
+-	  _LT_TRY_DLOPEN_SELF(
+-	    lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+-	    lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+-      ])
+-    fi
+-
+-    CPPFLAGS=$save_CPPFLAGS
+-    LDFLAGS=$save_LDFLAGS
+-    LIBS=$save_LIBS
+-    ;;
+-  esac
+-
+-  case $lt_cv_dlopen_self in
+-  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+-  *) enable_dlopen_self=unknown ;;
+-  esac
+-
+-  case $lt_cv_dlopen_self_static in
+-  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+-  *) enable_dlopen_self_static=unknown ;;
+-  esac
+-fi
+-_LT_DECL([dlopen_support], [enable_dlopen], [0],
+-	 [Whether dlopen is supported])
+-_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+-	 [Whether dlopen of programs is supported])
+-_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+-	 [Whether dlopen of statically linked programs is supported])
+-])# LT_SYS_DLOPEN_SELF
+-
+-# Old name:
+-AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+-
+-
+-# _LT_COMPILER_C_O([TAGNAME])
+-# ---------------------------
+-# Check to see if options -c and -o are simultaneously supported by compiler.
+-# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+-m4_defun([_LT_COMPILER_C_O],
+-[m4_require([_LT_DECL_SED])dnl
+-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_TAG_COMPILER])dnl
+-AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+-  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+-  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+-   $RM -r conftest 2>/dev/null
+-   mkdir conftest
+-   cd conftest
+-   mkdir out
+-   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+-
+-   lt_compiler_flag="-o out/conftest2.$ac_objext"
+-   # Insert the option either (1) after the last *FLAGS variable, or
+-   # (2) before a word containing "conftest.", or (3) at the end.
+-   # Note that $ac_compile itself does not contain backslashes and begins
+-   # with a dollar sign (not a hyphen), so the echo should work correctly.
+-   lt_compile=`echo "$ac_compile" | $SED \
+-   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+-   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+-   -e 's:$: $lt_compiler_flag:'`
+-   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+-   (eval "$lt_compile" 2>out/conftest.err)
+-   ac_status=$?
+-   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+-   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+-   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+-   then
+-     # The compiler can only warn and ignore the option if not recognized
+-     # So say no if there are warnings
+-     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+-     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+-     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+-       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+-     fi
+-   fi
+-   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+-   $RM conftest*
+-   # SGI C++ compiler will create directory out/ii_files/ for
+-   # template instantiation
+-   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+-   $RM out/* && rmdir out
+-   cd ..
+-   $RM -r conftest
+-   $RM conftest*
+-])
+-_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+-	[Does compiler simultaneously support -c and -o options?])
+-])# _LT_COMPILER_C_O
+-
+-
+-# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+-# ----------------------------------
+-# Check to see if we can do hard links to lock some files if needed
+-m4_defun([_LT_COMPILER_FILE_LOCKS],
+-[m4_require([_LT_ENABLE_LOCK])dnl
+-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-_LT_COMPILER_C_O([$1])
+-
+-hard_links=nottested
+-if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
+-  # do not overwrite the value of need_locks provided by the user
+-  AC_MSG_CHECKING([if we can lock with hard links])
+-  hard_links=yes
+-  $RM conftest*
+-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+-  touch conftest.a
+-  ln conftest.a conftest.b 2>&5 || hard_links=no
+-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+-  AC_MSG_RESULT([$hard_links])
+-  if test no = "$hard_links"; then
+-    AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
+-    need_locks=warn
+-  fi
+-else
+-  need_locks=no
+-fi
+-_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+-])# _LT_COMPILER_FILE_LOCKS
+-
+-
+-# _LT_CHECK_OBJDIR
+-# ----------------
+-m4_defun([_LT_CHECK_OBJDIR],
+-[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+-[rm -f .libs 2>/dev/null
+-mkdir .libs 2>/dev/null
+-if test -d .libs; then
+-  lt_cv_objdir=.libs
+-else
+-  # MS-DOS does not allow filenames that begin with a dot.
+-  lt_cv_objdir=_libs
+-fi
+-rmdir .libs 2>/dev/null])
+-objdir=$lt_cv_objdir
+-_LT_DECL([], [objdir], [0],
+-         [The name of the directory that contains temporary libtool files])dnl
+-m4_pattern_allow([LT_OBJDIR])dnl
+-AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
+-  [Define to the sub-directory where libtool stores uninstalled libraries.])
+-])# _LT_CHECK_OBJDIR
+-
+-
+-# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+-# --------------------------------------
+-# Check hardcoding attributes.
+-m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+-[AC_MSG_CHECKING([how to hardcode library paths into programs])
+-_LT_TAGVAR(hardcode_action, $1)=
+-if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+-   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+-   test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+-
+-  # We can hardcode non-existent directories.
+-  if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+-     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+-     # have to relink, otherwise we might link with an installed library
+-     # when we should be linking with a yet-to-be-installed one
+-     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+-     test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
+-    # Linking always hardcodes the temporary library directory.
+-    _LT_TAGVAR(hardcode_action, $1)=relink
+-  else
+-    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+-    _LT_TAGVAR(hardcode_action, $1)=immediate
+-  fi
+-else
+-  # We cannot hardcode anything, or else we can only hardcode existing
+-  # directories.
+-  _LT_TAGVAR(hardcode_action, $1)=unsupported
+-fi
+-AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+-
+-if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+-   test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+-  # Fast installation is not supported
+-  enable_fast_install=no
+-elif test yes = "$shlibpath_overrides_runpath" ||
+-     test no = "$enable_shared"; then
+-  # Fast installation is not necessary
+-  enable_fast_install=needless
+-fi
+-_LT_TAGDECL([], [hardcode_action], [0],
+-    [How to hardcode a shared library path into an executable])
+-])# _LT_LINKER_HARDCODE_LIBPATH
+-
+-
+-# _LT_CMD_STRIPLIB
+-# ----------------
+-m4_defun([_LT_CMD_STRIPLIB],
+-[m4_require([_LT_DECL_EGREP])
+-striplib=
+-old_striplib=
+-AC_MSG_CHECKING([whether stripping libraries is possible])
+-if test -z "$STRIP"; then
+-  AC_MSG_RESULT([no])
+-else
+-  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+-    old_striplib="$STRIP --strip-debug"
+-    striplib="$STRIP --strip-unneeded"
+-    AC_MSG_RESULT([yes])
+-  else
+-    case $host_os in
+-    darwin*)
+-      # FIXME - insert some real tests, host_os isn't really good enough
+-      striplib="$STRIP -x"
+-      old_striplib="$STRIP -S"
+-      AC_MSG_RESULT([yes])
+-      ;;
+-    freebsd*)
+-      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+-        old_striplib="$STRIP --strip-debug"
+-        striplib="$STRIP --strip-unneeded"
+-        AC_MSG_RESULT([yes])
+-      else
+-        AC_MSG_RESULT([no])
+-      fi
+-      ;;
+-    *)
+-      AC_MSG_RESULT([no])
+-      ;;
+-    esac
+-  fi
+-fi
+-_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+-_LT_DECL([], [striplib], [1])
+-])# _LT_CMD_STRIPLIB
+-
+-
+-# _LT_PREPARE_MUNGE_PATH_LIST
+-# ---------------------------
+-# Make sure func_munge_path_list() is defined correctly.
+-m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+-[[# func_munge_path_list VARIABLE PATH
+-# -----------------------------------
+-# VARIABLE is name of variable containing _space_ separated list of
+-# directories to be munged by the contents of PATH, which is string
+-# having a format:
+-# "DIR[:DIR]:"
+-#       string "DIR[ DIR]" will be prepended to VARIABLE
+-# ":DIR[:DIR]"
+-#       string "DIR[ DIR]" will be appended to VARIABLE
+-# "DIRP[:DIRP]::[DIRA:]DIRA"
+-#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+-#       "DIRA[ DIRA]" will be appended to VARIABLE
+-# "DIR[:DIR]"
+-#       VARIABLE will be replaced by "DIR[ DIR]"
+-func_munge_path_list ()
+-{
+-    case x@S|@2 in
+-    x)
+-        ;;
+-    *:)
+-        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
+-        ;;
+-    x:*)
+-        eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+-        ;;
+-    *::*)
+-        eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+-        eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
+-        ;;
+-    *)
+-        eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+-        ;;
+-    esac
+-}
+-]])# _LT_PREPARE_PATH_LIST
+-
+-
+-# _LT_SYS_DYNAMIC_LINKER([TAG])
+-# -----------------------------
+-# PORTME Fill in your ld.so characteristics
+-m4_defun([_LT_SYS_DYNAMIC_LINKER],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-m4_require([_LT_DECL_EGREP])dnl
+-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_DECL_OBJDUMP])dnl
+-m4_require([_LT_DECL_SED])dnl
+-m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+-m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+-AC_MSG_CHECKING([dynamic linker characteristics])
+-m4_if([$1],
+-	[], [
+-if test yes = "$GCC"; then
+-  case $host_os in
+-    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+-    *) lt_awk_arg='/^libraries:/' ;;
+-  esac
+-  case $host_os in
+-    mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
+-    *) lt_sed_strip_eq='s|=/|/|g' ;;
+-  esac
+-  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+-  case $lt_search_path_spec in
+-  *\;*)
+-    # if the path contains ";" then we assume it to be the separator
+-    # otherwise default to the standard path separator (i.e. ":") - it is
+-    # assumed that no part of a normal pathname contains ";" but that should
+-    # okay in the real world where ";" in dirpaths is itself problematic.
+-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+-    ;;
+-  *)
+-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+-    ;;
+-  esac
+-  # Ok, now we have the path, separated by spaces, we can step through it
+-  # and add multilib dir if necessary...
+-  lt_tmp_lt_search_path_spec=
+-  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+-  # ...but if some path component already ends with the multilib dir we assume
+-  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+-  case "$lt_multi_os_dir; $lt_search_path_spec " in
+-  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+-    lt_multi_os_dir=
+-    ;;
+-  esac
+-  for lt_sys_path in $lt_search_path_spec; do
+-    if test -d "$lt_sys_path$lt_multi_os_dir"; then
+-      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+-    elif test -n "$lt_multi_os_dir"; then
+-      test -d "$lt_sys_path" && \
+-	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+-    fi
+-  done
+-  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+-BEGIN {RS = " "; FS = "/|\n";} {
+-  lt_foo = "";
+-  lt_count = 0;
+-  for (lt_i = NF; lt_i > 0; lt_i--) {
+-    if ($lt_i != "" && $lt_i != ".") {
+-      if ($lt_i == "..") {
+-        lt_count++;
+-      } else {
+-        if (lt_count == 0) {
+-          lt_foo = "/" $lt_i lt_foo;
+-        } else {
+-          lt_count--;
+-        }
+-      }
+-    }
+-  }
+-  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+-  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+-}'`
+-  # AWK program above erroneously prepends '/' to C:/dos/paths
+-  # for these hosts.
+-  case $host_os in
+-    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+-      $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
+-  esac
+-  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+-else
+-  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+-fi])
+-library_names_spec=
+-libname_spec='lib$name'
+-soname_spec=
+-shrext_cmds=.so
+-postinstall_cmds=
+-postuninstall_cmds=
+-finish_cmds=
+-finish_eval=
+-shlibpath_var=
+-shlibpath_overrides_runpath=unknown
+-version_type=none
+-dynamic_linker="$host_os ld.so"
+-sys_lib_dlsearch_path_spec="/lib /usr/lib"
+-need_lib_prefix=unknown
+-hardcode_into_libs=no
+-
+-# when you set need_version to no, make sure it does not cause -set_version
+-# flags to be left without arguments
+-need_version=unknown
+-
+-AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+-[User-defined run-time library search path.])
+-
+-case $host_os in
+-aix3*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+-  shlibpath_var=LIBPATH
+-
+-  # AIX 3 has no versioning support, so we append a major version to the name.
+-  soname_spec='$libname$release$shared_ext$major'
+-  ;;
+-
+-aix[[4-9]]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  hardcode_into_libs=yes
+-  if test ia64 = "$host_cpu"; then
+-    # AIX 5 supports IA64
+-    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+-    shlibpath_var=LD_LIBRARY_PATH
+-  else
+-    # With GCC up to 2.95.x, collect2 would create an import file
+-    # for dependence libraries.  The import file would start with
+-    # the line '#! .'.  This would cause the generated library to
+-    # depend on '.', always an invalid library.  This was fixed in
+-    # development snapshots of GCC prior to 3.0.
+-    case $host_os in
+-      aix4 | aix4.[[01]] | aix4.[[01]].*)
+-      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+-	   echo ' yes '
+-	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+-	:
+-      else
+-	can_build_shared=no
+-      fi
+-      ;;
+-    esac
+-    # Using Import Files as archive members, it is possible to support
+-    # filename-based versioning of shared library archives on AIX. While
+-    # this would work for both with and without runtime linking, it will
+-    # prevent static linking of such archives. So we do filename-based
+-    # shared library versioning with .so extension only, which is used
+-    # when both runtime linking and shared linking is enabled.
+-    # Unfortunately, runtime linking may impact performance, so we do
+-    # not want this to be the default eventually. Also, we use the
+-    # versioned .so libs for executables only if there is the -brtl
+-    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+-    # To allow for filename-based versioning support, we need to create
+-    # libNAME.so.V as an archive file, containing:
+-    # *) an Import File, referring to the versioned filename of the
+-    #    archive as well as the shared archive member, telling the
+-    #    bitwidth (32 or 64) of that shared object, and providing the
+-    #    list of exported symbols of that shared object, eventually
+-    #    decorated with the 'weak' keyword
+-    # *) the shared object with the F_LOADONLY flag set, to really avoid
+-    #    it being seen by the linker.
+-    # At run time we better use the real file rather than another symlink,
+-    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+-
+-    case $with_aix_soname,$aix_use_runtimelinking in
+-    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+-    # soname into executable. Probably we can add versioning support to
+-    # collect2, so additional links can be useful in future.
+-    aix,yes) # traditional libtool
+-      dynamic_linker='AIX unversionable lib.so'
+-      # If using run time linking (on AIX 4.2 or later) use lib.so
+-      # instead of lib.a to let people know that these are not
+-      # typical AIX shared libraries.
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-      ;;
+-    aix,no) # traditional AIX only
+-      dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+-      # We preserve .a as extension for shared libraries through AIX4.2
+-      # and later when we are not doing run time linking.
+-      library_names_spec='$libname$release.a $libname.a'
+-      soname_spec='$libname$release$shared_ext$major'
+-      ;;
+-    svr4,*) # full svr4 only
+-      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+-      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+-      # We do not specify a path in Import Files, so LIBPATH fires.
+-      shlibpath_overrides_runpath=yes
+-      ;;
+-    *,yes) # both, prefer svr4
+-      dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+-      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+-      # unpreferred sharedlib libNAME.a needs extra handling
+-      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+-      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+-      # We do not specify a path in Import Files, so LIBPATH fires.
+-      shlibpath_overrides_runpath=yes
+-      ;;
+-    *,no) # both, prefer aix
+-      dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+-      library_names_spec='$libname$release.a $libname.a'
+-      soname_spec='$libname$release$shared_ext$major'
+-      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+-      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+-      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+-      ;;
+-    esac
+-    shlibpath_var=LIBPATH
+-  fi
+-  ;;
+-
+-amigaos*)
+-  case $host_cpu in
+-  powerpc)
+-    # Since July 2007 AmigaOS4 officially supports .so libraries.
+-    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    ;;
+-  m68k)
+-    library_names_spec='$libname.ixlibrary $libname.a'
+-    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+-    ;;
+-  esac
+-  ;;
+-
+-beos*)
+-  library_names_spec='$libname$shared_ext'
+-  dynamic_linker="$host_os ld.so"
+-  shlibpath_var=LIBRARY_PATH
+-  ;;
+-
+-bsdi[[45]]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+-  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+-  # the default ld.so.conf also contains /usr/contrib/lib and
+-  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+-  # libtool to hard-code these into programs
+-  ;;
+-
+-cygwin* | mingw* | pw32* | cegcc*)
+-  version_type=windows
+-  shrext_cmds=.dll
+-  need_version=no
+-  need_lib_prefix=no
+-
+-  case $GCC,$cc_basename in
+-  yes,*)
+-    # gcc
+-    library_names_spec='$libname.dll.a'
+-    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+-    postinstall_cmds='base_file=`basename \$file`~
+-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+-      dldir=$destdir/`dirname \$dlpath`~
+-      test -d \$dldir || mkdir -p \$dldir~
+-      $install_prog $dir/$dlname \$dldir/$dlname~
+-      chmod a+x \$dldir/$dlname~
+-      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+-        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+-      fi'
+-    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+-      dlpath=$dir/\$dldll~
+-       $RM \$dlpath'
+-    shlibpath_overrides_runpath=yes
+-
+-    case $host_os in
+-    cygwin*)
+-      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+-      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+-m4_if([$1], [],[
+-      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+-      ;;
+-    mingw* | cegcc*)
+-      # MinGW DLLs use traditional 'lib' prefix
+-      soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+-      ;;
+-    pw32*)
+-      # pw32 DLLs use 'pw' prefix rather than 'lib'
+-      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+-      ;;
+-    esac
+-    dynamic_linker='Win32 ld.exe'
+-    ;;
+-
+-  *,cl* | *,icl*)
+-    # Native MSVC or ICC
+-    libname_spec='$name'
+-    soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+-    library_names_spec='$libname.dll.lib'
+-
+-    case $build_os in
+-    mingw*)
+-      sys_lib_search_path_spec=
+-      lt_save_ifs=$IFS
+-      IFS=';'
+-      for lt_path in $LIB
+-      do
+-        IFS=$lt_save_ifs
+-        # Let DOS variable expansion print the short 8.3 style file name.
+-        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+-        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+-      done
+-      IFS=$lt_save_ifs
+-      # Convert to MSYS style.
+-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+-      ;;
+-    cygwin*)
+-      # Convert to unix form, then to dos form, then back to unix form
+-      # but this time dos style (no spaces!) so that the unix form looks
+-      # like /cygdrive/c/PROGRA~1:/cygdr...
+-      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+-      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+-      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+-      ;;
+-    *)
+-      sys_lib_search_path_spec=$LIB
+-      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+-        # It is most probably a Windows format PATH.
+-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+-      else
+-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+-      fi
+-      # FIXME: find the short name or the path components, as spaces are
+-      # common. (e.g. "Program Files" -> "PROGRA~1")
+-      ;;
+-    esac
+-
+-    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+-    postinstall_cmds='base_file=`basename \$file`~
+-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+-      dldir=$destdir/`dirname \$dlpath`~
+-      test -d \$dldir || mkdir -p \$dldir~
+-      $install_prog $dir/$dlname \$dldir/$dlname'
+-    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+-      dlpath=$dir/\$dldll~
+-       $RM \$dlpath'
+-    shlibpath_overrides_runpath=yes
+-    dynamic_linker='Win32 link.exe'
+-    ;;
+-
+-  *)
+-    # Assume MSVC and ICC wrapper
+-    library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
+-    dynamic_linker='Win32 ld.exe'
+-    ;;
+-  esac
+-  # FIXME: first we should search . and the directory the executable is in
+-  shlibpath_var=PATH
+-  ;;
+-
+-darwin* | rhapsody*)
+-  dynamic_linker="$host_os dyld"
+-  version_type=darwin
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+-  soname_spec='$libname$release$major$shared_ext'
+-  shlibpath_overrides_runpath=yes
+-  shlibpath_var=DYLD_LIBRARY_PATH
+-  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+-m4_if([$1], [],[
+-  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+-  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+-  ;;
+-
+-dgux*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  ;;
+-
+-freebsd* | dragonfly* | midnightbsd*)
+-  # DragonFly does not have aout.  When/if they implement a new
+-  # versioning mechanism, adjust this.
+-  if test -x /usr/bin/objformat; then
+-    objformat=`/usr/bin/objformat`
+-  else
+-    case $host_os in
+-    freebsd[[23]].*) objformat=aout ;;
+-    *) objformat=elf ;;
+-    esac
+-  fi
+-  version_type=freebsd-$objformat
+-  case $version_type in
+-    freebsd-elf*)
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-      soname_spec='$libname$release$shared_ext$major'
+-      need_version=no
+-      need_lib_prefix=no
+-      ;;
+-    freebsd-*)
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+-      need_version=yes
+-      ;;
+-  esac
+-  shlibpath_var=LD_LIBRARY_PATH
+-  case $host_os in
+-  freebsd2.*)
+-    shlibpath_overrides_runpath=yes
+-    ;;
+-  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+-    shlibpath_overrides_runpath=yes
+-    hardcode_into_libs=yes
+-    ;;
+-  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+-  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+-    shlibpath_overrides_runpath=no
+-    hardcode_into_libs=yes
+-    ;;
+-  *) # from 4.6 on, and DragonFly
+-    shlibpath_overrides_runpath=yes
+-    hardcode_into_libs=yes
+-    ;;
+-  esac
+-  ;;
+-
+-haiku*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  dynamic_linker="$host_os runtime_loader"
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+-  hardcode_into_libs=yes
+-  ;;
+-
+-hpux9* | hpux10* | hpux11*)
+-  # Give a soname corresponding to the major version so that dld.sl refuses to
+-  # link against other versions.
+-  version_type=sunos
+-  need_lib_prefix=no
+-  need_version=no
+-  case $host_cpu in
+-  ia64*)
+-    shrext_cmds='.so'
+-    hardcode_into_libs=yes
+-    dynamic_linker="$host_os dld.so"
+-    shlibpath_var=LD_LIBRARY_PATH
+-    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
+-    if test 32 = "$HPUX_IA64_MODE"; then
+-      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+-      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+-    else
+-      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+-      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+-    fi
+-    ;;
+-  hppa*64*)
+-    shrext_cmds='.sl'
+-    hardcode_into_libs=yes
+-    dynamic_linker="$host_os dld.sl"
+-    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+-    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
+-    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+-    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+-    ;;
+-  *)
+-    shrext_cmds='.sl'
+-    dynamic_linker="$host_os dld.sl"
+-    shlibpath_var=SHLIB_PATH
+-    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
+-    ;;
+-  esac
+-  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+-  postinstall_cmds='chmod 555 $lib'
+-  # or fails outright, so override atomically:
+-  install_override_mode=555
+-  ;;
+-
+-interix[[3-9]]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-  hardcode_into_libs=yes
+-  ;;
+-
+-irix5* | irix6* | nonstopux*)
+-  case $host_os in
+-    nonstopux*) version_type=nonstopux ;;
+-    *)
+-	if test yes = "$lt_cv_prog_gnu_ld"; then
+-		version_type=linux # correct to gnu/linux during the next big refactor
+-	else
+-		version_type=irix
+-	fi ;;
+-  esac
+-  need_lib_prefix=no
+-  need_version=no
+-  soname_spec='$libname$release$shared_ext$major'
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+-  case $host_os in
+-  irix5* | nonstopux*)
+-    libsuff= shlibsuff=
+-    ;;
+-  *)
+-    case $LD in # libtool.m4 will add one of these switches to LD
+-    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+-      libsuff= shlibsuff= libmagic=32-bit;;
+-    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+-      libsuff=32 shlibsuff=N32 libmagic=N32;;
+-    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+-      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+-    *) libsuff= shlibsuff= libmagic=never-match;;
+-    esac
+-    ;;
+-  esac
+-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+-  shlibpath_overrides_runpath=no
+-  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+-  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+-  hardcode_into_libs=yes
+-  ;;
+-
+-# No shared lib support for Linux oldld, aout, or coff.
+-linux*oldld* | linux*aout* | linux*coff*)
+-  dynamic_linker=no
+-  ;;
+-
+-linux*android*)
+-  version_type=none # Android doesn't support versioned libraries.
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext'
+-  soname_spec='$libname$release$shared_ext'
+-  finish_cmds=
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-
+-  # This implies no fast_install, which is unacceptable.
+-  # Some rework will be needed to allow for fast_install
+-  # before this can be enabled.
+-  hardcode_into_libs=yes
+-
+-  dynamic_linker='Android linker'
+-  # Don't embed -rpath directories since the linker doesn't support them.
+-  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-  ;;
+-
+-# This must be glibc/ELF.
+-linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-
+-  # Some binutils ld are patched to set DT_RUNPATH
+-  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+-    [lt_cv_shlibpath_overrides_runpath=no
+-    save_LDFLAGS=$LDFLAGS
+-    save_libdir=$libdir
+-    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+-	 LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+-    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+-      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+-	 [lt_cv_shlibpath_overrides_runpath=yes])])
+-    LDFLAGS=$save_LDFLAGS
+-    libdir=$save_libdir
+-    ])
+-  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+-
+-  # This implies no fast_install, which is unacceptable.
+-  # Some rework will be needed to allow for fast_install
+-  # before this can be enabled.
+-  hardcode_into_libs=yes
+-
+-  # Add ABI-specific directories to the system library path.
+-  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+-
+-  # Ideally, we could use ldconfig to report *all* directores which are
+-  # searched for libraries, however this is still not possible.  Aside from not
+-  # being certain /sbin/ldconfig is available, command
+-  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+-  # even though it is searched at run-time.  Try to do the best guess by
+-  # appending ld.so.conf contents (and includes) to the search path.
+-  if test -f /etc/ld.so.conf; then
+-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+-    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+-  fi
+-
+-  # We used to test for /lib/ld.so.1 and disable shared libraries on
+-  # powerpc, because MkLinux only supported shared libraries with the
+-  # GNU dynamic linker.  Since this was broken with cross compilers,
+-  # most powerpc-linux boxes support dynamic linking these days and
+-  # people can always --disable-shared, the test was removed, and we
+-  # assume the GNU/Linux dynamic linker is in use.
+-  dynamic_linker='GNU/Linux ld.so'
+-  ;;
+-
+-netbsd*)
+-  version_type=sunos
+-  need_lib_prefix=no
+-  need_version=no
+-  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+-    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+-    dynamic_linker='NetBSD (a.out) ld.so'
+-  else
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
+-    dynamic_linker='NetBSD ld.elf_so'
+-  fi
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-  hardcode_into_libs=yes
+-  ;;
+-
+-newsos6)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-  ;;
+-
+-*nto* | *qnx*)
+-  version_type=qnx
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-  hardcode_into_libs=yes
+-  dynamic_linker='ldqnx.so'
+-  ;;
+-
+-openbsd* | bitrig*)
+-  version_type=sunos
+-  sys_lib_dlsearch_path_spec=/usr/lib
+-  need_lib_prefix=no
+-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+-    need_version=no
+-  else
+-    need_version=yes
+-  fi
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-  ;;
+-
+-os2*)
+-  libname_spec='$name'
+-  version_type=windows
+-  shrext_cmds=.dll
+-  need_version=no
+-  need_lib_prefix=no
+-  # OS/2 can only load a DLL with a base name of 8 characters or less.
+-  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+-    v=$($ECHO $release$versuffix | tr -d .-);
+-    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+-    $ECHO $n$v`$shared_ext'
+-  library_names_spec='${libname}_dll.$libext'
+-  dynamic_linker='OS/2 ld.exe'
+-  shlibpath_var=BEGINLIBPATH
+-  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+-  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+-  postinstall_cmds='base_file=`basename \$file`~
+-    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+-    dldir=$destdir/`dirname \$dlpath`~
+-    test -d \$dldir || mkdir -p \$dldir~
+-    $install_prog $dir/$dlname \$dldir/$dlname~
+-    chmod a+x \$dldir/$dlname~
+-    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+-      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+-    fi'
+-  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+-    dlpath=$dir/\$dldll~
+-    $RM \$dlpath'
+-  ;;
+-
+-osf3* | osf4* | osf5*)
+-  version_type=osf
+-  need_lib_prefix=no
+-  need_version=no
+-  soname_spec='$libname$release$shared_ext$major'
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+-  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+-  ;;
+-
+-rdos*)
+-  dynamic_linker=no
+-  ;;
+-
+-solaris*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-  hardcode_into_libs=yes
+-  # ldd complains unless libraries are executable
+-  postinstall_cmds='chmod +x $lib'
+-  ;;
+-
+-sunos4*)
+-  version_type=sunos
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+-  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-  if test yes = "$with_gnu_ld"; then
+-    need_lib_prefix=no
+-  fi
+-  need_version=yes
+-  ;;
+-
+-sysv4 | sysv4.3*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  case $host_vendor in
+-    sni)
+-      shlibpath_overrides_runpath=no
+-      need_lib_prefix=no
+-      runpath_var=LD_RUN_PATH
+-      ;;
+-    siemens)
+-      need_lib_prefix=no
+-      ;;
+-    motorola)
+-      need_lib_prefix=no
+-      need_version=no
+-      shlibpath_overrides_runpath=no
+-      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+-      ;;
+-  esac
+-  ;;
+-
+-sysv4*MP*)
+-  if test -d /usr/nec; then
+-    version_type=linux # correct to gnu/linux during the next big refactor
+-    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+-    soname_spec='$libname$shared_ext.$major'
+-    shlibpath_var=LD_LIBRARY_PATH
+-  fi
+-  ;;
+-
+-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+-  version_type=sco
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-  hardcode_into_libs=yes
+-  if test yes = "$with_gnu_ld"; then
+-    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+-  else
+-    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+-    case $host_os in
+-      sco3.2v5*)
+-        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+-	;;
+-    esac
+-  fi
+-  sys_lib_dlsearch_path_spec='/usr/lib'
+-  ;;
+-
+-tpf*)
+-  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-  hardcode_into_libs=yes
+-  ;;
+-
+-uts4*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  ;;
+-
+-*)
+-  dynamic_linker=no
+-  ;;
+-esac
+-AC_MSG_RESULT([$dynamic_linker])
+-test no = "$dynamic_linker" && can_build_shared=no
+-
+-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+-if test yes = "$GCC"; then
+-  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+-fi
+-
+-if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+-  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+-fi
+-
+-if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+-  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+-fi
+-
+-# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+-configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+-
+-# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+-func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+-
+-# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+-configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+-
+-_LT_DECL([], [variables_saved_for_relink], [1],
+-    [Variables whose values should be saved in libtool wrapper scripts and
+-    restored at link time])
+-_LT_DECL([], [need_lib_prefix], [0],
+-    [Do we need the "lib" prefix for modules?])
+-_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+-_LT_DECL([], [version_type], [0], [Library versioning type])
+-_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+-_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+-_LT_DECL([], [shlibpath_overrides_runpath], [0],
+-    [Is shlibpath searched before the hard-coded library search path?])
+-_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+-_LT_DECL([], [library_names_spec], [1],
+-    [[List of archive names.  First name is the real one, the rest are links.
+-    The last name is the one that the linker finds with -lNAME]])
+-_LT_DECL([], [soname_spec], [1],
+-    [[The coded name of the library, if different from the real name]])
+-_LT_DECL([], [install_override_mode], [1],
+-    [Permission mode override for installation of shared libraries])
+-_LT_DECL([], [postinstall_cmds], [2],
+-    [Command to use after installation of a shared archive])
+-_LT_DECL([], [postuninstall_cmds], [2],
+-    [Command to use after uninstallation of a shared archive])
+-_LT_DECL([], [finish_cmds], [2],
+-    [Commands used to finish a libtool library installation in a directory])
+-_LT_DECL([], [finish_eval], [1],
+-    [[As "finish_cmds", except a single script fragment to be evaled but
+-    not shown]])
+-_LT_DECL([], [hardcode_into_libs], [0],
+-    [Whether we should hardcode library paths into libraries])
+-_LT_DECL([], [sys_lib_search_path_spec], [2],
+-    [Compile-time system search path for libraries])
+-_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
+-    [Detected run-time system search path for libraries])
+-_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+-    [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+-])# _LT_SYS_DYNAMIC_LINKER
+-
+-
+-# _LT_PATH_TOOL_PREFIX(TOOL)
+-# --------------------------
+-# find a file program that can recognize shared library
+-AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+-[m4_require([_LT_DECL_EGREP])dnl
+-AC_MSG_CHECKING([for $1])
+-AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+-[case $MAGIC_CMD in
+-[[\\/*] |  ?:[\\/]*])
+-  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+-  ;;
+-*)
+-  lt_save_MAGIC_CMD=$MAGIC_CMD
+-  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+-dnl $ac_dummy forces splitting on constant user-supplied paths.
+-dnl POSIX.2 word splitting is done only on the output of word expansions,
+-dnl not every word.  This closes a longstanding sh security hole.
+-  ac_dummy="m4_if([$2], , $PATH, [$2])"
+-  for ac_dir in $ac_dummy; do
+-    IFS=$lt_save_ifs
+-    test -z "$ac_dir" && ac_dir=.
+-    if test -f "$ac_dir/$1"; then
+-      lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
+-      if test -n "$file_magic_test_file"; then
+-	case $deplibs_check_method in
+-	"file_magic "*)
+-	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+-	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+-	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+-	    $EGREP "$file_magic_regex" > /dev/null; then
+-	    :
+-	  else
+-	    cat <<_LT_EOF 1>&2
+-
+-*** Warning: the command libtool uses to detect shared libraries,
+-*** $file_magic_cmd, produces output that libtool cannot recognize.
+-*** The result is that libtool may fail to recognize shared libraries
+-*** as such.  This will affect the creation of libtool libraries that
+-*** depend on shared libraries, but programs linked with such libtool
+-*** libraries will work regardless of this problem.  Nevertheless, you
+-*** may want to report the problem to your system manager and/or to
+-*** bug-libtool@gnu.org
+-
+-_LT_EOF
+-	  fi ;;
+-	esac
+-      fi
+-      break
+-    fi
+-  done
+-  IFS=$lt_save_ifs
+-  MAGIC_CMD=$lt_save_MAGIC_CMD
+-  ;;
+-esac])
+-MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+-if test -n "$MAGIC_CMD"; then
+-  AC_MSG_RESULT($MAGIC_CMD)
+-else
+-  AC_MSG_RESULT(no)
+-fi
+-_LT_DECL([], [MAGIC_CMD], [0],
+-	 [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+-])# _LT_PATH_TOOL_PREFIX
+-
+-# Old name:
+-AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+-
+-
+-# _LT_PATH_MAGIC
+-# --------------
+-# find a file program that can recognize a shared library
+-m4_defun([_LT_PATH_MAGIC],
+-[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+-if test -z "$lt_cv_path_MAGIC_CMD"; then
+-  if test -n "$ac_tool_prefix"; then
+-    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+-  else
+-    MAGIC_CMD=:
+-  fi
+-fi
+-])# _LT_PATH_MAGIC
+-
+-
+-# LT_PATH_LD
+-# ----------
+-# find the pathname to the GNU or non-GNU linker
+-AC_DEFUN([LT_PATH_LD],
+-[AC_REQUIRE([AC_PROG_CC])dnl
+-AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+-m4_require([_LT_DECL_SED])dnl
+-m4_require([_LT_DECL_EGREP])dnl
+-m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+-
+-AC_ARG_WITH([gnu-ld],
+-    [AS_HELP_STRING([--with-gnu-ld],
+-	[assume the C compiler uses GNU ld @<:@default=no@:>@])],
+-    [test no = "$withval" || with_gnu_ld=yes],
+-    [with_gnu_ld=no])dnl
+-
+-ac_prog=ld
+-if test yes = "$GCC"; then
+-  # Check if gcc -print-prog-name=ld gives a path.
+-  AC_MSG_CHECKING([for ld used by $CC])
+-  case $host in
+-  *-*-mingw*)
+-    # gcc leaves a trailing carriage return, which upsets mingw
+-    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+-  *)
+-    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+-  esac
+-  case $ac_prog in
+-    # Accept absolute paths.
+-    [[\\/]]* | ?:[[\\/]]*)
+-      re_direlt='/[[^/]][[^/]]*/\.\./'
+-      # Canonicalize the pathname of ld
+-      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+-      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+-	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+-      done
+-      test -z "$LD" && LD=$ac_prog
+-      ;;
+-  "")
+-    # If it fails, then pretend we aren't using GCC.
+-    ac_prog=ld
+-    ;;
+-  *)
+-    # If it is relative, then search for the first ld in PATH.
+-    with_gnu_ld=unknown
+-    ;;
+-  esac
+-elif test yes = "$with_gnu_ld"; then
+-  AC_MSG_CHECKING([for GNU ld])
+-else
+-  AC_MSG_CHECKING([for non-GNU ld])
+-fi
+-AC_CACHE_VAL(lt_cv_path_LD,
+-[if test -z "$LD"; then
+-  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+-  for ac_dir in $PATH; do
+-    IFS=$lt_save_ifs
+-    test -z "$ac_dir" && ac_dir=.
+-    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+-      lt_cv_path_LD=$ac_dir/$ac_prog
+-      # Check to see if the program is GNU ld.  I'd rather use --version,
+-      # but apparently some variants of GNU ld only accept -v.
+-      # Break only if it was the GNU/non-GNU ld that we prefer.
+-      case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i
+-cat conftest.i conftest.i >conftest2.i
+-: ${lt_DD:=$DD}
+-AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+-[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+-  cmp -s conftest.i conftest.out \
+-  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+-fi])
+-rm -f conftest.i conftest2.i conftest.out])
+-])# _LT_PATH_DD
+-
+-
+-# _LT_CMD_TRUNCATE
+-# ----------------
+-# find command to truncate a binary pipe
+-m4_defun([_LT_CMD_TRUNCATE],
+-[m4_require([_LT_PATH_DD])
+-AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+-[printf 0123456789abcdef0123456789abcdef >conftest.i
+-cat conftest.i conftest.i >conftest2.i
+-lt_cv_truncate_bin=
+-if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+-  cmp -s conftest.i conftest.out \
+-  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+-fi
+-rm -f conftest.i conftest2.i conftest.out
+-test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+-_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+-  [Command to truncate a binary pipe])
+-])# _LT_CMD_TRUNCATE
+-
+-
+-# _LT_CHECK_MAGIC_METHOD
+-# ----------------------
+-# how to check for library dependencies
+-#  -- PORTME fill in with the dynamic library characteristics
+-m4_defun([_LT_CHECK_MAGIC_METHOD],
+-[m4_require([_LT_DECL_EGREP])
+-m4_require([_LT_DECL_OBJDUMP])
+-AC_CACHE_CHECK([how to recognize dependent libraries],
+-lt_cv_deplibs_check_method,
+-[lt_cv_file_magic_cmd='$MAGIC_CMD'
+-lt_cv_file_magic_test_file=
+-lt_cv_deplibs_check_method='unknown'
+-# Need to set the preceding variable on all platforms that support
+-# interlibrary dependencies.
+-# 'none' -- dependencies not supported.
+-# 'unknown' -- same as none, but documents that we really don't know.
+-# 'pass_all' -- all dependencies passed with no checks.
+-# 'test_compile' -- check by making test program.
+-# 'file_magic [[regex]]' -- check by looking for files in library path
+-# that responds to the $file_magic_cmd with a given extended regex.
+-# If you have 'file' or equivalent on your system and you're not sure
+-# whether 'pass_all' will *always* work, you probably want this one.
+-
+-case $host_os in
+-aix[[4-9]]*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-beos*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-bsdi[[45]]*)
+-  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+-  lt_cv_file_magic_cmd='$FILECMD -L'
+-  lt_cv_file_magic_test_file=/shlib/libc.so
+-  ;;
+-
+-cygwin*)
+-  # func_win32_libid is a shell function defined in ltmain.sh
+-  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+-  lt_cv_file_magic_cmd='func_win32_libid'
+-  ;;
+-
+-mingw* | pw32*)
+-  # Base MSYS/MinGW do not provide the 'file' command needed by
+-  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+-  # unless we find 'file', for example because we are cross-compiling.
+-  if ( file / ) >/dev/null 2>&1; then
+-    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+-    lt_cv_file_magic_cmd='func_win32_libid'
+-  else
+-    # Keep this pattern in sync with the one in func_win32_libid.
+-    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+-    lt_cv_file_magic_cmd='$OBJDUMP -f'
+-  fi
+-  ;;
+-
+-cegcc*)
+-  # use the weaker test based on 'objdump'. See mingw*.
+-  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+-  lt_cv_file_magic_cmd='$OBJDUMP -f'
+-  ;;
+-
+-darwin* | rhapsody*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-freebsd* | dragonfly* | midnightbsd*)
+-  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+-    case $host_cpu in
+-    i*86 )
+-      # Not sure whether the presence of OpenBSD here was a mistake.
+-      # Let's accept both of them until this is cleared up.
+-      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+-      lt_cv_file_magic_cmd=$FILECMD
+-      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+-      ;;
+-    esac
+-  else
+-    lt_cv_deplibs_check_method=pass_all
+-  fi
+-  ;;
+-
+-haiku*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-hpux10.20* | hpux11*)
+-  lt_cv_file_magic_cmd=$FILECMD
+-  case $host_cpu in
+-  ia64*)
+-    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+-    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+-    ;;
+-  hppa*64*)
+-    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+-    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+-    ;;
+-  *)
+-    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+-    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+-    ;;
+-  esac
+-  ;;
+-
+-interix[[3-9]]*)
+-  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+-  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+-  ;;
+-
+-irix5* | irix6* | nonstopux*)
+-  case $LD in
+-  *-32|*"-32 ") libmagic=32-bit;;
+-  *-n32|*"-n32 ") libmagic=N32;;
+-  *-64|*"-64 ") libmagic=64-bit;;
+-  *) libmagic=never-match;;
+-  esac
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-# This must be glibc/ELF.
+-linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-netbsd*)
+-  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+-    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+-  else
+-    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+-  fi
+-  ;;
+-
+-newos6*)
+-  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+-  lt_cv_file_magic_cmd=$FILECMD
+-  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+-  ;;
+-
+-*nto* | *qnx*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-openbsd* | bitrig*)
+-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+-    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+-  else
+-    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+-  fi
+-  ;;
+-
+-osf3* | osf4* | osf5*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-rdos*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-solaris*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-
+-sysv4 | sysv4.3*)
+-  case $host_vendor in
+-  motorola)
+-    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+-    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+-    ;;
+-  ncr)
+-    lt_cv_deplibs_check_method=pass_all
+-    ;;
+-  sequent)
+-    lt_cv_file_magic_cmd='/bin/file'
+-    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+-    ;;
+-  sni)
+-    lt_cv_file_magic_cmd='/bin/file'
+-    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+-    lt_cv_file_magic_test_file=/lib/libc.so
+-    ;;
+-  siemens)
+-    lt_cv_deplibs_check_method=pass_all
+-    ;;
+-  pc)
+-    lt_cv_deplibs_check_method=pass_all
+-    ;;
+-  esac
+-  ;;
+-
+-tpf*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-os2*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-esac
+-])
+-
+-file_magic_glob=
+-want_nocaseglob=no
+-if test "$build" = "$host"; then
+-  case $host_os in
+-  mingw* | pw32*)
+-    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+-      want_nocaseglob=yes
+-    else
+-      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+-    fi
+-    ;;
+-  esac
+-fi
+-
+-file_magic_cmd=$lt_cv_file_magic_cmd
+-deplibs_check_method=$lt_cv_deplibs_check_method
+-test -z "$deplibs_check_method" && deplibs_check_method=unknown
+-
+-_LT_DECL([], [deplibs_check_method], [1],
+-    [Method to check whether dependent libraries are shared objects])
+-_LT_DECL([], [file_magic_cmd], [1],
+-    [Command to use when deplibs_check_method = "file_magic"])
+-_LT_DECL([], [file_magic_glob], [1],
+-    [How to find potential files when deplibs_check_method = "file_magic"])
+-_LT_DECL([], [want_nocaseglob], [1],
+-    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+-])# _LT_CHECK_MAGIC_METHOD
+-
+-
+-# LT_PATH_NM
+-# ----------
+-# find the pathname to a BSD- or MS-compatible name lister
+-AC_DEFUN([LT_PATH_NM],
+-[AC_REQUIRE([AC_PROG_CC])dnl
+-AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+-[if test -n "$NM"; then
+-  # Let the user override the test.
+-  lt_cv_path_NM=$NM
+-else
+-  lt_nm_to_check=${ac_tool_prefix}nm
+-  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+-    lt_nm_to_check="$lt_nm_to_check nm"
+-  fi
+-  for lt_tmp_nm in $lt_nm_to_check; do
+-    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+-    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+-      IFS=$lt_save_ifs
+-      test -z "$ac_dir" && ac_dir=.
+-      tmp_nm=$ac_dir/$lt_tmp_nm
+-      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+-	# Check to see if the nm accepts a BSD-compat flag.
+-	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+-	#   nm: unknown option "B" ignored
+-	# Tru64's nm complains that /dev/null is an invalid object file
+-	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+-	case $build_os in
+-	mingw*) lt_bad_file=conftest.nm/nofile ;;
+-	*) lt_bad_file=/dev/null ;;
+-	esac
+-	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+-	*$lt_bad_file* | *'Invalid file or object type'*)
+-	  lt_cv_path_NM="$tmp_nm -B"
+-	  break 2
+-	  ;;
+-	*)
+-	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+-	  */dev/null*)
+-	    lt_cv_path_NM="$tmp_nm -p"
+-	    break 2
+-	    ;;
+-	  *)
+-	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+-	    continue # so that we can try to find one that supports BSD flags
+-	    ;;
+-	  esac
+-	  ;;
+-	esac
+-      fi
+-    done
+-    IFS=$lt_save_ifs
+-  done
+-  : ${lt_cv_path_NM=no}
+-fi])
+-if test no != "$lt_cv_path_NM"; then
+-  NM=$lt_cv_path_NM
+-else
+-  # Didn't find any BSD compatible name lister, look for dumpbin.
+-  if test -n "$DUMPBIN"; then :
+-    # Let the user override the test.
+-  else
+-    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+-    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+-    *COFF*)
+-      DUMPBIN="$DUMPBIN -symbols -headers"
+-      ;;
+-    *)
+-      DUMPBIN=:
+-      ;;
+-    esac
+-  fi
+-  AC_SUBST([DUMPBIN])
+-  if test : != "$DUMPBIN"; then
+-    NM=$DUMPBIN
+-  fi
+-fi
+-test -z "$NM" && NM=nm
+-AC_SUBST([NM])
+-_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+-
+-AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+-  [lt_cv_nm_interface="BSD nm"
+-  echo "int some_variable = 0;" > conftest.$ac_ext
+-  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+-  (eval "$ac_compile" 2>conftest.err)
+-  cat conftest.err >&AS_MESSAGE_LOG_FD
+-  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+-  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+-  cat conftest.err >&AS_MESSAGE_LOG_FD
+-  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+-  cat conftest.out >&AS_MESSAGE_LOG_FD
+-  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+-    lt_cv_nm_interface="MS dumpbin"
+-  fi
+-  rm -f conftest*])
+-])# LT_PATH_NM
+-
+-# Old names:
+-AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+-AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AM_PROG_NM], [])
+-dnl AC_DEFUN([AC_PROG_NM], [])
+-
+-# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+-# --------------------------------
+-# how to determine the name of the shared library
+-# associated with a specific link library.
+-#  -- PORTME fill in with the dynamic library characteristics
+-m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+-[m4_require([_LT_DECL_EGREP])
+-m4_require([_LT_DECL_OBJDUMP])
+-m4_require([_LT_DECL_DLLTOOL])
+-AC_CACHE_CHECK([how to associate runtime and link libraries],
+-lt_cv_sharedlib_from_linklib_cmd,
+-[lt_cv_sharedlib_from_linklib_cmd='unknown'
+-
+-case $host_os in
+-cygwin* | mingw* | pw32* | cegcc*)
+-  # two different shell functions defined in ltmain.sh;
+-  # decide which one to use based on capabilities of $DLLTOOL
+-  case `$DLLTOOL --help 2>&1` in
+-  *--identify-strict*)
+-    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+-    ;;
+-  *)
+-    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+-    ;;
+-  esac
+-  ;;
+-*)
+-  # fallback: assume linklib IS sharedlib
+-  lt_cv_sharedlib_from_linklib_cmd=$ECHO
+-  ;;
+-esac
+-])
+-sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+-test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+-
+-_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+-    [Command to associate shared and link libraries])
+-])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+-
+-
+-# _LT_PATH_MANIFEST_TOOL
+-# ----------------------
+-# locate the manifest tool
+-m4_defun([_LT_PATH_MANIFEST_TOOL],
+-[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+-test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+-AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+-  [lt_cv_path_mainfest_tool=no
+-  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+-  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+-  cat conftest.err >&AS_MESSAGE_LOG_FD
+-  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+-    lt_cv_path_mainfest_tool=yes
+-  fi
+-  rm -f conftest*])
+-if test yes != "$lt_cv_path_mainfest_tool"; then
+-  MANIFEST_TOOL=:
+-fi
+-_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+-])# _LT_PATH_MANIFEST_TOOL
+-
+-
+-# _LT_DLL_DEF_P([FILE])
+-# ---------------------
+-# True iff FILE is a Windows DLL '.def' file.
+-# Keep in sync with func_dll_def_p in the libtool script
+-AC_DEFUN([_LT_DLL_DEF_P],
+-[dnl
+-  test DEF = "`$SED -n dnl
+-    -e '\''s/^[[	 ]]*//'\'' dnl Strip leading whitespace
+-    -e '\''/^\(;.*\)*$/d'\'' dnl      Delete empty lines and comments
+-    -e '\''s/^\(EXPORTS\|LIBRARY\)\([[	 ]].*\)*$/DEF/p'\'' dnl
+-    -e q dnl                          Only consider the first "real" line
+-    $1`" dnl
+-])# _LT_DLL_DEF_P
+-
+-
+-# LT_LIB_M
+-# --------
+-# check for math library
+-AC_DEFUN([LT_LIB_M],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-LIBM=
+-case $host in
+-*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+-  # These system don't have libm, or don't need it
+-  ;;
+-*-ncr-sysv4.3*)
+-  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
+-  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+-  ;;
+-*)
+-  AC_CHECK_LIB(m, cos, LIBM=-lm)
+-  ;;
+-esac
+-AC_SUBST([LIBM])
+-])# LT_LIB_M
+-
+-# Old name:
+-AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_CHECK_LIBM], [])
+-
+-
+-# _LT_COMPILER_NO_RTTI([TAGNAME])
+-# -------------------------------
+-m4_defun([_LT_COMPILER_NO_RTTI],
+-[m4_require([_LT_TAG_COMPILER])dnl
+-
+-_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+-
+-if test yes = "$GCC"; then
+-  case $cc_basename in
+-  nvcc*)
+-    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+-  *)
+-    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+-  esac
+-
+-  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+-    lt_cv_prog_compiler_rtti_exceptions,
+-    [-fno-rtti -fno-exceptions], [],
+-    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+-fi
+-_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+-	[Compiler flag to turn off builtin functions])
+-])# _LT_COMPILER_NO_RTTI
+-
+-
+-# _LT_CMD_GLOBAL_SYMBOLS
+-# ----------------------
+-m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-AC_REQUIRE([AC_PROG_CC])dnl
+-AC_REQUIRE([AC_PROG_AWK])dnl
+-AC_REQUIRE([LT_PATH_NM])dnl
+-AC_REQUIRE([LT_PATH_LD])dnl
+-m4_require([_LT_DECL_SED])dnl
+-m4_require([_LT_DECL_EGREP])dnl
+-m4_require([_LT_TAG_COMPILER])dnl
+-
+-# Check for command to grab the raw symbol name followed by C symbol from nm.
+-AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+-AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+-[
+-# These are sane defaults that work on at least a few old systems.
+-# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+-
+-# Character class describing NM global symbol codes.
+-symcode='[[BCDEGRST]]'
+-
+-# Regexp to match symbols that can be accessed directly from C.
+-sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+-
+-# Define system-specific variables.
+-case $host_os in
+-aix*)
+-  symcode='[[BCDT]]'
+-  ;;
+-cygwin* | mingw* | pw32* | cegcc*)
+-  symcode='[[ABCDGISTW]]'
+-  ;;
+-hpux*)
+-  if test ia64 = "$host_cpu"; then
+-    symcode='[[ABCDEGRST]]'
+-  fi
+-  ;;
+-irix* | nonstopux*)
+-  symcode='[[BCDEGRST]]'
+-  ;;
+-osf*)
+-  symcode='[[BCDEGQRST]]'
+-  ;;
+-solaris*)
+-  symcode='[[BDRT]]'
+-  ;;
+-sco3.2v5*)
+-  symcode='[[DT]]'
+-  ;;
+-sysv4.2uw2*)
+-  symcode='[[DT]]'
+-  ;;
+-sysv5* | sco5v6* | unixware* | OpenUNIX*)
+-  symcode='[[ABDT]]'
+-  ;;
+-sysv4)
+-  symcode='[[DFNSTU]]'
+-  ;;
+-esac
+-
+-# If we're using GNU nm, then use its standard symbol codes.
+-case `$NM -V 2>&1` in
+-*GNU* | *'with BFD'*)
+-  symcode='[[ABCDGIRSTW]]' ;;
+-esac
+-
+-if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+-  # Gets list of data symbols to import.
+-  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+-  # Adjust the below global symbol transforms to fixup imported variables.
+-  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+-  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
+-  lt_c_name_lib_hook="\
+-  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
+-  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
+-else
+-  # Disable hooks by default.
+-  lt_cv_sys_global_symbol_to_import=
+-  lt_cdecl_hook=
+-  lt_c_name_hook=
+-  lt_c_name_lib_hook=
+-fi
+-
+-# Transform an extracted symbol line into a proper C declaration.
+-# Some systems (esp. on ia64) link data and code symbols differently,
+-# so use this general approach.
+-lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+-$lt_cdecl_hook\
+-" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+-" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+-
+-# Transform an extracted symbol line into symbol name and symbol address
+-lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+-$lt_c_name_hook\
+-" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+-" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
+-
+-# Transform an extracted symbol line into symbol name with lib prefix and
+-# symbol address.
+-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+-$lt_c_name_lib_hook\
+-" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+-" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+-" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
+-
+-# Handle CRLF in mingw tool chain
+-opt_cr=
+-case $build_os in
+-mingw*)
+-  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+-  ;;
+-esac
+-
+-# Try without a prefix underscore, then with it.
+-for ac_symprfx in "" "_"; do
+-
+-  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+-  symxfrm="\\1 $ac_symprfx\\2 \\2"
+-
+-  # Write the raw and C identifiers.
+-  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+-    # Fake it for dumpbin and say T for any non-static function,
+-    # D for any global variable and I for any imported variable.
+-    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+-    # which start with @ or ?.
+-    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+-"     {last_section=section; section=\$ 3};"\
+-"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+-"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+-"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+-"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+-"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+-"     \$ 0!~/External *\|/{next};"\
+-"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+-"     {if(hide[section]) next};"\
+-"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+-"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+-"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+-"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+-"     ' prfx=^$ac_symprfx]"
+-  else
+-    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[	 ]]\($symcode$symcode*\)[[	 ]][[	 ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+-  fi
+-  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+-
+-  # Check to see that the pipe works correctly.
+-  pipe_works=no
+-
+-  rm -f conftest*
+-  cat > conftest.$ac_ext <<_LT_EOF
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-char nm_test_var;
+-void nm_test_func(void);
+-void nm_test_func(void){}
+-#ifdef __cplusplus
+-}
+-#endif
+-int main(){nm_test_var='a';nm_test_func();return(0);}
+-_LT_EOF
+-
+-  if AC_TRY_EVAL(ac_compile); then
+-    # Now try to grab the symbols.
+-    nlist=conftest.nm
+-    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+-      # Try sorting and uniquifying the output.
+-      if sort "$nlist" | uniq > "$nlist"T; then
+-	mv -f "$nlist"T "$nlist"
+-      else
+-	rm -f "$nlist"T
+-      fi
+-
+-      # Make sure that we snagged all the symbols we need.
+-      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+-	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+-	  cat <<_LT_EOF > conftest.$ac_ext
+-/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+-#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+-/* DATA imports from DLLs on WIN32 can't be const, because runtime
+-   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+-# define LT@&t@_DLSYM_CONST
+-#elif defined __osf__
+-/* This system does not cope well with relocations in const data.  */
+-# define LT@&t@_DLSYM_CONST
+-#else
+-# define LT@&t@_DLSYM_CONST const
+-#endif
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-_LT_EOF
+-	  # Now generate the symbol file.
+-	  eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+-
+-	  cat <<_LT_EOF >> conftest.$ac_ext
+-
+-/* The mapping between symbol names and symbols.  */
+-LT@&t@_DLSYM_CONST struct {
+-  const char *name;
+-  void       *address;
+-}
+-lt__PROGRAM__LTX_preloaded_symbols[[]] =
+-{
+-  { "@PROGRAM@", (void *) 0 },
+-_LT_EOF
+-	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+-	  cat <<\_LT_EOF >> conftest.$ac_ext
+-  {0, (void *) 0}
+-};
+-
+-/* This works around a problem in FreeBSD linker */
+-#ifdef FREEBSD_WORKAROUND
+-static const void *lt_preloaded_setup() {
+-  return lt__PROGRAM__LTX_preloaded_symbols;
+-}
+-#endif
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-_LT_EOF
+-	  # Now try linking the two files.
+-	  mv conftest.$ac_objext conftstm.$ac_objext
+-	  lt_globsym_save_LIBS=$LIBS
+-	  lt_globsym_save_CFLAGS=$CFLAGS
+-	  LIBS=conftstm.$ac_objext
+-	  CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+-	  if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+-	    pipe_works=yes
+-	  fi
+-	  LIBS=$lt_globsym_save_LIBS
+-	  CFLAGS=$lt_globsym_save_CFLAGS
+-	else
+-	  echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+-	fi
+-      else
+-	echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+-      fi
+-    else
+-      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+-    fi
+-  else
+-    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+-    cat conftest.$ac_ext >&5
+-  fi
+-  rm -rf conftest* conftst*
+-
+-  # Do not use the global_symbol_pipe unless it works.
+-  if test yes = "$pipe_works"; then
+-    break
+-  else
+-    lt_cv_sys_global_symbol_pipe=
+-  fi
+-done
+-])
+-if test -z "$lt_cv_sys_global_symbol_pipe"; then
+-  lt_cv_sys_global_symbol_to_cdecl=
+-fi
+-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+-  AC_MSG_RESULT(failed)
+-else
+-  AC_MSG_RESULT(ok)
+-fi
+-
+-# Response file support.
+-if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+-  nm_file_list_spec='@'
+-elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+-  nm_file_list_spec='@'
+-fi
+-
+-_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+-    [Take the output of nm and produce a listing of raw symbols and C names])
+-_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+-    [Transform the output of nm in a proper C declaration])
+-_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+-    [Transform the output of nm into a list of symbols to manually relocate])
+-_LT_DECL([global_symbol_to_c_name_address],
+-    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+-    [Transform the output of nm in a C name address pair])
+-_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+-    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+-    [Transform the output of nm in a C name address pair when lib prefix is needed])
+-_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
+-    [The name lister interface])
+-_LT_DECL([], [nm_file_list_spec], [1],
+-    [Specify filename containing input files for $NM])
+-]) # _LT_CMD_GLOBAL_SYMBOLS
+-
+-
+-# _LT_COMPILER_PIC([TAGNAME])
+-# ---------------------------
+-m4_defun([_LT_COMPILER_PIC],
+-[m4_require([_LT_TAG_COMPILER])dnl
+-_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+-_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+-_LT_TAGVAR(lt_prog_compiler_static, $1)=
+-
+-m4_if([$1], [CXX], [
+-  # C++ specific cases for pic, static, wl, etc.
+-  if test yes = "$GXX"; then
+-    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-
+-    case $host_os in
+-    aix*)
+-      # All AIX code is PIC.
+-      if test ia64 = "$host_cpu"; then
+-	# AIX 5 now supports IA64 processor
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      fi
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-      ;;
+-
+-    amigaos*)
+-      case $host_cpu in
+-      powerpc)
+-            # see comment about AmigaOS4 .so support
+-            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-        ;;
+-      m68k)
+-            # FIXME: we need at least 68020 code to build shared libraries, but
+-            # adding the '-m68020' flag to GCC prevents building anything better,
+-            # like '-m68040'.
+-            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+-        ;;
+-      esac
+-      ;;
+-
+-    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+-      # PIC is the default for these OSes.
+-      ;;
+-    mingw* | cygwin* | os2* | pw32* | cegcc*)
+-      # This hack is so that the source file can tell whether it is being
+-      # built for inclusion in a dll (and should export symbols for example).
+-      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+-      # (--disable-auto-import) libraries
+-      m4_if([$1], [GCJ], [],
+-	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+-      case $host_os in
+-      os2*)
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+-	;;
+-      esac
+-      ;;
+-    darwin* | rhapsody*)
+-      # PIC is the default on this platform
+-      # Common symbols not allowed in MH_DYLIB files
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+-      ;;
+-    *djgpp*)
+-      # DJGPP does not support shared libraries at all
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+-      ;;
+-    haiku*)
+-      # PIC is the default for Haiku.
+-      # The "-static" flag exists, but is broken.
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+-      ;;
+-    interix[[3-9]]*)
+-      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+-      # Instead, we relocate shared libraries at runtime.
+-      ;;
+-    sysv4*MP*)
+-      if test -d /usr/nec; then
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+-      fi
+-      ;;
+-    hpux*)
+-      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+-      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+-      # sets the default TLS model and affects inlining.
+-      case $host_cpu in
+-      hppa*64*)
+-	;;
+-      *)
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	;;
+-      esac
+-      ;;
+-    *qnx* | *nto*)
+-      # QNX uses GNU C++, but need to define -shared option too, otherwise
+-      # it will coredump.
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+-      ;;
+-    *)
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-      ;;
+-    esac
+-  else
+-    case $host_os in
+-      aix[[4-9]]*)
+-	# All AIX code is PIC.
+-	if test ia64 = "$host_cpu"; then
+-	  # AIX 5 now supports IA64 processor
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	else
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+-	fi
+-	;;
+-      chorus*)
+-	case $cc_basename in
+-	cxch68*)
+-	  # Green Hills C++ Compiler
+-	  # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+-	  ;;
+-	esac
+-	;;
+-      mingw* | cygwin* | os2* | pw32* | cegcc*)
+-	# This hack is so that the source file can tell whether it is being
+-	# built for inclusion in a dll (and should export symbols for example).
+-	m4_if([$1], [GCJ], [],
+-	  [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+-	;;
+-      dgux*)
+-	case $cc_basename in
+-	  ec++*)
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	    ;;
+-	  ghcx*)
+-	    # Green Hills C++ Compiler
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      freebsd* | dragonfly* | midnightbsd*)
+-	# FreeBSD uses GNU C++
+-	;;
+-      hpux9* | hpux10* | hpux11*)
+-	case $cc_basename in
+-	  CC*)
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+-	    if test ia64 != "$host_cpu"; then
+-	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+-	    fi
+-	    ;;
+-	  aCC*)
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+-	    case $host_cpu in
+-	    hppa*64*|ia64*)
+-	      # +Z the default
+-	      ;;
+-	    *)
+-	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+-	      ;;
+-	    esac
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      interix*)
+-	# This is c89, which is MS Visual C++ (no shared libs)
+-	# Anyone wants to do a port?
+-	;;
+-      irix5* | irix6* | nonstopux*)
+-	case $cc_basename in
+-	  CC*)
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-	    # CC pic flag -KPIC is the default.
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-	case $cc_basename in
+-	  KCC*)
+-	    # KAI C++ Compiler
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	    ;;
+-	  ecpc* )
+-	    # old Intel C++ for x86_64, which still supported -KPIC.
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-	    ;;
+-	  icpc* )
+-	    # Intel C++, used to be incompatible with GCC.
+-	    # ICC 10 doesn't accept -KPIC any more.
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-	    ;;
+-	  pgCC* | pgcpp*)
+-	    # Portland Group C++ compiler
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	    ;;
+-	  cxx*)
+-	    # Compaq C++
+-	    # Make sure the PIC flag is empty.  It appears that all Alpha
+-	    # Linux and Compaq Tru64 Unix objects are PIC.
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-	    ;;
+-	  xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+-	    # IBM XL 8.0, 9.0 on PPC and BlueGene
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+-	    ;;
+-	  *)
+-	    case `$CC -V 2>&1 | $SED 5q` in
+-	    *Sun\ C*)
+-	      # Sun C++ 5.9
+-	      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+-	      ;;
+-	    esac
+-	    ;;
+-	esac
+-	;;
+-      lynxos*)
+-	;;
+-      m88k*)
+-	;;
+-      mvs*)
+-	case $cc_basename in
+-	  cxx*)
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      netbsd*)
+-	;;
+-      *qnx* | *nto*)
+-        # QNX uses GNU C++, but need to define -shared option too, otherwise
+-        # it will coredump.
+-        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+-        ;;
+-      osf3* | osf4* | osf5*)
+-	case $cc_basename in
+-	  KCC*)
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+-	    ;;
+-	  RCC*)
+-	    # Rational C++ 2.4.1
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+-	    ;;
+-	  cxx*)
+-	    # Digital/Compaq C++
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    # Make sure the PIC flag is empty.  It appears that all Alpha
+-	    # Linux and Compaq Tru64 Unix objects are PIC.
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      psos*)
+-	;;
+-      solaris*)
+-	case $cc_basename in
+-	  CC* | sunCC*)
+-	    # Sun C++ 4.2, 5.x and Centerline C++
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+-	    ;;
+-	  gcx*)
+-	    # Green Hills C++ Compiler
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      sunos4*)
+-	case $cc_basename in
+-	  CC*)
+-	    # Sun C++ 4.x
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	    ;;
+-	  lcc*)
+-	    # Lucid
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+-	case $cc_basename in
+-	  CC*)
+-	    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	    _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	    ;;
+-	esac
+-	;;
+-      tandem*)
+-	case $cc_basename in
+-	  NCC*)
+-	    # NonStop-UX NCC 3.20
+-	    _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	    ;;
+-	  *)
+-	    ;;
+-	esac
+-	;;
+-      vxworks*)
+-	;;
+-      *)
+-	_LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+-	;;
+-    esac
+-  fi
+-],
+-[
+-  if test yes = "$GCC"; then
+-    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-
+-    case $host_os in
+-      aix*)
+-      # All AIX code is PIC.
+-      if test ia64 = "$host_cpu"; then
+-	# AIX 5 now supports IA64 processor
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      fi
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-      ;;
+-
+-    amigaos*)
+-      case $host_cpu in
+-      powerpc)
+-            # see comment about AmigaOS4 .so support
+-            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-        ;;
+-      m68k)
+-            # FIXME: we need at least 68020 code to build shared libraries, but
+-            # adding the '-m68020' flag to GCC prevents building anything better,
+-            # like '-m68040'.
+-            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+-        ;;
+-      esac
+-      ;;
+-
+-    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+-      # PIC is the default for these OSes.
+-      ;;
+-
+-    mingw* | cygwin* | pw32* | os2* | cegcc*)
+-      # This hack is so that the source file can tell whether it is being
+-      # built for inclusion in a dll (and should export symbols for example).
+-      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+-      # (--disable-auto-import) libraries
+-      m4_if([$1], [GCJ], [],
+-	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+-      case $host_os in
+-      os2*)
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+-	;;
+-      esac
+-      ;;
+-
+-    darwin* | rhapsody*)
+-      # PIC is the default on this platform
+-      # Common symbols not allowed in MH_DYLIB files
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+-      ;;
+-
+-    haiku*)
+-      # PIC is the default for Haiku.
+-      # The "-static" flag exists, but is broken.
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+-      ;;
+-
+-    hpux*)
+-      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+-      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+-      # sets the default TLS model and affects inlining.
+-      case $host_cpu in
+-      hppa*64*)
+-	# +Z the default
+-	;;
+-      *)
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	;;
+-      esac
+-      ;;
+-
+-    interix[[3-9]]*)
+-      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+-      # Instead, we relocate shared libraries at runtime.
+-      ;;
+-
+-    msdosdjgpp*)
+-      # Just because we use GCC doesn't mean we suddenly get shared libraries
+-      # on systems that don't support them.
+-      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+-      enable_shared=no
+-      ;;
+-
+-    *nto* | *qnx*)
+-      # QNX uses GNU C++, but need to define -shared option too, otherwise
+-      # it will coredump.
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+-      ;;
+-
+-    sysv4*MP*)
+-      if test -d /usr/nec; then
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+-      fi
+-      ;;
+-
+-    *)
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-      ;;
+-    esac
+-
+-    case $cc_basename in
+-    nvcc*) # Cuda Compiler Driver 2.2
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+-      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+-        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+-      fi
+-      ;;
+-    esac
+-  else
+-    # PORTME Check for flag to pass linker flags through the system compiler.
+-    case $host_os in
+-    aix*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      if test ia64 = "$host_cpu"; then
+-	# AIX 5 now supports IA64 processor
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      else
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+-      fi
+-      ;;
+-
+-    darwin* | rhapsody*)
+-      # PIC is the default on this platform
+-      # Common symbols not allowed in MH_DYLIB files
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+-      case $cc_basename in
+-      nagfor*)
+-        # NAG Fortran compiler
+-        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+-        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+-        _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-        ;;
+-      esac
+-      ;;
+-
+-    mingw* | cygwin* | pw32* | os2* | cegcc*)
+-      # This hack is so that the source file can tell whether it is being
+-      # built for inclusion in a dll (and should export symbols for example).
+-      m4_if([$1], [GCJ], [],
+-	[_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+-      case $host_os in
+-      os2*)
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+-	;;
+-      esac
+-      ;;
+-
+-    hpux9* | hpux10* | hpux11*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+-      # not for PA HP-UX.
+-      case $host_cpu in
+-      hppa*64*|ia64*)
+-	# +Z the default
+-	;;
+-      *)
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+-	;;
+-      esac
+-      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+-      ;;
+-
+-    irix5* | irix6* | nonstopux*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      # PIC (with -KPIC) is the default.
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-      ;;
+-
+-    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-      case $cc_basename in
+-      # old Intel for x86_64, which still supported -KPIC.
+-      ecc*)
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-        ;;
+-      # icc used to be incompatible with GCC.
+-      # ICC 10 doesn't accept -KPIC any more.
+-      icc* | ifort*)
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-        ;;
+-      # Lahey Fortran 8.1.
+-      lf95*)
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+-	;;
+-      nagfor*)
+-	# NAG Fortran compiler
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	;;
+-      tcc*)
+-	# Fabrice Bellard et al's Tiny C Compiler
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-	;;
+-      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+-        # Portland Group compilers (*not* the Pentium gcc compiler,
+-	# which looks to be a dead project)
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-        ;;
+-      ccc*)
+-        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-        # All Alpha code is PIC.
+-        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-        ;;
+-      xl* | bgxl* | bgf* | mpixl*)
+-	# IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+-	;;
+-      *)
+-	case `$CC -V 2>&1 | $SED 5q` in
+-	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+-	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+-	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+-	  ;;
+-	*Sun\ F* | *Sun*Fortran*)
+-	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+-	  ;;
+-	*Sun\ C*)
+-	  # Sun C 5.9
+-	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	  ;;
+-        *Intel*\ [[CF]]*Compiler*)
+-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+-	  ;;
+-	*Portland\ Group*)
+-	  _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-	  _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+-	  _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-	  ;;
+-	esac
+-	;;
+-      esac
+-      ;;
+-
+-    newsos6)
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      ;;
+-
+-    *nto* | *qnx*)
+-      # QNX uses GNU C++, but need to define -shared option too, otherwise
+-      # it will coredump.
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+-      ;;
+-
+-    osf3* | osf4* | osf5*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      # All OSF/1 code is PIC.
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-      ;;
+-
+-    rdos*)
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+-      ;;
+-
+-    solaris*)
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      case $cc_basename in
+-      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+-      *)
+-	_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+-      esac
+-      ;;
+-
+-    sunos4*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      ;;
+-
+-    sysv4 | sysv4.2uw2* | sysv4.3*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      ;;
+-
+-    sysv4*MP*)
+-      if test -d /usr/nec; then
+-	_LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+-	_LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      fi
+-      ;;
+-
+-    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      ;;
+-
+-    unicos*)
+-      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+-      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+-      ;;
+-
+-    uts4*)
+-      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+-      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+-      ;;
+-
+-    *)
+-      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+-      ;;
+-    esac
+-  fi
+-])
+-case $host_os in
+-  # For platforms that do not support PIC, -DPIC is meaningless:
+-  *djgpp*)
+-    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+-    ;;
+-  *)
+-    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+-    ;;
+-esac
+-
+-AC_CACHE_CHECK([for $compiler option to produce PIC],
+-  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+-  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+-_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+-
+-#
+-# Check to make sure the PIC flag actually works.
+-#
+-if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+-  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+-    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+-    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+-    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+-     "" | " "*) ;;
+-     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+-     esac],
+-    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+-     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+-fi
+-_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+-	[Additional compiler flags for building library objects])
+-
+-_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+-	[How to pass a linker flag through the compiler])
+-#
+-# Check to make sure the static flag actually works.
+-#
+-wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+-_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+-  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+-  $lt_tmp_static_flag,
+-  [],
+-  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+-_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+-	[Compiler flag to prevent dynamic linking])
+-])# _LT_COMPILER_PIC
+-
+-
+-# _LT_LINKER_SHLIBS([TAGNAME])
+-# ----------------------------
+-# See if the linker supports building shared libraries.
+-m4_defun([_LT_LINKER_SHLIBS],
+-[AC_REQUIRE([LT_PATH_LD])dnl
+-AC_REQUIRE([LT_PATH_NM])dnl
+-m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+-m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_DECL_EGREP])dnl
+-m4_require([_LT_DECL_SED])dnl
+-m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+-m4_require([_LT_TAG_COMPILER])dnl
+-AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+-m4_if([$1], [CXX], [
+-  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+-  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+-  case $host_os in
+-  aix[[4-9]]*)
+-    # If we're using GNU nm, then we don't want the "-C" option.
+-    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+-    # Without the "-l" option, or with the "-B" option, AIX nm treats
+-    # weak defined symbols like other global defined symbols, whereas
+-    # GNU nm marks them as "W".
+-    # While the 'weak' keyword is ignored in the Export File, we need
+-    # it in the Import File for the 'aix-soname' feature, so we have
+-    # to replace the "-B" option with "-P" for AIX nm.
+-    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+-      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+-    else
+-      _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+-    fi
+-    ;;
+-  pw32*)
+-    _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
+-    ;;
+-  cygwin* | mingw* | cegcc*)
+-    case $cc_basename in
+-    cl* | icl*)
+-      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+-      ;;
+-    *)
+-      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+-      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+-      ;;
+-    esac
+-    ;;
+-  *)
+-    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+-    ;;
+-  esac
+-], [
+-  runpath_var=
+-  _LT_TAGVAR(allow_undefined_flag, $1)=
+-  _LT_TAGVAR(always_export_symbols, $1)=no
+-  _LT_TAGVAR(archive_cmds, $1)=
+-  _LT_TAGVAR(archive_expsym_cmds, $1)=
+-  _LT_TAGVAR(compiler_needs_object, $1)=no
+-  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+-  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+-  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+-  _LT_TAGVAR(hardcode_automatic, $1)=no
+-  _LT_TAGVAR(hardcode_direct, $1)=no
+-  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+-  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+-  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+-  _LT_TAGVAR(hardcode_minus_L, $1)=no
+-  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+-  _LT_TAGVAR(inherit_rpath, $1)=no
+-  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+-  _LT_TAGVAR(module_cmds, $1)=
+-  _LT_TAGVAR(module_expsym_cmds, $1)=
+-  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+-  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+-  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+-  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+-  # include_expsyms should be a list of space-separated symbols to be *always*
+-  # included in the symbol list
+-  _LT_TAGVAR(include_expsyms, $1)=
+-  # exclude_expsyms can be an extended regexp of symbols to exclude
+-  # it will be wrapped by ' (' and ')$', so one must not match beginning or
+-  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+-  # as well as any symbol that contains 'd'.
+-  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+-  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+-  # platforms (ab)use it in PIC code, but their linkers get confused if
+-  # the symbol is explicitly referenced.  Since portable code cannot
+-  # rely on this symbol name, it's probably fine to never include it in
+-  # preloaded symbol tables.
+-  # Exclude shared library initialization/finalization symbols.
+-dnl Note also adjust exclude_expsyms for C++ above.
+-  extract_expsyms_cmds=
+-
+-  case $host_os in
+-  cygwin* | mingw* | pw32* | cegcc*)
+-    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+-    # When not using gcc, we currently assume that we are using
+-    # Microsoft Visual C++ or Intel C++ Compiler.
+-    if test yes != "$GCC"; then
+-      with_gnu_ld=no
+-    fi
+-    ;;
+-  interix*)
+-    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+-    with_gnu_ld=yes
+-    ;;
+-  openbsd* | bitrig*)
+-    with_gnu_ld=no
+-    ;;
+-  esac
+-
+-  _LT_TAGVAR(ld_shlibs, $1)=yes
+-
+-  # On some targets, GNU ld is compatible enough with the native linker
+-  # that we're better off using the native interface for both.
+-  lt_use_gnu_ld_interface=no
+-  if test yes = "$with_gnu_ld"; then
+-    case $host_os in
+-      aix*)
+-	# The AIX port of GNU ld has always aspired to compatibility
+-	# with the native linker.  However, as the warning in the GNU ld
+-	# block says, versions before 2.19.5* couldn't really create working
+-	# shared libraries, regardless of the interface used.
+-	case `$LD -v 2>&1` in
+-	  *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+-	  *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+-	  *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+-	  *)
+-	    lt_use_gnu_ld_interface=yes
+-	    ;;
+-	esac
+-	;;
+-      *)
+-	lt_use_gnu_ld_interface=yes
+-	;;
+-    esac
+-  fi
+-
+-  if test yes = "$lt_use_gnu_ld_interface"; then
+-    # If archive_cmds runs LD, not CC, wlarc should be empty
+-    wlarc='$wl'
+-
+-    # Set some defaults for GNU ld with shared library support. These
+-    # are reset later if shared libraries are not supported. Putting them
+-    # here allows them to be overridden if necessary.
+-    runpath_var=LD_RUN_PATH
+-    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+-    # ancient GNU ld didn't support --whole-archive et. al.
+-    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+-      _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+-    else
+-      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+-    fi
+-    supports_anon_versioning=no
+-    case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
+-      *GNU\ gold*) supports_anon_versioning=yes ;;
+-      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+-      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+-      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+-      *\ 2.11.*) ;; # other 2.11 versions
+-      *) supports_anon_versioning=yes ;;
+-    esac
+-
+-    # See if GNU ld supports shared libraries.
+-    case $host_os in
+-    aix[[3-9]]*)
+-      # On AIX/PPC, the GNU linker is very broken
+-      if test ia64 != "$host_cpu"; then
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-	cat <<_LT_EOF 1>&2
+-
+-*** Warning: the GNU linker, at least up to release 2.19, is reported
+-*** to be unable to reliably create shared libraries on AIX.
+-*** Therefore, libtool is disabling shared libraries support.  If you
+-*** really care for shared libraries, you may want to install binutils
+-*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+-*** You will then need to restart the configuration process.
+-
+-_LT_EOF
+-      fi
+-      ;;
+-
+-    amigaos*)
+-      case $host_cpu in
+-      powerpc)
+-            # see comment about AmigaOS4 .so support
+-            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+-        ;;
+-      m68k)
+-            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+-            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-        ;;
+-      esac
+-      ;;
+-
+-    beos*)
+-      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	# Joseph Beckenbach  says some releases of gcc
+-	# support --undefined.  This deserves some investigation.  FIXME
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-      else
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-      fi
+-      ;;
+-
+-    cygwin* | mingw* | pw32* | cegcc*)
+-      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+-      # as there is no search path for DLLs.
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+-      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-      _LT_TAGVAR(always_export_symbols, $1)=no
+-      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+-      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+-
+-      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+-        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-	# If the export-symbols file already is a .def file, use it as
+-	# is; otherwise, prepend EXPORTS...
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+-          cp $export_symbols $output_objdir/$soname.def;
+-        else
+-          echo EXPORTS > $output_objdir/$soname.def;
+-          cat $export_symbols >> $output_objdir/$soname.def;
+-        fi~
+-        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-      else
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-      fi
+-      ;;
+-
+-    haiku*)
+-      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-      _LT_TAGVAR(link_all_deplibs, $1)=yes
+-      ;;
+-
+-    os2*)
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-      shrext_cmds=.dll
+-      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	prefix_cmds="$SED"~
+-	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+-	  prefix_cmds="$prefix_cmds -e 1d";
+-	fi~
+-	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+-	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+-      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-      _LT_TAGVAR(file_list_spec, $1)='@'
+-      ;;
+-
+-    interix[[3-9]]*)
+-      _LT_TAGVAR(hardcode_direct, $1)=no
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+-      # Instead, shared libraries are loaded at an image base (0x10000000 by
+-      # default) and relocated if they conflict, which is a slow very memory
+-      # consuming and fragmenting process.  To avoid this, we pick a random,
+-      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+-      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+-      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+-      _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+-      ;;
+-
+-    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+-      tmp_diet=no
+-      if test linux-dietlibc = "$host_os"; then
+-	case $cc_basename in
+-	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+-	esac
+-      fi
+-      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+-	 && test no = "$tmp_diet"
+-      then
+-	tmp_addflag=' $pic_flag'
+-	tmp_sharedflag='-shared'
+-	case $cc_basename,$host_cpu in
+-        pgcc*)				# Portland Group C compiler
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+-	  tmp_addflag=' $pic_flag'
+-	  ;;
+-	pgf77* | pgf90* | pgf95* | pgfortran*)
+-					# Portland Group f77 and f90 compilers
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+-	  tmp_addflag=' $pic_flag -Mnomain' ;;
+-	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+-	  tmp_addflag=' -i_dynamic' ;;
+-	efc*,ia64* | ifort*,ia64*)	# Intel Fortran compiler on ia64
+-	  tmp_addflag=' -i_dynamic -nofor_main' ;;
+-	ifc* | ifort*)			# Intel Fortran compiler
+-	  tmp_addflag=' -nofor_main' ;;
+-	lf95*)				# Lahey Fortran 8.1
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+-	  tmp_sharedflag='--shared' ;;
+-        nagfor*)                        # NAGFOR 5.3
+-          tmp_sharedflag='-Wl,-shared' ;;
+-	xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+-	  tmp_sharedflag='-qmkshrobj'
+-	  tmp_addflag= ;;
+-	nvcc*)	# Cuda Compiler Driver 2.2
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+-	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+-	  ;;
+-	esac
+-	case `$CC -V 2>&1 | $SED 5q` in
+-	*Sun\ C*)			# Sun C 5.9
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+-	  _LT_TAGVAR(compiler_needs_object, $1)=yes
+-	  tmp_sharedflag='-G' ;;
+-	*Sun\ F*)			# Sun Fortran 8.3
+-	  tmp_sharedflag='-G' ;;
+-	esac
+-	_LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-
+-        if test yes = "$supports_anon_versioning"; then
+-          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+-            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+-            echo "local: *; };" >> $output_objdir/$libname.ver~
+-            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+-        fi
+-
+-	case $cc_basename in
+-	tcc*)
+-	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+-	  ;;
+-	xlf* | bgf* | bgxlf* | mpixlf*)
+-	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-	  _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+-	  if test yes = "$supports_anon_versioning"; then
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+-              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+-              echo "local: *; };" >> $output_objdir/$libname.ver~
+-              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+-	  fi
+-	  ;;
+-	esac
+-      else
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-      fi
+-      ;;
+-
+-    netbsd*)
+-      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+-	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+-	wlarc=
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-      fi
+-      ;;
+-
+-    solaris*)
+-      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-	cat <<_LT_EOF 1>&2
+-
+-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+-*** create shared libraries on Solaris systems.  Therefore, libtool
+-*** is disabling shared libraries support.  We urge you to upgrade GNU
+-*** binutils to release 2.9.1 or newer.  Another option is to modify
+-*** your PATH or compiler configuration so that the native linker is
+-*** used, and then restart.
+-
+-_LT_EOF
+-      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-      else
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-      fi
+-      ;;
+-
+-    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+-      case `$LD -v 2>&1` in
+-        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-	cat <<_LT_EOF 1>&2
+-
+-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+-*** reliably create shared libraries on SCO systems.  Therefore, libtool
+-*** is disabling shared libraries support.  We urge you to upgrade GNU
+-*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+-*** your PATH or compiler configuration so that the native linker is
+-*** used, and then restart.
+-
+-_LT_EOF
+-	;;
+-	*)
+-	  # For security reasons, it is highly recommended that you always
+-	  # use absolute paths for naming shared libraries, and exclude the
+-	  # DT_RUNPATH tag from executables and libraries.  But doing so
+-	  # requires that you compile everything twice, which is a pain.
+-	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-	  else
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	  fi
+-	;;
+-      esac
+-      ;;
+-
+-    sunos4*)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+-      wlarc=
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    *)
+-      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-      else
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-      fi
+-      ;;
+-    esac
+-
+-    if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
+-      runpath_var=
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+-      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+-    fi
+-  else
+-    # PORTME fill in a description of your system's linker (not GNU ld)
+-    case $host_os in
+-    aix3*)
+-      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-      _LT_TAGVAR(always_export_symbols, $1)=yes
+-      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+-      # Note: this linker hardcodes the directories in LIBPATH if there
+-      # are no directories specified by -L.
+-      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+-	# Neither direct hardcoding nor static linking is supported with a
+-	# broken collect2.
+-	_LT_TAGVAR(hardcode_direct, $1)=unsupported
+-      fi
+-      ;;
+-
+-    aix[[4-9]]*)
+-      if test ia64 = "$host_cpu"; then
+-	# On IA64, the linker does run time linking by default, so we don't
+-	# have to do anything special.
+-	aix_use_runtimelinking=no
+-	exp_sym_flag='-Bexport'
+-	no_entry_flag=
+-      else
+-	# If we're using GNU nm, then we don't want the "-C" option.
+-	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
+-	# Without the "-l" option, or with the "-B" option, AIX nm treats
+-	# weak defined symbols like other global defined symbols, whereas
+-	# GNU nm marks them as "W".
+-	# While the 'weak' keyword is ignored in the Export File, we need
+-	# it in the Import File for the 'aix-soname' feature, so we have
+-	# to replace the "-B" option with "-P" for AIX nm.
+-	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+-	  _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+-	else
+-	  _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+-	fi
+-	aix_use_runtimelinking=no
+-
+-	# Test if we are trying to use run time linking or normal
+-	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+-	# have runtime linking enabled, and use it for executables.
+-	# For shared libraries, we enable/disable runtime linking
+-	# depending on the kind of the shared library created -
+-	# when "with_aix_soname,aix_use_runtimelinking" is:
+-	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+-	# "aix,yes"  lib.so          shared, rtl:yes, for executables
+-	#            lib.a           static archive
+-	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
+-	#            lib.a(lib.so.V) shared, rtl:no,  for executables
+-	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+-	#            lib.a(lib.so.V) shared, rtl:no
+-	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+-	#            lib.a           static archive
+-	case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+-	  for ld_flag in $LDFLAGS; do
+-	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+-	    aix_use_runtimelinking=yes
+-	    break
+-	  fi
+-	  done
+-	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+-	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
+-	    # so we don't have lib.a shared libs to link our executables.
+-	    # We have to force runtime linking in this case.
+-	    aix_use_runtimelinking=yes
+-	    LDFLAGS="$LDFLAGS -Wl,-brtl"
+-	  fi
+-	  ;;
+-	esac
+-
+-	exp_sym_flag='-bexport'
+-	no_entry_flag='-bnoentry'
+-      fi
+-
+-      # When large executables or shared objects are built, AIX ld can
+-      # have problems creating the table of contents.  If linking a library
+-      # or program results in "error TOC overflow" add -mminimal-toc to
+-      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+-      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+-
+-      _LT_TAGVAR(archive_cmds, $1)=''
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+-      _LT_TAGVAR(link_all_deplibs, $1)=yes
+-      _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+-      case $with_aix_soname,$aix_use_runtimelinking in
+-      aix,*) ;; # traditional, no import file
+-      svr4,* | *,yes) # use import file
+-	# The Import File defines what to hardcode.
+-	_LT_TAGVAR(hardcode_direct, $1)=no
+-	_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+-	;;
+-      esac
+-
+-      if test yes = "$GCC"; then
+-	case $host_os in aix4.[[012]]|aix4.[[012]].*)
+-	# We only want to do this on AIX 4.2 and lower, the check
+-	# below for broken collect2 doesn't work under 4.3+
+-	  collect2name=`$CC -print-prog-name=collect2`
+-	  if test -f "$collect2name" &&
+-	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+-	  then
+-	  # We have reworked collect2
+-	  :
+-	  else
+-	  # We have old collect2
+-	  _LT_TAGVAR(hardcode_direct, $1)=unsupported
+-	  # It fails to find uninstalled libraries when the uninstalled
+-	  # path is not listed in the libpath.  Setting hardcode_minus_L
+-	  # to unsupported forces relinking
+-	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-	  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+-	  fi
+-	  ;;
+-	esac
+-	shared_flag='-shared'
+-	if test yes = "$aix_use_runtimelinking"; then
+-	  shared_flag="$shared_flag "'$wl-G'
+-	fi
+-	# Need to ensure runtime linking is disabled for the traditional
+-	# shared library, or the linker may eventually find shared libraries
+-	# /with/ Import File - we do not want to mix them.
+-	shared_flag_aix='-shared'
+-	shared_flag_svr4='-shared $wl-G'
+-      else
+-	# not using gcc
+-	if test ia64 = "$host_cpu"; then
+-	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+-	# chokes on -Wl,-G. The following line is correct:
+-	  shared_flag='-G'
+-	else
+-	  if test yes = "$aix_use_runtimelinking"; then
+-	    shared_flag='$wl-G'
+-	  else
+-	    shared_flag='$wl-bM:SRE'
+-	  fi
+-	  shared_flag_aix='$wl-bM:SRE'
+-	  shared_flag_svr4='$wl-G'
+-	fi
+-      fi
+-
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+-      # It seems that -bexpall does not export symbols beginning with
+-      # underscore (_), so it is better to generate a list of symbols to export.
+-      _LT_TAGVAR(always_export_symbols, $1)=yes
+-      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+-	# Warning - without using the other runtime loading flags (-brtl),
+-	# -berok will link without error, but may produce a broken library.
+-	_LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+-        # Determine the default libpath from the value encoded in an
+-        # empty executable.
+-        _LT_SYS_MODULE_PATH_AIX([$1])
+-        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+-        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+-      else
+-	if test ia64 = "$host_cpu"; then
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+-	  _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+-	else
+-	 # Determine the default libpath from the value encoded in an
+-	 # empty executable.
+-	 _LT_SYS_MODULE_PATH_AIX([$1])
+-	 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+-	  # Warning - without using the other run time loading flags,
+-	  # -berok will link without error, but may produce a broken library.
+-	  _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+-	  _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+-	  if test yes = "$with_gnu_ld"; then
+-	    # We only use this code for GNU lds that support --whole-archive.
+-	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+-	  else
+-	    # Exported symbols can be pulled into shared objects from archives
+-	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+-	  fi
+-	  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+-	  # -brtl affects multiple linker settings, -berok does not and is overridden later
+-	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+-	  if test svr4 != "$with_aix_soname"; then
+-	    # This is similar to how AIX traditionally builds its shared libraries.
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+-	  fi
+-	  if test aix != "$with_aix_soname"; then
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+-	  else
+-	    # used by -dlpreopen to get the symbols
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+-	  fi
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+-	fi
+-      fi
+-      ;;
+-
+-    amigaos*)
+-      case $host_cpu in
+-      powerpc)
+-            # see comment about AmigaOS4 .so support
+-            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+-        ;;
+-      m68k)
+-            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+-            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-        ;;
+-      esac
+-      ;;
+-
+-    bsdi[[45]]*)
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+-      ;;
+-
+-    cygwin* | mingw* | pw32* | cegcc*)
+-      # When not using gcc, we currently assume that we are using
+-      # Microsoft Visual C++ or Intel C++ Compiler.
+-      # hardcode_libdir_flag_spec is actually meaningless, as there is
+-      # no search path for DLLs.
+-      case $cc_basename in
+-      cl* | icl*)
+-	# Native MSVC or ICC
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+-	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	_LT_TAGVAR(always_export_symbols, $1)=yes
+-	_LT_TAGVAR(file_list_spec, $1)='@'
+-	# Tell ltmain to make .lib files, not .a files.
+-	libext=lib
+-	# Tell ltmain to make .dll files, not .so files.
+-	shrext_cmds=.dll
+-	# FIXME: Setting linknames here is a bad hack.
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+-            cp "$export_symbols" "$output_objdir/$soname.def";
+-            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+-          else
+-            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+-          fi~
+-          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+-          linknames='
+-	# The linker will not automatically build a static lib if we build a DLL.
+-	# _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+-	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-	_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+-	_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+-	# Don't use ranlib
+-	_LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+-	_LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+-          lt_tool_outputfile="@TOOL_OUTPUT@"~
+-          case $lt_outputfile in
+-            *.exe|*.EXE) ;;
+-            *)
+-              lt_outputfile=$lt_outputfile.exe
+-              lt_tool_outputfile=$lt_tool_outputfile.exe
+-              ;;
+-          esac~
+-          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+-            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+-            $RM "$lt_outputfile.manifest";
+-          fi'
+-	;;
+-      *)
+-	# Assume MSVC and ICC wrapper
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+-	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	# Tell ltmain to make .lib files, not .a files.
+-	libext=lib
+-	# Tell ltmain to make .dll files, not .so files.
+-	shrext_cmds=.dll
+-	# FIXME: Setting linknames here is a bad hack.
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+-	# The linker will automatically build a .lib file if we build a DLL.
+-	_LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+-	# FIXME: Should let the user specify the lib program.
+-	_LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+-	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-	;;
+-      esac
+-      ;;
+-
+-    darwin* | rhapsody*)
+-      _LT_DARWIN_LINKER_FEATURES($1)
+-      ;;
+-
+-    dgux*)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+-    # support.  Future versions do this automatically, but an explicit c++rt0.o
+-    # does not break anything, and helps significantly (at the cost of a little
+-    # extra space).
+-    freebsd2.2*)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+-    freebsd2.*)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+-    freebsd* | dragonfly* | midnightbsd*)
+-      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    hpux9*)
+-      if test yes = "$GCC"; then
+-	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+-      fi
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-
+-      # hardcode_minus_L: Not really in the search PATH,
+-      # but as the default location of the library.
+-      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-      ;;
+-
+-    hpux10*)
+-      if test yes,no = "$GCC,$with_gnu_ld"; then
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+-      fi
+-      if test no = "$with_gnu_ld"; then
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+-	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-	_LT_TAGVAR(hardcode_direct, $1)=yes
+-	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-	# hardcode_minus_L: Not really in the search PATH,
+-	# but as the default location of the library.
+-	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      fi
+-      ;;
+-
+-    hpux11*)
+-      if test yes,no = "$GCC,$with_gnu_ld"; then
+-	case $host_cpu in
+-	hppa*64*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-	ia64*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-	*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-	esac
+-      else
+-	case $host_cpu in
+-	hppa*64*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-	ia64*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-	*)
+-	m4_if($1, [], [
+-	  # Older versions of the 11.00 compiler do not understand -b yet
+-	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+-	  _LT_LINKER_OPTION([if $CC understands -b],
+-	    _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+-	    [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+-	    [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+-	  [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+-	  ;;
+-	esac
+-      fi
+-      if test no = "$with_gnu_ld"; then
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+-	_LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-
+-	case $host_cpu in
+-	hppa*64*|ia64*)
+-	  _LT_TAGVAR(hardcode_direct, $1)=no
+-	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	  ;;
+-	*)
+-	  _LT_TAGVAR(hardcode_direct, $1)=yes
+-	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-
+-	  # hardcode_minus_L: Not really in the search PATH,
+-	  # but as the default location of the library.
+-	  _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-	  ;;
+-	esac
+-      fi
+-      ;;
+-
+-    irix5* | irix6* | nonstopux*)
+-      if test yes = "$GCC"; then
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-	# Try to use the -exported_symbol ld option, if it does not
+-	# work, assume that -exports_file does not work either and
+-	# implicitly export all symbols.
+-	# This should be the same for all languages, so no per-tag cache variable.
+-	AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+-	  [lt_cv_irix_exported_symbol],
+-	  [save_LDFLAGS=$LDFLAGS
+-	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+-	   AC_LINK_IFELSE(
+-	     [AC_LANG_SOURCE(
+-	        [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+-			      [C++], [[int foo (void) { return 0; }]],
+-			      [Fortran 77], [[
+-      subroutine foo
+-      end]],
+-			      [Fortran], [[
+-      subroutine foo
+-      end]])])],
+-	      [lt_cv_irix_exported_symbol=yes],
+-	      [lt_cv_irix_exported_symbol=no])
+-           LDFLAGS=$save_LDFLAGS])
+-	if test yes = "$lt_cv_irix_exported_symbol"; then
+-          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+-	fi
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+-      fi
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-      _LT_TAGVAR(inherit_rpath, $1)=yes
+-      _LT_TAGVAR(link_all_deplibs, $1)=yes
+-      ;;
+-
+-    linux*)
+-      case $cc_basename in
+-      tcc*)
+-	# Fabrice Bellard et al's Tiny C Compiler
+-	_LT_TAGVAR(ld_shlibs, $1)=yes
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-	;;
+-      esac
+-      ;;
+-
+-    netbsd*)
+-      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+-	_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+-      fi
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    newsos6)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    *nto* | *qnx*)
+-      ;;
+-
+-    openbsd* | bitrig*)
+-      if test -f /usr/libexec/ld.so; then
+-	_LT_TAGVAR(hardcode_direct, $1)=yes
+-	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	_LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-	else
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	fi
+-      else
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-      fi
+-      ;;
+-
+-    os2*)
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-      shrext_cmds=.dll
+-      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	prefix_cmds="$SED"~
+-	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+-	  prefix_cmds="$prefix_cmds -e 1d";
+-	fi~
+-	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+-	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+-      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-      _LT_TAGVAR(file_list_spec, $1)='@'
+-      ;;
+-
+-    osf3*)
+-      if test yes = "$GCC"; then
+-	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-      else
+-	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-      fi
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-      ;;
+-
+-    osf4* | osf5*)	# as osf3* with the addition of -msym flag
+-      if test yes = "$GCC"; then
+-	_LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-      else
+-	_LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+-          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+-
+-	# Both c and cxx compiler support -rpath directly
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+-      fi
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-      ;;
+-
+-    solaris*)
+-      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+-      if test yes = "$GCC"; then
+-	wlarc='$wl'
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+-      else
+-	case `$CC -V 2>&1` in
+-	*"Compilers 5.0"*)
+-	  wlarc=''
+-	  _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+-	  ;;
+-	*)
+-	  wlarc='$wl'
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+-	  ;;
+-	esac
+-      fi
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      case $host_os in
+-      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+-      *)
+-	# The compiler driver will combine and reorder linker options,
+-	# but understands '-z linker_flag'.  GCC discards it without '$wl',
+-	# but is careful enough not to reorder.
+-	# Supported since Solaris 2.6 (maybe 2.5.1?)
+-	if test yes = "$GCC"; then
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+-	else
+-	  _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+-	fi
+-	;;
+-      esac
+-      _LT_TAGVAR(link_all_deplibs, $1)=yes
+-      ;;
+-
+-    sunos4*)
+-      if test sequent = "$host_vendor"; then
+-	# Use $CC to link under sequent, because it throws in some extra .o
+-	# files that make .init and .fini sections work.
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+-      fi
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-      _LT_TAGVAR(hardcode_direct, $1)=yes
+-      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    sysv4)
+-      case $host_vendor in
+-	sni)
+-	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-	  _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+-	;;
+-	siemens)
+-	  ## LD is ld it makes a PLAMLIB
+-	  ## CC just makes a GrossModule.
+-	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+-	  _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+-	  _LT_TAGVAR(hardcode_direct, $1)=no
+-        ;;
+-	motorola)
+-	  _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-	  _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+-	;;
+-      esac
+-      runpath_var='LD_RUN_PATH'
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    sysv4.3*)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+-      ;;
+-
+-    sysv4*MP*)
+-      if test -d /usr/nec; then
+-	_LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	runpath_var=LD_RUN_PATH
+-	hardcode_runpath_var=yes
+-	_LT_TAGVAR(ld_shlibs, $1)=yes
+-      fi
+-      ;;
+-
+-    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+-      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      runpath_var='LD_RUN_PATH'
+-
+-      if test yes = "$GCC"; then
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-      fi
+-      ;;
+-
+-    sysv5* | sco3.2v5* | sco5v6*)
+-      # Note: We CANNOT use -z defs as we might desire, because we do not
+-      # link with -lc, and that would cause any symbols used from libc to
+-      # always be unresolved, which means just about no library would
+-      # ever link correctly.  If we're not using GNU ld we use -z text
+-      # though, which does catch some bad symbols but isn't as heavy-handed
+-      # as -z defs.
+-      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+-      _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+-      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+-      _LT_TAGVAR(link_all_deplibs, $1)=yes
+-      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+-      runpath_var='LD_RUN_PATH'
+-
+-      if test yes = "$GCC"; then
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-      else
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-      fi
+-      ;;
+-
+-    uts4*)
+-      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+-      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      ;;
+-
+-    *)
+-      _LT_TAGVAR(ld_shlibs, $1)=no
+-      ;;
+-    esac
+-
+-    if test sni = "$host_vendor"; then
+-      case $host in
+-      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+-	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
+-	;;
+-      esac
+-    fi
+-  fi
+-])
+-AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+-test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+-
+-_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+-
+-_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+-_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+-_LT_DECL([], [extract_expsyms_cmds], [2],
+-    [The commands to extract the exported symbol list from a shared archive])
+-
+-#
+-# Do we need to explicitly link libc?
+-#
+-case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+-x|xyes)
+-  # Assume -lc should be added
+-  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+-
+-  if test yes,yes = "$GCC,$enable_shared"; then
+-    case $_LT_TAGVAR(archive_cmds, $1) in
+-    *'~'*)
+-      # FIXME: we may have to deal with multi-command sequences.
+-      ;;
+-    '$CC '*)
+-      # Test whether the compiler implicitly links with -lc since on some
+-      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+-      # to ld, don't add -lc before -lgcc.
+-      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+-	[lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+-	[$RM conftest*
+-	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+-
+-	if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+-	  soname=conftest
+-	  lib=conftest
+-	  libobjs=conftest.$ac_objext
+-	  deplibs=
+-	  wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+-	  pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+-	  compiler_flags=-v
+-	  linker_flags=-v
+-	  verstring=
+-	  output_objdir=.
+-	  libname=conftest
+-	  lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+-	  _LT_TAGVAR(allow_undefined_flag, $1)=
+-	  if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+-	  then
+-	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-	  else
+-	    lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+-	  fi
+-	  _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+-	else
+-	  cat conftest.err 1>&5
+-	fi
+-	$RM conftest*
+-	])
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+-      ;;
+-    esac
+-  fi
+-  ;;
+-esac
+-
+-_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+-    [Whether or not to add -lc for building shared libraries])
+-_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+-    [enable_shared_with_static_runtimes], [0],
+-    [Whether or not to disallow shared libs when runtime libs are static])
+-_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+-    [Compiler flag to allow reflexive dlopens])
+-_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+-    [Compiler flag to generate shared objects directly from archives])
+-_LT_TAGDECL([], [compiler_needs_object], [1],
+-    [Whether the compiler copes with passing no objects directly])
+-_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+-    [Create an old-style archive from a shared archive])
+-_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+-    [Create a temporary old-style archive to link instead of a shared archive])
+-_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+-_LT_TAGDECL([], [archive_expsym_cmds], [2])
+-_LT_TAGDECL([], [module_cmds], [2],
+-    [Commands used to build a loadable module if different from building
+-    a shared archive.])
+-_LT_TAGDECL([], [module_expsym_cmds], [2])
+-_LT_TAGDECL([], [with_gnu_ld], [1],
+-    [Whether we are building with GNU ld or not])
+-_LT_TAGDECL([], [allow_undefined_flag], [1],
+-    [Flag that allows shared libraries with undefined symbols to be built])
+-_LT_TAGDECL([], [no_undefined_flag], [1],
+-    [Flag that enforces no undefined symbols])
+-_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+-    [Flag to hardcode $libdir into a binary during linking.
+-    This must work even if $libdir does not exist])
+-_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+-    [Whether we need a single "-rpath" flag with a separated argument])
+-_LT_TAGDECL([], [hardcode_direct], [0],
+-    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+-    DIR into the resulting binary])
+-_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+-    [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+-    DIR into the resulting binary and the resulting library dependency is
+-    "absolute", i.e impossible to change by setting $shlibpath_var if the
+-    library is relocated])
+-_LT_TAGDECL([], [hardcode_minus_L], [0],
+-    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+-    into the resulting binary])
+-_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+-    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+-    into the resulting binary])
+-_LT_TAGDECL([], [hardcode_automatic], [0],
+-    [Set to "yes" if building a shared library automatically hardcodes DIR
+-    into the library and all subsequent libraries and executables linked
+-    against it])
+-_LT_TAGDECL([], [inherit_rpath], [0],
+-    [Set to yes if linker adds runtime paths of dependent libraries
+-    to runtime path list])
+-_LT_TAGDECL([], [link_all_deplibs], [0],
+-    [Whether libtool must link a program against all its dependency libraries])
+-_LT_TAGDECL([], [always_export_symbols], [0],
+-    [Set to "yes" if exported symbols are required])
+-_LT_TAGDECL([], [export_symbols_cmds], [2],
+-    [The commands to list exported symbols])
+-_LT_TAGDECL([], [exclude_expsyms], [1],
+-    [Symbols that should not be listed in the preloaded symbols])
+-_LT_TAGDECL([], [include_expsyms], [1],
+-    [Symbols that must always be exported])
+-_LT_TAGDECL([], [prelink_cmds], [2],
+-    [Commands necessary for linking programs (against libraries) with templates])
+-_LT_TAGDECL([], [postlink_cmds], [2],
+-    [Commands necessary for finishing linking programs])
+-_LT_TAGDECL([], [file_list_spec], [1],
+-    [Specify filename containing input files])
+-dnl FIXME: Not yet implemented
+-dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+-dnl    [Compiler flag to generate thread safe objects])
+-])# _LT_LINKER_SHLIBS
+-
+-
+-# _LT_LANG_C_CONFIG([TAG])
+-# ------------------------
+-# Ensure that the configuration variables for a C compiler are suitably
+-# defined.  These variables are subsequently used by _LT_CONFIG to write
+-# the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_C_CONFIG],
+-[m4_require([_LT_DECL_EGREP])dnl
+-lt_save_CC=$CC
+-AC_LANG_PUSH(C)
+-
+-# Source file extension for C test sources.
+-ac_ext=c
+-
+-# Object file extension for compiled C test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# Code to be used in simple compile tests
+-lt_simple_compile_test_code="int some_variable = 0;"
+-
+-# Code to be used in simple link tests
+-lt_simple_link_test_code='int main(){return(0);}'
+-
+-_LT_TAG_COMPILER
+-# Save the default compiler, since it gets overwritten when the other
+-# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+-compiler_DEFAULT=$CC
+-
+-# save warnings/boilerplate of simple test code
+-_LT_COMPILER_BOILERPLATE
+-_LT_LINKER_BOILERPLATE
+-
+-if test -n "$compiler"; then
+-  _LT_COMPILER_NO_RTTI($1)
+-  _LT_COMPILER_PIC($1)
+-  _LT_COMPILER_C_O($1)
+-  _LT_COMPILER_FILE_LOCKS($1)
+-  _LT_LINKER_SHLIBS($1)
+-  _LT_SYS_DYNAMIC_LINKER($1)
+-  _LT_LINKER_HARDCODE_LIBPATH($1)
+-  LT_SYS_DLOPEN_SELF
+-  _LT_CMD_STRIPLIB
+-
+-  # Report what library types will actually be built
+-  AC_MSG_CHECKING([if libtool supports shared libraries])
+-  AC_MSG_RESULT([$can_build_shared])
+-
+-  AC_MSG_CHECKING([whether to build shared libraries])
+-  test no = "$can_build_shared" && enable_shared=no
+-
+-  # On AIX, shared libraries and static libraries use the same namespace, and
+-  # are all built from PIC.
+-  case $host_os in
+-  aix3*)
+-    test yes = "$enable_shared" && enable_static=no
+-    if test -n "$RANLIB"; then
+-      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+-      postinstall_cmds='$RANLIB $lib'
+-    fi
+-    ;;
+-
+-  aix[[4-9]]*)
+-    if test ia64 != "$host_cpu"; then
+-      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+-      yes,aix,yes) ;;			# shared object as lib.so file only
+-      yes,svr4,*) ;;			# shared object as lib.so archive member only
+-      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+-      esac
+-    fi
+-    ;;
+-  esac
+-  AC_MSG_RESULT([$enable_shared])
+-
+-  AC_MSG_CHECKING([whether to build static libraries])
+-  # Make sure either enable_shared or enable_static is yes.
+-  test yes = "$enable_shared" || enable_static=yes
+-  AC_MSG_RESULT([$enable_static])
+-
+-  _LT_CONFIG($1)
+-fi
+-AC_LANG_POP
+-CC=$lt_save_CC
+-])# _LT_LANG_C_CONFIG
+-
+-
+-# _LT_LANG_CXX_CONFIG([TAG])
+-# --------------------------
+-# Ensure that the configuration variables for a C++ compiler are suitably
+-# defined.  These variables are subsequently used by _LT_CONFIG to write
+-# the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_CXX_CONFIG],
+-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-m4_require([_LT_DECL_EGREP])dnl
+-m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+-if test -n "$CXX" && ( test no != "$CXX" &&
+-    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+-    (test g++ != "$CXX"))); then
+-  AC_PROG_CXXCPP
+-else
+-  _lt_caught_CXX_error=yes
+-fi
+-
+-AC_LANG_PUSH(C++)
+-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-_LT_TAGVAR(allow_undefined_flag, $1)=
+-_LT_TAGVAR(always_export_symbols, $1)=no
+-_LT_TAGVAR(archive_expsym_cmds, $1)=
+-_LT_TAGVAR(compiler_needs_object, $1)=no
+-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+-_LT_TAGVAR(hardcode_direct, $1)=no
+-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+-_LT_TAGVAR(hardcode_libdir_separator, $1)=
+-_LT_TAGVAR(hardcode_minus_L, $1)=no
+-_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+-_LT_TAGVAR(hardcode_automatic, $1)=no
+-_LT_TAGVAR(inherit_rpath, $1)=no
+-_LT_TAGVAR(module_cmds, $1)=
+-_LT_TAGVAR(module_expsym_cmds, $1)=
+-_LT_TAGVAR(link_all_deplibs, $1)=unknown
+-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+-_LT_TAGVAR(reload_flag, $1)=$reload_flag
+-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+-_LT_TAGVAR(no_undefined_flag, $1)=
+-_LT_TAGVAR(whole_archive_flag_spec, $1)=
+-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+-
+-# Source file extension for C++ test sources.
+-ac_ext=cpp
+-
+-# Object file extension for compiled C++ test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# No sense in running all these tests if we already determined that
+-# the CXX compiler isn't working.  Some variables (like enable_shared)
+-# are currently assumed to apply to all compilers on this platform,
+-# and will be corrupted by setting them based on a non-working compiler.
+-if test yes != "$_lt_caught_CXX_error"; then
+-  # Code to be used in simple compile tests
+-  lt_simple_compile_test_code="int some_variable = 0;"
+-
+-  # Code to be used in simple link tests
+-  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+-
+-  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+-  _LT_TAG_COMPILER
+-
+-  # save warnings/boilerplate of simple test code
+-  _LT_COMPILER_BOILERPLATE
+-  _LT_LINKER_BOILERPLATE
+-
+-  # Allow CC to be a program name with arguments.
+-  lt_save_CC=$CC
+-  lt_save_CFLAGS=$CFLAGS
+-  lt_save_LD=$LD
+-  lt_save_GCC=$GCC
+-  GCC=$GXX
+-  lt_save_with_gnu_ld=$with_gnu_ld
+-  lt_save_path_LD=$lt_cv_path_LD
+-  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+-    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+-  else
+-    $as_unset lt_cv_prog_gnu_ld
+-  fi
+-  if test -n "${lt_cv_path_LDCXX+set}"; then
+-    lt_cv_path_LD=$lt_cv_path_LDCXX
+-  else
+-    $as_unset lt_cv_path_LD
+-  fi
+-  test -z "${LDCXX+set}" || LD=$LDCXX
+-  CC=${CXX-"c++"}
+-  CFLAGS=$CXXFLAGS
+-  compiler=$CC
+-  _LT_TAGVAR(compiler, $1)=$CC
+-  _LT_CC_BASENAME([$compiler])
+-
+-  if test -n "$compiler"; then
+-    # We don't want -fno-exception when compiling C++ code, so set the
+-    # no_builtin_flag separately
+-    if test yes = "$GXX"; then
+-      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+-    else
+-      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+-    fi
+-
+-    if test yes = "$GXX"; then
+-      # Set up default GNU C++ configuration
+-
+-      LT_PATH_LD
+-
+-      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+-      # archiving commands below assume that GNU ld is being used.
+-      if test yes = "$with_gnu_ld"; then
+-        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-
+-        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+-
+-        # If archive_cmds runs LD, not CC, wlarc should be empty
+-        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+-        #     investigate it a little bit more. (MM)
+-        wlarc='$wl'
+-
+-        # ancient GNU ld didn't support --whole-archive et. al.
+-        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+-	  $GREP 'no-whole-archive' > /dev/null; then
+-          _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+-        else
+-          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+-        fi
+-      else
+-        with_gnu_ld=no
+-        wlarc=
+-
+-        # A generic and very simple default shared library creation
+-        # command for GNU C++ for the case where it uses the native
+-        # linker, instead of GNU ld.  If possible, this setting should
+-        # overridden to take advantage of the native linker features on
+-        # the platform it is being used on.
+-        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+-      fi
+-
+-      # Commands to make compiler produce verbose output that lists
+-      # what "hidden" libraries, object files and flags are used when
+-      # linking a shared library.
+-      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+-
+-    else
+-      GXX=no
+-      with_gnu_ld=no
+-      wlarc=
+-    fi
+-
+-    # PORTME: fill in a description of your system's C++ link characteristics
+-    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+-    _LT_TAGVAR(ld_shlibs, $1)=yes
+-    case $host_os in
+-      aix3*)
+-        # FIXME: insert proper C++ library support
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-        ;;
+-      aix[[4-9]]*)
+-        if test ia64 = "$host_cpu"; then
+-          # On IA64, the linker does run time linking by default, so we don't
+-          # have to do anything special.
+-          aix_use_runtimelinking=no
+-          exp_sym_flag='-Bexport'
+-          no_entry_flag=
+-        else
+-          aix_use_runtimelinking=no
+-
+-          # Test if we are trying to use run time linking or normal
+-          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+-          # have runtime linking enabled, and use it for executables.
+-          # For shared libraries, we enable/disable runtime linking
+-          # depending on the kind of the shared library created -
+-          # when "with_aix_soname,aix_use_runtimelinking" is:
+-          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+-          # "aix,yes"  lib.so          shared, rtl:yes, for executables
+-          #            lib.a           static archive
+-          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
+-          #            lib.a(lib.so.V) shared, rtl:no,  for executables
+-          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+-          #            lib.a(lib.so.V) shared, rtl:no
+-          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+-          #            lib.a           static archive
+-          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+-	    for ld_flag in $LDFLAGS; do
+-	      case $ld_flag in
+-	      *-brtl*)
+-	        aix_use_runtimelinking=yes
+-	        break
+-	        ;;
+-	      esac
+-	    done
+-	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+-	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
+-	      # so we don't have lib.a shared libs to link our executables.
+-	      # We have to force runtime linking in this case.
+-	      aix_use_runtimelinking=yes
+-	      LDFLAGS="$LDFLAGS -Wl,-brtl"
+-	    fi
+-	    ;;
+-          esac
+-
+-          exp_sym_flag='-bexport'
+-          no_entry_flag='-bnoentry'
+-        fi
+-
+-        # When large executables or shared objects are built, AIX ld can
+-        # have problems creating the table of contents.  If linking a library
+-        # or program results in "error TOC overflow" add -mminimal-toc to
+-        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+-        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+-
+-        _LT_TAGVAR(archive_cmds, $1)=''
+-        _LT_TAGVAR(hardcode_direct, $1)=yes
+-        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+-        _LT_TAGVAR(link_all_deplibs, $1)=yes
+-        _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+-        case $with_aix_soname,$aix_use_runtimelinking in
+-        aix,*) ;;	# no import file
+-        svr4,* | *,yes) # use import file
+-          # The Import File defines what to hardcode.
+-          _LT_TAGVAR(hardcode_direct, $1)=no
+-          _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+-          ;;
+-        esac
+-
+-        if test yes = "$GXX"; then
+-          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+-          # We only want to do this on AIX 4.2 and lower, the check
+-          # below for broken collect2 doesn't work under 4.3+
+-	  collect2name=`$CC -print-prog-name=collect2`
+-	  if test -f "$collect2name" &&
+-	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+-	  then
+-	    # We have reworked collect2
+-	    :
+-	  else
+-	    # We have old collect2
+-	    _LT_TAGVAR(hardcode_direct, $1)=unsupported
+-	    # It fails to find uninstalled libraries when the uninstalled
+-	    # path is not listed in the libpath.  Setting hardcode_minus_L
+-	    # to unsupported forces relinking
+-	    _LT_TAGVAR(hardcode_minus_L, $1)=yes
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-	    _LT_TAGVAR(hardcode_libdir_separator, $1)=
+-	  fi
+-          esac
+-          shared_flag='-shared'
+-	  if test yes = "$aix_use_runtimelinking"; then
+-	    shared_flag=$shared_flag' $wl-G'
+-	  fi
+-	  # Need to ensure runtime linking is disabled for the traditional
+-	  # shared library, or the linker may eventually find shared libraries
+-	  # /with/ Import File - we do not want to mix them.
+-	  shared_flag_aix='-shared'
+-	  shared_flag_svr4='-shared $wl-G'
+-        else
+-          # not using gcc
+-          if test ia64 = "$host_cpu"; then
+-	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+-	  # chokes on -Wl,-G. The following line is correct:
+-	  shared_flag='-G'
+-          else
+-	    if test yes = "$aix_use_runtimelinking"; then
+-	      shared_flag='$wl-G'
+-	    else
+-	      shared_flag='$wl-bM:SRE'
+-	    fi
+-	    shared_flag_aix='$wl-bM:SRE'
+-	    shared_flag_svr4='$wl-G'
+-          fi
+-        fi
+-
+-        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+-        # It seems that -bexpall does not export symbols beginning with
+-        # underscore (_), so it is better to generate a list of symbols to
+-	# export.
+-        _LT_TAGVAR(always_export_symbols, $1)=yes
+-	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+-          # Warning - without using the other runtime loading flags (-brtl),
+-          # -berok will link without error, but may produce a broken library.
+-          # The "-G" linker flag allows undefined symbols.
+-          _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+-          # Determine the default libpath from the value encoded in an empty
+-          # executable.
+-          _LT_SYS_MODULE_PATH_AIX([$1])
+-          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+-
+-          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+-        else
+-          if test ia64 = "$host_cpu"; then
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+-	    _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+-          else
+-	    # Determine the default libpath from the value encoded in an
+-	    # empty executable.
+-	    _LT_SYS_MODULE_PATH_AIX([$1])
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+-	    # Warning - without using the other run time loading flags,
+-	    # -berok will link without error, but may produce a broken library.
+-	    _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+-	    _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+-	    if test yes = "$with_gnu_ld"; then
+-	      # We only use this code for GNU lds that support --whole-archive.
+-	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+-	    else
+-	      # Exported symbols can be pulled into shared objects from archives
+-	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+-	    fi
+-	    _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+-	    # -brtl affects multiple linker settings, -berok does not and is overridden later
+-	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+-	    if test svr4 != "$with_aix_soname"; then
+-	      # This is similar to how AIX traditionally builds its shared
+-	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+-	    fi
+-	    if test aix != "$with_aix_soname"; then
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+-	    else
+-	      # used by -dlpreopen to get the symbols
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+-	    fi
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+-          fi
+-        fi
+-        ;;
+-
+-      beos*)
+-	if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	  # Joseph Beckenbach  says some releases of gcc
+-	  # support --undefined.  This deserves some investigation.  FIXME
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	else
+-	  _LT_TAGVAR(ld_shlibs, $1)=no
+-	fi
+-	;;
+-
+-      chorus*)
+-        case $cc_basename in
+-          *)
+-	  # FIXME: insert proper C++ library support
+-	  _LT_TAGVAR(ld_shlibs, $1)=no
+-	  ;;
+-        esac
+-        ;;
+-
+-      cygwin* | mingw* | pw32* | cegcc*)
+-	case $GXX,$cc_basename in
+-	,cl* | no,cl* | ,icl* | no,icl*)
+-	  # Native MSVC or ICC
+-	  # hardcode_libdir_flag_spec is actually meaningless, as there is
+-	  # no search path for DLLs.
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+-	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	  _LT_TAGVAR(always_export_symbols, $1)=yes
+-	  _LT_TAGVAR(file_list_spec, $1)='@'
+-	  # Tell ltmain to make .lib files, not .a files.
+-	  libext=lib
+-	  # Tell ltmain to make .dll files, not .so files.
+-	  shrext_cmds=.dll
+-	  # FIXME: Setting linknames here is a bad hack.
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+-              cp "$export_symbols" "$output_objdir/$soname.def";
+-              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+-            else
+-              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+-            fi~
+-            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+-            linknames='
+-	  # The linker will not automatically build a static lib if we build a DLL.
+-	  # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+-	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-	  # Don't use ranlib
+-	  _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+-	  _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+-            lt_tool_outputfile="@TOOL_OUTPUT@"~
+-            case $lt_outputfile in
+-              *.exe|*.EXE) ;;
+-              *)
+-                lt_outputfile=$lt_outputfile.exe
+-                lt_tool_outputfile=$lt_tool_outputfile.exe
+-                ;;
+-            esac~
+-            func_to_tool_file "$lt_outputfile"~
+-            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+-              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+-              $RM "$lt_outputfile.manifest";
+-            fi'
+-	  ;;
+-	*)
+-	  # g++
+-	  # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+-	  # as there is no search path for DLLs.
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-	  _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+-	  _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	  _LT_TAGVAR(always_export_symbols, $1)=no
+-	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-
+-	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-	    # If the export-symbols file already is a .def file, use it as
+-	    # is; otherwise, prepend EXPORTS...
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+-              cp $export_symbols $output_objdir/$soname.def;
+-            else
+-              echo EXPORTS > $output_objdir/$soname.def;
+-              cat $export_symbols >> $output_objdir/$soname.def;
+-            fi~
+-            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-	  else
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	  fi
+-	  ;;
+-	esac
+-	;;
+-      darwin* | rhapsody*)
+-        _LT_DARWIN_LINKER_FEATURES($1)
+-	;;
+-
+-      os2*)
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+-	_LT_TAGVAR(hardcode_minus_L, $1)=yes
+-	_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+-	shrext_cmds=.dll
+-	_LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+-	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+-	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	  emximp -o $lib $output_objdir/$libname.def'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+-	  prefix_cmds="$SED"~
+-	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
+-	    prefix_cmds="$prefix_cmds -e 1d";
+-	  fi~
+-	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+-	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+-	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	  emximp -o $lib $output_objdir/$libname.def'
+-	_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+-	_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+-	_LT_TAGVAR(file_list_spec, $1)='@'
+-	;;
+-
+-      dgux*)
+-        case $cc_basename in
+-          ec++*)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          ghcx*)
+-	    # Green Hills C++ Compiler
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          *)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-        esac
+-        ;;
+-
+-      freebsd2.*)
+-        # C++ shared libraries reported to be fairly broken before
+-	# switch to ELF
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-        ;;
+-
+-      freebsd-elf*)
+-        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-        ;;
+-
+-      freebsd* | dragonfly* | midnightbsd*)
+-        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+-        # conventions
+-        _LT_TAGVAR(ld_shlibs, $1)=yes
+-        ;;
+-
+-      haiku*)
+-        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-        _LT_TAGVAR(link_all_deplibs, $1)=yes
+-        ;;
+-
+-      hpux9*)
+-        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+-        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-        _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-        _LT_TAGVAR(hardcode_direct, $1)=yes
+-        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+-				             # but as the default
+-				             # location of the library.
+-
+-        case $cc_basename in
+-          CC*)
+-            # FIXME: insert proper C++ library support
+-            _LT_TAGVAR(ld_shlibs, $1)=no
+-            ;;
+-          aCC*)
+-            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+-            # Commands to make compiler produce verbose output that lists
+-            # what "hidden" libraries, object files and flags are used when
+-            # linking a shared library.
+-            #
+-            # There doesn't appear to be a way to prevent this compiler from
+-            # explicitly linking system object files so we need to strip them
+-            # from the output so that they don't get included in the library
+-            # dependencies.
+-            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+-            ;;
+-          *)
+-            if test yes = "$GXX"; then
+-              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+-            else
+-              # FIXME: insert proper C++ library support
+-              _LT_TAGVAR(ld_shlibs, $1)=no
+-            fi
+-            ;;
+-        esac
+-        ;;
+-
+-      hpux10*|hpux11*)
+-        if test no = "$with_gnu_ld"; then
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+-	  _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-
+-          case $host_cpu in
+-            hppa*64*|ia64*)
+-              ;;
+-            *)
+-	      _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-              ;;
+-          esac
+-        fi
+-        case $host_cpu in
+-          hppa*64*|ia64*)
+-            _LT_TAGVAR(hardcode_direct, $1)=no
+-            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-            ;;
+-          *)
+-            _LT_TAGVAR(hardcode_direct, $1)=yes
+-            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+-					         # but as the default
+-					         # location of the library.
+-            ;;
+-        esac
+-
+-        case $cc_basename in
+-          CC*)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          aCC*)
+-	    case $host_cpu in
+-	      hppa*64*)
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	        ;;
+-	      ia64*)
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	        ;;
+-	      *)
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	        ;;
+-	    esac
+-	    # Commands to make compiler produce verbose output that lists
+-	    # what "hidden" libraries, object files and flags are used when
+-	    # linking a shared library.
+-	    #
+-	    # There doesn't appear to be a way to prevent this compiler from
+-	    # explicitly linking system object files so we need to strip them
+-	    # from the output so that they don't get included in the library
+-	    # dependencies.
+-	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+-	    ;;
+-          *)
+-	    if test yes = "$GXX"; then
+-	      if test no = "$with_gnu_ld"; then
+-	        case $host_cpu in
+-	          hppa*64*)
+-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	            ;;
+-	          ia64*)
+-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	            ;;
+-	          *)
+-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	            ;;
+-	        esac
+-	      fi
+-	    else
+-	      # FIXME: insert proper C++ library support
+-	      _LT_TAGVAR(ld_shlibs, $1)=no
+-	    fi
+-	    ;;
+-        esac
+-        ;;
+-
+-      interix[[3-9]]*)
+-	_LT_TAGVAR(hardcode_direct, $1)=no
+-	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+-	# Instead, shared libraries are loaded at an image base (0x10000000 by
+-	# default) and relocated if they conflict, which is a slow very memory
+-	# consuming and fragmenting process.  To avoid this, we pick a random,
+-	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+-	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+-	_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+-	_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+-	;;
+-      irix5* | irix6*)
+-        case $cc_basename in
+-          CC*)
+-	    # SGI C++
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-
+-	    # Archives containing C++ object files must be created using
+-	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+-	    # necessary to make sure instantiated templates are included
+-	    # in the archive.
+-	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+-	    ;;
+-          *)
+-	    if test yes = "$GXX"; then
+-	      if test no = "$with_gnu_ld"; then
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-	      else
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+-	      fi
+-	    fi
+-	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+-	    ;;
+-        esac
+-        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-        _LT_TAGVAR(inherit_rpath, $1)=yes
+-        ;;
+-
+-      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-        case $cc_basename in
+-          KCC*)
+-	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+-
+-	    # KCC will only create a shared library if the output file
+-	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+-	    # to its proper name (with version) after linking.
+-	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+-	    # Commands to make compiler produce verbose output that lists
+-	    # what "hidden" libraries, object files and flags are used when
+-	    # linking a shared library.
+-	    #
+-	    # There doesn't appear to be a way to prevent this compiler from
+-	    # explicitly linking system object files so we need to strip them
+-	    # from the output so that they don't get included in the library
+-	    # dependencies.
+-	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+-
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+-
+-	    # Archives containing C++ object files must be created using
+-	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+-	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+-	    ;;
+-	  icpc* | ecpc* )
+-	    # Intel C++
+-	    with_gnu_ld=yes
+-	    # version 8.0 and above of icpc choke on multiply defined symbols
+-	    # if we add $predep_objects and $postdep_objects, however 7.1 and
+-	    # earlier do not add the objects themselves.
+-	    case `$CC -V 2>&1` in
+-	      *"Version 7."*)
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-		;;
+-	      *)  # Version 8.0 or newer
+-	        tmp_idyn=
+-	        case $host_cpu in
+-		  ia64*) tmp_idyn=' -i_dynamic';;
+-		esac
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-		_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-		;;
+-	    esac
+-	    _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+-	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+-	    ;;
+-          pgCC* | pgcpp*)
+-            # Portland Group C++ compiler
+-	    case `$CC -V` in
+-	    *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+-	      _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+-               rm -rf $tpldir~
+-               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+-               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+-	      _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+-                rm -rf $tpldir~
+-                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+-                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+-                $RANLIB $oldlib'
+-	      _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+-                rm -rf $tpldir~
+-                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+-                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+-                rm -rf $tpldir~
+-                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+-                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-	      ;;
+-	    *) # Version 6 and above use weak symbols
+-	      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+-	      ;;
+-	    esac
+-
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
+-	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+-	    _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+-            ;;
+-	  cxx*)
+-	    # Compaq C++
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
+-
+-	    runpath_var=LD_RUN_PATH
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+-	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-
+-	    # Commands to make compiler produce verbose output that lists
+-	    # what "hidden" libraries, object files and flags are used when
+-	    # linking a shared library.
+-	    #
+-	    # There doesn't appear to be a way to prevent this compiler from
+-	    # explicitly linking system object files so we need to strip them
+-	    # from the output so that they don't get included in the library
+-	    # dependencies.
+-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+-	    ;;
+-	  xl* | mpixl* | bgxl*)
+-	    # IBM XL 8.0 on PPC, with GNU ld
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	    if test yes = "$supports_anon_versioning"; then
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+-                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+-                echo "local: *; };" >> $output_objdir/$libname.ver~
+-                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+-	    fi
+-	    ;;
+-	  *)
+-	    case `$CC -V 2>&1 | $SED 5q` in
+-	    *Sun\ C*)
+-	      # Sun C++ 5.9
+-	      _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+-	      _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	      _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+-	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-	      _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+-	      _LT_TAGVAR(compiler_needs_object, $1)=yes
+-
+-	      # Not sure whether something based on
+-	      # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+-	      # would be better.
+-	      output_verbose_link_cmd='func_echo_all'
+-
+-	      # Archives containing C++ object files must be created using
+-	      # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+-	      # necessary to make sure instantiated templates are included
+-	      # in the archive.
+-	      _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+-	      ;;
+-	    esac
+-	    ;;
+-	esac
+-	;;
+-
+-      lynxos*)
+-        # FIXME: insert proper C++ library support
+-	_LT_TAGVAR(ld_shlibs, $1)=no
+-	;;
+-
+-      m88k*)
+-        # FIXME: insert proper C++ library support
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-	;;
+-
+-      mvs*)
+-        case $cc_basename in
+-          cxx*)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-	  *)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-	esac
+-	;;
+-
+-      netbsd*)
+-        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+-	  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+-	  wlarc=
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-	  _LT_TAGVAR(hardcode_direct, $1)=yes
+-	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	fi
+-	# Workaround some broken pre-1.5 toolchains
+-	output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+-	;;
+-
+-      *nto* | *qnx*)
+-        _LT_TAGVAR(ld_shlibs, $1)=yes
+-	;;
+-
+-      openbsd* | bitrig*)
+-	if test -f /usr/libexec/ld.so; then
+-	  _LT_TAGVAR(hardcode_direct, $1)=yes
+-	  _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	  _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+-	  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+-	    _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+-	    _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+-	  fi
+-	  output_verbose_link_cmd=func_echo_all
+-	else
+-	  _LT_TAGVAR(ld_shlibs, $1)=no
+-	fi
+-	;;
+-
+-      osf3* | osf4* | osf5*)
+-        case $cc_basename in
+-          KCC*)
+-	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+-
+-	    # KCC will only create a shared library if the output file
+-	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+-	    # to its proper name (with version) after linking.
+-	    _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+-
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+-	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-
+-	    # Archives containing C++ object files must be created using
+-	    # the KAI C++ compiler.
+-	    case $host in
+-	      osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+-	      *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+-	    esac
+-	    ;;
+-          RCC*)
+-	    # Rational C++ 2.4.1
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          cxx*)
+-	    case $host in
+-	      osf3*)
+-	        _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-		;;
+-	      *)
+-	        _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-	        _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+-                  echo "-hidden">> $lib.exp~
+-                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+-                  $RM $lib.exp'
+-	        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+-		;;
+-	    esac
+-
+-	    _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-
+-	    # Commands to make compiler produce verbose output that lists
+-	    # what "hidden" libraries, object files and flags are used when
+-	    # linking a shared library.
+-	    #
+-	    # There doesn't appear to be a way to prevent this compiler from
+-	    # explicitly linking system object files so we need to strip them
+-	    # from the output so that they don't get included in the library
+-	    # dependencies.
+-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+-	    ;;
+-	  *)
+-	    if test yes,no = "$GXX,$with_gnu_ld"; then
+-	      _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+-	      case $host in
+-	        osf3*)
+-	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-		  ;;
+-	        *)
+-	          _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-		  ;;
+-	      esac
+-
+-	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+-	      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+-
+-	      # Commands to make compiler produce verbose output that lists
+-	      # what "hidden" libraries, object files and flags are used when
+-	      # linking a shared library.
+-	      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+-
+-	    else
+-	      # FIXME: insert proper C++ library support
+-	      _LT_TAGVAR(ld_shlibs, $1)=no
+-	    fi
+-	    ;;
+-        esac
+-        ;;
+-
+-      psos*)
+-        # FIXME: insert proper C++ library support
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-        ;;
+-
+-      sunos4*)
+-        case $cc_basename in
+-          CC*)
+-	    # Sun C++ 4.x
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          lcc*)
+-	    # Lucid
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          *)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-        esac
+-        ;;
+-
+-      solaris*)
+-        case $cc_basename in
+-          CC* | sunCC*)
+-	    # Sun C++ 4.2, 5.x and Centerline C++
+-            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+-	    _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+-
+-	    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+-	    _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	    case $host_os in
+-	      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+-	      *)
+-		# The compiler driver will combine and reorder linker options,
+-		# but understands '-z linker_flag'.
+-	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+-		_LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+-	        ;;
+-	    esac
+-	    _LT_TAGVAR(link_all_deplibs, $1)=yes
+-
+-	    output_verbose_link_cmd='func_echo_all'
+-
+-	    # Archives containing C++ object files must be created using
+-	    # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+-	    # necessary to make sure instantiated templates are included
+-	    # in the archive.
+-	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+-	    ;;
+-          gcx*)
+-	    # Green Hills C++ Compiler
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+-
+-	    # The C++ compiler must be used to create the archive.
+-	    _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+-	    ;;
+-          *)
+-	    # GNU C++ compiler with Solaris linker
+-	    if test yes,no = "$GXX,$with_gnu_ld"; then
+-	      _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
+-	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+-	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+-
+-	        # Commands to make compiler produce verbose output that lists
+-	        # what "hidden" libraries, object files and flags are used when
+-	        # linking a shared library.
+-	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+-	      else
+-	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
+-	        # platform.
+-	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+-	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+-
+-	        # Commands to make compiler produce verbose output that lists
+-	        # what "hidden" libraries, object files and flags are used when
+-	        # linking a shared library.
+-	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+-	      fi
+-
+-	      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
+-	      case $host_os in
+-		solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+-		*)
+-		  _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+-		  ;;
+-	      esac
+-	    fi
+-	    ;;
+-        esac
+-        ;;
+-
+-    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+-      _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+-      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-      runpath_var='LD_RUN_PATH'
+-
+-      case $cc_basename in
+-        CC*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-	*)
+-	  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  ;;
+-      esac
+-      ;;
+-
+-      sysv5* | sco3.2v5* | sco5v6*)
+-	# Note: We CANNOT use -z defs as we might desire, because we do not
+-	# link with -lc, and that would cause any symbols used from libc to
+-	# always be unresolved, which means just about no library would
+-	# ever link correctly.  If we're not using GNU ld we use -z text
+-	# though, which does catch some bad symbols but isn't as heavy-handed
+-	# as -z defs.
+-	_LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+-	_LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+-	_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-	_LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+-	_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+-	_LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+-	_LT_TAGVAR(link_all_deplibs, $1)=yes
+-	_LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+-	runpath_var='LD_RUN_PATH'
+-
+-	case $cc_basename in
+-          CC*)
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	    _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+-              '"$_LT_TAGVAR(old_archive_cmds, $1)"
+-	    _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+-              '"$_LT_TAGVAR(reload_cmds, $1)"
+-	    ;;
+-	  *)
+-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	    _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	    ;;
+-	esac
+-      ;;
+-
+-      tandem*)
+-        case $cc_basename in
+-          NCC*)
+-	    # NonStop-UX NCC 3.20
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-          *)
+-	    # FIXME: insert proper C++ library support
+-	    _LT_TAGVAR(ld_shlibs, $1)=no
+-	    ;;
+-        esac
+-        ;;
+-
+-      vxworks*)
+-        # FIXME: insert proper C++ library support
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-        ;;
+-
+-      *)
+-        # FIXME: insert proper C++ library support
+-        _LT_TAGVAR(ld_shlibs, $1)=no
+-        ;;
+-    esac
+-
+-    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+-    test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+-
+-    _LT_TAGVAR(GCC, $1)=$GXX
+-    _LT_TAGVAR(LD, $1)=$LD
+-
+-    ## CAVEAT EMPTOR:
+-    ## There is no encapsulation within the following macros, do not change
+-    ## the running order or otherwise move them around unless you know exactly
+-    ## what you are doing...
+-    _LT_SYS_HIDDEN_LIBDEPS($1)
+-    _LT_COMPILER_PIC($1)
+-    _LT_COMPILER_C_O($1)
+-    _LT_COMPILER_FILE_LOCKS($1)
+-    _LT_LINKER_SHLIBS($1)
+-    _LT_SYS_DYNAMIC_LINKER($1)
+-    _LT_LINKER_HARDCODE_LIBPATH($1)
+-
+-    _LT_CONFIG($1)
+-  fi # test -n "$compiler"
+-
+-  CC=$lt_save_CC
+-  CFLAGS=$lt_save_CFLAGS
+-  LDCXX=$LD
+-  LD=$lt_save_LD
+-  GCC=$lt_save_GCC
+-  with_gnu_ld=$lt_save_with_gnu_ld
+-  lt_cv_path_LDCXX=$lt_cv_path_LD
+-  lt_cv_path_LD=$lt_save_path_LD
+-  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+-  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+-fi # test yes != "$_lt_caught_CXX_error"
+-
+-AC_LANG_POP
+-])# _LT_LANG_CXX_CONFIG
+-
+-
+-# _LT_FUNC_STRIPNAME_CNF
+-# ----------------------
+-# func_stripname_cnf prefix suffix name
+-# strip PREFIX and SUFFIX off of NAME.
+-# PREFIX and SUFFIX must not contain globbing or regex special
+-# characters, hashes, percent signs, but SUFFIX may contain a leading
+-# dot (in which case that matches only a dot).
+-#
+-# This function is identical to the (non-XSI) version of func_stripname,
+-# except this one can be used by m4 code that may be executed by configure,
+-# rather than the libtool script.
+-m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+-AC_REQUIRE([_LT_DECL_SED])
+-AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+-func_stripname_cnf ()
+-{
+-  case @S|@2 in
+-  .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
+-  *)  func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
+-  esac
+-} # func_stripname_cnf
+-])# _LT_FUNC_STRIPNAME_CNF
+-
+-
+-# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+-# ---------------------------------
+-# Figure out "hidden" library dependencies from verbose
+-# compiler output when linking a shared library.
+-# Parse the compiler output and extract the necessary
+-# objects, libraries and library flags.
+-m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+-[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+-AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+-# Dependencies to place before and after the object being linked:
+-_LT_TAGVAR(predep_objects, $1)=
+-_LT_TAGVAR(postdep_objects, $1)=
+-_LT_TAGVAR(predeps, $1)=
+-_LT_TAGVAR(postdeps, $1)=
+-_LT_TAGVAR(compiler_lib_search_path, $1)=
+-
+-dnl we can't use the lt_simple_compile_test_code here,
+-dnl because it contains code intended for an executable,
+-dnl not a library.  It's possible we should let each
+-dnl tag define a new lt_????_link_test_code variable,
+-dnl but it's only used here...
+-m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+-int a;
+-void foo (void) { a = 0; }
+-_LT_EOF
+-], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+-class Foo
+-{
+-public:
+-  Foo (void) { a = 0; }
+-private:
+-  int a;
+-};
+-_LT_EOF
+-], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+-      subroutine foo
+-      implicit none
+-      integer*4 a
+-      a=0
+-      return
+-      end
+-_LT_EOF
+-], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+-      subroutine foo
+-      implicit none
+-      integer a
+-      a=0
+-      return
+-      end
+-_LT_EOF
+-], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+-public class foo {
+-  private int a;
+-  public void bar (void) {
+-    a = 0;
+-  }
+-};
+-_LT_EOF
+-], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+-package foo
+-func foo() {
+-}
+-_LT_EOF
+-])
+-
+-_lt_libdeps_save_CFLAGS=$CFLAGS
+-case "$CC $CFLAGS " in #(
+-*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+-*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+-*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+-esac
+-
+-dnl Parse the compiler output and extract the necessary
+-dnl objects, libraries and library flags.
+-if AC_TRY_EVAL(ac_compile); then
+-  # Parse the compiler output and extract the necessary
+-  # objects, libraries and library flags.
+-
+-  # Sentinel used to keep track of whether or not we are before
+-  # the conftest object file.
+-  pre_test_object_deps_done=no
+-
+-  for p in `eval "$output_verbose_link_cmd"`; do
+-    case $prev$p in
+-
+-    -L* | -R* | -l*)
+-       # Some compilers place space between "-{L,R}" and the path.
+-       # Remove the space.
+-       if test x-L = "$p" ||
+-          test x-R = "$p"; then
+-	 prev=$p
+-	 continue
+-       fi
+-
+-       # Expand the sysroot to ease extracting the directories later.
+-       if test -z "$prev"; then
+-         case $p in
+-         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+-         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+-         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+-         esac
+-       fi
+-       case $p in
+-       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+-       esac
+-       if test no = "$pre_test_object_deps_done"; then
+-	 case $prev in
+-	 -L | -R)
+-	   # Internal compiler library paths should come after those
+-	   # provided the user.  The postdeps already come after the
+-	   # user supplied libs so there is no need to process them.
+-	   if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+-	     _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
+-	   else
+-	     _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
+-	   fi
+-	   ;;
+-	 # The "-l" case would never come before the object being
+-	 # linked, so don't bother handling this case.
+-	 esac
+-       else
+-	 if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+-	   _LT_TAGVAR(postdeps, $1)=$prev$p
+-	 else
+-	   _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
+-	 fi
+-       fi
+-       prev=
+-       ;;
+-
+-    *.lto.$objext) ;; # Ignore GCC LTO objects
+-    *.$objext)
+-       # This assumes that the test object file only shows up
+-       # once in the compiler output.
+-       if test "$p" = "conftest.$objext"; then
+-	 pre_test_object_deps_done=yes
+-	 continue
+-       fi
+-
+-       if test no = "$pre_test_object_deps_done"; then
+-	 if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+-	   _LT_TAGVAR(predep_objects, $1)=$p
+-	 else
+-	   _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+-	 fi
+-       else
+-	 if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+-	   _LT_TAGVAR(postdep_objects, $1)=$p
+-	 else
+-	   _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+-	 fi
+-       fi
+-       ;;
+-
+-    *) ;; # Ignore the rest.
+-
+-    esac
+-  done
+-
+-  # Clean up.
+-  rm -f a.out a.exe
+-else
+-  echo "libtool.m4: error: problem compiling $1 test program"
+-fi
+-
+-$RM -f confest.$objext
+-CFLAGS=$_lt_libdeps_save_CFLAGS
+-
+-# PORTME: override above test on systems where it is broken
+-m4_if([$1], [CXX],
+-[case $host_os in
+-interix[[3-9]]*)
+-  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+-  # hack all around it, let's just trust "g++" to DTRT.
+-  _LT_TAGVAR(predep_objects,$1)=
+-  _LT_TAGVAR(postdep_objects,$1)=
+-  _LT_TAGVAR(postdeps,$1)=
+-  ;;
+-esac
+-])
+-
+-case " $_LT_TAGVAR(postdeps, $1) " in
+-*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+-esac
+- _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+-if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+- _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
+-fi
+-_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+-    [The directories searched by this compiler when creating a shared library])
+-_LT_TAGDECL([], [predep_objects], [1],
+-    [Dependencies to place before and after the objects being linked to
+-    create a shared library])
+-_LT_TAGDECL([], [postdep_objects], [1])
+-_LT_TAGDECL([], [predeps], [1])
+-_LT_TAGDECL([], [postdeps], [1])
+-_LT_TAGDECL([], [compiler_lib_search_path], [1],
+-    [The library search path used internally by the compiler when linking
+-    a shared library])
+-])# _LT_SYS_HIDDEN_LIBDEPS
+-
+-
+-# _LT_LANG_F77_CONFIG([TAG])
+-# --------------------------
+-# Ensure that the configuration variables for a Fortran 77 compiler are
+-# suitably defined.  These variables are subsequently used by _LT_CONFIG
+-# to write the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_F77_CONFIG],
+-[AC_LANG_PUSH(Fortran 77)
+-if test -z "$F77" || test no = "$F77"; then
+-  _lt_disable_F77=yes
+-fi
+-
+-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-_LT_TAGVAR(allow_undefined_flag, $1)=
+-_LT_TAGVAR(always_export_symbols, $1)=no
+-_LT_TAGVAR(archive_expsym_cmds, $1)=
+-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+-_LT_TAGVAR(hardcode_direct, $1)=no
+-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+-_LT_TAGVAR(hardcode_libdir_separator, $1)=
+-_LT_TAGVAR(hardcode_minus_L, $1)=no
+-_LT_TAGVAR(hardcode_automatic, $1)=no
+-_LT_TAGVAR(inherit_rpath, $1)=no
+-_LT_TAGVAR(module_cmds, $1)=
+-_LT_TAGVAR(module_expsym_cmds, $1)=
+-_LT_TAGVAR(link_all_deplibs, $1)=unknown
+-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+-_LT_TAGVAR(reload_flag, $1)=$reload_flag
+-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+-_LT_TAGVAR(no_undefined_flag, $1)=
+-_LT_TAGVAR(whole_archive_flag_spec, $1)=
+-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+-
+-# Source file extension for f77 test sources.
+-ac_ext=f
+-
+-# Object file extension for compiled f77 test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# No sense in running all these tests if we already determined that
+-# the F77 compiler isn't working.  Some variables (like enable_shared)
+-# are currently assumed to apply to all compilers on this platform,
+-# and will be corrupted by setting them based on a non-working compiler.
+-if test yes != "$_lt_disable_F77"; then
+-  # Code to be used in simple compile tests
+-  lt_simple_compile_test_code="\
+-      subroutine t
+-      return
+-      end
+-"
+-
+-  # Code to be used in simple link tests
+-  lt_simple_link_test_code="\
+-      program t
+-      end
+-"
+-
+-  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+-  _LT_TAG_COMPILER
+-
+-  # save warnings/boilerplate of simple test code
+-  _LT_COMPILER_BOILERPLATE
+-  _LT_LINKER_BOILERPLATE
+-
+-  # Allow CC to be a program name with arguments.
+-  lt_save_CC=$CC
+-  lt_save_GCC=$GCC
+-  lt_save_CFLAGS=$CFLAGS
+-  CC=${F77-"f77"}
+-  CFLAGS=$FFLAGS
+-  compiler=$CC
+-  _LT_TAGVAR(compiler, $1)=$CC
+-  _LT_CC_BASENAME([$compiler])
+-  GCC=$G77
+-  if test -n "$compiler"; then
+-    AC_MSG_CHECKING([if libtool supports shared libraries])
+-    AC_MSG_RESULT([$can_build_shared])
+-
+-    AC_MSG_CHECKING([whether to build shared libraries])
+-    test no = "$can_build_shared" && enable_shared=no
+-
+-    # On AIX, shared libraries and static libraries use the same namespace, and
+-    # are all built from PIC.
+-    case $host_os in
+-      aix3*)
+-        test yes = "$enable_shared" && enable_static=no
+-        if test -n "$RANLIB"; then
+-          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+-          postinstall_cmds='$RANLIB $lib'
+-        fi
+-        ;;
+-      aix[[4-9]]*)
+-	if test ia64 != "$host_cpu"; then
+-	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+-	  yes,aix,yes) ;;		# shared object as lib.so file only
+-	  yes,svr4,*) ;;		# shared object as lib.so archive member only
+-	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+-	  esac
+-	fi
+-        ;;
+-    esac
+-    AC_MSG_RESULT([$enable_shared])
+-
+-    AC_MSG_CHECKING([whether to build static libraries])
+-    # Make sure either enable_shared or enable_static is yes.
+-    test yes = "$enable_shared" || enable_static=yes
+-    AC_MSG_RESULT([$enable_static])
+-
+-    _LT_TAGVAR(GCC, $1)=$G77
+-    _LT_TAGVAR(LD, $1)=$LD
+-
+-    ## CAVEAT EMPTOR:
+-    ## There is no encapsulation within the following macros, do not change
+-    ## the running order or otherwise move them around unless you know exactly
+-    ## what you are doing...
+-    _LT_COMPILER_PIC($1)
+-    _LT_COMPILER_C_O($1)
+-    _LT_COMPILER_FILE_LOCKS($1)
+-    _LT_LINKER_SHLIBS($1)
+-    _LT_SYS_DYNAMIC_LINKER($1)
+-    _LT_LINKER_HARDCODE_LIBPATH($1)
+-
+-    _LT_CONFIG($1)
+-  fi # test -n "$compiler"
+-
+-  GCC=$lt_save_GCC
+-  CC=$lt_save_CC
+-  CFLAGS=$lt_save_CFLAGS
+-fi # test yes != "$_lt_disable_F77"
+-
+-AC_LANG_POP
+-])# _LT_LANG_F77_CONFIG
+-
+-
+-# _LT_LANG_FC_CONFIG([TAG])
+-# -------------------------
+-# Ensure that the configuration variables for a Fortran compiler are
+-# suitably defined.  These variables are subsequently used by _LT_CONFIG
+-# to write the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_FC_CONFIG],
+-[AC_LANG_PUSH(Fortran)
+-
+-if test -z "$FC" || test no = "$FC"; then
+-  _lt_disable_FC=yes
+-fi
+-
+-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-_LT_TAGVAR(allow_undefined_flag, $1)=
+-_LT_TAGVAR(always_export_symbols, $1)=no
+-_LT_TAGVAR(archive_expsym_cmds, $1)=
+-_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+-_LT_TAGVAR(hardcode_direct, $1)=no
+-_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+-_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+-_LT_TAGVAR(hardcode_libdir_separator, $1)=
+-_LT_TAGVAR(hardcode_minus_L, $1)=no
+-_LT_TAGVAR(hardcode_automatic, $1)=no
+-_LT_TAGVAR(inherit_rpath, $1)=no
+-_LT_TAGVAR(module_cmds, $1)=
+-_LT_TAGVAR(module_expsym_cmds, $1)=
+-_LT_TAGVAR(link_all_deplibs, $1)=unknown
+-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+-_LT_TAGVAR(reload_flag, $1)=$reload_flag
+-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+-_LT_TAGVAR(no_undefined_flag, $1)=
+-_LT_TAGVAR(whole_archive_flag_spec, $1)=
+-_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+-
+-# Source file extension for fc test sources.
+-ac_ext=${ac_fc_srcext-f}
+-
+-# Object file extension for compiled fc test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# No sense in running all these tests if we already determined that
+-# the FC compiler isn't working.  Some variables (like enable_shared)
+-# are currently assumed to apply to all compilers on this platform,
+-# and will be corrupted by setting them based on a non-working compiler.
+-if test yes != "$_lt_disable_FC"; then
+-  # Code to be used in simple compile tests
+-  lt_simple_compile_test_code="\
+-      subroutine t
+-      return
+-      end
+-"
+-
+-  # Code to be used in simple link tests
+-  lt_simple_link_test_code="\
+-      program t
+-      end
+-"
+-
+-  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+-  _LT_TAG_COMPILER
+-
+-  # save warnings/boilerplate of simple test code
+-  _LT_COMPILER_BOILERPLATE
+-  _LT_LINKER_BOILERPLATE
+-
+-  # Allow CC to be a program name with arguments.
+-  lt_save_CC=$CC
+-  lt_save_GCC=$GCC
+-  lt_save_CFLAGS=$CFLAGS
+-  CC=${FC-"f95"}
+-  CFLAGS=$FCFLAGS
+-  compiler=$CC
+-  GCC=$ac_cv_fc_compiler_gnu
+-
+-  _LT_TAGVAR(compiler, $1)=$CC
+-  _LT_CC_BASENAME([$compiler])
+-
+-  if test -n "$compiler"; then
+-    AC_MSG_CHECKING([if libtool supports shared libraries])
+-    AC_MSG_RESULT([$can_build_shared])
+-
+-    AC_MSG_CHECKING([whether to build shared libraries])
+-    test no = "$can_build_shared" && enable_shared=no
+-
+-    # On AIX, shared libraries and static libraries use the same namespace, and
+-    # are all built from PIC.
+-    case $host_os in
+-      aix3*)
+-        test yes = "$enable_shared" && enable_static=no
+-        if test -n "$RANLIB"; then
+-          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+-          postinstall_cmds='$RANLIB $lib'
+-        fi
+-        ;;
+-      aix[[4-9]]*)
+-	if test ia64 != "$host_cpu"; then
+-	  case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+-	  yes,aix,yes) ;;		# shared object as lib.so file only
+-	  yes,svr4,*) ;;		# shared object as lib.so archive member only
+-	  yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+-	  esac
+-	fi
+-        ;;
+-    esac
+-    AC_MSG_RESULT([$enable_shared])
+-
+-    AC_MSG_CHECKING([whether to build static libraries])
+-    # Make sure either enable_shared or enable_static is yes.
+-    test yes = "$enable_shared" || enable_static=yes
+-    AC_MSG_RESULT([$enable_static])
+-
+-    _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
+-    _LT_TAGVAR(LD, $1)=$LD
+-
+-    ## CAVEAT EMPTOR:
+-    ## There is no encapsulation within the following macros, do not change
+-    ## the running order or otherwise move them around unless you know exactly
+-    ## what you are doing...
+-    _LT_SYS_HIDDEN_LIBDEPS($1)
+-    _LT_COMPILER_PIC($1)
+-    _LT_COMPILER_C_O($1)
+-    _LT_COMPILER_FILE_LOCKS($1)
+-    _LT_LINKER_SHLIBS($1)
+-    _LT_SYS_DYNAMIC_LINKER($1)
+-    _LT_LINKER_HARDCODE_LIBPATH($1)
+-
+-    _LT_CONFIG($1)
+-  fi # test -n "$compiler"
+-
+-  GCC=$lt_save_GCC
+-  CC=$lt_save_CC
+-  CFLAGS=$lt_save_CFLAGS
+-fi # test yes != "$_lt_disable_FC"
+-
+-AC_LANG_POP
+-])# _LT_LANG_FC_CONFIG
+-
+-
+-# _LT_LANG_GCJ_CONFIG([TAG])
+-# --------------------------
+-# Ensure that the configuration variables for the GNU Java Compiler compiler
+-# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+-# to write the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_GCJ_CONFIG],
+-[AC_REQUIRE([LT_PROG_GCJ])dnl
+-AC_LANG_SAVE
+-
+-# Source file extension for Java test sources.
+-ac_ext=java
+-
+-# Object file extension for compiled Java test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# Code to be used in simple compile tests
+-lt_simple_compile_test_code="class foo {}"
+-
+-# Code to be used in simple link tests
+-lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+-
+-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+-_LT_TAG_COMPILER
+-
+-# save warnings/boilerplate of simple test code
+-_LT_COMPILER_BOILERPLATE
+-_LT_LINKER_BOILERPLATE
+-
+-# Allow CC to be a program name with arguments.
+-lt_save_CC=$CC
+-lt_save_CFLAGS=$CFLAGS
+-lt_save_GCC=$GCC
+-GCC=yes
+-CC=${GCJ-"gcj"}
+-CFLAGS=$GCJFLAGS
+-compiler=$CC
+-_LT_TAGVAR(compiler, $1)=$CC
+-_LT_TAGVAR(LD, $1)=$LD
+-_LT_CC_BASENAME([$compiler])
+-
+-# GCJ did not exist at the time GCC didn't implicitly link libc in.
+-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-
+-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+-_LT_TAGVAR(reload_flag, $1)=$reload_flag
+-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+-
+-if test -n "$compiler"; then
+-  _LT_COMPILER_NO_RTTI($1)
+-  _LT_COMPILER_PIC($1)
+-  _LT_COMPILER_C_O($1)
+-  _LT_COMPILER_FILE_LOCKS($1)
+-  _LT_LINKER_SHLIBS($1)
+-  _LT_LINKER_HARDCODE_LIBPATH($1)
+-
+-  _LT_CONFIG($1)
+-fi
+-
+-AC_LANG_RESTORE
+-
+-GCC=$lt_save_GCC
+-CC=$lt_save_CC
+-CFLAGS=$lt_save_CFLAGS
+-])# _LT_LANG_GCJ_CONFIG
+-
+-
+-# _LT_LANG_GO_CONFIG([TAG])
+-# --------------------------
+-# Ensure that the configuration variables for the GNU Go compiler
+-# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+-# to write the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_GO_CONFIG],
+-[AC_REQUIRE([LT_PROG_GO])dnl
+-AC_LANG_SAVE
+-
+-# Source file extension for Go test sources.
+-ac_ext=go
+-
+-# Object file extension for compiled Go test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# Code to be used in simple compile tests
+-lt_simple_compile_test_code="package main; func main() { }"
+-
+-# Code to be used in simple link tests
+-lt_simple_link_test_code='package main; func main() { }'
+-
+-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+-_LT_TAG_COMPILER
+-
+-# save warnings/boilerplate of simple test code
+-_LT_COMPILER_BOILERPLATE
+-_LT_LINKER_BOILERPLATE
+-
+-# Allow CC to be a program name with arguments.
+-lt_save_CC=$CC
+-lt_save_CFLAGS=$CFLAGS
+-lt_save_GCC=$GCC
+-GCC=yes
+-CC=${GOC-"gccgo"}
+-CFLAGS=$GOFLAGS
+-compiler=$CC
+-_LT_TAGVAR(compiler, $1)=$CC
+-_LT_TAGVAR(LD, $1)=$LD
+-_LT_CC_BASENAME([$compiler])
+-
+-# Go did not exist at the time GCC didn't implicitly link libc in.
+-_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+-
+-_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+-_LT_TAGVAR(reload_flag, $1)=$reload_flag
+-_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+-
+-if test -n "$compiler"; then
+-  _LT_COMPILER_NO_RTTI($1)
+-  _LT_COMPILER_PIC($1)
+-  _LT_COMPILER_C_O($1)
+-  _LT_COMPILER_FILE_LOCKS($1)
+-  _LT_LINKER_SHLIBS($1)
+-  _LT_LINKER_HARDCODE_LIBPATH($1)
+-
+-  _LT_CONFIG($1)
+-fi
+-
+-AC_LANG_RESTORE
+-
+-GCC=$lt_save_GCC
+-CC=$lt_save_CC
+-CFLAGS=$lt_save_CFLAGS
+-])# _LT_LANG_GO_CONFIG
+-
+-
+-# _LT_LANG_RC_CONFIG([TAG])
+-# -------------------------
+-# Ensure that the configuration variables for the Windows resource compiler
+-# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+-# to write the compiler configuration to 'libtool'.
+-m4_defun([_LT_LANG_RC_CONFIG],
+-[AC_REQUIRE([LT_PROG_RC])dnl
+-AC_LANG_SAVE
+-
+-# Source file extension for RC test sources.
+-ac_ext=rc
+-
+-# Object file extension for compiled RC test sources.
+-objext=o
+-_LT_TAGVAR(objext, $1)=$objext
+-
+-# Code to be used in simple compile tests
+-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+-
+-# Code to be used in simple link tests
+-lt_simple_link_test_code=$lt_simple_compile_test_code
+-
+-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+-_LT_TAG_COMPILER
+-
+-# save warnings/boilerplate of simple test code
+-_LT_COMPILER_BOILERPLATE
+-_LT_LINKER_BOILERPLATE
+-
+-# Allow CC to be a program name with arguments.
+-lt_save_CC=$CC
+-lt_save_CFLAGS=$CFLAGS
+-lt_save_GCC=$GCC
+-GCC=
+-CC=${RC-"windres"}
+-CFLAGS=
+-compiler=$CC
+-_LT_TAGVAR(compiler, $1)=$CC
+-_LT_CC_BASENAME([$compiler])
+-_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+-
+-if test -n "$compiler"; then
+-  :
+-  _LT_CONFIG($1)
+-fi
+-
+-GCC=$lt_save_GCC
+-AC_LANG_RESTORE
+-CC=$lt_save_CC
+-CFLAGS=$lt_save_CFLAGS
+-])# _LT_LANG_RC_CONFIG
+-
+-
+-# LT_PROG_GCJ
+-# -----------
+-AC_DEFUN([LT_PROG_GCJ],
+-[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+-  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+-    [AC_CHECK_TOOL(GCJ, gcj,)
+-      test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
+-      AC_SUBST(GCJFLAGS)])])[]dnl
+-])
+-
+-# Old name:
+-AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+-
+-
+-# LT_PROG_GO
+-# ----------
+-AC_DEFUN([LT_PROG_GO],
+-[AC_CHECK_TOOL(GOC, gccgo,)
+-])
+-
+-
+-# LT_PROG_RC
+-# ----------
+-AC_DEFUN([LT_PROG_RC],
+-[AC_CHECK_TOOL(RC, windres,)
+-])
+-
+-# Old name:
+-AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([LT_AC_PROG_RC], [])
+-
+-
+-# _LT_DECL_EGREP
+-# --------------
+-# If we don't have a new enough Autoconf to choose the best grep
+-# available, choose the one first in the user's PATH.
+-m4_defun([_LT_DECL_EGREP],
+-[AC_REQUIRE([AC_PROG_EGREP])dnl
+-AC_REQUIRE([AC_PROG_FGREP])dnl
+-test -z "$GREP" && GREP=grep
+-_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+-_LT_DECL([], [EGREP], [1], [An ERE matcher])
+-_LT_DECL([], [FGREP], [1], [A literal string matcher])
+-dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+-AC_SUBST([GREP])
+-])
+-
+-
+-# _LT_DECL_OBJDUMP
+-# --------------
+-# If we don't have a new enough Autoconf to choose the best objdump
+-# available, choose the one first in the user's PATH.
+-m4_defun([_LT_DECL_OBJDUMP],
+-[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+-test -z "$OBJDUMP" && OBJDUMP=objdump
+-_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+-AC_SUBST([OBJDUMP])
+-])
+-
+-# _LT_DECL_DLLTOOL
+-# ----------------
+-# Ensure DLLTOOL variable is set.
+-m4_defun([_LT_DECL_DLLTOOL],
+-[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+-test -z "$DLLTOOL" && DLLTOOL=dlltool
+-_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+-AC_SUBST([DLLTOOL])
+-])
+-
+-# _LT_DECL_FILECMD
+-# ----------------
+-# Check for a file(cmd) program that can be used to detect file type and magic
+-m4_defun([_LT_DECL_FILECMD],
+-[AC_CHECK_TOOL([FILECMD], [file], [:])
+-_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
+-])# _LD_DECL_FILECMD
+-
+-# _LT_DECL_SED
+-# ------------
+-# Check for a fully-functional sed program, that truncates
+-# as few characters as possible.  Prefer GNU sed if found.
+-m4_defun([_LT_DECL_SED],
+-[AC_PROG_SED
+-test -z "$SED" && SED=sed
+-Xsed="$SED -e 1s/^X//"
+-_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+-_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+-    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+-])# _LT_DECL_SED
+-
+-m4_ifndef([AC_PROG_SED], [
+-# NOTE: This macro has been submitted for inclusion into   #
+-#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+-#  a released version of Autoconf we should remove this    #
+-#  macro and use it instead.                               #
+-
+-m4_defun([AC_PROG_SED],
+-[AC_MSG_CHECKING([for a sed that does not truncate output])
+-AC_CACHE_VAL(lt_cv_path_SED,
+-[# Loop through the user's path and test for sed and gsed.
+-# Then use that list of sed's as ones to test for truncation.
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  test -z "$as_dir" && as_dir=.
+-  for lt_ac_prog in sed gsed; do
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+-        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+-      fi
+-    done
+-  done
+-done
+-IFS=$as_save_IFS
+-lt_ac_max=0
+-lt_ac_count=0
+-# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+-# along with /bin/sed that truncates output.
+-for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+-  test ! -f "$lt_ac_sed" && continue
+-  cat /dev/null > conftest.in
+-  lt_ac_count=0
+-  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+-  # Check for GNU sed and select it if it is found.
+-  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+-    lt_cv_path_SED=$lt_ac_sed
+-    break
+-  fi
+-  while true; do
+-    cat conftest.in conftest.in >conftest.tmp
+-    mv conftest.tmp conftest.in
+-    cp conftest.in conftest.nl
+-    echo >>conftest.nl
+-    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+-    cmp -s conftest.out conftest.nl || break
+-    # 10000 chars as input seems more than enough
+-    test 10 -lt "$lt_ac_count" && break
+-    lt_ac_count=`expr $lt_ac_count + 1`
+-    if test "$lt_ac_count" -gt "$lt_ac_max"; then
+-      lt_ac_max=$lt_ac_count
+-      lt_cv_path_SED=$lt_ac_sed
+-    fi
+-  done
+-done
+-])
+-SED=$lt_cv_path_SED
+-AC_SUBST([SED])
+-AC_MSG_RESULT([$SED])
+-])#AC_PROG_SED
+-])#m4_ifndef
+-
+-# Old name:
+-AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([LT_AC_PROG_SED], [])
+-
+-
+-# _LT_CHECK_SHELL_FEATURES
+-# ------------------------
+-# Find out whether the shell is Bourne or XSI compatible,
+-# or has some other useful features.
+-m4_defun([_LT_CHECK_SHELL_FEATURES],
+-[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+-  lt_unset=unset
+-else
+-  lt_unset=false
+-fi
+-_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+-
+-# test EBCDIC or ASCII
+-case `echo X|tr X '\101'` in
+- A) # ASCII based system
+-    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+-  lt_SP2NL='tr \040 \012'
+-  lt_NL2SP='tr \015\012 \040\040'
+-  ;;
+- *) # EBCDIC based system
+-  lt_SP2NL='tr \100 \n'
+-  lt_NL2SP='tr \r\n \100\100'
+-  ;;
+-esac
+-_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+-_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+-])# _LT_CHECK_SHELL_FEATURES
+-
+-
+-# _LT_PATH_CONVERSION_FUNCTIONS
+-# -----------------------------
+-# Determine what file name conversion functions should be used by
+-# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
+-# for certain cross-compile configurations and native mingw.
+-m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+-AC_MSG_CHECKING([how to convert $build file names to $host format])
+-AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+-[case $host in
+-  *-*-mingw* )
+-    case $build in
+-      *-*-mingw* ) # actually msys
+-        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+-        ;;
+-      *-*-cygwin* )
+-        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+-        ;;
+-      * ) # otherwise, assume *nix
+-        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+-        ;;
+-    esac
+-    ;;
+-  *-*-cygwin* )
+-    case $build in
+-      *-*-mingw* ) # actually msys
+-        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+-        ;;
+-      *-*-cygwin* )
+-        lt_cv_to_host_file_cmd=func_convert_file_noop
+-        ;;
+-      * ) # otherwise, assume *nix
+-        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+-        ;;
+-    esac
+-    ;;
+-  * ) # unhandled hosts (and "normal" native builds)
+-    lt_cv_to_host_file_cmd=func_convert_file_noop
+-    ;;
+-esac
+-])
+-to_host_file_cmd=$lt_cv_to_host_file_cmd
+-AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+-_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+-         [0], [convert $build file names to $host format])dnl
+-
+-AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+-AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+-[#assume ordinary cross tools, or native build.
+-lt_cv_to_tool_file_cmd=func_convert_file_noop
+-case $host in
+-  *-*-mingw* )
+-    case $build in
+-      *-*-mingw* ) # actually msys
+-        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+-        ;;
+-    esac
+-    ;;
+-esac
+-])
+-to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+-AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+-_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+-         [0], [convert $build files to toolchain format])dnl
+-])# _LT_PATH_CONVERSION_FUNCTIONS
+-
+-# Helper functions for option handling.                    -*- Autoconf -*-
+-#
+-#   Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
+-#   Software Foundation, Inc.
+-#   Written by Gary V. Vaughan, 2004
+-#
+-# This file is free software; the Free Software Foundation gives
+-# unlimited permission to copy and/or distribute it, with or without
+-# modifications, as long as this notice is preserved.
+-
+-# serial 8 ltoptions.m4
+-
+-# This is to help aclocal find these macros, as it can't see m4_define.
+-AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+-
+-
+-# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+-# ------------------------------------------
+-m4_define([_LT_MANGLE_OPTION],
+-[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+-
+-
+-# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+-# ---------------------------------------
+-# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+-# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+-# saved as a flag.
+-m4_define([_LT_SET_OPTION],
+-[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+-m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+-        _LT_MANGLE_DEFUN([$1], [$2]),
+-    [m4_warning([Unknown $1 option '$2'])])[]dnl
+-])
+-
+-
+-# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+-# ------------------------------------------------------------
+-# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+-m4_define([_LT_IF_OPTION],
+-[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+-
+-
+-# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+-# -------------------------------------------------------
+-# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+-# are set.
+-m4_define([_LT_UNLESS_OPTIONS],
+-[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+-	    [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+-		      [m4_define([$0_found])])])[]dnl
+-m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+-])[]dnl
+-])
+-
+-
+-# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+-# ----------------------------------------
+-# OPTION-LIST is a space-separated list of Libtool options associated
+-# with MACRO-NAME.  If any OPTION has a matching handler declared with
+-# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+-# the unknown option and exit.
+-m4_defun([_LT_SET_OPTIONS],
+-[# Set options
+-m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+-    [_LT_SET_OPTION([$1], _LT_Option)])
+-
+-m4_if([$1],[LT_INIT],[
+-  dnl
+-  dnl Simply set some default values (i.e off) if boolean options were not
+-  dnl specified:
+-  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+-  ])
+-  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+-  ])
+-  dnl
+-  dnl If no reference was made to various pairs of opposing options, then
+-  dnl we run the default mode handler for the pair.  For example, if neither
+-  dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
+-  dnl archives by default:
+-  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+-  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+-  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+-  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+-		   [_LT_ENABLE_FAST_INSTALL])
+-  _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+-		   [_LT_WITH_AIX_SONAME([aix])])
+-  ])
+-])# _LT_SET_OPTIONS
+-
+-
+-
+-# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+-# -----------------------------------------
+-m4_define([_LT_MANGLE_DEFUN],
+-[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+-
+-
+-# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+-# -----------------------------------------------
+-m4_define([LT_OPTION_DEFINE],
+-[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+-])# LT_OPTION_DEFINE
+-
+-
+-# dlopen
+-# ------
+-LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+-])
+-
+-AU_DEFUN([AC_LIBTOOL_DLOPEN],
+-[_LT_SET_OPTION([LT_INIT], [dlopen])
+-AC_DIAGNOSE([obsolete],
+-[$0: Remove this warning and the call to _LT_SET_OPTION when you
+-put the 'dlopen' option into LT_INIT's first parameter.])
+-])
+-
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+-
+-
+-# win32-dll
+-# ---------
+-# Declare package support for building win32 dll's.
+-LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+-[enable_win32_dll=yes
+-
+-case $host in
+-*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+-  AC_CHECK_TOOL(AS, as, false)
+-  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+-  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+-  ;;
+-esac
+-
+-test -z "$AS" && AS=as
+-_LT_DECL([], [AS],      [1], [Assembler program])dnl
+-
+-test -z "$DLLTOOL" && DLLTOOL=dlltool
+-_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+-
+-test -z "$OBJDUMP" && OBJDUMP=objdump
+-_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+-])# win32-dll
+-
+-AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+-[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+-_LT_SET_OPTION([LT_INIT], [win32-dll])
+-AC_DIAGNOSE([obsolete],
+-[$0: Remove this warning and the call to _LT_SET_OPTION when you
+-put the 'win32-dll' option into LT_INIT's first parameter.])
+-])
+-
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+-
+-
+-# _LT_ENABLE_SHARED([DEFAULT])
+-# ----------------------------
+-# implement the --enable-shared flag, and supports the 'shared' and
+-# 'disable-shared' LT_INIT options.
+-# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+-m4_define([_LT_ENABLE_SHARED],
+-[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+-AC_ARG_ENABLE([shared],
+-    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+-	[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+-    [p=${PACKAGE-default}
+-    case $enableval in
+-    yes) enable_shared=yes ;;
+-    no) enable_shared=no ;;
+-    *)
+-      enable_shared=no
+-      # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+-      for pkg in $enableval; do
+-	IFS=$lt_save_ifs
+-	if test "X$pkg" = "X$p"; then
+-	  enable_shared=yes
+-	fi
+-      done
+-      IFS=$lt_save_ifs
+-      ;;
+-    esac],
+-    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+-
+-    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+-	[Whether or not to build shared libraries])
+-])# _LT_ENABLE_SHARED
+-
+-LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+-LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+-
+-# Old names:
+-AC_DEFUN([AC_ENABLE_SHARED],
+-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+-])
+-
+-AC_DEFUN([AC_DISABLE_SHARED],
+-[_LT_SET_OPTION([LT_INIT], [disable-shared])
+-])
+-
+-AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+-AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+-
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+-dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+-
+-
+-
+-# _LT_ENABLE_STATIC([DEFAULT])
+-# ----------------------------
+-# implement the --enable-static flag, and support the 'static' and
+-# 'disable-static' LT_INIT options.
+-# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+-m4_define([_LT_ENABLE_STATIC],
+-[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+-AC_ARG_ENABLE([static],
+-    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+-	[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+-    [p=${PACKAGE-default}
+-    case $enableval in
+-    yes) enable_static=yes ;;
+-    no) enable_static=no ;;
+-    *)
+-     enable_static=no
+-      # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+-      for pkg in $enableval; do
+-	IFS=$lt_save_ifs
+-	if test "X$pkg" = "X$p"; then
+-	  enable_static=yes
+-	fi
+-      done
+-      IFS=$lt_save_ifs
+-      ;;
+-    esac],
+-    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+-
+-    _LT_DECL([build_old_libs], [enable_static], [0],
+-	[Whether or not to build static libraries])
+-])# _LT_ENABLE_STATIC
+-
+-LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+-LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+-
+-# Old names:
+-AC_DEFUN([AC_ENABLE_STATIC],
+-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+-])
+-
+-AC_DEFUN([AC_DISABLE_STATIC],
+-[_LT_SET_OPTION([LT_INIT], [disable-static])
+-])
+-
+-AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+-AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+-
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+-dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+-
+-
+-
+-# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+-# ----------------------------------
+-# implement the --enable-fast-install flag, and support the 'fast-install'
+-# and 'disable-fast-install' LT_INIT options.
+-# DEFAULT is either 'yes' or 'no'.  If omitted, it defaults to 'yes'.
+-m4_define([_LT_ENABLE_FAST_INSTALL],
+-[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+-AC_ARG_ENABLE([fast-install],
+-    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+-    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+-    [p=${PACKAGE-default}
+-    case $enableval in
+-    yes) enable_fast_install=yes ;;
+-    no) enable_fast_install=no ;;
+-    *)
+-      enable_fast_install=no
+-      # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+-      for pkg in $enableval; do
+-	IFS=$lt_save_ifs
+-	if test "X$pkg" = "X$p"; then
+-	  enable_fast_install=yes
+-	fi
+-      done
+-      IFS=$lt_save_ifs
+-      ;;
+-    esac],
+-    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+-
+-_LT_DECL([fast_install], [enable_fast_install], [0],
+-	 [Whether or not to optimize for fast installation])dnl
+-])# _LT_ENABLE_FAST_INSTALL
+-
+-LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+-LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+-
+-# Old names:
+-AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+-[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+-AC_DIAGNOSE([obsolete],
+-[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+-the 'fast-install' option into LT_INIT's first parameter.])
+-])
+-
+-AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+-[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+-AC_DIAGNOSE([obsolete],
+-[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+-the 'disable-fast-install' option into LT_INIT's first parameter.])
+-])
+-
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+-dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+-
+-
+-# _LT_WITH_AIX_SONAME([DEFAULT])
+-# ----------------------------------
+-# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+-# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+-# is either `aix', `both' or `svr4'.  If omitted, it defaults to `aix'.
+-m4_define([_LT_WITH_AIX_SONAME],
+-[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+-shared_archive_member_spec=
+-case $host,$enable_shared in
+-power*-*-aix[[5-9]]*,yes)
+-  AC_MSG_CHECKING([which variant of shared library versioning to provide])
+-  AC_ARG_WITH([aix-soname],
+-    [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+-      [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+-    [case $withval in
+-    aix|svr4|both)
+-      ;;
+-    *)
+-      AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+-      ;;
+-    esac
+-    lt_cv_with_aix_soname=$with_aix_soname],
+-    [AC_CACHE_VAL([lt_cv_with_aix_soname],
+-      [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+-    with_aix_soname=$lt_cv_with_aix_soname])
+-  AC_MSG_RESULT([$with_aix_soname])
+-  if test aix != "$with_aix_soname"; then
+-    # For the AIX way of multilib, we name the shared archive member
+-    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+-    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+-    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+-    # the AIX toolchain works better with OBJECT_MODE set (default 32).
+-    if test 64 = "${OBJECT_MODE-32}"; then
+-      shared_archive_member_spec=shr_64
+-    else
+-      shared_archive_member_spec=shr
+-    fi
+-  fi
+-  ;;
+-*)
+-  with_aix_soname=aix
+-  ;;
+-esac
+-
+-_LT_DECL([], [shared_archive_member_spec], [0],
+-    [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+-])# _LT_WITH_AIX_SONAME
+-
+-LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+-LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+-LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+-
+-
+-# _LT_WITH_PIC([MODE])
+-# --------------------
+-# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
+-# LT_INIT options.
+-# MODE is either 'yes' or 'no'.  If omitted, it defaults to 'both'.
+-m4_define([_LT_WITH_PIC],
+-[AC_ARG_WITH([pic],
+-    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+-	[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+-    [lt_p=${PACKAGE-default}
+-    case $withval in
+-    yes|no) pic_mode=$withval ;;
+-    *)
+-      pic_mode=default
+-      # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+-      for lt_pkg in $withval; do
+-	IFS=$lt_save_ifs
+-	if test "X$lt_pkg" = "X$lt_p"; then
+-	  pic_mode=yes
+-	fi
+-      done
+-      IFS=$lt_save_ifs
+-      ;;
+-    esac],
+-    [pic_mode=m4_default([$1], [default])])
+-
+-_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+-])# _LT_WITH_PIC
+-
+-LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+-LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+-
+-# Old name:
+-AU_DEFUN([AC_LIBTOOL_PICMODE],
+-[_LT_SET_OPTION([LT_INIT], [pic-only])
+-AC_DIAGNOSE([obsolete],
+-[$0: Remove this warning and the call to _LT_SET_OPTION when you
+-put the 'pic-only' option into LT_INIT's first parameter.])
+-])
+-
+-dnl aclocal-1.4 backwards compatibility:
+-dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+-
+-
+-m4_define([_LTDL_MODE], [])
+-LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+-		 [m4_define([_LTDL_MODE], [nonrecursive])])
+-LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+-		 [m4_define([_LTDL_MODE], [recursive])])
+-LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+-		 [m4_define([_LTDL_MODE], [subproject])])
+-
+-m4_define([_LTDL_TYPE], [])
+-LT_OPTION_DEFINE([LTDL_INIT], [installable],
+-		 [m4_define([_LTDL_TYPE], [installable])])
+-LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+-		 [m4_define([_LTDL_TYPE], [convenience])])
+-
+-# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+-#
+-# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
+-# Foundation, Inc.
+-# Written by Gary V. Vaughan, 2004
+-#
+-# This file is free software; the Free Software Foundation gives
+-# unlimited permission to copy and/or distribute it, with or without
+-# modifications, as long as this notice is preserved.
+-
+-# serial 6 ltsugar.m4
+-
+-# This is to help aclocal find these macros, as it can't see m4_define.
+-AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+-
+-
+-# lt_join(SEP, ARG1, [ARG2...])
+-# -----------------------------
+-# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+-# associated separator.
+-# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+-# versions in m4sugar had bugs.
+-m4_define([lt_join],
+-[m4_if([$#], [1], [],
+-       [$#], [2], [[$2]],
+-       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+-m4_define([_lt_join],
+-[m4_if([$#$2], [2], [],
+-       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+-
+-
+-# lt_car(LIST)
+-# lt_cdr(LIST)
+-# ------------
+-# Manipulate m4 lists.
+-# These macros are necessary as long as will still need to support
+-# Autoconf-2.59, which quotes differently.
+-m4_define([lt_car], [[$1]])
+-m4_define([lt_cdr],
+-[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+-       [$#], 1, [],
+-       [m4_dquote(m4_shift($@))])])
+-m4_define([lt_unquote], $1)
+-
+-
+-# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+-# ------------------------------------------
+-# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
+-# Note that neither SEPARATOR nor STRING are expanded; they are appended
+-# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+-# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+-# than defined and empty).
+-#
+-# This macro is needed until we can rely on Autoconf 2.62, since earlier
+-# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+-m4_define([lt_append],
+-[m4_define([$1],
+-	   m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+-
+-
+-
+-# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+-# ----------------------------------------------------------
+-# Produce a SEP delimited list of all paired combinations of elements of
+-# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+-# has the form PREFIXmINFIXSUFFIXn.
+-# Needed until we can rely on m4_combine added in Autoconf 2.62.
+-m4_define([lt_combine],
+-[m4_if(m4_eval([$# > 3]), [1],
+-       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+-[[m4_foreach([_Lt_prefix], [$2],
+-	     [m4_foreach([_Lt_suffix],
+-		]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+-	[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+-
+-
+-# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+-# -----------------------------------------------------------------------
+-# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+-# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+-m4_define([lt_if_append_uniq],
+-[m4_ifdef([$1],
+-	  [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+-		 [lt_append([$1], [$2], [$3])$4],
+-		 [$5])],
+-	  [lt_append([$1], [$2], [$3])$4])])
+-
+-
+-# lt_dict_add(DICT, KEY, VALUE)
+-# -----------------------------
+-m4_define([lt_dict_add],
+-[m4_define([$1($2)], [$3])])
+-
+-
+-# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+-# --------------------------------------------
+-m4_define([lt_dict_add_subkey],
+-[m4_define([$1($2:$3)], [$4])])
+-
+-
+-# lt_dict_fetch(DICT, KEY, [SUBKEY])
+-# ----------------------------------
+-m4_define([lt_dict_fetch],
+-[m4_ifval([$3],
+-	m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+-    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+-
+-
+-# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+-# -----------------------------------------------------------------
+-m4_define([lt_if_dict_fetch],
+-[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+-	[$5],
+-    [$6])])
+-
+-
+-# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+-# --------------------------------------------------------------
+-m4_define([lt_dict_filter],
+-[m4_if([$5], [], [],
+-  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+-           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+-		      [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+-])
+-
+-# ltversion.m4 -- version numbers			-*- Autoconf -*-
+-#
+-#   Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
+-#   Inc.
+-#   Written by Scott James Remnant, 2004
+-#
+-# This file is free software; the Free Software Foundation gives
+-# unlimited permission to copy and/or distribute it, with or without
+-# modifications, as long as this notice is preserved.
+-
+-# @configure_input@
+-
+-# serial 4245 ltversion.m4
+-# This file is part of GNU Libtool
+-
+-m4_define([LT_PACKAGE_VERSION], [2.4.7])
+-m4_define([LT_PACKAGE_REVISION], [2.4.7])
+-
+-AC_DEFUN([LTVERSION_VERSION],
+-[macro_version='2.4.7'
+-macro_revision='2.4.7'
+-_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+-_LT_DECL(, macro_revision, 0)
+-])
+-
+-# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+-#
+-#   Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
+-#   Software Foundation, Inc.
+-#   Written by Scott James Remnant, 2004.
+-#
+-# This file is free software; the Free Software Foundation gives
+-# unlimited permission to copy and/or distribute it, with or without
+-# modifications, as long as this notice is preserved.
+-
+-# serial 5 lt~obsolete.m4
+-
+-# These exist entirely to fool aclocal when bootstrapping libtool.
+-#
+-# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
+-# which have later been changed to m4_define as they aren't part of the
+-# exported API, or moved to Autoconf or Automake where they belong.
+-#
+-# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+-# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+-# using a macro with the same name in our local m4/libtool.m4 it'll
+-# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+-# and doesn't know about Autoconf macros at all.)
+-#
+-# So we provide this file, which has a silly filename so it's always
+-# included after everything else.  This provides aclocal with the
+-# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+-# because those macros already exist, or will be overwritten later.
+-# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+-#
+-# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+-# Yes, that means every name once taken will need to remain here until
+-# we give up compatibility with versions before 1.7, at which point
+-# we need to keep only those names which we still refer to.
+-
+-# This is to help aclocal find these macros, as it can't see m4_define.
+-AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+-
+-m4_ifndef([AC_LIBTOOL_LINKER_OPTION],	[AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+-m4_ifndef([AC_PROG_EGREP],		[AC_DEFUN([AC_PROG_EGREP])])
+-m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+-m4_ifndef([_LT_AC_SHELL_INIT],		[AC_DEFUN([_LT_AC_SHELL_INIT])])
+-m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],	[AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+-m4_ifndef([_LT_PROG_LTMAIN],		[AC_DEFUN([_LT_PROG_LTMAIN])])
+-m4_ifndef([_LT_AC_TAGVAR],		[AC_DEFUN([_LT_AC_TAGVAR])])
+-m4_ifndef([AC_LTDL_ENABLE_INSTALL],	[AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+-m4_ifndef([AC_LTDL_PREOPEN],		[AC_DEFUN([AC_LTDL_PREOPEN])])
+-m4_ifndef([_LT_AC_SYS_COMPILER],	[AC_DEFUN([_LT_AC_SYS_COMPILER])])
+-m4_ifndef([_LT_AC_LOCK],		[AC_DEFUN([_LT_AC_LOCK])])
+-m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],	[AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+-m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],	[AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+-m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],	[AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+-m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+-m4_ifndef([AC_LIBTOOL_OBJDIR],		[AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+-m4_ifndef([AC_LTDL_OBJDIR],		[AC_DEFUN([AC_LTDL_OBJDIR])])
+-m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+-m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],	[AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+-m4_ifndef([AC_PATH_MAGIC],		[AC_DEFUN([AC_PATH_MAGIC])])
+-m4_ifndef([AC_PROG_LD_GNU],		[AC_DEFUN([AC_PROG_LD_GNU])])
+-m4_ifndef([AC_PROG_LD_RELOAD_FLAG],	[AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+-m4_ifndef([AC_DEPLIBS_CHECK_METHOD],	[AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+-m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+-m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+-m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS],	[AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+-m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP],	[AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+-m4_ifndef([LT_AC_PROG_EGREP],		[AC_DEFUN([LT_AC_PROG_EGREP])])
+-m4_ifndef([LT_AC_PROG_SED],		[AC_DEFUN([LT_AC_PROG_SED])])
+-m4_ifndef([_LT_CC_BASENAME],		[AC_DEFUN([_LT_CC_BASENAME])])
+-m4_ifndef([_LT_COMPILER_BOILERPLATE],	[AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+-m4_ifndef([_LT_LINKER_BOILERPLATE],	[AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+-m4_ifndef([_AC_PROG_LIBTOOL],		[AC_DEFUN([_AC_PROG_LIBTOOL])])
+-m4_ifndef([AC_LIBTOOL_SETUP],		[AC_DEFUN([AC_LIBTOOL_SETUP])])
+-m4_ifndef([_LT_AC_CHECK_DLFCN],		[AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+-m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],	[AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+-m4_ifndef([_LT_AC_TAGCONFIG],		[AC_DEFUN([_LT_AC_TAGCONFIG])])
+-m4_ifndef([AC_DISABLE_FAST_INSTALL],	[AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+-m4_ifndef([_LT_AC_LANG_CXX],		[AC_DEFUN([_LT_AC_LANG_CXX])])
+-m4_ifndef([_LT_AC_LANG_F77],		[AC_DEFUN([_LT_AC_LANG_F77])])
+-m4_ifndef([_LT_AC_LANG_GCJ],		[AC_DEFUN([_LT_AC_LANG_GCJ])])
+-m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+-m4_ifndef([_LT_AC_LANG_C_CONFIG],	[AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+-m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+-m4_ifndef([_LT_AC_LANG_CXX_CONFIG],	[AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+-m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+-m4_ifndef([_LT_AC_LANG_F77_CONFIG],	[AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+-m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+-m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],	[AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+-m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG],	[AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+-m4_ifndef([_LT_AC_LANG_RC_CONFIG],	[AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+-m4_ifndef([AC_LIBTOOL_CONFIG],		[AC_DEFUN([AC_LIBTOOL_CONFIG])])
+-m4_ifndef([_LT_AC_FILE_LTDLL_C],	[AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+-m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],	[AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+-m4_ifndef([_LT_AC_PROG_CXXCPP],		[AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+-m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],	[AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+-m4_ifndef([_LT_PROG_ECHO_BACKSLASH],	[AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+-m4_ifndef([_LT_PROG_F77],		[AC_DEFUN([_LT_PROG_F77])])
+-m4_ifndef([_LT_PROG_FC],		[AC_DEFUN([_LT_PROG_FC])])
+-m4_ifndef([_LT_PROG_CXX],		[AC_DEFUN([_LT_PROG_CXX])])
+-
+-# Copyright (C) 2002-2021 Free Software Foundation, Inc.
++# Copyright (C) 2002-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9099,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
+ [am__api_version='1.16'
+ dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+ dnl require some minimum version.  Point them to the right macro.
+-m4_if([$1], [1.16.5], [],
++m4_if([$1], [1.16.2], [],
+       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+ ])
+ 
+@@ -9115,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
+ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+ # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+ AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+-[AM_AUTOMAKE_VERSION([1.16.5])dnl
++[AM_AUTOMAKE_VERSION([1.16.2])dnl
+ m4_ifndef([AC_AUTOCONF_VERSION],
+   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+ 
+ # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+ 
+-# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9174,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
+ 
+ # AM_CONDITIONAL                                            -*- Autoconf -*-
+ 
+-# Copyright (C) 1997-2021 Free Software Foundation, Inc.
++# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9205,7 +141,7 @@ AC_CONFIG_COMMANDS_PRE(
+ Usually this means the macro was only invoked conditionally.]])
+ fi])])
+ 
+-# Copyright (C) 1999-2021 Free Software Foundation, Inc.
++# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9396,7 +332,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
+ 
+ # Generate code to set up dependency tracking.              -*- Autoconf -*-
+ 
+-# Copyright (C) 1999-2021 Free Software Foundation, Inc.
++# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9464,7 +400,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+ 
+ # Do all the work for Automake.                             -*- Autoconf -*-
+ 
+-# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9492,10 +428,6 @@ m4_defn([AC_PROG_CC])
+ # release and drop the old call support.
+ AC_DEFUN([AM_INIT_AUTOMAKE],
+ [AC_PREREQ([2.65])dnl
+-m4_ifdef([_$0_ALREADY_INIT],
+-  [m4_fatal([$0 expanded multiple times
+-]m4_defn([_$0_ALREADY_INIT]))],
+-  [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
+ dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+ dnl the ones we care about.
+ m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+@@ -9532,7 +464,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ [_AM_SET_OPTIONS([$1])dnl
+ dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+ m4_if(
+-  m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
++  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+   [ok:ok],,
+   [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+  AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+@@ -9584,20 +516,6 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ 		  [m4_define([AC_PROG_OBJCXX],
+ 			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+ ])
+-# Variables for tags utilities; see am/tags.am
+-if test -z "$CTAGS"; then
+-  CTAGS=ctags
+-fi
+-AC_SUBST([CTAGS])
+-if test -z "$ETAGS"; then
+-  ETAGS=etags
+-fi
+-AC_SUBST([ETAGS])
+-if test -z "$CSCOPE"; then
+-  CSCOPE=cscope
+-fi
+-AC_SUBST([CSCOPE])
+-
+ AC_REQUIRE([AM_SILENT_RULES])dnl
+ dnl The testsuite driver may need to know about EXEEXT, so add the
+ dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+@@ -9679,7 +597,7 @@ for _am_header in $config_headers :; do
+ done
+ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+ 
+-# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9700,29 +618,10 @@ if test x"${install_sh+set}" != xset; then
+ fi
+ AC_SUBST([install_sh])])
+ 
+-# Copyright (C) 2003-2021 Free Software Foundation, Inc.
+-#
+-# This file is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# Check whether the underlying file-system supports filenames
+-# with a leading dot.  For instance MS-DOS doesn't.
+-AC_DEFUN([AM_SET_LEADING_DOT],
+-[rm -rf .tst 2>/dev/null
+-mkdir .tst 2>/dev/null
+-if test -d .tst; then
+-  am__leading_dot=.
+-else
+-  am__leading_dot=_
+-fi
+-rmdir .tst 2>/dev/null
+-AC_SUBST([am__leading_dot])])
+-
+ # Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+ # From Jim Meyering
+ 
+-# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9757,7 +656,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ 
+ # Check to see how 'make' treats includes.	            -*- Autoconf -*-
+ 
+-# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9800,7 +699,7 @@ AC_SUBST([am__quote])])
+ 
+ # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+ 
+-# Copyright (C) 1997-2021 Free Software Foundation, Inc.
++# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9821,7 +720,12 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
+ [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+ AC_REQUIRE_AUX_FILE([missing])dnl
+ if test x"${MISSING+set}" != xset; then
+-  MISSING="\${SHELL} '$am_aux_dir/missing'"
++  case $am_aux_dir in
++  *\ * | *\	*)
++    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
++  *)
++    MISSING="\${SHELL} $am_aux_dir/missing" ;;
++  esac
+ fi
+ # Use eval to expand $SHELL
+ if eval "$MISSING --is-lightweight"; then
+@@ -9834,7 +738,7 @@ fi
+ 
+ # Helper functions for option handling.                     -*- Autoconf -*-
+ 
+-# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9863,7 +767,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
+ AC_DEFUN([_AM_IF_OPTION],
+ [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+ 
+-# Copyright (C) 1999-2021 Free Software Foundation, Inc.
++# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9910,7 +814,7 @@ AC_LANG_POP([C])])
+ # For backward compatibility.
+ AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+ 
+-# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -9929,7 +833,7 @@ AC_DEFUN([AM_RUN_LOG],
+ 
+ # Check to make sure that the build environment is sane.    -*- Autoconf -*-
+ 
+-# Copyright (C) 1996-2021 Free Software Foundation, Inc.
++# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -10010,7 +914,7 @@ AC_CONFIG_COMMANDS_PRE(
+ rm -f conftest.file
+ ])
+ 
+-# Copyright (C) 2009-2021 Free Software Foundation, Inc.
++# Copyright (C) 2009-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -10070,7 +974,7 @@ AC_SUBST([AM_BACKSLASH])dnl
+ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+ ])
+ 
+-# Copyright (C) 2001-2021 Free Software Foundation, Inc.
++# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -10098,7 +1002,7 @@ fi
+ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+ AC_SUBST([INSTALL_STRIP_PROGRAM])])
+ 
+-# Copyright (C) 2006-2021 Free Software Foundation, Inc.
++# Copyright (C) 2006-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -10117,7 +1021,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+ 
+ # Check how to create a tarball.                            -*- Autoconf -*-
+ 
+-# Copyright (C) 2004-2021 Free Software Foundation, Inc.
++# Copyright (C) 2004-2020 Free Software Foundation, Inc.
+ #
+ # This file is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+@@ -10248,3 +1152,14 @@ AC_SUBST([am__tar])
+ AC_SUBST([am__untar])
+ ]) # _AM_PROG_TAR
+ 
++m4_include([../config/acx.m4])
++m4_include([../config/depstand.m4])
++m4_include([../config/lead-dot.m4])
++m4_include([../config/lthostflags.m4])
++m4_include([../config/override.m4])
++m4_include([../config/warnings.m4])
++m4_include([../libtool.m4])
++m4_include([../ltoptions.m4])
++m4_include([../ltsugar.m4])
++m4_include([../ltversion.m4])
++m4_include([../lt~obsolete.m4])
+diff --git a/bolt-plugin/config.h.in b/bolt-plugin/config.h.in
+index 9e9d316ec..ddbde7619 100644
+--- a/bolt-plugin/config.h.in
++++ b/bolt-plugin/config.h.in
+@@ -6,15 +6,12 @@
+ /* Define to 1 if you have the  header file. */
+ #undef HAVE_INTTYPES_H
+ 
+-/* Define to 1 if you have the  header file. */
+-#undef HAVE_MINIX_CONFIG_H
++/* Define to 1 if you have the  header file. */
++#undef HAVE_MEMORY_H
+ 
+ /* Define to 1 if you have the  header file. */
+ #undef HAVE_STDINT_H
+ 
+-/* Define to 1 if you have the  header file. */
+-#undef HAVE_STDIO_H
+-
+ /* Define to 1 if you have the  header file. */
+ #undef HAVE_STDLIB_H
+ 
+@@ -36,10 +33,8 @@
+ /* Define to 1 if you have the  header file. */
+ #undef HAVE_UNISTD_H
+ 
+-/* Define to 1 if you have the  header file. */
+-#undef HAVE_WCHAR_H
+-
+-/* Define to the sub-directory where libtool stores uninstalled libraries. */
++/* Define to the sub-directory in which libtool stores uninstalled libraries.
++   */
+ #undef LT_OBJDIR
+ 
+ /* Name of package */
+@@ -63,108 +58,55 @@
+ /* Define to the version of this package. */
+ #undef PACKAGE_VERSION
+ 
+-/* Define to 1 if all of the C90 standard headers exist (not just the ones
+-   required in a freestanding environment). This macro is provided for
+-   backward compatibility; new code need not use it. */
++/* Define to 1 if you have the ANSI C header files. */
+ #undef STDC_HEADERS
+ 
+ /* Enable extensions on AIX 3, Interix.  */
+ #ifndef _ALL_SOURCE
+ # undef _ALL_SOURCE
+ #endif
+-/* Enable general extensions on macOS.  */
+-#ifndef _DARWIN_C_SOURCE
+-# undef _DARWIN_C_SOURCE
+-#endif
+-/* Enable general extensions on Solaris.  */
+-#ifndef __EXTENSIONS__
+-# undef __EXTENSIONS__
+-#endif
+ /* Enable GNU extensions on systems that have them.  */
+ #ifndef _GNU_SOURCE
+ # undef _GNU_SOURCE
+ #endif
+-/* Enable X/Open compliant socket functions that do not require linking
+-   with -lxnet on HP-UX 11.11.  */
+-#ifndef _HPUX_ALT_XOPEN_SOCKET_API
+-# undef _HPUX_ALT_XOPEN_SOCKET_API
+-#endif
+-/* Identify the host operating system as Minix.
+-   This macro does not affect the system headers' behavior.
+-   A future release of Autoconf may stop defining this macro.  */
+-#ifndef _MINIX
+-# undef _MINIX
+-#endif
+-/* Enable general extensions on NetBSD.
+-   Enable NetBSD compatibility extensions on Minix.  */
+-#ifndef _NETBSD_SOURCE
+-# undef _NETBSD_SOURCE
+-#endif
+-/* Enable OpenBSD compatibility extensions on NetBSD.
+-   Oddly enough, this does nothing on OpenBSD.  */
+-#ifndef _OPENBSD_SOURCE
+-# undef _OPENBSD_SOURCE
+-#endif
+-/* Define to 1 if needed for POSIX-compatible behavior.  */
+-#ifndef _POSIX_SOURCE
+-# undef _POSIX_SOURCE
+-#endif
+-/* Define to 2 if needed for POSIX-compatible behavior.  */
+-#ifndef _POSIX_1_SOURCE
+-# undef _POSIX_1_SOURCE
+-#endif
+-/* Enable POSIX-compatible threading on Solaris.  */
++/* Enable threading extensions on Solaris.  */
+ #ifndef _POSIX_PTHREAD_SEMANTICS
+ # undef _POSIX_PTHREAD_SEMANTICS
+ #endif
+-/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
+-#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+-# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+-#endif
+-/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
+-#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
+-# undef __STDC_WANT_IEC_60559_BFP_EXT__
+-#endif
+-/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
+-#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
+-# undef __STDC_WANT_IEC_60559_DFP_EXT__
+-#endif
+-/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
+-#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
+-# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
+-#endif
+-/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
+-#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
+-# undef __STDC_WANT_IEC_60559_TYPES_EXT__
+-#endif
+-/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
+-#ifndef __STDC_WANT_LIB_EXT2__
+-# undef __STDC_WANT_LIB_EXT2__
+-#endif
+-/* Enable extensions specified by ISO/IEC 24747:2009.  */
+-#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
+-# undef __STDC_WANT_MATH_SPEC_FUNCS__
+-#endif
+ /* Enable extensions on HP NonStop.  */
+ #ifndef _TANDEM_SOURCE
+ # undef _TANDEM_SOURCE
+ #endif
+-/* Enable X/Open extensions.  Define to 500 only if necessary
+-   to make mbstate_t available.  */
+-#ifndef _XOPEN_SOURCE
+-# undef _XOPEN_SOURCE
++/* Enable general extensions on Solaris.  */
++#ifndef __EXTENSIONS__
++# undef __EXTENSIONS__
+ #endif
+ 
+ 
+ /* Version number of package */
+ #undef VERSION
+ 
++/* Enable large inode numbers on Mac OS X 10.5.  */
++#ifndef _DARWIN_USE_64_BIT_INODE
++# define _DARWIN_USE_64_BIT_INODE 1
++#endif
++
+ /* Number of bits in a file offset, on hosts where this is settable. */
+ #undef _FILE_OFFSET_BITS
+ 
+ /* Define for large files, on AIX-style hosts. */
+ #undef _LARGE_FILES
+ 
++/* Define to 1 if on MINIX. */
++#undef _MINIX
++
++/* Define to 2 if the system does not provide POSIX.1 features except with
++   this defined. */
++#undef _POSIX_1_SOURCE
++
++/* Define to 1 if you need to in order for `stat' and other things to work. */
++#undef _POSIX_SOURCE
++
+ /* Define for Solaris 2.5.1 so the uint64_t typedef from ,
+    , or  is not used. If the typedef were allowed, the
+    #define below would cause a syntax error. */
+diff --git a/bolt-plugin/configure b/bolt-plugin/configure
+index 63bde9a41..78e7e57c3 100755
+--- a/bolt-plugin/configure
++++ b/bolt-plugin/configure
+@@ -1,10 +1,9 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.71 for bolt plugin for ld 0.1.
++# Generated by GNU Autoconf 2.69 for bolt plugin for ld 0.1.
+ #
+ #
+-# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+-# Inc.
++# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+ #
+ #
+ # This configure script is free software; the Free Software Foundation
+@@ -15,16 +14,14 @@
+ 
+ # Be more Bourne compatible
+ DUALCASE=1; export DUALCASE # for MKS sh
+-as_nop=:
+-if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+-then :
++if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+   emulate sh
+   NULLCMD=:
+   # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+   # is contrary to our usage.  Disable this feature.
+   alias -g '${1+"$@"}'='"$@"'
+   setopt NO_GLOB_SUBST
+-else $as_nop
++else
+   case `(set -o) 2>/dev/null` in #(
+   *posix*) :
+     set -o posix ;; #(
+@@ -34,46 +31,46 @@ esac
+ fi
+ 
+ 
+-
+-# Reset variables that may have inherited troublesome values from
+-# the environment.
+-
+-# IFS needs to be set, to space, tab, and newline, in precisely that order.
+-# (If _AS_PATH_WALK were called with IFS unset, it would have the
+-# side effect of setting IFS to empty, thus disabling word splitting.)
+-# Quoting is to prevent editors from complaining about space-tab.
+ as_nl='
+ '
+ export as_nl
+-IFS=" ""	$as_nl"
+-
+-PS1='$ '
+-PS2='> '
+-PS4='+ '
+-
+-# Ensure predictable behavior from utilities with locale-dependent output.
+-LC_ALL=C
+-export LC_ALL
+-LANGUAGE=C
+-export LANGUAGE
+-
+-# We cannot yet rely on "unset" to work, but we need these variables
+-# to be unset--not just set to an empty or harmless value--now, to
+-# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
+-# also avoids known problems related to "unset" and subshell syntax
+-# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+-for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+-do eval test \${$as_var+y} \
+-  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+-done
+-
+-# Ensure that fds 0, 1, and 2 are open.
+-if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+-if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
++# Printing a long string crashes Solaris 7 /usr/bin/printf.
++as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
++# Prefer a ksh shell builtin over an external printf program on Solaris,
++# but without wasting forks for bash or zsh.
++if test -z "$BASH_VERSION$ZSH_VERSION" \
++    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
++  as_echo='print -r --'
++  as_echo_n='print -rn --'
++elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
++  as_echo='printf %s\n'
++  as_echo_n='printf %s'
++else
++  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
++    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
++    as_echo_n='/usr/ucb/echo -n'
++  else
++    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
++    as_echo_n_body='eval
++      arg=$1;
++      case $arg in #(
++      *"$as_nl"*)
++	expr "X$arg" : "X\\(.*\\)$as_nl";
++	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
++      esac;
++      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
++    '
++    export as_echo_n_body
++    as_echo_n='sh -c $as_echo_n_body as_echo'
++  fi
++  export as_echo_body
++  as_echo='sh -c $as_echo_body as_echo'
++fi
+ 
+ # The user is always right.
+-if ${PATH_SEPARATOR+false} :; then
++if test "${PATH_SEPARATOR+set}" != set; then
+   PATH_SEPARATOR=:
+   (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+     (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+@@ -82,6 +79,13 @@ if ${PATH_SEPARATOR+false} :; then
+ fi
+ 
+ 
++# IFS
++# We need space, tab and new line, in precisely that order.  Quoting is
++# there to prevent editors from complaining about space-tab.
++# (If _AS_PATH_WALK were called with IFS unset, it would disable word
++# splitting by setting IFS to empty value.)
++IFS=" ""	$as_nl"
++
+ # Find who we are.  Look in the path if we contain no directory separator.
+ as_myself=
+ case $0 in #((
+@@ -90,12 +94,8 @@ case $0 in #((
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
++  test -z "$as_dir" && as_dir=.
++    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+   done
+ IFS=$as_save_IFS
+ 
+@@ -107,10 +107,30 @@ if test "x$as_myself" = x; then
+   as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+-  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
++  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+   exit 1
+ fi
+ 
++# Unset variables that we do not need and which cause bugs (e.g. in
++# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
++# suppresses any "Segmentation fault" message there.  '((' could
++# trigger a bug in pdksh 5.2.14.
++for as_var in BASH_ENV ENV MAIL MAILPATH
++do eval test x\${$as_var+set} = xset \
++  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
++done
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# NLS nuisances.
++LC_ALL=C
++export LC_ALL
++LANGUAGE=C
++export LANGUAGE
++
++# CDPATH.
++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+ 
+ # Use a proper internal environment variable to ensure we don't fall
+   # into an infinite loop, continuously re-executing ourselves.
+@@ -132,22 +152,20 @@ esac
+ exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+ # Admittedly, this is quite paranoid, since all the known shells bail
+ # out after a failed `exec'.
+-printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+-exit 255
++$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
++as_fn_exit 255
+   fi
+   # We don't want this to propagate to other subprocesses.
+           { _as_can_reexec=; unset _as_can_reexec;}
+ if test "x$CONFIG_SHELL" = x; then
+-  as_bourne_compatible="as_nop=:
+-if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+-then :
++  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+   emulate sh
+   NULLCMD=:
+   # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+   # is contrary to our usage.  Disable this feature.
+   alias -g '\${1+\"\$@\"}'='\"\$@\"'
+   setopt NO_GLOB_SUBST
+-else \$as_nop
++else
+   case \`(set -o) 2>/dev/null\` in #(
+   *posix*) :
+     set -o posix ;; #(
+@@ -167,20 +185,18 @@ as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+ as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+ as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+ as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+-if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+-then :
++if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+ 
+-else \$as_nop
++else
+   exitcode=1; echo positional parameters were not saved.
+ fi
+ test x\$exitcode = x0 || exit 1
+-blah=\$(echo \$(echo blah))
+-test x\"\$blah\" = xblah || exit 1
+ test -x / || exit 1"
+   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+   test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
++test \$(( 1 + 1 )) = 2 || exit 1
+ 
+   test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+     ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+@@ -188,40 +204,31 @@ test -x / || exit 1"
+     ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+     PATH=/empty FPATH=/empty; export PATH FPATH
+     test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+-      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+-test \$(( 1 + 1 )) = 2 || exit 1"
+-  if (eval "$as_required") 2>/dev/null
+-then :
++      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
++  if (eval "$as_required") 2>/dev/null; then :
+   as_have_required=yes
+-else $as_nop
++else
+   as_have_required=no
+ fi
+-  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+-then :
++  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ 
+-else $as_nop
++else
+   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ as_found=false
+ for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+   as_found=:
+   case $as_dir in #(
+ 	 /*)
+ 	   for as_base in sh bash ksh sh5; do
+ 	     # Try only shells that exist, to save several forks.
+-	     as_shell=$as_dir$as_base
++	     as_shell=$as_dir/$as_base
+ 	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+-		    as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+-then :
++		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+   CONFIG_SHELL=$as_shell as_have_required=yes
+-		   if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+-then :
++		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+   break 2
+ fi
+ fi
+@@ -229,21 +236,14 @@ fi
+        esac
+   as_found=false
+ done
+-IFS=$as_save_IFS
+-if $as_found
+-then :
+-
+-else $as_nop
+-  if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+-	      as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+-then :
++$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
++	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+   CONFIG_SHELL=$SHELL as_have_required=yes
+-fi
+-fi
++fi; }
++IFS=$as_save_IFS
+ 
+ 
+-      if test "x$CONFIG_SHELL" != x
+-then :
++      if test "x$CONFIG_SHELL" != x; then :
+   export CONFIG_SHELL
+              # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+@@ -261,19 +261,18 @@ esac
+ exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+ # Admittedly, this is quite paranoid, since all the known shells bail
+ # out after a failed `exec'.
+-printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
++$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+ exit 255
+ fi
+ 
+-    if test x$as_have_required = xno
+-then :
+-  printf "%s\n" "$0: This script requires a shell more modern than all"
+-  printf "%s\n" "$0: the shells that I found on your system."
+-  if test ${ZSH_VERSION+y} ; then
+-    printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+-    printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
++    if test x$as_have_required = xno; then :
++  $as_echo "$0: This script requires a shell more modern than all"
++  $as_echo "$0: the shells that I found on your system."
++  if test x${ZSH_VERSION+set} = xset ; then
++    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
++    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+   else
+-    printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
++    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ $0: including any error possibly output before this
+ $0: message. Then install a modern shell, or manually run
+ $0: the script under such a shell if you do have one."
+@@ -300,7 +299,6 @@ as_fn_unset ()
+ }
+ as_unset=as_fn_unset
+ 
+-
+ # as_fn_set_status STATUS
+ # -----------------------
+ # Set $? to STATUS, without forking.
+@@ -318,14 +316,6 @@ as_fn_exit ()
+   as_fn_set_status $1
+   exit $1
+ } # as_fn_exit
+-# as_fn_nop
+-# ---------
+-# Do nothing but, unlike ":", preserve the value of $?.
+-as_fn_nop ()
+-{
+-  return $?
+-}
+-as_nop=as_fn_nop
+ 
+ # as_fn_mkdir_p
+ # -------------
+@@ -340,7 +330,7 @@ as_fn_mkdir_p ()
+     as_dirs=
+     while :; do
+       case $as_dir in #(
+-      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
++      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+       *) as_qdir=$as_dir;;
+       esac
+       as_dirs="'$as_qdir' $as_dirs"
+@@ -349,7 +339,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ 	 X"$as_dir" : 'X\(//\)[^/]' \| \
+ 	 X"$as_dir" : 'X\(//\)$' \| \
+ 	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X"$as_dir" |
++$as_echo X"$as_dir" |
+     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -388,13 +378,12 @@ as_fn_executable_p ()
+ # advantage of any shell optimizations that allow amortized linear growth over
+ # repeated appends, instead of the typical quadratic growth present in naive
+ # implementations.
+-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+-then :
++if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+   eval 'as_fn_append ()
+   {
+     eval $1+=\$2
+   }'
+-else $as_nop
++else
+   as_fn_append ()
+   {
+     eval $1=\$$1\$2
+@@ -406,27 +395,18 @@ fi # as_fn_append
+ # Perform arithmetic evaluation on the ARGs, and store the result in the
+ # global $as_val. Take advantage of shells that can avoid forks. The arguments
+ # must be portable across $(()) and expr.
+-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+-then :
++if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+   eval 'as_fn_arith ()
+   {
+     as_val=$(( $* ))
+   }'
+-else $as_nop
++else
+   as_fn_arith ()
+   {
+     as_val=`expr "$@" || test $? -eq 1`
+   }
+ fi # as_fn_arith
+ 
+-# as_fn_nop
+-# ---------
+-# Do nothing but, unlike ":", preserve the value of $?.
+-as_fn_nop ()
+-{
+-  return $?
+-}
+-as_nop=as_fn_nop
+ 
+ # as_fn_error STATUS ERROR [LINENO LOG_FD]
+ # ----------------------------------------
+@@ -438,9 +418,9 @@ as_fn_error ()
+   as_status=$1; test $as_status -eq 0 && as_status=1
+   if test "$4"; then
+     as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
++    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+   fi
+-  printf "%s\n" "$as_me: error: $2" >&2
++  $as_echo "$as_me: error: $2" >&2
+   as_fn_exit $as_status
+ } # as_fn_error
+ 
+@@ -467,7 +447,7 @@ as_me=`$as_basename -- "$0" ||
+ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ 	 X"$0" : 'X\(//\)$' \| \
+ 	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X/"$0" |
++$as_echo X/"$0" |
+     sed '/^.*\/\([^/][^/]*\)\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -511,7 +491,7 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
+       s/-\n.*//
+     ' >$as_me.lineno &&
+   chmod +x "$as_me.lineno" ||
+-    { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
++    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ 
+   # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+   # already done that, so ensure we don't try to do so again and fall
+@@ -525,10 +505,6 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
+   exit
+ }
+ 
+-
+-# Determine whether it's possible to make 'echo' print without a newline.
+-# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+-# for compatibility with existing Makefiles.
+ ECHO_C= ECHO_N= ECHO_T=
+ case `echo -n x` in #(((((
+ -n*)
+@@ -542,13 +518,6 @@ case `echo -n x` in #(((((
+   ECHO_N='-n';;
+ esac
+ 
+-# For backward compatibility with old third-party macros, we provide
+-# the shell variables $as_echo and $as_echo_n.  New code should use
+-# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+-as_echo='printf %s\n'
+-as_echo_n='printf %s'
+-
+-
+ rm -f conf$$ conf$$.exe conf$$.file
+ if test -d conf$$.dir; then
+   rm -f conf$$.dir/conf$$.file
+@@ -625,75 +594,78 @@ PACKAGE_URL=''
+ 
+ # Factoring default headers for most tests.
+ ac_includes_default="\
+-#include 
+-#ifdef HAVE_STDIO_H
+-# include 
++#include 
++#ifdef HAVE_SYS_TYPES_H
++# include 
+ #endif
+-#ifdef HAVE_STDLIB_H
++#ifdef HAVE_SYS_STAT_H
++# include 
++#endif
++#ifdef STDC_HEADERS
+ # include 
++# include 
++#else
++# ifdef HAVE_STDLIB_H
++#  include 
++# endif
+ #endif
+ #ifdef HAVE_STRING_H
++# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
++#  include 
++# endif
+ # include 
+ #endif
++#ifdef HAVE_STRINGS_H
++# include 
++#endif
+ #ifdef HAVE_INTTYPES_H
+ # include 
+ #endif
+ #ifdef HAVE_STDINT_H
+ # include 
+ #endif
+-#ifdef HAVE_STRINGS_H
+-# include 
+-#endif
+-#ifdef HAVE_SYS_TYPES_H
+-# include 
+-#endif
+-#ifdef HAVE_SYS_STAT_H
+-# include 
+-#endif
+ #ifdef HAVE_UNISTD_H
+ # include 
+ #endif"
+ 
+-ac_header_c_list=
+ ac_subst_vars='am__EXEEXT_FALSE
+ am__EXEEXT_TRUE
+ LTLIBOBJS
+ LIBOBJS
+ target_noncanonical
++lt_host_flags
+ CXXCPP
+-LT_SYS_LIBRARY_PATH
+ OTOOL64
+ OTOOL
+ LIPO
+ NMEDIT
+ DSYMUTIL
+-MANIFEST_TOOL
+ RANLIB
+-ac_ct_AR
+ AR
+-DLLTOOL
+ OBJDUMP
+-FILECMD
+ LN_S
+ NM
+ ac_ct_DUMPBIN
+ DUMPBIN
+ LD
+ FGREP
+-EGREP
+-GREP
+ SED
+ LIBTOOL
++get_gcc_base_ver
+ real_target_noncanonical
+ accel_dir_suffix
+ gcc_build_dir
+ ac_bolt_plugin_ldflags
++ac_bolt_plugin_warn_cflags
+ am__fastdepCXX_FALSE
+ am__fastdepCXX_TRUE
+ CXXDEPMODE
+ ac_ct_CXX
+ CXXFLAGS
+ CXX
++EGREP
++GREP
++CPP
+ am__fastdepCC_FALSE
+ am__fastdepCC_TRUE
+ CCDEPMODE
+@@ -718,9 +690,6 @@ AM_BACKSLASH
+ AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V
+ AM_V
+-CSCOPE
+-ETAGS
+-CTAGS
+ am__untar
+ am__tar
+ AMTAR
+@@ -744,6 +713,10 @@ am__isrc
+ INSTALL_DATA
+ INSTALL_SCRIPT
+ INSTALL_PROGRAM
++target_subdir
++host_subdir
++build_subdir
++build_libsubdir
+ target_os
+ target_vendor
+ target_cpu
+@@ -775,7 +748,6 @@ infodir
+ docdir
+ oldincludedir
+ includedir
+-runstatedir
+ localstatedir
+ sharedstatedir
+ sysconfdir
+@@ -799,18 +771,18 @@ am__quote'
+ ac_subst_files=''
+ ac_user_opts='
+ enable_option_checking
++with_build_libsubdir
+ enable_silent_rules
+ enable_maintainer_mode
+ with_libiberty
+ enable_dependency_tracking
+ enable_largefile
++with_gcc_major_version_only
+ enable_shared
+ enable_static
+ with_pic
+ enable_fast_install
+-with_aix_soname
+ with_gnu_ld
+-with_sysroot
+ enable_libtool_lock
+ '
+       ac_precious_vars='build_alias
+@@ -821,10 +793,10 @@ CFLAGS
+ LDFLAGS
+ LIBS
+ CPPFLAGS
++CPP
+ CXX
+ CXXFLAGS
+ CCC
+-LT_SYS_LIBRARY_PATH
+ CXXCPP'
+ 
+ 
+@@ -864,7 +836,6 @@ datadir='${datarootdir}'
+ sysconfdir='${prefix}/etc'
+ sharedstatedir='${prefix}/com'
+ localstatedir='${prefix}/var'
+-runstatedir='${localstatedir}/run'
+ includedir='${prefix}/include'
+ oldincludedir='/usr/include'
+ docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+@@ -894,6 +865,8 @@ do
+   *)    ac_optarg=yes ;;
+   esac
+ 
++  # Accept the important Cygnus configure options, so we can diagnose typos.
++
+   case $ac_dashdash$ac_option in
+   --)
+     ac_dashdash=yes ;;
+@@ -934,9 +907,9 @@ do
+     ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+-      as_fn_error $? "invalid feature name: \`$ac_useropt'"
++      as_fn_error $? "invalid feature name: $ac_useropt"
+     ac_useropt_orig=$ac_useropt
+-    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+     case $ac_user_opts in
+       *"
+ "enable_$ac_useropt"
+@@ -960,9 +933,9 @@ do
+     ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+-      as_fn_error $? "invalid feature name: \`$ac_useropt'"
++      as_fn_error $? "invalid feature name: $ac_useropt"
+     ac_useropt_orig=$ac_useropt
+-    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+     case $ac_user_opts in
+       *"
+ "enable_$ac_useropt"
+@@ -1115,15 +1088,6 @@ do
+   | -silent | --silent | --silen | --sile | --sil)
+     silent=yes ;;
+ 
+-  -runstatedir | --runstatedir | --runstatedi | --runstated \
+-  | --runstate | --runstat | --runsta | --runst | --runs \
+-  | --run | --ru | --r)
+-    ac_prev=runstatedir ;;
+-  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+-  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+-  | --run=* | --ru=* | --r=*)
+-    runstatedir=$ac_optarg ;;
+-
+   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+     ac_prev=sbindir ;;
+   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+@@ -1173,9 +1137,9 @@ do
+     ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+-      as_fn_error $? "invalid package name: \`$ac_useropt'"
++      as_fn_error $? "invalid package name: $ac_useropt"
+     ac_useropt_orig=$ac_useropt
+-    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+     case $ac_user_opts in
+       *"
+ "with_$ac_useropt"
+@@ -1189,9 +1153,9 @@ do
+     ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+     # Reject names that are not valid shell variable names.
+     expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+-      as_fn_error $? "invalid package name: \`$ac_useropt'"
++      as_fn_error $? "invalid package name: $ac_useropt"
+     ac_useropt_orig=$ac_useropt
+-    ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
++    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+     case $ac_user_opts in
+       *"
+ "with_$ac_useropt"
+@@ -1235,9 +1199,9 @@ Try \`$0 --help' for more information"
+ 
+   *)
+     # FIXME: should be removed in autoconf 3.0.
+-    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
++    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+     expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+-      printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
++      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+     : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+     ;;
+ 
+@@ -1253,7 +1217,7 @@ if test -n "$ac_unrecognized_opts"; then
+   case $enable_option_checking in
+     no) ;;
+     fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+-    *)     printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
++    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+   esac
+ fi
+ 
+@@ -1261,7 +1225,7 @@ fi
+ for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ 		datadir sysconfdir sharedstatedir localstatedir includedir \
+ 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+-		libdir localedir mandir runstatedir
++		libdir localedir mandir
+ do
+   eval ac_val=\$$ac_var
+   # Remove trailing slashes.
+@@ -1317,7 +1281,7 @@ $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ 	 X"$as_myself" : 'X\(//\)[^/]' \| \
+ 	 X"$as_myself" : 'X\(//\)$' \| \
+ 	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X"$as_myself" |
++$as_echo X"$as_myself" |
+     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -1414,7 +1378,6 @@ Fine tuning of the installation directories:
+   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
+   --libdir=DIR            object code libraries [EPREFIX/lib]
+   --includedir=DIR        C header files [PREFIX/include]
+   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+@@ -1473,16 +1436,14 @@ Optional Features:
+ Optional Packages:
+   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
++  --with-build-libsubdir=DIR  Directory where to find libraries for build system
+   --with-libiberty=PATH   specify the directory where to find libiberty
+                           [../libiberty]
+-  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
++  --with-gcc-major-version-only
++                          use only GCC major number in filesystem paths
++  --with-pic              try to use only PIC/non-PIC objects [default=use
+                           both]
+-  --with-aix-soname=aix|svr4|both
+-                          shared library versioning (aka "SONAME") variant to
+-                          provide on AIX, [default=aix].
+   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+-  --with-sysroot[=DIR]    Search for dependent libraries within DIR (or the
+-                          compiler's sysroot if not specified).
+ 
+ Some influential environment variables:
+   CC          C compiler command
+@@ -1492,10 +1453,9 @@ Some influential environment variables:
+   LIBS        libraries to pass to the linker, e.g. -l
+   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I if
+               you have headers in a nonstandard directory 
++  CPP         C preprocessor
+   CXX         C++ compiler command
+   CXXFLAGS    C++ compiler flags
+-  LT_SYS_LIBRARY_PATH
+-              User-defined run-time library search path.
+   CXXCPP      C++ preprocessor
+ 
+ Use these variables to override the choices made by `configure' or to help
+@@ -1517,9 +1477,9 @@ if test "$ac_init_help" = "recursive"; then
+ case "$ac_dir" in
+ .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *)
+-  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
++  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+   # A ".." for each directory in $ac_dir_suffix.
+-  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
++  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+   case $ac_top_builddir_sub in
+   "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+   *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+@@ -1547,8 +1507,7 @@ esac
+ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+ 
+     cd "$ac_dir" || { ac_status=$?; continue; }
+-    # Check for configure.gnu first; this name is used for a wrapper for
+-    # Metaconfig's "Configure" on case-insensitive file systems.
++    # Check for guested configure.
+     if test -f "$ac_srcdir/configure.gnu"; then
+       echo &&
+       $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+@@ -1556,7 +1515,7 @@ ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+       echo &&
+       $SHELL "$ac_srcdir/configure" --help=recursive
+     else
+-      printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
++      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+     fi || ac_status=$?
+     cd "$ac_pwd" || { ac_status=$?; break; }
+   done
+@@ -1566,9 +1525,9 @@ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+ bolt plugin for ld configure 0.1
+-generated by GNU Autoconf 2.71
++generated by GNU Autoconf 2.69
+ 
+-Copyright (C) 2021 Free Software Foundation, Inc.
++Copyright (C) 2012 Free Software Foundation, Inc.
+ This configure script is free software; the Free Software Foundation
+ gives unlimited permission to copy, distribute and modify it.
+ _ACEOF
+@@ -1585,14 +1544,14 @@ fi
+ ac_fn_c_try_compile ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  rm -f conftest.$ac_objext conftest.beam
++  rm -f conftest.$ac_objext
+   if { { ac_try="$ac_compile"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_compile") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -1600,15 +1559,14 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+     mv -f conftest.er1 conftest.err
+   fi
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } && {
+ 	 test -z "$ac_c_werror_flag" ||
+ 	 test ! -s conftest.err
+-       } && test -s conftest.$ac_objext
+-then :
++       } && test -s conftest.$ac_objext; then :
+   ac_retval=0
+-else $as_nop
+-  printf "%s\n" "$as_me: failed program was:" >&5
++else
++  $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+ 	ac_retval=1
+@@ -1618,6 +1576,172 @@ fi
+ 
+ } # ac_fn_c_try_compile
+ 
++# ac_fn_c_try_cpp LINENO
++# ----------------------
++# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
++ac_fn_c_try_cpp ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  if { { ac_try="$ac_cpp conftest.$ac_ext"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++$as_echo "$ac_try_echo"; } >&5
++  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
++  ac_status=$?
++  if test -s conftest.err; then
++    grep -v '^ *+' conftest.err >conftest.er1
++    cat conftest.er1 >&5
++    mv -f conftest.er1 conftest.err
++  fi
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } > conftest.i && {
++	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
++	 test ! -s conftest.err
++       }; then :
++  ac_retval=0
++else
++  $as_echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++    ac_retval=1
++fi
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_c_try_cpp
++
++# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
++# -------------------------------------------------------
++# Tests whether HEADER exists, giving a warning if it cannot be compiled using
++# the include files in INCLUDES and setting the cache variable VAR
++# accordingly.
++ac_fn_c_check_header_mongrel ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  if eval \${$3+:} false; then :
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if eval \${$3+:} false; then :
++  $as_echo_n "(cached) " >&6
++fi
++eval ac_res=\$$3
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
++else
++  # Is the header compilable?
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
++$as_echo_n "checking $2 usability... " >&6; }
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++$4
++#include <$2>
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_header_compiler=yes
++else
++  ac_header_compiler=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
++$as_echo "$ac_header_compiler" >&6; }
++
++# Is the header present?
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
++$as_echo_n "checking $2 presence... " >&6; }
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include <$2>
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++  ac_header_preproc=yes
++else
++  ac_header_preproc=no
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
++$as_echo "$ac_header_preproc" >&6; }
++
++# So?  What about this header?
++case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
++  yes:no: )
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
++$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
++$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
++    ;;
++  no:yes:* )
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
++$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
++$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
++$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
++$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
++$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
++    ;;
++esac
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if eval \${$3+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  eval "$3=\$ac_header_compiler"
++fi
++eval ac_res=\$$3
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
++fi
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++
++} # ac_fn_c_check_header_mongrel
++
++# ac_fn_c_try_run LINENO
++# ----------------------
++# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
++# that executables *can* be run.
++ac_fn_c_try_run ()
++{
++  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
++  if { { ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++$as_echo "$ac_try_echo"; } >&5
++  (eval "$ac_link") 2>&5
++  ac_status=$?
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
++  { { case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
++$as_echo "$ac_try_echo"; } >&5
++  (eval "$ac_try") 2>&5
++  ac_status=$?
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; }; then :
++  ac_retval=0
++else
++  $as_echo "$as_me: program exited with status $ac_status" >&5
++       $as_echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++       ac_retval=$ac_status
++fi
++  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
++  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
++  as_fn_set_status $ac_retval
++
++} # ac_fn_c_try_run
++
+ # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+ # -------------------------------------------------------
+ # Tests whether HEADER exists and can be compiled using the include files in
+@@ -1625,28 +1749,26 @@ fi
+ ac_fn_c_check_header_compile ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+-printf %s "checking for $2... " >&6; }
+-if eval test \${$3+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if eval \${$3+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ $4
+ #include <$2>
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   eval "$3=yes"
+-else $as_nop
++else
+   eval "$3=no"
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ eval ac_res=\$$3
+-	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+-printf "%s\n" "$ac_res" >&6; }
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
+   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ 
+ } # ac_fn_c_check_header_compile
+@@ -1657,14 +1779,14 @@ printf "%s\n" "$ac_res" >&6; }
+ ac_fn_cxx_try_compile ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  rm -f conftest.$ac_objext conftest.beam
++  rm -f conftest.$ac_objext
+   if { { ac_try="$ac_compile"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_compile") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -1672,15 +1794,14 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+     mv -f conftest.er1 conftest.err
+   fi
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } && {
+ 	 test -z "$ac_cxx_werror_flag" ||
+ 	 test ! -s conftest.err
+-       } && test -s conftest.$ac_objext
+-then :
++       } && test -s conftest.$ac_objext; then :
+   ac_retval=0
+-else $as_nop
+-  printf "%s\n" "$as_me: failed program was:" >&5
++else
++  $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+ 	ac_retval=1
+@@ -1696,14 +1817,14 @@ fi
+ ac_fn_c_try_link ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
++  rm -f conftest.$ac_objext conftest$ac_exeext
+   if { { ac_try="$ac_link"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_link") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -1711,18 +1832,17 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+     mv -f conftest.er1 conftest.err
+   fi
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } && {
+ 	 test -z "$ac_c_werror_flag" ||
+ 	 test ! -s conftest.err
+        } && test -s conftest$ac_exeext && {
+ 	 test "$cross_compiling" = yes ||
+ 	 test -x conftest$ac_exeext
+-       }
+-then :
++       }; then :
+   ac_retval=0
+-else $as_nop
+-  printf "%s\n" "$as_me: failed program was:" >&5
++else
++  $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+ 	ac_retval=1
+@@ -1743,12 +1863,11 @@ fi
+ ac_fn_c_check_func ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+-printf %s "checking for $2... " >&6; }
+-if eval test \${$3+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
++$as_echo_n "checking for $2... " >&6; }
++if eval \${$3+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ /* Define $2 to an innocuous variant, in case  declares $2.
+@@ -1756,9 +1875,16 @@ else $as_nop
+ #define $2 innocuous_$2
+ 
+ /* System header to define __stub macros and hopefully few prototypes,
+-   which can conflict with char $2 (); below.  */
++    which can conflict with char $2 (); below.
++    Prefer  to  if __STDC__ is defined, since
++     exists even on freestanding compilers.  */
++
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
+ 
+-#include 
+ #undef $2
+ 
+ /* Override any GCC internal prototype to avoid an error.
+@@ -1776,25 +1902,24 @@ choke me
+ #endif
+ 
+ int
+-main (void)
++main ()
+ {
+ return $2 ();
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   eval "$3=yes"
+-else $as_nop
++else
+   eval "$3=no"
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ fi
+ eval ac_res=\$$3
+-	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+-printf "%s\n" "$ac_res" >&6; }
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
+   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ 
+ } # ac_fn_c_check_func
+@@ -1811,7 +1936,7 @@ case "(($ac_try" in
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -1819,15 +1944,14 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+     mv -f conftest.er1 conftest.err
+   fi
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } > conftest.i && {
+ 	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ 	 test ! -s conftest.err
+-       }
+-then :
++       }; then :
+   ac_retval=0
+-else $as_nop
+-  printf "%s\n" "$as_me: failed program was:" >&5
++else
++  $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+     ac_retval=1
+@@ -1843,14 +1967,14 @@ fi
+ ac_fn_cxx_try_link ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
++  rm -f conftest.$ac_objext conftest$ac_exeext
+   if { { ac_try="$ac_link"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_link") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -1858,18 +1982,17 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+     mv -f conftest.er1 conftest.err
+   fi
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } && {
+ 	 test -z "$ac_cxx_werror_flag" ||
+ 	 test ! -s conftest.err
+        } && test -s conftest$ac_exeext && {
+ 	 test "$cross_compiling" = yes ||
+ 	 test -x conftest$ac_exeext
+-       }
+-then :
++       }; then :
+   ac_retval=0
+-else $as_nop
+-  printf "%s\n" "$as_me: failed program was:" >&5
++else
++  $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+ 	ac_retval=1
+@@ -1891,12 +2014,11 @@ fi
+ ac_fn_c_find_intX_t ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
+-printf %s "checking for int$2_t... " >&6; }
+-if eval test \${$3+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
++$as_echo_n "checking for int$2_t... " >&6; }
++if eval \${$3+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   eval "$3=no"
+      # Order is important - never check a type that is potentially smaller
+      # than half of the expected target width.
+@@ -1907,7 +2029,7 @@ else $as_nop
+ $ac_includes_default
+ 	     enum { N = $2 / 2 - 1 };
+ int
+-main (void)
++main ()
+ {
+ static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
+ test_array [0] = 0;
+@@ -1917,14 +2039,13 @@ return test_array [0];
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ $ac_includes_default
+ 	        enum { N = $2 / 2 - 1 };
+ int
+-main (void)
++main ()
+ {
+ static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+ 		 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
+@@ -1935,10 +2056,9 @@ return test_array [0];
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+ 
+-else $as_nop
++else
+   case $ac_type in #(
+   int$2_t) :
+     eval "$3=yes" ;; #(
+@@ -1946,20 +2066,19 @@ else $as_nop
+     eval "$3=\$ac_type" ;;
+ esac
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+-       if eval test \"x\$"$3"\" = x"no"
+-then :
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++       if eval test \"x\$"$3"\" = x"no"; then :
+ 
+-else $as_nop
++else
+   break
+ fi
+      done
+ fi
+ eval ac_res=\$$3
+-	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+-printf "%s\n" "$ac_res" >&6; }
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
+   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ 
+ } # ac_fn_c_find_intX_t
+@@ -1971,12 +2090,11 @@ printf "%s\n" "$ac_res" >&6; }
+ ac_fn_c_find_uintX_t ()
+ {
+   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+-printf %s "checking for uint$2_t... " >&6; }
+-if eval test \${$3+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
++$as_echo_n "checking for uint$2_t... " >&6; }
++if eval \${$3+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   eval "$3=no"
+      # Order is important - never check a type that is potentially smaller
+      # than half of the expected target width.
+@@ -1986,7 +2104,7 @@ else $as_nop
+ /* end confdefs.h.  */
+ $ac_includes_default
+ int
+-main (void)
++main ()
+ {
+ static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
+ test_array [0] = 0;
+@@ -1996,8 +2114,7 @@ return test_array [0];
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   case $ac_type in #(
+   uint$2_t) :
+     eval "$3=yes" ;; #(
+@@ -2005,49 +2122,28 @@ then :
+     eval "$3=\$ac_type" ;;
+ esac
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+-       if eval test \"x\$"$3"\" = x"no"
+-then :
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++       if eval test \"x\$"$3"\" = x"no"; then :
+ 
+-else $as_nop
++else
+   break
+ fi
+      done
+ fi
+ eval ac_res=\$$3
+-	       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+-printf "%s\n" "$ac_res" >&6; }
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
+   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ 
+ } # ac_fn_c_find_uintX_t
+-ac_configure_args_raw=
+-for ac_arg
+-do
+-  case $ac_arg in
+-  *\'*)
+-    ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+-  esac
+-  as_fn_append ac_configure_args_raw " '$ac_arg'"
+-done
+-
+-case $ac_configure_args_raw in
+-  *$as_nl*)
+-    ac_safe_unquote= ;;
+-  *)
+-    ac_unsafe_z='|&;<>()$`\\"*?[ ''	' # This string ends in space, tab.
+-    ac_unsafe_a="$ac_unsafe_z#~"
+-    ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+-    ac_configure_args_raw=`      printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+-esac
+-
+ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+ It was created by bolt plugin for ld $as_me 0.1, which was
+-generated by GNU Autoconf 2.71.  Invocation command line was
++generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+-  $ $0$ac_configure_args_raw
++  $ $0 $@
+ 
+ _ACEOF
+ exec 5>>config.log
+@@ -2080,12 +2176,8 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    printf "%s\n" "PATH: $as_dir"
++  test -z "$as_dir" && as_dir=.
++    $as_echo "PATH: $as_dir"
+   done
+ IFS=$as_save_IFS
+ 
+@@ -2120,7 +2212,7 @@ do
+     | -silent | --silent | --silen | --sile | --sil)
+       continue ;;
+     *\'*)
+-      ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
++      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+     esac
+     case $ac_pass in
+     1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+@@ -2155,13 +2247,11 @@ done
+ # WARNING: Use '\'' to represent an apostrophe within the trap.
+ # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+ trap 'exit_status=$?
+-  # Sanitize IFS.
+-  IFS=" ""	$as_nl"
+   # Save into config.log some information that might help in debugging.
+   {
+     echo
+ 
+-    printf "%s\n" "## ---------------- ##
++    $as_echo "## ---------------- ##
+ ## Cache variables. ##
+ ## ---------------- ##"
+     echo
+@@ -2172,8 +2262,8 @@ trap 'exit_status=$?
+     case $ac_val in #(
+     *${as_nl}*)
+       case $ac_var in #(
+-      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+-printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
++      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
++$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+       esac
+       case $ac_var in #(
+       _ | IFS | as_nl) ;; #(
+@@ -2197,7 +2287,7 @@ printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;}
+ )
+     echo
+ 
+-    printf "%s\n" "## ----------------- ##
++    $as_echo "## ----------------- ##
+ ## Output variables. ##
+ ## ----------------- ##"
+     echo
+@@ -2205,14 +2295,14 @@ printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;}
+     do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+-      *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
++      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+-      printf "%s\n" "$ac_var='\''$ac_val'\''"
++      $as_echo "$ac_var='\''$ac_val'\''"
+     done | sort
+     echo
+ 
+     if test -n "$ac_subst_files"; then
+-      printf "%s\n" "## ------------------- ##
++      $as_echo "## ------------------- ##
+ ## File substitutions. ##
+ ## ------------------- ##"
+       echo
+@@ -2220,15 +2310,15 @@ printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;}
+       do
+ 	eval ac_val=\$$ac_var
+ 	case $ac_val in
+-	*\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
++	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ 	esac
+-	printf "%s\n" "$ac_var='\''$ac_val'\''"
++	$as_echo "$ac_var='\''$ac_val'\''"
+       done | sort
+       echo
+     fi
+ 
+     if test -s confdefs.h; then
+-      printf "%s\n" "## ----------- ##
++      $as_echo "## ----------- ##
+ ## confdefs.h. ##
+ ## ----------- ##"
+       echo
+@@ -2236,8 +2326,8 @@ printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;}
+       echo
+     fi
+     test "$ac_signal" != 0 &&
+-      printf "%s\n" "$as_me: caught signal $ac_signal"
+-    printf "%s\n" "$as_me: exit $exit_status"
++      $as_echo "$as_me: caught signal $ac_signal"
++    $as_echo "$as_me: exit $exit_status"
+   } >&5
+   rm -f core *.core core.conftest.* &&
+     rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+@@ -2251,48 +2341,63 @@ ac_signal=0
+ # confdefs.h avoids OS command line length limits that DEFS can exceed.
+ rm -f -r conftest* confdefs.h
+ 
+-printf "%s\n" "/* confdefs.h */" > confdefs.h
++$as_echo "/* confdefs.h */" > confdefs.h
+ 
+ # Predefined preprocessor variables.
+ 
+-printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_NAME "$PACKAGE_NAME"
++_ACEOF
+ 
+-printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
++_ACEOF
+ 
+-printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_VERSION "$PACKAGE_VERSION"
++_ACEOF
+ 
+-printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_STRING "$PACKAGE_STRING"
++_ACEOF
+ 
+-printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
++_ACEOF
+ 
+-printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE_URL "$PACKAGE_URL"
++_ACEOF
+ 
+ 
+ # Let the site file select an alternate cache file if it wants to.
+ # Prefer an explicitly selected file to automatically selected ones.
++ac_site_file1=NONE
++ac_site_file2=NONE
+ if test -n "$CONFIG_SITE"; then
+-  ac_site_files="$CONFIG_SITE"
++  # We do not want a PATH search for config.site.
++  case $CONFIG_SITE in #((
++    -*)  ac_site_file1=./$CONFIG_SITE;;
++    */*) ac_site_file1=$CONFIG_SITE;;
++    *)   ac_site_file1=./$CONFIG_SITE;;
++  esac
+ elif test "x$prefix" != xNONE; then
+-  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
++  ac_site_file1=$prefix/share/config.site
++  ac_site_file2=$prefix/etc/config.site
+ else
+-  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
++  ac_site_file1=$ac_default_prefix/share/config.site
++  ac_site_file2=$ac_default_prefix/etc/config.site
+ fi
+-
+-for ac_site_file in $ac_site_files
++for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+ do
+-  case $ac_site_file in #(
+-  */*) :
+-     ;; #(
+-  *) :
+-    ac_site_file=./$ac_site_file ;;
+-esac
+-  if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+-printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
++  test "x$ac_site_file" = xNONE && continue
++  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
++    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
++$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+     sed 's/^/| /' "$ac_site_file" >&5
+     . "$ac_site_file" \
+-      || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "failed to load site script $ac_site_file
+ See \`config.log' for more details" "$LINENO" 5; }
+   fi
+@@ -2302,745 +2407,139 @@ if test -r "$cache_file"; then
+   # Some versions of bash will fail to source /dev/null (special files
+   # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+   if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+-printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
++$as_echo "$as_me: loading cache $cache_file" >&6;}
+     case $cache_file in
+       [\\/]* | ?:[\\/]* ) . "$cache_file";;
+       *)                      . "./$cache_file";;
+     esac
+   fi
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+-printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
++$as_echo "$as_me: creating cache $cache_file" >&6;}
+   >$cache_file
+ fi
+ 
+-as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+-# Test code for whether the C compiler supports C89 (global declarations)
+-ac_c_conftest_c89_globals='
+-/* Does the compiler advertise C89 conformance?
+-   Do not test the value of __STDC__, because some compilers set it to 0
+-   while being otherwise adequately conformant. */
+-#if !defined __STDC__
+-# error "Compiler does not advertise C89 conformance"
+-#endif
++# Check that the precious variables saved in the cache have kept the same
++# value.
++ac_cache_corrupted=false
++for ac_var in $ac_precious_vars; do
++  eval ac_old_set=\$ac_cv_env_${ac_var}_set
++  eval ac_new_set=\$ac_env_${ac_var}_set
++  eval ac_old_val=\$ac_cv_env_${ac_var}_value
++  eval ac_new_val=\$ac_env_${ac_var}_value
++  case $ac_old_set,$ac_new_set in
++    set,)
++      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
++$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
++      ac_cache_corrupted=: ;;
++    ,set)
++      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
++$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
++      ac_cache_corrupted=: ;;
++    ,);;
++    *)
++      if test "x$ac_old_val" != "x$ac_new_val"; then
++	# differences in whitespace do not lead to failure.
++	ac_old_val_w=`echo x $ac_old_val`
++	ac_new_val_w=`echo x $ac_new_val`
++	if test "$ac_old_val_w" != "$ac_new_val_w"; then
++	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
++$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
++	  ac_cache_corrupted=:
++	else
++	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
++$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
++	  eval $ac_var=\$ac_old_val
++	fi
++	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
++$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
++	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
++$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
++      fi;;
++  esac
++  # Pass precious variables to config.status.
++  if test "$ac_new_set" = set; then
++    case $ac_new_val in
++    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
++    *) ac_arg=$ac_var=$ac_new_val ;;
++    esac
++    case " $ac_configure_args " in
++      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
++      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
++    esac
++  fi
++done
++if $ac_cache_corrupted; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
++$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
++  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
++fi
++## -------------------- ##
++## Main body of script. ##
++## -------------------- ##
+ 
+-#include 
+-#include 
+-struct stat;
+-/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */
+-struct buf { int x; };
+-struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+-static char *e (p, i)
+-     char **p;
+-     int i;
+-{
+-  return p[i];
+-}
+-static char *f (char * (*g) (char **, int), char **p, ...)
+-{
+-  char *s;
+-  va_list v;
+-  va_start (v,p);
+-  s = g (p, va_arg (v,int));
+-  va_end (v);
+-  return s;
+-}
+-
+-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+-   function prototypes and stuff, but not \xHH hex character constants.
+-   These do not provoke an error unfortunately, instead are silently treated
+-   as an "x".  The following induces an error, until -std is added to get
+-   proper ANSI mode.  Curiously \x00 != x always comes out true, for an
+-   array size at least.  It is necessary to write \x00 == 0 to get something
+-   that is true only with -std.  */
+-int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+-
+-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+-   inside strings and character constants.  */
+-#define FOO(x) '\''x'\''
+-int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+-
+-int test (int i, double x);
+-struct s1 {int (*f) (int a);};
+-struct s2 {int (*f) (double a);};
+-int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+-               int, int);'
+-
+-# Test code for whether the C compiler supports C89 (body of main).
+-ac_c_conftest_c89_main='
+-ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+-'
+-
+-# Test code for whether the C compiler supports C99 (global declarations)
+-ac_c_conftest_c99_globals='
+-// Does the compiler advertise C99 conformance?
+-#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+-# error "Compiler does not advertise C99 conformance"
+-#endif
+-
+-#include 
+-extern int puts (const char *);
+-extern int printf (const char *, ...);
+-extern int dprintf (int, const char *, ...);
+-extern void *malloc (size_t);
+-
+-// Check varargs macros.  These examples are taken from C99 6.10.3.5.
+-// dprintf is used instead of fprintf to avoid needing to declare
+-// FILE and stderr.
+-#define debug(...) dprintf (2, __VA_ARGS__)
+-#define showlist(...) puts (#__VA_ARGS__)
+-#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+-static void
+-test_varargs_macros (void)
+-{
+-  int x = 1234;
+-  int y = 5678;
+-  debug ("Flag");
+-  debug ("X = %d\n", x);
+-  showlist (The first, second, and third items.);
+-  report (x>y, "x is %d but y is %d", x, y);
+-}
+-
+-// Check long long types.
+-#define BIG64 18446744073709551615ull
+-#define BIG32 4294967295ul
+-#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+-#if !BIG_OK
+-  #error "your preprocessor is broken"
+-#endif
+-#if BIG_OK
+-#else
+-  #error "your preprocessor is broken"
+-#endif
+-static long long int bignum = -9223372036854775807LL;
+-static unsigned long long int ubignum = BIG64;
+-
+-struct incomplete_array
+-{
+-  int datasize;
+-  double data[];
+-};
+-
+-struct named_init {
+-  int number;
+-  const wchar_t *name;
+-  double average;
+-};
+-
+-typedef const char *ccp;
+-
+-static inline int
+-test_restrict (ccp restrict text)
+-{
+-  // See if C++-style comments work.
+-  // Iterate through items via the restricted pointer.
+-  // Also check for declarations in for loops.
+-  for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+-    continue;
+-  return 0;
+-}
+-
+-// Check varargs and va_copy.
+-static bool
+-test_varargs (const char *format, ...)
+-{
+-  va_list args;
+-  va_start (args, format);
+-  va_list args_copy;
+-  va_copy (args_copy, args);
+-
+-  const char *str = "";
+-  int number = 0;
+-  float fnumber = 0;
+-
+-  while (*format)
+-    {
+-      switch (*format++)
+-	{
+-	case '\''s'\'': // string
+-	  str = va_arg (args_copy, const char *);
+-	  break;
+-	case '\''d'\'': // int
+-	  number = va_arg (args_copy, int);
+-	  break;
+-	case '\''f'\'': // float
+-	  fnumber = va_arg (args_copy, double);
+-	  break;
+-	default:
+-	  break;
+-	}
+-    }
+-  va_end (args_copy);
+-  va_end (args);
+-
+-  return *str && number && fnumber;
+-}
+-'
+-
+-# Test code for whether the C compiler supports C99 (body of main).
+-ac_c_conftest_c99_main='
+-  // Check bool.
+-  _Bool success = false;
+-  success |= (argc != 0);
+-
+-  // Check restrict.
+-  if (test_restrict ("String literal") == 0)
+-    success = true;
+-  char *restrict newvar = "Another string";
+-
+-  // Check varargs.
+-  success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+-  test_varargs_macros ();
+-
+-  // Check flexible array members.
+-  struct incomplete_array *ia =
+-    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+-  ia->datasize = 10;
+-  for (int i = 0; i < ia->datasize; ++i)
+-    ia->data[i] = i * 1.234;
+-
+-  // Check named initializers.
+-  struct named_init ni = {
+-    .number = 34,
+-    .name = L"Test wide string",
+-    .average = 543.34343,
+-  };
+-
+-  ni.number = 58;
+-
+-  int dynamic_array[ni.number];
+-  dynamic_array[0] = argv[0][0];
+-  dynamic_array[ni.number - 1] = 543;
+-
+-  // work around unused variable warnings
+-  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+-	 || dynamic_array[ni.number - 1] != 543);
+-'
+-
+-# Test code for whether the C compiler supports C11 (global declarations)
+-ac_c_conftest_c11_globals='
+-// Does the compiler advertise C11 conformance?
+-#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+-# error "Compiler does not advertise C11 conformance"
+-#endif
+-
+-// Check _Alignas.
+-char _Alignas (double) aligned_as_double;
+-char _Alignas (0) no_special_alignment;
+-extern char aligned_as_int;
+-char _Alignas (0) _Alignas (int) aligned_as_int;
+-
+-// Check _Alignof.
+-enum
+-{
+-  int_alignment = _Alignof (int),
+-  int_array_alignment = _Alignof (int[100]),
+-  char_alignment = _Alignof (char)
+-};
+-_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+-
+-// Check _Noreturn.
+-int _Noreturn does_not_return (void) { for (;;) continue; }
+-
+-// Check _Static_assert.
+-struct test_static_assert
+-{
+-  int x;
+-  _Static_assert (sizeof (int) <= sizeof (long int),
+-                  "_Static_assert does not work in struct");
+-  long int y;
+-};
+-
+-// Check UTF-8 literals.
+-#define u8 syntax error!
+-char const utf8_literal[] = u8"happens to be ASCII" "another string";
+-
+-// Check duplicate typedefs.
+-typedef long *long_ptr;
+-typedef long int *long_ptr;
+-typedef long_ptr long_ptr;
+-
+-// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+-struct anonymous
+-{
+-  union {
+-    struct { int i; int j; };
+-    struct { int k; long int l; } w;
+-  };
+-  int m;
+-} v1;
+-'
+-
+-# Test code for whether the C compiler supports C11 (body of main).
+-ac_c_conftest_c11_main='
+-  _Static_assert ((offsetof (struct anonymous, i)
+-		   == offsetof (struct anonymous, w.k)),
+-		  "Anonymous union alignment botch");
+-  v1.i = 2;
+-  v1.w.k = 5;
+-  ok |= v1.i != 5;
+-'
+-
+-# Test code for whether the C compiler supports C11 (complete).
+-ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+-${ac_c_conftest_c99_globals}
+-${ac_c_conftest_c11_globals}
+-
+-int
+-main (int argc, char **argv)
+-{
+-  int ok = 0;
+-  ${ac_c_conftest_c89_main}
+-  ${ac_c_conftest_c99_main}
+-  ${ac_c_conftest_c11_main}
+-  return ok;
+-}
+-"
+-
+-# Test code for whether the C compiler supports C99 (complete).
+-ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+-${ac_c_conftest_c99_globals}
+-
+-int
+-main (int argc, char **argv)
+-{
+-  int ok = 0;
+-  ${ac_c_conftest_c89_main}
+-  ${ac_c_conftest_c99_main}
+-  return ok;
+-}
+-"
+-
+-# Test code for whether the C compiler supports C89 (complete).
+-ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+-
+-int
+-main (int argc, char **argv)
+-{
+-  int ok = 0;
+-  ${ac_c_conftest_c89_main}
+-  return ok;
+-}
+-"
+-
+-as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+-as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+-as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+-as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+-as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+-as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+-as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+-as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+-as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H"
+-as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H"
+-# Test code for whether the C++ compiler supports C++98 (global declarations)
+-ac_cxx_conftest_cxx98_globals='
+-// Does the compiler advertise C++98 conformance?
+-#if !defined __cplusplus || __cplusplus < 199711L
+-# error "Compiler does not advertise C++98 conformance"
+-#endif
+-
+-// These inclusions are to reject old compilers that
+-// lack the unsuffixed header files.
+-#include 
+-#include 
+-
+-//  and  are *not* freestanding headers in C++98.
+-extern void assert (int);
+-namespace std {
+-  extern int strcmp (const char *, const char *);
+-}
+-
+-// Namespaces, exceptions, and templates were all added after "C++ 2.0".
+-using std::exception;
+-using std::strcmp;
+-
+-namespace {
+-
+-void test_exception_syntax()
+-{
+-  try {
+-    throw "test";
+-  } catch (const char *s) {
+-    // Extra parentheses suppress a warning when building autoconf itself,
+-    // due to lint rules shared with more typical C programs.
+-    assert (!(strcmp) (s, "test"));
+-  }
+-}
+-
+-template  struct test_template
+-{
+-  T const val;
+-  explicit test_template(T t) : val(t) {}
+-  template  T add(U u) { return static_cast(u) + val; }
+-};
+-
+-} // anonymous namespace
+-'
+-
+-# Test code for whether the C++ compiler supports C++98 (body of main)
+-ac_cxx_conftest_cxx98_main='
+-  assert (argc);
+-  assert (! argv[0]);
+-{
+-  test_exception_syntax ();
+-  test_template tt (2.0);
+-  assert (tt.add (4) == 6.0);
+-  assert (true && !false);
+-}
+-'
+-
+-# Test code for whether the C++ compiler supports C++11 (global declarations)
+-ac_cxx_conftest_cxx11_globals='
+-// Does the compiler advertise C++ 2011 conformance?
+-#if !defined __cplusplus || __cplusplus < 201103L
+-# error "Compiler does not advertise C++11 conformance"
+-#endif
+-
+-namespace cxx11test
+-{
+-  constexpr int get_val() { return 20; }
+-
+-  struct testinit
+-  {
+-    int i;
+-    double d;
+-  };
+-
+-  class delegate
+-  {
+-  public:
+-    delegate(int n) : n(n) {}
+-    delegate(): delegate(2354) {}
+-
+-    virtual int getval() { return this->n; };
+-  protected:
+-    int n;
+-  };
+-
+-  class overridden : public delegate
+-  {
+-  public:
+-    overridden(int n): delegate(n) {}
+-    virtual int getval() override final { return this->n * 2; }
+-  };
+-
+-  class nocopy
+-  {
+-  public:
+-    nocopy(int i): i(i) {}
+-    nocopy() = default;
+-    nocopy(const nocopy&) = delete;
+-    nocopy & operator=(const nocopy&) = delete;
+-  private:
+-    int i;
+-  };
+-
+-  // for testing lambda expressions
+-  template  Ret eval(Fn f, Ret v)
+-  {
+-    return f(v);
+-  }
+-
+-  // for testing variadic templates and trailing return types
+-  template  auto sum(V first) -> V
+-  {
+-    return first;
+-  }
+-  template  auto sum(V first, Args... rest) -> V
+-  {
+-    return first + sum(rest...);
+-  }
+-}
+-'
+-
+-# Test code for whether the C++ compiler supports C++11 (body of main)
+-ac_cxx_conftest_cxx11_main='
+-{
+-  // Test auto and decltype
+-  auto a1 = 6538;
+-  auto a2 = 48573953.4;
+-  auto a3 = "String literal";
+-
+-  int total = 0;
+-  for (auto i = a3; *i; ++i) { total += *i; }
+-
+-  decltype(a2) a4 = 34895.034;
+-}
+-{
+-  // Test constexpr
+-  short sa[cxx11test::get_val()] = { 0 };
+-}
+-{
+-  // Test initializer lists
+-  cxx11test::testinit il = { 4323, 435234.23544 };
+-}
+-{
+-  // Test range-based for
+-  int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3,
+-                 14, 19, 17, 8, 6, 20, 16, 2, 11, 1};
+-  for (auto &x : array) { x += 23; }
+-}
+-{
+-  // Test lambda expressions
+-  using cxx11test::eval;
+-  assert (eval ([](int x) { return x*2; }, 21) == 42);
+-  double d = 2.0;
+-  assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0);
+-  assert (d == 5.0);
+-  assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0);
+-  assert (d == 5.0);
+-}
+-{
+-  // Test use of variadic templates
+-  using cxx11test::sum;
+-  auto a = sum(1);
+-  auto b = sum(1, 2);
+-  auto c = sum(1.0, 2.0, 3.0);
+-}
+-{
+-  // Test constructor delegation
+-  cxx11test::delegate d1;
+-  cxx11test::delegate d2();
+-  cxx11test::delegate d3(45);
+-}
+-{
+-  // Test override and final
+-  cxx11test::overridden o1(55464);
+-}
+-{
+-  // Test nullptr
+-  char *c = nullptr;
+-}
+-{
+-  // Test template brackets
+-  test_template<::test_template> v(test_template(12));
+-}
+-{
+-  // Unicode literals
+-  char const *utf8 = u8"UTF-8 string \u2500";
+-  char16_t const *utf16 = u"UTF-8 string \u2500";
+-  char32_t const *utf32 = U"UTF-32 string \u2500";
+-}
+-'
+-
+-# Test code for whether the C compiler supports C++11 (complete).
+-ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals}
+-${ac_cxx_conftest_cxx11_globals}
+-
+-int
+-main (int argc, char **argv)
+-{
+-  int ok = 0;
+-  ${ac_cxx_conftest_cxx98_main}
+-  ${ac_cxx_conftest_cxx11_main}
+-  return ok;
+-}
+-"
+-
+-# Test code for whether the C compiler supports C++98 (complete).
+-ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals}
+-int
+-main (int argc, char **argv)
+-{
+-  int ok = 0;
+-  ${ac_cxx_conftest_cxx98_main}
+-  return ok;
+-}
+-"
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+ 
+-# Auxiliary files required by this configure script.
+-ac_aux_files="ltmain.sh compile missing install-sh config.guess config.sub"
+ 
+-# Locations in which to look for auxiliary files.
+-ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
+ 
+-# Search for a directory containing all of the required auxiliary files,
+-# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+-# If we don't find one directory that contains all the files we need,
+-# we report the set of missing files from the *first* directory in
+-# $ac_aux_dir_candidates and give up.
+-ac_missing_aux_files=""
+-ac_first_candidate=:
+-printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-as_found=false
+-for as_dir in $ac_aux_dir_candidates
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-  as_found=:
+ 
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}:  trying $as_dir" >&5
+-  ac_aux_dir_found=yes
+-  ac_install_sh=
+-  for ac_aux in $ac_aux_files
+-  do
+-    # As a special case, if "install-sh" is required, that requirement
+-    # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+-    # and $ac_install_sh is set appropriately for whichever one is found.
+-    if test x"$ac_aux" = x"install-sh"
+-    then
+-      if test -f "${as_dir}install-sh"; then
+-        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install-sh found" >&5
+-        ac_install_sh="${as_dir}install-sh -c"
+-      elif test -f "${as_dir}install.sh"; then
+-        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}install.sh found" >&5
+-        ac_install_sh="${as_dir}install.sh -c"
+-      elif test -f "${as_dir}shtool"; then
+-        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}shtool found" >&5
+-        ac_install_sh="${as_dir}shtool install -c"
+-      else
+-        ac_aux_dir_found=no
+-        if $ac_first_candidate; then
+-          ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+-        else
+-          break
+-        fi
+-      fi
+-    else
+-      if test -f "${as_dir}${ac_aux}"; then
+-        printf "%s\n" "$as_me:${as_lineno-$LINENO}:   ${as_dir}${ac_aux} found" >&5
+-      else
+-        ac_aux_dir_found=no
+-        if $ac_first_candidate; then
+-          ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+-        else
+-          break
+-        fi
+-      fi
+-    fi
+-  done
+-  if test "$ac_aux_dir_found" = yes; then
+-    ac_aux_dir="$as_dir"
++ac_aux_dir=
++for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
++  if test -f "$ac_dir/install-sh"; then
++    ac_aux_dir=$ac_dir
++    ac_install_sh="$ac_aux_dir/install-sh -c"
++    break
++  elif test -f "$ac_dir/install.sh"; then
++    ac_aux_dir=$ac_dir
++    ac_install_sh="$ac_aux_dir/install.sh -c"
++    break
++  elif test -f "$ac_dir/shtool"; then
++    ac_aux_dir=$ac_dir
++    ac_install_sh="$ac_aux_dir/shtool install -c"
+     break
+   fi
+-  ac_first_candidate=false
+-
+-  as_found=false
+ done
+-IFS=$as_save_IFS
+-if $as_found
+-then :
+-
+-else $as_nop
+-  as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
++if test -z "$ac_aux_dir"; then
++  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+ fi
+ 
+-
+ # These three variables are undocumented and unsupported,
+ # and are intended to be withdrawn in a future Autoconf release.
+ # They can cause serious problems if a builder's source tree is in a directory
+ # whose full name contains unusual characters.
+-if test -f "${ac_aux_dir}config.guess"; then
+-  ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+-fi
+-if test -f "${ac_aux_dir}config.sub"; then
+-  ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+-fi
+-if test -f "$ac_aux_dir/configure"; then
+-  ac_configure="$SHELL ${ac_aux_dir}configure"
+-fi
++ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
++ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
++ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+ 
+-# Check that the precious variables saved in the cache have kept the same
+-# value.
+-ac_cache_corrupted=false
+-for ac_var in $ac_precious_vars; do
+-  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+-  eval ac_new_set=\$ac_env_${ac_var}_set
+-  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+-  eval ac_new_val=\$ac_env_${ac_var}_value
+-  case $ac_old_set,$ac_new_set in
+-    set,)
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+-printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+-      ac_cache_corrupted=: ;;
+-    ,set)
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+-printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+-      ac_cache_corrupted=: ;;
+-    ,);;
+-    *)
+-      if test "x$ac_old_val" != "x$ac_new_val"; then
+-	# differences in whitespace do not lead to failure.
+-	ac_old_val_w=`echo x $ac_old_val`
+-	ac_new_val_w=`echo x $ac_new_val`
+-	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+-	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+-printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+-	  ac_cache_corrupted=:
+-	else
+-	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+-printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+-	  eval $ac_var=\$ac_old_val
+-	fi
+-	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+-printf "%s\n" "$as_me:   former value:  \`$ac_old_val'" >&2;}
+-	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+-printf "%s\n" "$as_me:   current value: \`$ac_new_val'" >&2;}
+-      fi;;
+-  esac
+-  # Pass precious variables to config.status.
+-  if test "$ac_new_set" = set; then
+-    case $ac_new_val in
+-    *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+-    *) ac_arg=$ac_var=$ac_new_val ;;
+-    esac
+-    case " $ac_configure_args " in
+-      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+-      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+-    esac
+-  fi
+-done
+-if $ac_cache_corrupted; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+-printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+-  as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+-	    and start over" "$LINENO" 5
+-fi
+-## -------------------- ##
+-## Main body of script. ##
+-## -------------------- ##
+-
+-ac_ext=c
+-ac_cpp='$CPP $CPPFLAGS'
+-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+-ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
++# Make sure we can run config.sub.
++$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
++  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+ 
+-
+-
+-
+-  # Make sure we can run config.sub.
+-$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+-  as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+-printf %s "checking build system type... " >&6; }
+-if test ${ac_cv_build+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
++$as_echo_n "checking build system type... " >&6; }
++if ${ac_cv_build+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_build_alias=$build_alias
+ test "x$ac_build_alias" = x &&
+-  ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
++  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ test "x$ac_build_alias" = x &&
+   as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+-ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+-  as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
++ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
++  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+-printf "%s\n" "$ac_cv_build" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
++$as_echo "$ac_cv_build" >&6; }
+ case $ac_cv_build in
+ *-*-*) ;;
+ *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+@@ -3059,22 +2558,21 @@ IFS=$ac_save_IFS
+ case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+-printf %s "checking host system type... " >&6; }
+-if test ${ac_cv_host+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
++$as_echo_n "checking host system type... " >&6; }
++if ${ac_cv_host+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test "x$host_alias" = x; then
+   ac_cv_host=$ac_cv_build
+ else
+-  ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+-    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
++  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
++    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ fi
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+-printf "%s\n" "$ac_cv_host" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
++$as_echo "$ac_cv_host" >&6; }
+ case $ac_cv_host in
+ *-*-*) ;;
+ *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+@@ -3093,22 +2591,21 @@ IFS=$ac_save_IFS
+ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+-printf %s "checking target system type... " >&6; }
+-if test ${ac_cv_target+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
++$as_echo_n "checking target system type... " >&6; }
++if ${ac_cv_target+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test "x$target_alias" = x; then
+   ac_cv_target=$ac_cv_host
+ else
+-  ac_cv_target=`$SHELL "${ac_aux_dir}config.sub" $target_alias` ||
+-    as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $target_alias failed" "$LINENO" 5
++  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
++    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+ fi
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+-printf "%s\n" "$ac_cv_target" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
++$as_echo "$ac_cv_target" >&6; }
+ case $ac_cv_target in
+ *-*-*) ;;
+ *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+@@ -3133,11 +2630,54 @@ test -n "$target_alias" &&
+   test "$program_prefix$program_suffix$program_transform_name" = \
+     NONENONEs,x,x, &&
+   program_prefix=${target_alias}-
+-GCC_TOPLEV_SUBDIRS
+-am__api_version='1.16'
++ case ${build_alias} in
++  "") build_noncanonical=${build} ;;
++  *) build_noncanonical=${build_alias} ;;
++esac
++
++ case ${host_alias} in
++  "") host_noncanonical=${build_noncanonical} ;;
++  *) host_noncanonical=${host_alias} ;;
++esac
++
++ case ${target_alias} in
++  "") target_noncanonical=${host_noncanonical} ;;
++  *) target_noncanonical=${target_alias} ;;
++esac
++
++
++# post-stage1 host modules use a different CC_FOR_BUILD so, in order to
++# have matching libraries, they should use host libraries: Makefile.tpl
++# arranges to pass --with-build-libsubdir=$(HOST_SUBDIR).
++# However, they still use the build modules, because the corresponding
++# host modules (e.g. bison) are only built for the host when bootstrap
++# finishes. So:
++# - build_subdir is where we find build modules, and never changes.
++# - build_libsubdir is where we find build libraries, and can be overridden.
++
++# Prefix 'build-' so this never conflicts with target_subdir.
++build_subdir="build-${build_noncanonical}"
++
++# Check whether --with-build-libsubdir was given.
++if test "${with_build_libsubdir+set}" = set; then :
++  withval=$with_build_libsubdir; build_libsubdir="$withval"
++else
++  build_libsubdir="$build_subdir"
++fi
++
++# --srcdir=. covers the toplevel, while "test -d" covers the subdirectories
++if ( test $srcdir = . && test -d gcc ) \
++   || test -d $srcdir/../host-${host_noncanonical}; then
++  host_subdir="host-${host_noncanonical}"
++else
++  host_subdir=.
++fi
++# No prefix.
++target_subdir=${target_noncanonical}
+ 
++am__api_version='1.16'
+ 
+-  # Find a good install program.  We prefer a C program (faster),
++# Find a good install program.  We prefer a C program (faster),
+ # so one script is as good as another.  But avoid the broken or
+ # incompatible versions:
+ # SysV /etc/install, /usr/sbin/install
+@@ -3151,25 +2691,20 @@ am__api_version='1.16'
+ # OS/2's system install, which has a completely different semantic
+ # ./install, which can be erroneously created by make from ./install.sh.
+ # Reject install programs that cannot install multiple files.
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+-printf %s "checking for a BSD-compatible install... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
++$as_echo_n "checking for a BSD-compatible install... " >&6; }
+ if test -z "$INSTALL"; then
+-if test ${ac_cv_path_install+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++if ${ac_cv_path_install+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    # Account for fact that we put trailing slashes in our PATH walk.
+-case $as_dir in #((
+-  ./ | /[cC]/* | \
++  test -z "$as_dir" && as_dir=.
++    # Account for people who put trailing slashes in PATH elements.
++case $as_dir/ in #((
++  ./ | .// | /[cC]/* | \
+   /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+   ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+   /usr/ucb/* ) ;;
+@@ -3179,13 +2714,13 @@ case $as_dir in #((
+     # by default.
+     for ac_prog in ginstall scoinst install; do
+       for ac_exec_ext in '' $ac_executable_extensions; do
+-	if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
++	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ 	  if test $ac_prog = install &&
+-	    grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ 	    # AIX install.  It has an incompatible calling convention.
+ 	    :
+ 	  elif test $ac_prog = install &&
+-	    grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
++	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ 	    # program-specific install script used by HP pwplus--don't use.
+ 	    :
+ 	  else
+@@ -3193,12 +2728,12 @@ case $as_dir in #((
+ 	    echo one > conftest.one
+ 	    echo two > conftest.two
+ 	    mkdir conftest.dir
+-	    if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
++	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ 	      test -s conftest.one && test -s conftest.two &&
+ 	      test -s conftest.dir/conftest.one &&
+ 	      test -s conftest.dir/conftest.two
+ 	    then
+-	      ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
++	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ 	      break 3
+ 	    fi
+ 	  fi
+@@ -3214,7 +2749,7 @@ IFS=$as_save_IFS
+ rm -rf conftest.one conftest.two conftest.dir
+ 
+ fi
+-  if test ${ac_cv_path_install+y}; then
++  if test "${ac_cv_path_install+set}" = set; then
+     INSTALL=$ac_cv_path_install
+   else
+     # As a last resort, use the slow shell script.  Don't cache a
+@@ -3224,8 +2759,8 @@ fi
+     INSTALL=$ac_install_sh
+   fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+-printf "%s\n" "$INSTALL" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
++$as_echo "$INSTALL" >&6; }
+ 
+ # Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+ # It thinks the first close brace ends the variable substitution.
+@@ -3235,8 +2770,8 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+ 
+ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+-printf %s "checking whether build environment is sane... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
++$as_echo_n "checking whether build environment is sane... " >&6; }
+ # Reject unsafe characters in $srcdir or the absolute working directory
+ # name.  Accept space and tab only in the latter.
+ am_lf='
+@@ -3290,8 +2825,8 @@ else
+    as_fn_error $? "newly created file is older than distributed files!
+ Check your system clock" "$LINENO" 5
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
+ # If we didn't sleep, we still need to ensure time stamps of config.status and
+ # generated files are strictly newer.
+ am_sleep_pid=
+@@ -3310,23 +2845,26 @@ test "$program_suffix" != NONE &&
+ # Double any \ or $.
+ # By default was `s,x,x', remove it if useless.
+ ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+-program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"`
+-
++program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+ 
+ # Expand $ac_aux_dir to an absolute path.
+ am_aux_dir=`cd "$ac_aux_dir" && pwd`
+ 
+-
+-  if test x"${MISSING+set}" != xset; then
+-  MISSING="\${SHELL} '$am_aux_dir/missing'"
++if test x"${MISSING+set}" != xset; then
++  case $am_aux_dir in
++  *\ * | *\	*)
++    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
++  *)
++    MISSING="\${SHELL} $am_aux_dir/missing" ;;
++  esac
+ fi
+ # Use eval to expand $SHELL
+ if eval "$MISSING --is-lightweight"; then
+   am_missing_run="$MISSING "
+ else
+   am_missing_run=
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+-printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
++$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+ fi
+ 
+ if test x"${install_sh+set}" != xset; then
+@@ -3346,12 +2884,11 @@ if test "$cross_compiling" != no; then
+   if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}strip; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_STRIP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_STRIP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$STRIP"; then
+   ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+ else
+@@ -3359,15 +2896,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -3378,11 +2911,11 @@ fi
+ fi
+ STRIP=$ac_cv_prog_STRIP
+ if test -n "$STRIP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+-printf "%s\n" "$STRIP" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
++$as_echo "$STRIP" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -3391,12 +2924,11 @@ if test -z "$ac_cv_prog_STRIP"; then
+   ac_ct_STRIP=$STRIP
+   # Extract the first word of "strip", so it can be a program name with args.
+ set dummy strip; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_STRIP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_STRIP"; then
+   ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+ else
+@@ -3404,15 +2936,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_STRIP="strip"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -3423,11 +2951,11 @@ fi
+ fi
+ ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+ if test -n "$ac_ct_STRIP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+-printf "%s\n" "$ac_ct_STRIP" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
++$as_echo "$ac_ct_STRIP" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_STRIP" = x; then
+@@ -3435,8 +2963,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     STRIP=$ac_ct_STRIP
+@@ -3448,31 +2976,25 @@ fi
+ fi
+ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+ 
+-
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
+-printf %s "checking for a race-free mkdir -p... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
++$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+ if test -z "$MKDIR_P"; then
+-  if test ${ac_cv_path_mkdir+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  if ${ac_cv_path_mkdir+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_prog in mkdir gmkdir; do
+ 	 for ac_exec_ext in '' $ac_executable_extensions; do
+-	   as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue
+-	   case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #(
+-	     'mkdir ('*'coreutils) '* | \
+-	     'BusyBox '* | \
++	   as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
++	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
++	     'mkdir (GNU coreutils) '* | \
++	     'mkdir (coreutils) '* | \
+ 	     'mkdir (fileutils) '4.1*)
+-	       ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext
++	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ 	       break 3;;
+ 	   esac
+ 	 done
+@@ -3483,7 +3005,7 @@ IFS=$as_save_IFS
+ fi
+ 
+   test -d ./--version && rmdir ./--version
+-  if test ${ac_cv_path_mkdir+y}; then
++  if test "${ac_cv_path_mkdir+set}" = set; then
+     MKDIR_P="$ac_cv_path_mkdir -p"
+   else
+     # As a last resort, use the slow shell script.  Don't cache a
+@@ -3493,19 +3015,18 @@ fi
+     MKDIR_P="$ac_install_sh -d"
+   fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+-printf "%s\n" "$MKDIR_P" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
++$as_echo "$MKDIR_P" >&6; }
+ 
+ for ac_prog in gawk mawk nawk awk
+ do
+   # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_AWK+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_AWK+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$AWK"; then
+   ac_cv_prog_AWK="$AWK" # Let the user override the test.
+ else
+@@ -3513,15 +3034,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_AWK="$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -3532,25 +3049,24 @@ fi
+ fi
+ AWK=$ac_cv_prog_AWK
+ if test -n "$AWK"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+-printf "%s\n" "$AWK" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
++$as_echo "$AWK" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+   test -n "$AWK" && break
+ done
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+-printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
++$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+ set x ${MAKE-make}
+-ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+-if eval test \${ac_cv_prog_make_${ac_make}_set+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
++if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat >conftest.make <<\_ACEOF
+ SHELL = /bin/sh
+ all:
+@@ -3566,12 +3082,12 @@ esac
+ rm -f conftest.make
+ fi
+ if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
+   SET_MAKE=
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+   SET_MAKE="MAKE=${MAKE-make}"
+ fi
+ 
+@@ -3585,8 +3101,7 @@ fi
+ rmdir .tst 2>/dev/null
+ 
+ # Check whether --enable-silent-rules was given.
+-if test ${enable_silent_rules+y}
+-then :
++if test "${enable_silent_rules+set}" = set; then :
+   enableval=$enable_silent_rules;
+ fi
+ 
+@@ -3596,13 +3111,12 @@ case $enable_silent_rules in # (((
+     *) AM_DEFAULT_VERBOSITY=1;;
+ esac
+ am_make=${MAKE-make}
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+-printf %s "checking whether $am_make supports nested variables... " >&6; }
+-if test ${am_cv_make_support_nested_variables+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if printf "%s\n" 'TRUE=$(BAR$(V))
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
++$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
++if ${am_cv_make_support_nested_variables+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  if $as_echo 'TRUE=$(BAR$(V))
+ BAR0=false
+ BAR1=true
+ V=1
+@@ -3614,8 +3128,8 @@ else
+   am_cv_make_support_nested_variables=no
+ fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+-printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
++$as_echo "$am_cv_make_support_nested_variables" >&6; }
+ if test $am_cv_make_support_nested_variables = yes; then
+     AM_V='$(V)'
+   AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+@@ -3650,10 +3164,14 @@ fi
+  VERSION='0.1'
+ 
+ 
+-printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define PACKAGE "$PACKAGE"
++_ACEOF
+ 
+ 
+-printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define VERSION "$VERSION"
++_ACEOF
+ 
+ # Some tools Automake needs.
+ 
+@@ -3693,20 +3211,6 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+ 
+ 
+ 
+-# Variables for tags utilities; see am/tags.am
+-if test -z "$CTAGS"; then
+-  CTAGS=ctags
+-fi
+-
+-if test -z "$ETAGS"; then
+-  ETAGS=etags
+-fi
+-
+-if test -z "$CSCOPE"; then
+-  CSCOPE=cscope
+-fi
+-
+-
+ 
+ # POSIX will say in a future version that running "rm -f" with no argument
+ # is OK; and we want to be able to make that assumption in our Makefile
+@@ -3751,18 +3255,17 @@ END
+ fi
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+-printf %s "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
++$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+     # Check whether --enable-maintainer-mode was given.
+-if test ${enable_maintainer_mode+y}
+-then :
++if test "${enable_maintainer_mode+set}" = set; then :
+   enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+-else $as_nop
++else
+   USE_MAINTAINER_MODE=no
+ fi
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+-printf "%s\n" "$USE_MAINTAINER_MODE" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
++$as_echo "$USE_MAINTAINER_MODE" >&6; }
+    if test $USE_MAINTAINER_MODE = yes; then
+   MAINTAINER_MODE_TRUE=
+   MAINTAINER_MODE_FALSE='#'
+@@ -3776,29 +3279,19 @@ fi
+ 
+ 
+ # Check whether --with-libiberty was given.
+-if test ${with_libiberty+y}
+-then :
++if test "${with_libiberty+set}" = set; then :
+   withval=$with_libiberty;
+-else $as_nop
++else
+   with_libiberty=../libiberty
+ fi
+ 
+ 
+-
+-
+-
+-
+-
+-
+-
+-
+-
+ DEPDIR="${am__leading_dot}deps"
+ 
+ ac_config_commands="$ac_config_commands depfiles"
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+-printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
++$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
+ cat > confinc.mk << 'END'
+ am__doit:
+ 	@echo this is the am__doit target >confinc.out
+@@ -3834,12 +3327,11 @@ esac
+   fi
+ done
+ rm -f confinc.* confmf.*
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+-printf "%s\n" "${_am_result}" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
++$as_echo "${_am_result}" >&6; }
+ 
+ # Check whether --enable-dependency-tracking was given.
+-if test ${enable_dependency_tracking+y}
+-then :
++if test "${enable_dependency_tracking+set}" = set; then :
+   enableval=$enable_dependency_tracking;
+ fi
+ 
+@@ -3865,12 +3357,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}gcc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -3878,15 +3369,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CC="${ac_tool_prefix}gcc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -3897,11 +3384,11 @@ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -3910,12 +3397,11 @@ if test -z "$ac_cv_prog_CC"; then
+   ac_ct_CC=$CC
+   # Extract the first word of "gcc", so it can be a program name with args.
+ set dummy gcc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_CC"; then
+   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+ else
+@@ -3923,15 +3409,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_CC="gcc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -3942,11 +3424,11 @@ fi
+ fi
+ ac_ct_CC=$ac_cv_prog_ac_ct_CC
+ if test -n "$ac_ct_CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+-printf "%s\n" "$ac_ct_CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_CC" = x; then
+@@ -3954,8 +3436,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     CC=$ac_ct_CC
+@@ -3968,12 +3450,11 @@ if test -z "$CC"; then
+           if test -n "$ac_tool_prefix"; then
+     # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}cc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -3981,15 +3462,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CC="${ac_tool_prefix}cc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -4000,11 +3477,11 @@ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -4013,12 +3490,11 @@ fi
+ if test -z "$CC"; then
+   # Extract the first word of "cc", so it can be a program name with args.
+ set dummy cc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -4027,19 +3503,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+        continue
+      fi
+     ac_cv_prog_CC="cc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -4055,18 +3527,18 @@ if test $ac_prog_rejected = yes; then
+     # However, it has the same basename, so the bogon will be chosen
+     # first if we set CC to just the basename; use the full file name.
+     shift
+-    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
++    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+   fi
+ fi
+ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -4077,12 +3549,11 @@ if test -z "$CC"; then
+   do
+     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+ set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -4090,15 +3561,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -4109,11 +3576,11 @@ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -4126,118 +3593,11 @@ if test -z "$CC"; then
+ do
+   # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$ac_ct_CC"; then
+-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_CC="$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-ac_ct_CC=$ac_cv_prog_ac_ct_CC
+-if test -n "$ac_ct_CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+-printf "%s\n" "$ac_ct_CC" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-
+-  test -n "$ac_ct_CC" && break
+-done
+-
+-  if test "x$ac_ct_CC" = x; then
+-    CC=""
+-  else
+-    case $cross_compiling:$ac_tool_warned in
+-yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+-ac_tool_warned=yes ;;
+-esac
+-    CC=$ac_ct_CC
+-  fi
+-fi
+-
+-fi
+-if test -z "$CC"; then
+-  if test -n "$ac_tool_prefix"; then
+-  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+-set dummy ${ac_tool_prefix}clang; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$CC"; then
+-  ac_cv_prog_CC="$CC" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_CC="${ac_tool_prefix}clang"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-CC=$ac_cv_prog_CC
+-if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-
+-fi
+-if test -z "$ac_cv_prog_CC"; then
+-  ac_ct_CC=$CC
+-  # Extract the first word of "clang", so it can be a program name with args.
+-set dummy clang; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_CC"; then
+   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+ else
+@@ -4245,15 +3605,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_CC="clang"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_CC="$ac_prog"
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -4264,48 +3620,50 @@ fi
+ fi
+ ac_ct_CC=$ac_cv_prog_ac_ct_CC
+ if test -n "$ac_ct_CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+-printf "%s\n" "$ac_ct_CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
++
++  test -n "$ac_ct_CC" && break
++done
++
+   if test "x$ac_ct_CC" = x; then
+     CC=""
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     CC=$ac_ct_CC
+   fi
+-else
+-  CC="$ac_cv_prog_CC"
+ fi
+ 
+ fi
+ 
+ 
+-test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "no acceptable C compiler found in \$PATH
+ See \`config.log' for more details" "$LINENO" 5; }
+ 
+ # Provide some information about the compiler.
+-printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
++$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+ set X $ac_compile
+ ac_compiler=$2
+-for ac_option in --version -v -V -qversion -version; do
++for ac_option in --version -v -V -qversion; do
+   { { ac_try="$ac_compiler $ac_option >&5"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -4315,7 +3673,7 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+   fi
+   rm -f conftest.er1 conftest.err
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }
+ done
+ 
+@@ -4323,7 +3681,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+@@ -4335,9 +3693,9 @@ ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+ # Try to create an executable without -o first, disregard a.out.
+ # It will help us diagnose broken compilers, and finding out an intuition
+ # of exeext.
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+-printf %s "checking whether the C compiler works... " >&6; }
+-ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
++$as_echo_n "checking whether the C compiler works... " >&6; }
++ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+ 
+ # The possible output files:
+ ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+@@ -4358,12 +3716,11 @@ case "(($ac_try" in
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_link_default") 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }
+-then :
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then :
+   # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+ # So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+ # in a Makefile.  We should not override ac_cv_exeext if it was cached,
+@@ -4380,7 +3737,7 @@ do
+ 	# certainly right.
+ 	break;;
+     *.* )
+-	if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
++	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ 	then :; else
+ 	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ 	fi
+@@ -4396,46 +3753,44 @@ do
+ done
+ test "$ac_cv_exeext" = no && ac_cv_exeext=
+ 
+-else $as_nop
++else
+   ac_file=''
+ fi
+-if test -z "$ac_file"
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-printf "%s\n" "$as_me: failed program was:" >&5
++if test -z "$ac_file"; then :
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++$as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+-{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error 77 "C compiler cannot create executables
+ See \`config.log' for more details" "$LINENO" 5; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+-printf %s "checking for C compiler default output file name... " >&6; }
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+-printf "%s\n" "$ac_file" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
++$as_echo_n "checking for C compiler default output file name... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
++$as_echo "$ac_file" >&6; }
+ ac_exeext=$ac_cv_exeext
+ 
+ rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ ac_clean_files=$ac_clean_files_save
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+-printf %s "checking for suffix of executables... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
++$as_echo_n "checking for suffix of executables... " >&6; }
+ if { { ac_try="$ac_link"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_link") 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }
+-then :
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then :
+   # If both `conftest.exe' and `conftest' are `present' (well, observable)
+ # catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+ # work properly (i.e., refer to `conftest.exe'), while it won't with
+@@ -4449,15 +3804,15 @@ for ac_file in conftest.exe conftest conftest.*; do
+     * ) break;;
+   esac
+ done
+-else $as_nop
+-  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++else
++  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+ See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ rm -f conftest conftest$ac_cv_exeext
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+-printf "%s\n" "$ac_cv_exeext" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
++$as_echo "$ac_cv_exeext" >&6; }
+ 
+ rm -f conftest.$ac_ext
+ EXEEXT=$ac_cv_exeext
+@@ -4466,7 +3821,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #include 
+ int
+-main (void)
++main ()
+ {
+ FILE *f = fopen ("conftest.out", "w");
+  return ferror (f) || fclose (f) != 0;
+@@ -4478,8 +3833,8 @@ _ACEOF
+ ac_clean_files="$ac_clean_files conftest.out"
+ # Check that the compiler produces executables we can run.  If not, either
+ # the compiler is broken, or we cross compile.
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+-printf %s "checking whether we are cross compiling... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
++$as_echo_n "checking whether we are cross compiling... " >&6; }
+ if test "$cross_compiling" != yes; then
+   { { ac_try="$ac_link"
+ case "(($ac_try" in
+@@ -4487,10 +3842,10 @@ case "(($ac_try" in
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_link") 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }
+   if { ac_try='./conftest$ac_cv_exeext'
+   { { case "(($ac_try" in
+@@ -4498,40 +3853,39 @@ printf "%s\n" "$ac_try_echo"; } >&5
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_try") 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; }; then
+     cross_compiling=no
+   else
+     if test "$cross_compiling" = maybe; then
+ 	cross_compiling=yes
+     else
+-	{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+-as_fn_error 77 "cannot run C compiled programs.
++	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "cannot run C compiled programs.
+ If you meant to cross compile, use \`--host'.
+ See \`config.log' for more details" "$LINENO" 5; }
+     fi
+   fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+-printf "%s\n" "$cross_compiling" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
++$as_echo "$cross_compiling" >&6; }
+ 
+ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ ac_clean_files=$ac_clean_files_save
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+-printf %s "checking for suffix of object files... " >&6; }
+-if test ${ac_cv_objext+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
++$as_echo_n "checking for suffix of object files... " >&6; }
++if ${ac_cv_objext+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+@@ -4545,12 +3899,11 @@ case "(($ac_try" in
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_compile") 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }
+-then :
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; }; then :
+   for ac_file in conftest.o conftest.obj conftest.*; do
+   test -f "$ac_file" || continue;
+   case $ac_file in
+@@ -4559,32 +3912,31 @@ then :
+        break;;
+   esac
+ done
+-else $as_nop
+-  printf "%s\n" "$as_me: failed program was:" >&5
++else
++  $as_echo "$as_me: failed program was:" >&5
+ sed 's/^/| /' conftest.$ac_ext >&5
+ 
+-{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "cannot compute suffix of object files: cannot compile
+ See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ rm -f conftest.$ac_cv_objext conftest.$ac_ext
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+-printf "%s\n" "$ac_cv_objext" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
++$as_echo "$ac_cv_objext" >&6; }
+ OBJEXT=$ac_cv_objext
+ ac_objext=$OBJEXT
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+-printf %s "checking whether the compiler supports GNU C... " >&6; }
+-if test ${ac_cv_c_compiler_gnu+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
++$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
++if ${ac_cv_c_compiler_gnu+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ #ifndef __GNUC__
+        choke me
+@@ -4594,33 +3946,29 @@ main (void)
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_compiler_gnu=yes
+-else $as_nop
++else
+   ac_compiler_gnu=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_c_compiler_gnu=$ac_compiler_gnu
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+-printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+-ac_compiler_gnu=$ac_cv_c_compiler_gnu
+-
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
++$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+ if test $ac_compiler_gnu = yes; then
+   GCC=yes
+ else
+   GCC=
+ fi
+-ac_test_CFLAGS=${CFLAGS+y}
++ac_test_CFLAGS=${CFLAGS+set}
+ ac_save_CFLAGS=$CFLAGS
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+-printf %s "checking whether $CC accepts -g... " >&6; }
+-if test ${ac_cv_prog_cc_g+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
++$as_echo_n "checking whether $CC accepts -g... " >&6; }
++if ${ac_cv_prog_cc_g+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_save_c_werror_flag=$ac_c_werror_flag
+    ac_c_werror_flag=yes
+    ac_cv_prog_cc_g=no
+@@ -4629,60 +3977,57 @@ else $as_nop
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_prog_cc_g=yes
+-else $as_nop
++else
+   CFLAGS=""
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+ 
+-else $as_nop
++else
+   ac_c_werror_flag=$ac_save_c_werror_flag
+ 	 CFLAGS="-g"
+ 	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_prog_cc_g=yes
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_c_werror_flag=$ac_save_c_werror_flag
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+-printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+-if test $ac_test_CFLAGS; then
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
++$as_echo "$ac_cv_prog_cc_g" >&6; }
++if test "$ac_test_CFLAGS" = set; then
+   CFLAGS=$ac_save_CFLAGS
+ elif test $ac_cv_prog_cc_g = yes; then
+   if test "$GCC" = yes; then
+@@ -4697,144 +4042,94 @@ else
+     CFLAGS=
+   fi
+ fi
+-ac_prog_cc_stdc=no
+-if test x$ac_prog_cc_stdc = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+-printf %s "checking for $CC option to enable C11 features... " >&6; }
+-if test ${ac_cv_prog_cc_c11+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cc_c11=no
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
++$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
++if ${ac_cv_prog_cc_c89+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  ac_cv_prog_cc_c89=no
+ ac_save_CC=$CC
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+-$ac_c_conftest_c11_program
+-_ACEOF
+-for ac_arg in '' -std=gnu11
+-do
+-  CC="$ac_save_CC $ac_arg"
+-  if ac_fn_c_try_compile "$LINENO"
+-then :
+-  ac_cv_prog_cc_c11=$ac_arg
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
+-  test "x$ac_cv_prog_cc_c11" != "xno" && break
+-done
+-rm -f conftest.$ac_ext
+-CC=$ac_save_CC
+-fi
++#include 
++#include 
++struct stat;
++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
++struct buf { int x; };
++FILE * (*rcsopen) (struct buf *, struct stat *, int);
++static char *e (p, i)
++     char **p;
++     int i;
++{
++  return p[i];
++}
++static char *f (char * (*g) (char **, int), char **p, ...)
++{
++  char *s;
++  va_list v;
++  va_start (v,p);
++  s = g (p, va_arg (v,int));
++  va_end (v);
++  return s;
++}
+ 
+-if test "x$ac_cv_prog_cc_c11" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cc_c11" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+-printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+-     CC="$CC $ac_cv_prog_cc_c11"
+-fi
+-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+-  ac_prog_cc_stdc=c11
+-fi
+-fi
+-if test x$ac_prog_cc_stdc = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+-printf %s "checking for $CC option to enable C99 features... " >&6; }
+-if test ${ac_cv_prog_cc_c99+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cc_c99=no
+-ac_save_CC=$CC
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-$ac_c_conftest_c99_program
+-_ACEOF
+-for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+-do
+-  CC="$ac_save_CC $ac_arg"
+-  if ac_fn_c_try_compile "$LINENO"
+-then :
+-  ac_cv_prog_cc_c99=$ac_arg
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
+-  test "x$ac_cv_prog_cc_c99" != "xno" && break
+-done
+-rm -f conftest.$ac_ext
+-CC=$ac_save_CC
+-fi
++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
++   function prototypes and stuff, but not '\xHH' hex character constants.
++   These don't provoke an error unfortunately, instead are silently treated
++   as 'x'.  The following induces an error, until -std is added to get
++   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
++   array size at least.  It's necessary to write '\x00'==0 to get something
++   that's true only with -std.  */
++int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+ 
+-if test "x$ac_cv_prog_cc_c99" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cc_c99" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+-printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+-     CC="$CC $ac_cv_prog_cc_c99"
+-fi
+-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+-  ac_prog_cc_stdc=c99
+-fi
+-fi
+-if test x$ac_prog_cc_stdc = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+-printf %s "checking for $CC option to enable C89 features... " >&6; }
+-if test ${ac_cv_prog_cc_c89+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cc_c89=no
+-ac_save_CC=$CC
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-$ac_c_conftest_c89_program
++/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
++   inside strings and character constants.  */
++#define FOO(x) 'x'
++int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
++
++int test (int i, double x);
++struct s1 {int (*f) (int a);};
++struct s2 {int (*f) (double a);};
++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
++int argc;
++char **argv;
++int
++main ()
++{
++return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
++  ;
++  return 0;
++}
+ _ACEOF
+-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
++for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
++	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+ do
+   CC="$ac_save_CC $ac_arg"
+-  if ac_fn_c_try_compile "$LINENO"
+-then :
++  if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_prog_cc_c89=$ac_arg
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
++rm -f core conftest.err conftest.$ac_objext
+   test "x$ac_cv_prog_cc_c89" != "xno" && break
+ done
+ rm -f conftest.$ac_ext
+ CC=$ac_save_CC
+-fi
+ 
+-if test "x$ac_cv_prog_cc_c89" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cc_c89" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+-printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+-     CC="$CC $ac_cv_prog_cc_c89"
+-fi
+-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+-  ac_prog_cc_stdc=c89
+ fi
++# AC_CACHE_VAL
++case "x$ac_cv_prog_cc_c89" in
++  x)
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++$as_echo "none needed" >&6; } ;;
++  xno)
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++$as_echo "unsupported" >&6; } ;;
++  *)
++    CC="$CC $ac_cv_prog_cc_c89"
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
++$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
++esac
++if test "x$ac_cv_prog_cc_c89" != xno; then :
++
+ fi
+ 
+ ac_ext=c
+@@ -4843,23 +4138,21 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+-
+-  ac_ext=c
++ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+-printf %s "checking whether $CC understands -c and -o together... " >&6; }
+-if test ${am_cv_prog_cc_c_o+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
++$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
++if ${am_cv_prog_cc_c_o+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+@@ -4887,8 +4180,8 @@ _ACEOF
+   rm -f core conftest*
+   unset am_i
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+-printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
++$as_echo "$am_cv_prog_cc_c_o" >&6; }
+ if test "$am_cv_prog_cc_c_o" != yes; then
+    # Losing compiler, so override with the script.
+    # FIXME: It is wrong to rewrite CC.
+@@ -4906,12 +4199,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+ depcc="$CC"   am_compiler_list=
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+-printf %s "checking dependency style of $depcc... " >&6; }
+-if test ${am_cv_CC_dependencies_compiler_type+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
++$as_echo_n "checking dependency style of $depcc... " >&6; }
++if ${am_cv_CC_dependencies_compiler_type+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+   # We make a subdir and do the tests there.  Otherwise we can end up
+   # making bogus files that we don't know about and never remove.  For
+@@ -5014,195 +4306,483 @@ else $as_nop
+   cd ..
+   rm -rf conftest.dir
+ else
+-  am_cv_CC_dependencies_compiler_type=none
+-fi
+-
++  am_cv_CC_dependencies_compiler_type=none
++fi
++
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
++$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
++CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
++
++ if
++  test "x$enable_dependency_tracking" != xno \
++  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
++  am__fastdepCC_TRUE=
++  am__fastdepCC_FALSE='#'
++else
++  am__fastdepCC_TRUE='#'
++  am__fastdepCC_FALSE=
++fi
++
++
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
++$as_echo_n "checking how to run the C preprocessor... " >&6; }
++# On Suns, sometimes $CPP names a directory.
++if test -n "$CPP" && test -d "$CPP"; then
++  CPP=
++fi
++if test -z "$CPP"; then
++  if ${ac_cv_prog_CPP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++      # Double quotes because CPP needs to be expanded
++    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
++    do
++      ac_preproc_ok=false
++for ac_c_preproc_warn_flag in '' yes
++do
++  # Use a header file that comes with gcc, so configuring glibc
++  # with a fresh cross-compiler works.
++  # Prefer  to  if __STDC__ is defined, since
++  #  exists even on freestanding compilers.
++  # On the NeXT, cc -E runs the code through the compiler's parser,
++  # not just through cpp. "Syntax error" is here to catch this case.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
++		     Syntax error
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++
++else
++  # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++  # OK, works on sane cases.  Now check whether nonexistent headers
++  # can be detected and how.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++  # Broken: success on invalid input.
++continue
++else
++  # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.i conftest.err conftest.$ac_ext
++if $ac_preproc_ok; then :
++  break
++fi
++
++    done
++    ac_cv_prog_CPP=$CPP
++
++fi
++  CPP=$ac_cv_prog_CPP
++else
++  ac_cv_prog_CPP=$CPP
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
++$as_echo "$CPP" >&6; }
++ac_preproc_ok=false
++for ac_c_preproc_warn_flag in '' yes
++do
++  # Use a header file that comes with gcc, so configuring glibc
++  # with a fresh cross-compiler works.
++  # Prefer  to  if __STDC__ is defined, since
++  #  exists even on freestanding compilers.
++  # On the NeXT, cc -E runs the code through the compiler's parser,
++  # not just through cpp. "Syntax error" is here to catch this case.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
++		     Syntax error
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++
++else
++  # Broken: fails on valid input.
++continue
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++  # OK, works on sane cases.  Now check whether nonexistent headers
++  # can be detected and how.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
++_ACEOF
++if ac_fn_c_try_cpp "$LINENO"; then :
++  # Broken: success on invalid input.
++continue
++else
++  # Passes both tests.
++ac_preproc_ok=:
++break
++fi
++rm -f conftest.err conftest.i conftest.$ac_ext
++
++done
++# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
++rm -f conftest.i conftest.err conftest.$ac_ext
++if $ac_preproc_ok; then :
++
++else
++  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
++as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
++See \`config.log' for more details" "$LINENO" 5; }
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
++$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
++if ${ac_cv_path_GREP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  if test -z "$GREP"; then
++  ac_path_GREP_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++    for ac_prog in grep ggrep; do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_GREP" || continue
++# Check for GNU ac_path_GREP and select it if it is found.
++  # Check for GNU $ac_path_GREP
++case `"$ac_path_GREP" --version 2>&1` in
++*GNU*)
++  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
++*)
++  ac_count=0
++  $as_echo_n 0123456789 >"conftest.in"
++  while :
++  do
++    cat "conftest.in" "conftest.in" >"conftest.tmp"
++    mv "conftest.tmp" "conftest.in"
++    cp "conftest.in" "conftest.nl"
++    $as_echo 'GREP' >> "conftest.nl"
++    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++    as_fn_arith $ac_count + 1 && ac_count=$as_val
++    if test $ac_count -gt ${ac_path_GREP_max-0}; then
++      # Best one so far, save it but keep looking for a better one
++      ac_cv_path_GREP="$ac_path_GREP"
++      ac_path_GREP_max=$ac_count
++    fi
++    # 10*(2^10) chars as input seems more than enough
++    test $ac_count -gt 10 && break
++  done
++  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++      $ac_path_GREP_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_GREP"; then
++    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++  fi
++else
++  ac_cv_path_GREP=$GREP
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+-printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
+-CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+ 
+- if
+-  test "x$enable_dependency_tracking" != xno \
+-  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+-  am__fastdepCC_TRUE=
+-  am__fastdepCC_FALSE='#'
+-else
+-  am__fastdepCC_TRUE='#'
+-  am__fastdepCC_FALSE=
+ fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
++$as_echo "$ac_cv_path_GREP" >&6; }
++ GREP="$ac_cv_path_GREP"
+ 
+ 
+-
+-ac_header= ac_cache=
+-for ac_item in $ac_header_c_list
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
++$as_echo_n "checking for egrep... " >&6; }
++if ${ac_cv_path_EGREP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
++   then ac_cv_path_EGREP="$GREP -E"
++   else
++     if test -z "$EGREP"; then
++  ac_path_EGREP_found=false
++  # Loop through the user's path and test for each of PROGNAME-LIST
++  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ do
+-  if test $ac_cache; then
+-    ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+-    if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+-      printf "%s\n" "#define $ac_item 1" >> confdefs.h
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++    for ac_prog in egrep; do
++    for ac_exec_ext in '' $ac_executable_extensions; do
++      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
++      as_fn_executable_p "$ac_path_EGREP" || continue
++# Check for GNU ac_path_EGREP and select it if it is found.
++  # Check for GNU $ac_path_EGREP
++case `"$ac_path_EGREP" --version 2>&1` in
++*GNU*)
++  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
++*)
++  ac_count=0
++  $as_echo_n 0123456789 >"conftest.in"
++  while :
++  do
++    cat "conftest.in" "conftest.in" >"conftest.tmp"
++    mv "conftest.tmp" "conftest.in"
++    cp "conftest.in" "conftest.nl"
++    $as_echo 'EGREP' >> "conftest.nl"
++    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++    as_fn_arith $ac_count + 1 && ac_count=$as_val
++    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
++      # Best one so far, save it but keep looking for a better one
++      ac_cv_path_EGREP="$ac_path_EGREP"
++      ac_path_EGREP_max=$ac_count
+     fi
+-    ac_header= ac_cache=
+-  elif test $ac_header; then
+-    ac_cache=$ac_item
+-  else
+-    ac_header=$ac_item
+-  fi
+-done
+-
+-
+-
+-
+-
+-
+-
+-
+-if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+-then :
+-
+-printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
++    # 10*(2^10) chars as input seems more than enough
++    test $ac_count -gt 10 && break
++  done
++  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
+ 
++      $ac_path_EGREP_found && break 3
++    done
++  done
++  done
++IFS=$as_save_IFS
++  if test -z "$ac_cv_path_EGREP"; then
++    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++  fi
++else
++  ac_cv_path_EGREP=$EGREP
+ fi
+ 
++   fi
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
++$as_echo "$ac_cv_path_EGREP" >&6; }
++ EGREP="$ac_cv_path_EGREP"
+ 
+ 
+-
+-
+-
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+-printf %s "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+-if test ${ac_cv_safe_to_define___extensions__+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
++$as_echo_n "checking for ANSI C header files... " >&6; }
++if ${ac_cv_header_stdc+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
++#include 
++#include 
++#include 
++#include 
+ 
+-#         define __EXTENSIONS__ 1
+-          $ac_includes_default
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
+-  ac_cv_safe_to_define___extensions__=yes
+-else $as_nop
+-  ac_cv_safe_to_define___extensions__=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_cv_header_stdc=yes
++else
++  ac_cv_header_stdc=no
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+-printf "%s\n" "$ac_cv_safe_to_define___extensions__" >&6; }
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _XOPEN_SOURCE should be defined" >&5
+-printf %s "checking whether _XOPEN_SOURCE should be defined... " >&6; }
+-if test ${ac_cv_should_define__xopen_source+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_should_define__xopen_source=no
+-    if test $ac_cv_header_wchar_h = yes
+-then :
++if test $ac_cv_header_stdc = yes; then
++  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
++#include 
+ 
+-          #include 
+-          mbstate_t x;
+-int
+-main (void)
+-{
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++  $EGREP "memchr" >/dev/null 2>&1; then :
++
++else
++  ac_cv_header_stdc=no
++fi
++rm -f conftest*
++
++fi
++
++if test $ac_cv_header_stdc = yes; then
++  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++#include 
+ 
+-  ;
+-  return 0;
+-}
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++  $EGREP "free" >/dev/null 2>&1; then :
++
++else
++  ac_cv_header_stdc=no
++fi
++rm -f conftest*
+ 
+-else $as_nop
++fi
++
++if test $ac_cv_header_stdc = yes; then
++  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
++  if test "$cross_compiling" = yes; then :
++  :
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
++#include 
++#include 
++#if ((' ' & 0x0FF) == 0x020)
++# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
++# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
++#else
++# define ISLOWER(c) \
++		   (('a' <= (c) && (c) <= 'i') \
++		     || ('j' <= (c) && (c) <= 'r') \
++		     || ('s' <= (c) && (c) <= 'z'))
++# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
++#endif
+ 
+-            #define _XOPEN_SOURCE 500
+-            #include 
+-            mbstate_t x;
++#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+ int
+-main (void)
++main ()
+ {
+-
+-  ;
++  int i;
++  for (i = 0; i < 256; i++)
++    if (XOR (islower (i), ISLOWER (i))
++	|| toupper (i) != TOUPPER (i))
++      return 2;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
+-  ac_cv_should_define__xopen_source=yes
++if ac_fn_c_try_run "$LINENO"; then :
++
++else
++  ac_cv_header_stdc=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
++  conftest.$ac_objext conftest.beam conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++
+ fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_should_define__xopen_source" >&5
+-printf "%s\n" "$ac_cv_should_define__xopen_source" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
++$as_echo "$ac_cv_header_stdc" >&6; }
++if test $ac_cv_header_stdc = yes; then
+ 
+-  printf "%s\n" "#define _ALL_SOURCE 1" >>confdefs.h
++$as_echo "#define STDC_HEADERS 1" >>confdefs.h
++
++fi
+ 
+-  printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h
++# On IRIX 5.3, sys/types and inttypes.h are conflicting.
++for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
++		  inttypes.h stdint.h unistd.h
++do :
++  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
++ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
++"
++if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
++  cat >>confdefs.h <<_ACEOF
++#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
++_ACEOF
+ 
+-  printf "%s\n" "#define _GNU_SOURCE 1" >>confdefs.h
++fi
+ 
+-  printf "%s\n" "#define _HPUX_ALT_XOPEN_SOCKET_API 1" >>confdefs.h
++done
+ 
+-  printf "%s\n" "#define _NETBSD_SOURCE 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define _OPENBSD_SOURCE 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
++  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
++if test "x$ac_cv_header_minix_config_h" = xyes; then :
++  MINIX=yes
++else
++  MINIX=
++fi
+ 
+-  printf "%s\n" "#define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define __STDC_WANT_IEC_60559_BFP_EXT__ 1" >>confdefs.h
++  if test "$MINIX" = yes; then
+ 
+-  printf "%s\n" "#define __STDC_WANT_IEC_60559_DFP_EXT__ 1" >>confdefs.h
++$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1" >>confdefs.h
++$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+ 
+-  printf "%s\n" "#define __STDC_WANT_LIB_EXT2__ 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define __STDC_WANT_MATH_SPEC_FUNCS__ 1" >>confdefs.h
++$as_echo "#define _MINIX 1" >>confdefs.h
+ 
+-  printf "%s\n" "#define _TANDEM_SOURCE 1" >>confdefs.h
++  fi
+ 
+-  if test $ac_cv_header_minix_config_h = yes
+-then :
+-  MINIX=yes
+-    printf "%s\n" "#define _MINIX 1" >>confdefs.h
+ 
+-    printf "%s\n" "#define _POSIX_SOURCE 1" >>confdefs.h
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
++$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
++if ${ac_cv_safe_to_define___extensions__+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
+ 
+-    printf "%s\n" "#define _POSIX_1_SOURCE 2" >>confdefs.h
++#         define __EXTENSIONS__ 1
++          $ac_includes_default
++int
++main ()
++{
+ 
+-else $as_nop
+-  MINIX=
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  ac_cv_safe_to_define___extensions__=yes
++else
++  ac_cv_safe_to_define___extensions__=no
+ fi
+-  if test $ac_cv_safe_to_define___extensions__ = yes
+-then :
+-  printf "%s\n" "#define __EXTENSIONS__ 1" >>confdefs.h
+-
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-  if test $ac_cv_should_define__xopen_source = yes
+-then :
+-  printf "%s\n" "#define _XOPEN_SOURCE 500" >>confdefs.h
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
++$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
++  test $ac_cv_safe_to_define___extensions__ = yes &&
++    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
++
++  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
++
++  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
++
++  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
++
++  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+ 
+-fi
+ 
+ ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+@@ -5212,12 +4792,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}gcc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -5225,15 +4804,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CC="${ac_tool_prefix}gcc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -5244,11 +4819,11 @@ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -5257,12 +4832,11 @@ if test -z "$ac_cv_prog_CC"; then
+   ac_ct_CC=$CC
+   # Extract the first word of "gcc", so it can be a program name with args.
+ set dummy gcc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_CC"; then
+   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+ else
+@@ -5270,15 +4844,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_CC="gcc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -5289,11 +4859,11 @@ fi
+ fi
+ ac_ct_CC=$ac_cv_prog_ac_ct_CC
+ if test -n "$ac_ct_CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+-printf "%s\n" "$ac_ct_CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_CC" = x; then
+@@ -5301,8 +4871,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     CC=$ac_ct_CC
+@@ -5315,12 +4885,11 @@ if test -z "$CC"; then
+           if test -n "$ac_tool_prefix"; then
+     # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}cc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -5328,15 +4897,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CC="${ac_tool_prefix}cc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -5347,11 +4912,11 @@ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -5360,12 +4925,11 @@ fi
+ if test -z "$CC"; then
+   # Extract the first word of "cc", so it can be a program name with args.
+ set dummy cc; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -5374,19 +4938,15 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+        continue
+      fi
+     ac_cv_prog_CC="cc"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -5402,18 +4962,18 @@ if test $ac_prog_rejected = yes; then
+     # However, it has the same basename, so the bogon will be chosen
+     # first if we set CC to just the basename; use the full file name.
+     shift
+-    ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
++    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+   fi
+ fi
+ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -5424,12 +4984,11 @@ if test -z "$CC"; then
+   do
+     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+ set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CC"; then
+   ac_cv_prog_CC="$CC" # Let the user override the test.
+ else
+@@ -5437,15 +4996,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -5456,11 +5011,11 @@ fi
+ fi
+ CC=$ac_cv_prog_CC
+ if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
++$as_echo "$CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -5473,12 +5028,11 @@ if test -z "$CC"; then
+ do
+   # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_CC"; then
+   ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+ else
+@@ -5486,15 +5040,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_CC="$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -5505,11 +5055,11 @@ fi
+ fi
+ ac_ct_CC=$ac_cv_prog_ac_ct_CC
+ if test -n "$ac_ct_CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+-printf "%s\n" "$ac_ct_CC" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
++$as_echo "$ac_ct_CC" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -5521,138 +5071,34 @@ done
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+-ac_tool_warned=yes ;;
+-esac
+-    CC=$ac_ct_CC
+-  fi
+-fi
+-
+-fi
+-if test -z "$CC"; then
+-  if test -n "$ac_tool_prefix"; then
+-  # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+-set dummy ${ac_tool_prefix}clang; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$CC"; then
+-  ac_cv_prog_CC="$CC" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_CC="${ac_tool_prefix}clang"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-CC=$ac_cv_prog_CC
+-if test -n "$CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+-printf "%s\n" "$CC" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-
+-fi
+-if test -z "$ac_cv_prog_CC"; then
+-  ac_ct_CC=$CC
+-  # Extract the first word of "clang", so it can be a program name with args.
+-set dummy clang; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$ac_ct_CC"; then
+-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_CC="clang"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-ac_ct_CC=$ac_cv_prog_ac_ct_CC
+-if test -n "$ac_ct_CC"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+-printf "%s\n" "$ac_ct_CC" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-  if test "x$ac_ct_CC" = x; then
+-    CC=""
+-  else
+-    case $cross_compiling:$ac_tool_warned in
+-yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     CC=$ac_ct_CC
+   fi
+-else
+-  CC="$ac_cv_prog_CC"
+ fi
+ 
+ fi
+ 
+ 
+-test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "no acceptable C compiler found in \$PATH
+ See \`config.log' for more details" "$LINENO" 5; }
+ 
+ # Provide some information about the compiler.
+-printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
++$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+ set X $ac_compile
+ ac_compiler=$2
+-for ac_option in --version -v -V -qversion -version; do
++for ac_option in --version -v -V -qversion; do
+   { { ac_try="$ac_compiler $ac_option >&5"
+ case "(($ac_try" in
+   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -5662,21 +5108,20 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+   fi
+   rm -f conftest.er1 conftest.err
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }
+ done
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+-printf %s "checking whether the compiler supports GNU C... " >&6; }
+-if test ${ac_cv_c_compiler_gnu+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
++$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
++if ${ac_cv_c_compiler_gnu+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ #ifndef __GNUC__
+        choke me
+@@ -5686,33 +5131,29 @@ main (void)
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_compiler_gnu=yes
+-else $as_nop
++else
+   ac_compiler_gnu=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_c_compiler_gnu=$ac_compiler_gnu
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+-printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+-ac_compiler_gnu=$ac_cv_c_compiler_gnu
+-
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
++$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+ if test $ac_compiler_gnu = yes; then
+   GCC=yes
+ else
+   GCC=
+ fi
+-ac_test_CFLAGS=${CFLAGS+y}
++ac_test_CFLAGS=${CFLAGS+set}
+ ac_save_CFLAGS=$CFLAGS
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+-printf %s "checking whether $CC accepts -g... " >&6; }
+-if test ${ac_cv_prog_cc_g+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
++$as_echo_n "checking whether $CC accepts -g... " >&6; }
++if ${ac_cv_prog_cc_g+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_save_c_werror_flag=$ac_c_werror_flag
+    ac_c_werror_flag=yes
+    ac_cv_prog_cc_g=no
+@@ -5721,60 +5162,57 @@ else $as_nop
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_prog_cc_g=yes
+-else $as_nop
++else
+   CFLAGS=""
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+ 
+-else $as_nop
++else
+   ac_c_werror_flag=$ac_save_c_werror_flag
+ 	 CFLAGS="-g"
+ 	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_prog_cc_g=yes
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_c_werror_flag=$ac_save_c_werror_flag
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+-printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+-if test $ac_test_CFLAGS; then
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
++$as_echo "$ac_cv_prog_cc_g" >&6; }
++if test "$ac_test_CFLAGS" = set; then
+   CFLAGS=$ac_save_CFLAGS
+ elif test $ac_cv_prog_cc_g = yes; then
+   if test "$GCC" = yes; then
+@@ -5786,147 +5224,97 @@ else
+   if test "$GCC" = yes; then
+     CFLAGS="-O2"
+   else
+-    CFLAGS=
+-  fi
+-fi
+-ac_prog_cc_stdc=no
+-if test x$ac_prog_cc_stdc = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+-printf %s "checking for $CC option to enable C11 features... " >&6; }
+-if test ${ac_cv_prog_cc_c11+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cc_c11=no
+-ac_save_CC=$CC
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-$ac_c_conftest_c11_program
+-_ACEOF
+-for ac_arg in '' -std=gnu11
+-do
+-  CC="$ac_save_CC $ac_arg"
+-  if ac_fn_c_try_compile "$LINENO"
+-then :
+-  ac_cv_prog_cc_c11=$ac_arg
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
+-  test "x$ac_cv_prog_cc_c11" != "xno" && break
+-done
+-rm -f conftest.$ac_ext
+-CC=$ac_save_CC
+-fi
+-
+-if test "x$ac_cv_prog_cc_c11" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cc_c11" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+-printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+-     CC="$CC $ac_cv_prog_cc_c11"
+-fi
+-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+-  ac_prog_cc_stdc=c11
+-fi
+-fi
+-if test x$ac_prog_cc_stdc = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+-printf %s "checking for $CC option to enable C99 features... " >&6; }
+-if test ${ac_cv_prog_cc_c99+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cc_c99=no
+-ac_save_CC=$CC
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-$ac_c_conftest_c99_program
+-_ACEOF
+-for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+-do
+-  CC="$ac_save_CC $ac_arg"
+-  if ac_fn_c_try_compile "$LINENO"
+-then :
+-  ac_cv_prog_cc_c99=$ac_arg
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
+-  test "x$ac_cv_prog_cc_c99" != "xno" && break
+-done
+-rm -f conftest.$ac_ext
+-CC=$ac_save_CC
++    CFLAGS=
++  fi
+ fi
+-
+-if test "x$ac_cv_prog_cc_c99" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cc_c99" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+-printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+-     CC="$CC $ac_cv_prog_cc_c99"
+-fi
+-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+-  ac_prog_cc_stdc=c99
+-fi
+-fi
+-if test x$ac_prog_cc_stdc = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+-printf %s "checking for $CC option to enable C89 features... " >&6; }
+-if test ${ac_cv_prog_cc_c89+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
++$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
++if ${ac_cv_prog_cc_c89+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_cv_prog_cc_c89=no
+ ac_save_CC=$CC
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+-$ac_c_conftest_c89_program
++#include 
++#include 
++struct stat;
++/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
++struct buf { int x; };
++FILE * (*rcsopen) (struct buf *, struct stat *, int);
++static char *e (p, i)
++     char **p;
++     int i;
++{
++  return p[i];
++}
++static char *f (char * (*g) (char **, int), char **p, ...)
++{
++  char *s;
++  va_list v;
++  va_start (v,p);
++  s = g (p, va_arg (v,int));
++  va_end (v);
++  return s;
++}
++
++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
++   function prototypes and stuff, but not '\xHH' hex character constants.
++   These don't provoke an error unfortunately, instead are silently treated
++   as 'x'.  The following induces an error, until -std is added to get
++   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
++   array size at least.  It's necessary to write '\x00'==0 to get something
++   that's true only with -std.  */
++int osf4_cc_array ['\x00' == 0 ? 1 : -1];
++
++/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
++   inside strings and character constants.  */
++#define FOO(x) 'x'
++int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
++
++int test (int i, double x);
++struct s1 {int (*f) (int a);};
++struct s2 {int (*f) (double a);};
++int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
++int argc;
++char **argv;
++int
++main ()
++{
++return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
++  ;
++  return 0;
++}
+ _ACEOF
+-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
++for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
++	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+ do
+   CC="$ac_save_CC $ac_arg"
+-  if ac_fn_c_try_compile "$LINENO"
+-then :
++  if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_prog_cc_c89=$ac_arg
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
++rm -f core conftest.err conftest.$ac_objext
+   test "x$ac_cv_prog_cc_c89" != "xno" && break
+ done
+ rm -f conftest.$ac_ext
+ CC=$ac_save_CC
+-fi
+ 
+-if test "x$ac_cv_prog_cc_c89" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cc_c89" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+-printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+-     CC="$CC $ac_cv_prog_cc_c89"
+-fi
+-  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+-  ac_prog_cc_stdc=c89
+ fi
++# AC_CACHE_VAL
++case "x$ac_cv_prog_cc_c89" in
++  x)
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
++$as_echo "none needed" >&6; } ;;
++  xno)
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
++$as_echo "unsupported" >&6; } ;;
++  *)
++    CC="$CC $ac_cv_prog_cc_c89"
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
++$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
++esac
++if test "x$ac_cv_prog_cc_c89" != xno; then :
++
+ fi
+ 
+ ac_ext=c
+@@ -5935,23 +5323,21 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+-
+-  ac_ext=c
++ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+-printf %s "checking whether $CC understands -c and -o together... " >&6; }
+-if test ${am_cv_prog_cc_c_o+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
++$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
++if ${am_cv_prog_cc_c_o+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+@@ -5979,8 +5365,8 @@ _ACEOF
+   rm -f core conftest*
+   unset am_i
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+-printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
++$as_echo "$am_cv_prog_cc_c_o" >&6; }
+ if test "$am_cv_prog_cc_c_o" != yes; then
+    # Losing compiler, so override with the script.
+    # FIXME: It is wrong to rewrite CC.
+@@ -5998,12 +5384,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+ depcc="$CC"   am_compiler_list=
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+-printf %s "checking dependency style of $depcc... " >&6; }
+-if test ${am_cv_CC_dependencies_compiler_type+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
++$as_echo_n "checking dependency style of $depcc... " >&6; }
++if ${am_cv_CC_dependencies_compiler_type+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+   # We make a subdir and do the tests there.  Otherwise we can end up
+   # making bogus files that we don't know about and never remove.  For
+@@ -6110,8 +5495,8 @@ else
+ fi
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+-printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
++$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+ CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+ 
+  if
+@@ -6125,12 +5510,6 @@ else
+ fi
+ 
+ 
+-
+-
+-
+-
+-
+-
+ ac_ext=cpp
+ ac_cpp='$CXXCPP $CPPFLAGS'
+ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+@@ -6141,16 +5520,15 @@ if test -z "$CXX"; then
+     CXX=$CCC
+   else
+     if test -n "$ac_tool_prefix"; then
+-  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
++  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+   do
+     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+ set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$CXX"; then
+   ac_cv_prog_CXX="$CXX" # Let the user override the test.
+ else
+@@ -6158,15 +5536,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -6177,11 +5551,11 @@ fi
+ fi
+ CXX=$ac_cv_prog_CXX
+ if test -n "$CXX"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+-printf "%s\n" "$CXX" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
++$as_echo "$CXX" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -6190,16 +5564,15 @@ fi
+ fi
+ if test -z "$CXX"; then
+   ac_ct_CXX=$CXX
+-  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++
++  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+   # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_CXX"; then
+   ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+ else
+@@ -6207,15 +5580,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_CXX="$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -6226,11 +5595,11 @@ fi
+ fi
+ ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+ if test -n "$ac_ct_CXX"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+-printf "%s\n" "$ac_ct_CXX" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
++$as_echo "$ac_ct_CXX" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -6242,8 +5611,8 @@ done
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     CXX=$ac_ct_CXX
+@@ -6253,7 +5622,7 @@ fi
+   fi
+ fi
+ # Provide some information about the compiler.
+-printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
++$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+ set X $ac_compile
+ ac_compiler=$2
+ for ac_option in --version -v -V -qversion; do
+@@ -6263,7 +5632,7 @@ case "(($ac_try" in
+   *) ac_try_echo=$ac_try;;
+ esac
+ eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+-printf "%s\n" "$ac_try_echo"; } >&5
++$as_echo "$ac_try_echo"; } >&5
+   (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+   ac_status=$?
+   if test -s conftest.err; then
+@@ -6273,21 +5642,20 @@ printf "%s\n" "$ac_try_echo"; } >&5
+     cat conftest.er1 >&5
+   fi
+   rm -f conftest.er1 conftest.err
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }
+ done
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5
+-printf %s "checking whether the compiler supports GNU C++... " >&6; }
+-if test ${ac_cv_cxx_compiler_gnu+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
++$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
++if ${ac_cv_cxx_compiler_gnu+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ #ifndef __GNUC__
+        choke me
+@@ -6297,33 +5665,29 @@ main (void)
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_compile "$LINENO"
+-then :
++if ac_fn_cxx_try_compile "$LINENO"; then :
+   ac_compiler_gnu=yes
+-else $as_nop
++else
+   ac_compiler_gnu=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+-printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; }
+-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+-
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
++$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+ if test $ac_compiler_gnu = yes; then
+   GXX=yes
+ else
+   GXX=
+ fi
+-ac_test_CXXFLAGS=${CXXFLAGS+y}
++ac_test_CXXFLAGS=${CXXFLAGS+set}
+ ac_save_CXXFLAGS=$CXXFLAGS
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+-printf %s "checking whether $CXX accepts -g... " >&6; }
+-if test ${ac_cv_prog_cxx_g+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
++$as_echo_n "checking whether $CXX accepts -g... " >&6; }
++if ${ac_cv_prog_cxx_g+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+    ac_cxx_werror_flag=yes
+    ac_cv_prog_cxx_g=no
+@@ -6332,60 +5696,57 @@ else $as_nop
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_compile "$LINENO"
+-then :
++if ac_fn_cxx_try_compile "$LINENO"; then :
+   ac_cv_prog_cxx_g=yes
+-else $as_nop
++else
+   CXXFLAGS=""
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_compile "$LINENO"
+-then :
++if ac_fn_cxx_try_compile "$LINENO"; then :
+ 
+-else $as_nop
++else
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ 	 CXXFLAGS="-g"
+ 	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_compile "$LINENO"
+-then :
++if ac_fn_cxx_try_compile "$LINENO"; then :
+   ac_cv_prog_cxx_g=yes
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+-printf "%s\n" "$ac_cv_prog_cxx_g" >&6; }
+-if test $ac_test_CXXFLAGS; then
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
++$as_echo "$ac_cv_prog_cxx_g" >&6; }
++if test "$ac_test_CXXFLAGS" = set; then
+   CXXFLAGS=$ac_save_CXXFLAGS
+ elif test $ac_cv_prog_cxx_g = yes; then
+   if test "$GXX" = yes; then
+@@ -6400,100 +5761,6 @@ else
+     CXXFLAGS=
+   fi
+ fi
+-ac_prog_cxx_stdcxx=no
+-if test x$ac_prog_cxx_stdcxx = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
+-printf %s "checking for $CXX option to enable C++11 features... " >&6; }
+-if test ${ac_cv_prog_cxx_cxx11+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cxx_cxx11=no
+-ac_save_CXX=$CXX
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-$ac_cxx_conftest_cxx11_program
+-_ACEOF
+-for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA
+-do
+-  CXX="$ac_save_CXX $ac_arg"
+-  if ac_fn_cxx_try_compile "$LINENO"
+-then :
+-  ac_cv_prog_cxx_cxx11=$ac_arg
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
+-  test "x$ac_cv_prog_cxx_cxx11" != "xno" && break
+-done
+-rm -f conftest.$ac_ext
+-CXX=$ac_save_CXX
+-fi
+-
+-if test "x$ac_cv_prog_cxx_cxx11" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cxx_cxx11" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5
+-printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; }
+-     CXX="$CXX $ac_cv_prog_cxx_cxx11"
+-fi
+-  ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11
+-  ac_prog_cxx_stdcxx=cxx11
+-fi
+-fi
+-if test x$ac_prog_cxx_stdcxx = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
+-printf %s "checking for $CXX option to enable C++98 features... " >&6; }
+-if test ${ac_cv_prog_cxx_cxx98+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  ac_cv_prog_cxx_cxx98=no
+-ac_save_CXX=$CXX
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-$ac_cxx_conftest_cxx98_program
+-_ACEOF
+-for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA
+-do
+-  CXX="$ac_save_CXX $ac_arg"
+-  if ac_fn_cxx_try_compile "$LINENO"
+-then :
+-  ac_cv_prog_cxx_cxx98=$ac_arg
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
+-  test "x$ac_cv_prog_cxx_cxx98" != "xno" && break
+-done
+-rm -f conftest.$ac_ext
+-CXX=$ac_save_CXX
+-fi
+-
+-if test "x$ac_cv_prog_cxx_cxx98" = xno
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+-printf "%s\n" "unsupported" >&6; }
+-else $as_nop
+-  if test "x$ac_cv_prog_cxx_cxx98" = x
+-then :
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+-printf "%s\n" "none needed" >&6; }
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5
+-printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; }
+-     CXX="$CXX $ac_cv_prog_cxx_cxx98"
+-fi
+-  ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98
+-  ac_prog_cxx_stdcxx=cxx98
+-fi
+-fi
+-
+ ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+@@ -6502,12 +5769,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+ depcc="$CXX"  am_compiler_list=
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+-printf %s "checking dependency style of $depcc... " >&6; }
+-if test ${am_cv_CXX_dependencies_compiler_type+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
++$as_echo_n "checking dependency style of $depcc... " >&6; }
++if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+   # We make a subdir and do the tests there.  Otherwise we can end up
+   # making bogus files that we don't know about and never remove.  For
+@@ -6614,8 +5880,8 @@ else
+ fi
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+-printf "%s\n" "$am_cv_CXX_dependencies_compiler_type" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
++$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+ CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+ 
+  if
+@@ -6630,19 +5896,17 @@ fi
+ 
+ 
+ # Check whether --enable-largefile was given.
+-if test ${enable_largefile+y}
+-then :
++if test "${enable_largefile+set}" = set; then :
+   enableval=$enable_largefile;
+ fi
+ 
+ if test "$enable_largefile" != no; then
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+-printf %s "checking for special C compiler options needed for large files... " >&6; }
+-if test ${ac_cv_sys_largefile_CC+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
++$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
++if ${ac_cv_sys_largefile_CC+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_cv_sys_largefile_CC=no
+      if test "$GCC" != yes; then
+        ac_save_CC=$CC
+@@ -6656,47 +5920,44 @@ else $as_nop
+     We can't simply define LARGE_OFF_T to be 9223372036854775807,
+     since some C++ compilers masquerading as C compilers
+     incorrectly reject 9223372036854775807.  */
+-#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ 		       && LARGE_OFF_T % 2147483647 == 1)
+ 		      ? 1 : -1];
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-	 if ac_fn_c_try_compile "$LINENO"
+-then :
++	 if ac_fn_c_try_compile "$LINENO"; then :
+   break
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
++rm -f core conftest.err conftest.$ac_objext
+ 	 CC="$CC -n32"
+-	 if ac_fn_c_try_compile "$LINENO"
+-then :
++	 if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_sys_largefile_CC=' -n32'; break
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam
++rm -f core conftest.err conftest.$ac_objext
+ 	 break
+        done
+        CC=$ac_save_CC
+        rm -f conftest.$ac_ext
+     fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+-printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
++$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+   if test "$ac_cv_sys_largefile_CC" != no; then
+     CC=$CC$ac_cv_sys_largefile_CC
+   fi
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+-printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+-if test ${ac_cv_sys_file_offset_bits+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
++$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
++if ${ac_cv_sys_file_offset_bits+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   while :; do
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+@@ -6705,23 +5966,22 @@ else $as_nop
+     We can't simply define LARGE_OFF_T to be 9223372036854775807,
+     since some C++ compilers masquerading as C compilers
+     incorrectly reject 9223372036854775807.  */
+-#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ 		       && LARGE_OFF_T % 2147483647 == 1)
+ 		      ? 1 : -1];
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_sys_file_offset_bits=no; break
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #define _FILE_OFFSET_BITS 64
+@@ -6730,43 +5990,43 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+     We can't simply define LARGE_OFF_T to be 9223372036854775807,
+     since some C++ compilers masquerading as C compilers
+     incorrectly reject 9223372036854775807.  */
+-#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ 		       && LARGE_OFF_T % 2147483647 == 1)
+ 		      ? 1 : -1];
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_sys_file_offset_bits=64; break
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cv_sys_file_offset_bits=unknown
+   break
+ done
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+-printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
++$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+ case $ac_cv_sys_file_offset_bits in #(
+   no | unknown) ;;
+   *)
+-printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
++_ACEOF
+ ;;
+ esac
+ rm -rf conftest*
+   if test $ac_cv_sys_file_offset_bits = unknown; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+-printf %s "checking for _LARGE_FILES value needed for large files... " >&6; }
+-if test ${ac_cv_sys_large_files+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
++$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
++if ${ac_cv_sys_large_files+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   while :; do
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+@@ -6775,23 +6035,22 @@ else $as_nop
+     We can't simply define LARGE_OFF_T to be 9223372036854775807,
+     since some C++ compilers masquerading as C compilers
+     incorrectly reject 9223372036854775807.  */
+-#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ 		       && LARGE_OFF_T % 2147483647 == 1)
+ 		      ? 1 : -1];
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_sys_large_files=no; break
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #define _LARGE_FILES 1
+@@ -6800,60 +6059,119 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+     We can't simply define LARGE_OFF_T to be 9223372036854775807,
+     since some C++ compilers masquerading as C compilers
+     incorrectly reject 9223372036854775807.  */
+-#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
++#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ 		       && LARGE_OFF_T % 2147483647 == 1)
+ 		      ? 1 : -1];
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_sys_large_files=1; break
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cv_sys_large_files=unknown
+   break
+ done
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+-printf "%s\n" "$ac_cv_sys_large_files" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
++$as_echo "$ac_cv_sys_large_files" >&6; }
+ case $ac_cv_sys_large_files in #(
+   no | unknown) ;;
+   *)
+-printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define _LARGE_FILES $ac_cv_sys_large_files
++_ACEOF
+ ;;
+ esac
+ rm -rf conftest*
+   fi
++
++
++fi
++
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
++ac_bolt_plugin_warn_cflags=
++save_CFLAGS="$CFLAGS"
++for real_option in -Wall; do
++  # Do the check with the no- prefix removed since gcc silently
++  # accepts any -Wno-* option on purpose
++  case $real_option in
++    -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
++    *) option=$real_option ;;
++  esac
++  as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
++
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
++$as_echo_n "checking whether $CC supports $option... " >&6; }
++if eval \${$as_acx_Woption+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  CFLAGS="$option"
++    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  eval "$as_acx_Woption=yes"
++else
++  eval "$as_acx_Woption=no"
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
+ fi
++eval ac_res=\$$as_acx_Woption
++	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
++$as_echo "$ac_res" >&6; }
++  if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
++  ac_bolt_plugin_warn_cflags="$ac_bolt_plugin_warn_cflags${ac_bolt_plugin_warn_cflags:+ }$real_option"
++fi
++  done
++CFLAGS="$save_CFLAGS"
++ac_ext=c
++ac_cpp='$CPP $CPPFLAGS'
++ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
++ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
++ac_compiler_gnu=$ac_cv_c_compiler_gnu
++
+ 
+ 
+ # Check whether -static-libgcc is supported.
+ saved_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -static-libgcc"
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -static-libgcc" >&5
+-printf %s "checking for -static-libgcc... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-libgcc" >&5
++$as_echo_n "checking for -static-libgcc... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+   int main() {}
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   have_static_libgcc=yes
+-else $as_nop
++else
+   have_static_libgcc=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_static_libgcc" >&5
+-printf "%s\n" "$have_static_libgcc" >&6; };
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_static_libgcc" >&5
++$as_echo "$have_static_libgcc" >&6; };
+ LDFLAGS="$saved_LDFLAGS"
+ # Need -Wc to get it through libtool.
+ if test "x$have_static_libgcc" = xyes; then
+@@ -6879,19 +6197,30 @@ fi
+ 
+ 
+ # Determine what GCC version number to use in filesystem paths.
+-GCC_BASE_VER
++
++  get_gcc_base_ver="cat"
++
++# Check whether --with-gcc-major-version-only was given.
++if test "${with_gcc_major_version_only+set}" = set; then :
++  withval=$with_gcc_major_version_only; if test x$with_gcc_major_version_only = xyes ; then
++        get_gcc_base_ver="sed -e 's/^\([0-9]*\).*/\1/'"
++      fi
++
++fi
++
++
++
+ 
+ case `pwd` in
+   *\ * | *\	*)
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+-printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
++$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+ esac
+ 
+ 
+ 
+-macro_version='2.4.7'
+-macro_revision='2.4.7'
+-
++macro_version='2.2.7a'
++macro_revision='1.3134'
+ 
+ 
+ 
+@@ -6905,7 +6234,7 @@ macro_revision='2.4.7'
+ 
+ 
+ 
+-ltmain=$ac_aux_dir/ltmain.sh
++ltmain="$ac_aux_dir/ltmain.sh"
+ 
+ # Backslashify metacharacters that are still active within
+ # double-quoted strings.
+@@ -6928,10 +6257,10 @@ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+-printf %s "checking how to print strings... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
++$as_echo_n "checking how to print strings... " >&6; }
+ # Test print first, because it will be a builtin if present.
+-if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
++if test "X`print -r -- -n 2>/dev/null`" = X-n && \
+    test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+   ECHO='print -r --'
+ elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+@@ -6954,13 +6283,13 @@ func_echo_all ()
+     $ECHO ""
+ }
+ 
+-case $ECHO in
+-  printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+-printf "%s\n" "printf" >&6; } ;;
+-  print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+-printf "%s\n" "print -r" >&6; } ;;
+-  *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+-printf "%s\n" "cat" >&6; } ;;
++case "$ECHO" in
++  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
++$as_echo "printf" >&6; } ;;
++  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
++$as_echo "print -r" >&6; } ;;
++  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
++$as_echo "cat" >&6; } ;;
+ esac
+ 
+ 
+@@ -6976,12 +6305,11 @@ esac
+ 
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+-printf %s "checking for a sed that does not truncate output... " >&6; }
+-if test ${ac_cv_path_SED+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
++$as_echo_n "checking for a sed that does not truncate output... " >&6; }
++if ${ac_cv_path_SED+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+             ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+      for ac_i in 1 2 3 4 5 6 7; do
+        ac_script="$ac_script$as_nl$ac_script"
+@@ -6995,15 +6323,10 @@ else $as_nop
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_prog in sed gsed
+-   do
++  test -z "$as_dir" && as_dir=.
++    for ac_prog in sed gsed; do
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-      ac_path_SED="$as_dir$ac_prog$ac_exec_ext"
++      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+       as_fn_executable_p "$ac_path_SED" || continue
+ # Check for GNU ac_path_SED and select it if it is found.
+   # Check for GNU $ac_path_SED
+@@ -7012,13 +6335,13 @@ case `"$ac_path_SED" --version 2>&1` in
+   ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+ *)
+   ac_count=0
+-  printf %s 0123456789 >"conftest.in"
++  $as_echo_n 0123456789 >"conftest.in"
+   while :
+   do
+     cat "conftest.in" "conftest.in" >"conftest.tmp"
+     mv "conftest.tmp" "conftest.in"
+     cp "conftest.in" "conftest.nl"
+-    printf "%s\n" '' >> "conftest.nl"
++    $as_echo '' >> "conftest.nl"
+     "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+     diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+     as_fn_arith $ac_count + 1 && ac_count=$as_val
+@@ -7046,172 +6369,29 @@ else
+ fi
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+-printf "%s\n" "$ac_cv_path_SED" >&6; }
+- SED="$ac_cv_path_SED"
+-  rm -f conftest.sed
+-
+-test -z "$SED" && SED=sed
+-Xsed="$SED -e 1s/^X//"
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+-printf %s "checking for grep that handles long lines and -e... " >&6; }
+-if test ${ac_cv_path_GREP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -z "$GREP"; then
+-  ac_path_GREP_found=false
+-  # Loop through the user's path and test for each of PROGNAME-LIST
+-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_prog in grep ggrep
+-   do
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-      ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+-      as_fn_executable_p "$ac_path_GREP" || continue
+-# Check for GNU ac_path_GREP and select it if it is found.
+-  # Check for GNU $ac_path_GREP
+-case `"$ac_path_GREP" --version 2>&1` in
+-*GNU*)
+-  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+-*)
+-  ac_count=0
+-  printf %s 0123456789 >"conftest.in"
+-  while :
+-  do
+-    cat "conftest.in" "conftest.in" >"conftest.tmp"
+-    mv "conftest.tmp" "conftest.in"
+-    cp "conftest.in" "conftest.nl"
+-    printf "%s\n" 'GREP' >> "conftest.nl"
+-    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+-    as_fn_arith $ac_count + 1 && ac_count=$as_val
+-    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+-      # Best one so far, save it but keep looking for a better one
+-      ac_cv_path_GREP="$ac_path_GREP"
+-      ac_path_GREP_max=$ac_count
+-    fi
+-    # 10*(2^10) chars as input seems more than enough
+-    test $ac_count -gt 10 && break
+-  done
+-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+-esac
+-
+-      $ac_path_GREP_found && break 3
+-    done
+-  done
+-  done
+-IFS=$as_save_IFS
+-  if test -z "$ac_cv_path_GREP"; then
+-    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+-  fi
+-else
+-  ac_cv_path_GREP=$GREP
+-fi
+-
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+-printf "%s\n" "$ac_cv_path_GREP" >&6; }
+- GREP="$ac_cv_path_GREP"
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+-printf %s "checking for egrep... " >&6; }
+-if test ${ac_cv_path_EGREP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+-   then ac_cv_path_EGREP="$GREP -E"
+-   else
+-     if test -z "$EGREP"; then
+-  ac_path_EGREP_found=false
+-  # Loop through the user's path and test for each of PROGNAME-LIST
+-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_prog in egrep
+-   do
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-      ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+-      as_fn_executable_p "$ac_path_EGREP" || continue
+-# Check for GNU ac_path_EGREP and select it if it is found.
+-  # Check for GNU $ac_path_EGREP
+-case `"$ac_path_EGREP" --version 2>&1` in
+-*GNU*)
+-  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+-*)
+-  ac_count=0
+-  printf %s 0123456789 >"conftest.in"
+-  while :
+-  do
+-    cat "conftest.in" "conftest.in" >"conftest.tmp"
+-    mv "conftest.tmp" "conftest.in"
+-    cp "conftest.in" "conftest.nl"
+-    printf "%s\n" 'EGREP' >> "conftest.nl"
+-    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+-    as_fn_arith $ac_count + 1 && ac_count=$as_val
+-    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+-      # Best one so far, save it but keep looking for a better one
+-      ac_cv_path_EGREP="$ac_path_EGREP"
+-      ac_path_EGREP_max=$ac_count
+-    fi
+-    # 10*(2^10) chars as input seems more than enough
+-    test $ac_count -gt 10 && break
+-  done
+-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+-esac
+-
+-      $ac_path_EGREP_found && break 3
+-    done
+-  done
+-  done
+-IFS=$as_save_IFS
+-  if test -z "$ac_cv_path_EGREP"; then
+-    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+-  fi
+-else
+-  ac_cv_path_EGREP=$EGREP
+-fi
+-
+-   fi
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+-printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+- EGREP="$ac_cv_path_EGREP"
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
++$as_echo "$ac_cv_path_SED" >&6; }
++ SED="$ac_cv_path_SED"
++  rm -f conftest.sed
++
++test -z "$SED" && SED=sed
++Xsed="$SED -e 1s/^X//"
++
++
++
++
++
++
++
++
++
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+-printf %s "checking for fgrep... " >&6; }
+-if test ${ac_cv_path_FGREP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
++$as_echo_n "checking for fgrep... " >&6; }
++if ${ac_cv_path_FGREP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+    then ac_cv_path_FGREP="$GREP -F"
+    else
+@@ -7222,15 +6402,10 @@ else $as_nop
+ for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_prog in fgrep
+-   do
++  test -z "$as_dir" && as_dir=.
++    for ac_prog in fgrep; do
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-      ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext"
++      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+       as_fn_executable_p "$ac_path_FGREP" || continue
+ # Check for GNU ac_path_FGREP and select it if it is found.
+   # Check for GNU $ac_path_FGREP
+@@ -7239,13 +6414,13 @@ case `"$ac_path_FGREP" --version 2>&1` in
+   ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+ *)
+   ac_count=0
+-  printf %s 0123456789 >"conftest.in"
++  $as_echo_n 0123456789 >"conftest.in"
+   while :
+   do
+     cat "conftest.in" "conftest.in" >"conftest.tmp"
+     mv "conftest.tmp" "conftest.in"
+     cp "conftest.in" "conftest.nl"
+-    printf "%s\n" 'FGREP' >> "conftest.nl"
++    $as_echo 'FGREP' >> "conftest.nl"
+     "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+     diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+     as_fn_arith $ac_count + 1 && ac_count=$as_val
+@@ -7274,8 +6449,8 @@ fi
+ 
+    fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+-printf "%s\n" "$ac_cv_path_FGREP" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
++$as_echo "$ac_cv_path_FGREP" >&6; }
+  FGREP="$ac_cv_path_FGREP"
+ 
+ 
+@@ -7300,21 +6475,20 @@ test -z "$GREP" && GREP=grep
+ 
+ 
+ # Check whether --with-gnu-ld was given.
+-if test ${with_gnu_ld+y}
+-then :
+-  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+-else $as_nop
++if test "${with_gnu_ld+set}" = set; then :
++  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
++else
+   with_gnu_ld=no
+ fi
+ 
+ ac_prog=ld
+-if test yes = "$GCC"; then
++if test "$GCC" = yes; then
+   # Check if gcc -print-prog-name=ld gives a path.
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+-printf %s "checking for ld used by $CC... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
++$as_echo_n "checking for ld used by $CC... " >&6; }
+   case $host in
+   *-*-mingw*)
+-    # gcc leaves a trailing carriage return, which upsets mingw
++    # gcc leaves a trailing carriage return which upsets mingw
+     ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+   *)
+     ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+@@ -7328,7 +6502,7 @@ printf %s "checking for ld used by $CC... " >&6; }
+       while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ 	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+       done
+-      test -z "$LD" && LD=$ac_prog
++      test -z "$LD" && LD="$ac_prog"
+       ;;
+   "")
+     # If it fails, then pretend we aren't using GCC.
+@@ -7339,58 +6513,56 @@ printf %s "checking for ld used by $CC... " >&6; }
+     with_gnu_ld=unknown
+     ;;
+   esac
+-elif test yes = "$with_gnu_ld"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+-printf %s "checking for GNU ld... " >&6; }
++elif test "$with_gnu_ld" = yes; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
++$as_echo_n "checking for GNU ld... " >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+-printf %s "checking for non-GNU ld... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
++$as_echo_n "checking for non-GNU ld... " >&6; }
+ fi
+-if test ${lt_cv_path_LD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++if ${lt_cv_path_LD+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -z "$LD"; then
+-  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+   for ac_dir in $PATH; do
+-    IFS=$lt_save_ifs
++    IFS="$lt_save_ifs"
+     test -z "$ac_dir" && ac_dir=.
+     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+-      lt_cv_path_LD=$ac_dir/$ac_prog
++      lt_cv_path_LD="$ac_dir/$ac_prog"
+       # Check to see if the program is GNU ld.  I'd rather use --version,
+       # but apparently some variants of GNU ld only accept -v.
+       # Break only if it was the GNU/non-GNU ld that we prefer.
+       case `"$lt_cv_path_LD" -v 2>&1 &5
+-printf "%s\n" "$LD" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
++$as_echo "$LD" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+-printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
+-if test ${lt_cv_prog_gnu_ld+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
++$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
++if ${lt_cv_prog_gnu_ld+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   # I'd rather use --version here, but apparently some GNU lds only accept -v.
+ case `$LD -v 2>&1 &1 &5
+-printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
++$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+ with_gnu_ld=$lt_cv_prog_gnu_ld
+ 
+ 
+@@ -7413,46 +6585,40 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
+ 
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+-printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+-if test ${lt_cv_path_NM+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
++$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
++if ${lt_cv_path_NM+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$NM"; then
+   # Let the user override the test.
+-  lt_cv_path_NM=$NM
++  lt_cv_path_NM="$NM"
+ else
+-  lt_nm_to_check=${ac_tool_prefix}nm
++  lt_nm_to_check="${ac_tool_prefix}nm"
+   if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+     lt_nm_to_check="$lt_nm_to_check nm"
+   fi
+   for lt_tmp_nm in $lt_nm_to_check; do
+-    lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+     for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+-      IFS=$lt_save_ifs
++      IFS="$lt_save_ifs"
+       test -z "$ac_dir" && ac_dir=.
+-      tmp_nm=$ac_dir/$lt_tmp_nm
+-      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
++      tmp_nm="$ac_dir/$lt_tmp_nm"
++      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ 	# Check to see if the nm accepts a BSD-compat flag.
+-	# Adding the 'sed 1q' prevents false positives on HP-UX, which says:
++	# Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ 	#   nm: unknown option "B" ignored
+ 	# Tru64's nm complains that /dev/null is an invalid object file
+-	# MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+-	case $build_os in
+-	mingw*) lt_bad_file=conftest.nm/nofile ;;
+-	*) lt_bad_file=/dev/null ;;
+-	esac
+-	case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+-	*$lt_bad_file* | *'Invalid file or object type'*)
++	case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
++	*/dev/null* | *'Invalid file or object type'*)
+ 	  lt_cv_path_NM="$tmp_nm -B"
+-	  break 2
++	  break
+ 	  ;;
+ 	*)
+-	  case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
++	  case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ 	  */dev/null*)
+ 	    lt_cv_path_NM="$tmp_nm -p"
+-	    break 2
++	    break
+ 	    ;;
+ 	  *)
+ 	    lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+@@ -7463,15 +6629,15 @@ else
+ 	esac
+       fi
+     done
+-    IFS=$lt_save_ifs
++    IFS="$lt_save_ifs"
+   done
+   : ${lt_cv_path_NM=no}
+ fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+-printf "%s\n" "$lt_cv_path_NM" >&6; }
+-if test no != "$lt_cv_path_NM"; then
+-  NM=$lt_cv_path_NM
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
++$as_echo "$lt_cv_path_NM" >&6; }
++if test "$lt_cv_path_NM" != "no"; then
++  NM="$lt_cv_path_NM"
+ else
+   # Didn't find any BSD compatible name lister, look for dumpbin.
+   if test -n "$DUMPBIN"; then :
+@@ -7482,12 +6648,11 @@ else
+   do
+     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+ set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_DUMPBIN+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_DUMPBIN+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$DUMPBIN"; then
+   ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+ else
+@@ -7495,15 +6660,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -7514,11 +6675,11 @@ fi
+ fi
+ DUMPBIN=$ac_cv_prog_DUMPBIN
+ if test -n "$DUMPBIN"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+-printf "%s\n" "$DUMPBIN" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
++$as_echo "$DUMPBIN" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -7531,12 +6692,11 @@ if test -z "$DUMPBIN"; then
+ do
+   # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_DUMPBIN+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_DUMPBIN"; then
+   ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+ else
+@@ -7544,15 +6704,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -7563,11 +6719,11 @@ fi
+ fi
+ ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+ if test -n "$ac_ct_DUMPBIN"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+-printf "%s\n" "$ac_ct_DUMPBIN" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
++$as_echo "$ac_ct_DUMPBIN" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -7579,17 +6735,17 @@ done
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     DUMPBIN=$ac_ct_DUMPBIN
+   fi
+ fi
+ 
+-    case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
++    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+     *COFF*)
+-      DUMPBIN="$DUMPBIN -symbols -headers"
++      DUMPBIN="$DUMPBIN -symbols"
+       ;;
+     *)
+       DUMPBIN=:
+@@ -7597,8 +6753,8 @@ fi
+     esac
+   fi
+ 
+-  if test : != "$DUMPBIN"; then
+-    NM=$DUMPBIN
++  if test "$DUMPBIN" != ":"; then
++    NM="$DUMPBIN"
+   fi
+ fi
+ test -z "$NM" && NM=nm
+@@ -7608,12 +6764,11 @@ test -z "$NM" && NM=nm
+ 
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+-printf %s "checking the name lister ($NM) interface... " >&6; }
+-if test ${lt_cv_nm_interface+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
++$as_echo_n "checking the name lister ($NM) interface... " >&6; }
++if ${lt_cv_nm_interface+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_nm_interface="BSD nm"
+   echo "int some_variable = 0;" > conftest.$ac_ext
+   (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+@@ -7629,29 +6784,28 @@ else $as_nop
+   fi
+   rm -f conftest*
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+-printf "%s\n" "$lt_cv_nm_interface" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
++$as_echo "$lt_cv_nm_interface" >&6; }
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+-printf %s "checking whether ln -s works... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
++$as_echo_n "checking whether ln -s works... " >&6; }
+ LN_S=$as_ln_s
+ if test "$LN_S" = "ln -s"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+-printf "%s\n" "no, using $LN_S" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
++$as_echo "no, using $LN_S" >&6; }
+ fi
+ 
+ # find the maximum length of command line arguments
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+-printf %s "checking the maximum length of command line arguments... " >&6; }
+-if test ${lt_cv_sys_max_cmd_len+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
++$as_echo_n "checking the maximum length of command line arguments... " >&6; }
++if ${lt_cv_sys_max_cmd_len+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+     i=0
+-  teststring=ABCD
++  teststring="ABCD"
+ 
+   case $build_os in
+   msdosdjgpp*)
+@@ -7691,7 +6845,7 @@ else $as_nop
+     lt_cv_sys_max_cmd_len=8192;
+     ;;
+ 
+-  bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
++  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+     # This has been around since 386BSD, at least.  Likely further.
+     if test -x /sbin/sysctl; then
+       lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+@@ -7710,11 +6864,6 @@ else $as_nop
+     lt_cv_sys_max_cmd_len=196608
+     ;;
+ 
+-  os2*)
+-    # The test takes a long time on OS/2.
+-    lt_cv_sys_max_cmd_len=8192
+-    ;;
+-
+   osf*)
+     # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+     # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+@@ -7734,30 +6883,29 @@ else $as_nop
+   sysv5* | sco5v6* | sysv4.2uw2*)
+     kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+     if test -n "$kargmax"; then
+-      lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[	 ]//'`
++      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[	 ]//'`
+     else
+       lt_cv_sys_max_cmd_len=32768
+     fi
+     ;;
+   *)
+     lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+-    if test -n "$lt_cv_sys_max_cmd_len" && \
+-       test undefined != "$lt_cv_sys_max_cmd_len"; then
++    if test -n "$lt_cv_sys_max_cmd_len"; then
+       lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+       lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+     else
+       # Make teststring a little bigger before we do anything with it.
+       # a 1K string should be a reasonable start.
+-      for i in 1 2 3 4 5 6 7 8; do
++      for i in 1 2 3 4 5 6 7 8 ; do
+         teststring=$teststring$teststring
+       done
+       SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+       # If test is not a shell built-in, we'll probably end up computing a
+       # maximum length that is only half of the actual maximum length, but
+       # we can't tell.
+-      while { test X`env echo "$teststring$teststring" 2>/dev/null` \
++      while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+ 	         = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+-	      test 17 != "$i" # 1/2 MB should be enough
++	      test $i != 17 # 1/2 MB should be enough
+       do
+         i=`expr $i + 1`
+         teststring=$teststring$teststring
+@@ -7775,12 +6923,12 @@ else $as_nop
+ 
+ fi
+ 
+-if test -n "$lt_cv_sys_max_cmd_len"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+-printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; }
++if test -n $lt_cv_sys_max_cmd_len ; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
++$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
+-printf "%s\n" "none" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
++$as_echo "none" >&6; }
+ fi
+ max_cmd_len=$lt_cv_sys_max_cmd_len
+ 
+@@ -7793,6 +6941,30 @@ max_cmd_len=$lt_cv_sys_max_cmd_len
+ : ${MV="mv -f"}
+ : ${RM="rm -f"}
+ 
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
++$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
++# Try some XSI features
++xsi_shell=no
++( _lt_dummy="a/b/c"
++  test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
++      = c,a/b,, \
++    && eval 'test $(( 1 + 1 )) -eq 2 \
++    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
++  && xsi_shell=yes
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
++$as_echo "$xsi_shell" >&6; }
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
++$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
++lt_shell_append=no
++( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
++    >/dev/null 2>&1 \
++  && lt_shell_append=yes
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
++$as_echo "$lt_shell_append" >&6; }
++
++
+ if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+   lt_unset=unset
+ else
+@@ -7824,92 +6996,15 @@ esac
+ 
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+-printf %s "checking how to convert $build file names to $host format... " >&6; }
+-if test ${lt_cv_to_host_file_cmd+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  case $host in
+-  *-*-mingw* )
+-    case $build in
+-      *-*-mingw* ) # actually msys
+-        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+-        ;;
+-      *-*-cygwin* )
+-        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+-        ;;
+-      * ) # otherwise, assume *nix
+-        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+-        ;;
+-    esac
+-    ;;
+-  *-*-cygwin* )
+-    case $build in
+-      *-*-mingw* ) # actually msys
+-        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+-        ;;
+-      *-*-cygwin* )
+-        lt_cv_to_host_file_cmd=func_convert_file_noop
+-        ;;
+-      * ) # otherwise, assume *nix
+-        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+-        ;;
+-    esac
+-    ;;
+-  * ) # unhandled hosts (and "normal" native builds)
+-    lt_cv_to_host_file_cmd=func_convert_file_noop
+-    ;;
+-esac
+-
+-fi
+-
+-to_host_file_cmd=$lt_cv_to_host_file_cmd
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+-printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; }
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+-printf %s "checking how to convert $build file names to toolchain format... " >&6; }
+-if test ${lt_cv_to_tool_file_cmd+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  #assume ordinary cross tools, or native build.
+-lt_cv_to_tool_file_cmd=func_convert_file_noop
+-case $host in
+-  *-*-mingw* )
+-    case $build in
+-      *-*-mingw* ) # actually msys
+-        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+-        ;;
+-    esac
+-    ;;
+-esac
+-
+-fi
+-
+-to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+-printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; }
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+-printf %s "checking for $LD option to reload object files... " >&6; }
+-if test ${lt_cv_ld_reload_flag+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
++$as_echo_n "checking for $LD option to reload object files... " >&6; }
++if ${lt_cv_ld_reload_flag+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_ld_reload_flag='-r'
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+-printf "%s\n" "$lt_cv_ld_reload_flag" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
++$as_echo "$lt_cv_ld_reload_flag" >&6; }
+ reload_flag=$lt_cv_ld_reload_flag
+ case $reload_flag in
+ "" | " "*) ;;
+@@ -7917,14 +7012,9 @@ case $reload_flag in
+ esac
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ case $host_os in
+-  cygwin* | mingw* | pw32* | cegcc*)
+-    if test yes != "$GCC"; then
+-      reload_cmds=false
+-    fi
+-    ;;
+   darwin*)
+-    if test yes = "$GCC"; then
+-      reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
++    if test "$GCC" = yes; then
++      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+     else
+       reload_cmds='$LD$reload_flag -o $output$reload_objs'
+     fi
+@@ -7939,123 +7029,14 @@ esac
+ 
+ 
+ 
+-if test -n "$ac_tool_prefix"; then
+-  # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args.
+-set dummy ${ac_tool_prefix}file; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_FILECMD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$FILECMD"; then
+-  ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_FILECMD="${ac_tool_prefix}file"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-FILECMD=$ac_cv_prog_FILECMD
+-if test -n "$FILECMD"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
+-printf "%s\n" "$FILECMD" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-
+-fi
+-if test -z "$ac_cv_prog_FILECMD"; then
+-  ac_ct_FILECMD=$FILECMD
+-  # Extract the first word of "file", so it can be a program name with args.
+-set dummy file; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_FILECMD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$ac_ct_FILECMD"; then
+-  ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_FILECMD="file"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD
+-if test -n "$ac_ct_FILECMD"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5
+-printf "%s\n" "$ac_ct_FILECMD" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-  if test "x$ac_ct_FILECMD" = x; then
+-    FILECMD=":"
+-  else
+-    case $cross_compiling:$ac_tool_warned in
+-yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+-ac_tool_warned=yes ;;
+-esac
+-    FILECMD=$ac_ct_FILECMD
+-  fi
+-else
+-  FILECMD="$ac_cv_prog_FILECMD"
+-fi
+-
+-
+-
+-
+-
+-
+-
+ if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}objdump; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_OBJDUMP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_OBJDUMP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$OBJDUMP"; then
+   ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+ else
+@@ -8063,15 +7044,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8082,11 +7059,11 @@ fi
+ fi
+ OBJDUMP=$ac_cv_prog_OBJDUMP
+ if test -n "$OBJDUMP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+-printf "%s\n" "$OBJDUMP" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
++$as_echo "$OBJDUMP" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -8095,12 +7072,11 @@ if test -z "$ac_cv_prog_OBJDUMP"; then
+   ac_ct_OBJDUMP=$OBJDUMP
+   # Extract the first word of "objdump", so it can be a program name with args.
+ set dummy objdump; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_OBJDUMP"; then
+   ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+ else
+@@ -8108,15 +7084,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_OBJDUMP="objdump"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8127,11 +7099,11 @@ fi
+ fi
+ ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+ if test -n "$ac_ct_OBJDUMP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+-printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
++$as_echo "$ac_ct_OBJDUMP" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_OBJDUMP" = x; then
+@@ -8139,8 +7111,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     OBJDUMP=$ac_ct_OBJDUMP
+@@ -8159,25 +7131,24 @@ test -z "$OBJDUMP" && OBJDUMP=objdump
+ 
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+-printf %s "checking how to recognize dependent libraries... " >&6; }
+-if test ${lt_cv_deplibs_check_method+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
++$as_echo_n "checking how to recognize dependent libraries... " >&6; }
++if ${lt_cv_deplibs_check_method+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_file_magic_cmd='$MAGIC_CMD'
+ lt_cv_file_magic_test_file=
+ lt_cv_deplibs_check_method='unknown'
+ # Need to set the preceding variable on all platforms that support
+ # interlibrary dependencies.
+ # 'none' -- dependencies not supported.
+-# 'unknown' -- same as none, but documents that we really don't know.
++# `unknown' -- same as none, but documents that we really don't know.
+ # 'pass_all' -- all dependencies passed with no checks.
+ # 'test_compile' -- check by making test program.
+ # 'file_magic [[regex]]' -- check by looking for files in library path
+-# that responds to the $file_magic_cmd with a given extended regex.
+-# If you have 'file' or equivalent on your system and you're not sure
+-# whether 'pass_all' will *always* work, you probably want this one.
++# which responds to the $file_magic_cmd with a given extended regex.
++# If you have `file' or equivalent on your system and you're not sure
++# whether `pass_all' will *always* work, you probably want this one.
+ 
+ case $host_os in
+ aix[4-9]*)
+@@ -8190,7 +7161,7 @@ beos*)
+ 
+ bsdi[45]*)
+   lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+-  lt_cv_file_magic_cmd='$FILECMD -L'
++  lt_cv_file_magic_cmd='/usr/bin/file -L'
+   lt_cv_file_magic_test_file=/shlib/libc.so
+   ;;
+ 
+@@ -8204,12 +7175,12 @@ mingw* | pw32*)
+   # Base MSYS/MinGW do not provide the 'file' command needed by
+   # func_win32_libid shell function, so use a weaker test based on 'objdump',
+   # unless we find 'file', for example because we are cross-compiling.
+-  if ( file / ) >/dev/null 2>&1; then
++  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
++  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+     lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+     lt_cv_file_magic_cmd='func_win32_libid'
+   else
+-    # Keep this pattern in sync with the one in func_win32_libid.
+-    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
++    lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+     lt_cv_file_magic_cmd='$OBJDUMP -f'
+   fi
+   ;;
+@@ -8224,14 +7195,14 @@ darwin* | rhapsody*)
+   lt_cv_deplibs_check_method=pass_all
+   ;;
+ 
+-freebsd* | dragonfly* | midnightbsd*)
++freebsd* | dragonfly*)
+   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+     case $host_cpu in
+     i*86 )
+       # Not sure whether the presence of OpenBSD here was a mistake.
+       # Let's accept both of them until this is cleared up.
+       lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+-      lt_cv_file_magic_cmd=$FILECMD
++      lt_cv_file_magic_cmd=/usr/bin/file
+       lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+       ;;
+     esac
+@@ -8240,12 +7211,16 @@ freebsd* | dragonfly* | midnightbsd*)
+   fi
+   ;;
+ 
++gnu*)
++  lt_cv_deplibs_check_method=pass_all
++  ;;
++
+ haiku*)
+   lt_cv_deplibs_check_method=pass_all
+   ;;
+ 
+ hpux10.20* | hpux11*)
+-  lt_cv_file_magic_cmd=$FILECMD
++  lt_cv_file_magic_cmd=/usr/bin/file
+   case $host_cpu in
+   ia64*)
+     lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+@@ -8277,8 +7252,8 @@ irix5* | irix6* | nonstopux*)
+   lt_cv_deplibs_check_method=pass_all
+   ;;
+ 
+-# This must be glibc/ELF.
+-linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++# This must be Linux ELF.
++linux* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)
+   lt_cv_deplibs_check_method=pass_all
+   ;;
+ 
+@@ -8292,7 +7267,7 @@ netbsd*)
+ 
+ newos6*)
+   lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+-  lt_cv_file_magic_cmd=$FILECMD
++  lt_cv_file_magic_cmd=/usr/bin/file
+   lt_cv_file_magic_test_file=/usr/lib/libnls.so
+   ;;
+ 
+@@ -8300,8 +7275,8 @@ newos6*)
+   lt_cv_deplibs_check_method=pass_all
+   ;;
+ 
+-openbsd* | bitrig*)
+-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++openbsd*)
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+   else
+     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+@@ -8333,220 +7308,40 @@ sysv4 | sysv4.3*)
+   ncr)
+     lt_cv_deplibs_check_method=pass_all
+     ;;
+-  sequent)
+-    lt_cv_file_magic_cmd='/bin/file'
+-    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+-    ;;
+-  sni)
+-    lt_cv_file_magic_cmd='/bin/file'
+-    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+-    lt_cv_file_magic_test_file=/lib/libc.so
+-    ;;
+-  siemens)
+-    lt_cv_deplibs_check_method=pass_all
+-    ;;
+-  pc)
+-    lt_cv_deplibs_check_method=pass_all
+-    ;;
+-  esac
+-  ;;
+-
+-tpf*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-os2*)
+-  lt_cv_deplibs_check_method=pass_all
+-  ;;
+-esac
+-
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+-printf "%s\n" "$lt_cv_deplibs_check_method" >&6; }
+-
+-file_magic_glob=
+-want_nocaseglob=no
+-if test "$build" = "$host"; then
+-  case $host_os in
+-  mingw* | pw32*)
+-    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+-      want_nocaseglob=yes
+-    else
+-      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+-    fi
+-    ;;
+-  esac
+-fi
+-
+-file_magic_cmd=$lt_cv_file_magic_cmd
+-deplibs_check_method=$lt_cv_deplibs_check_method
+-test -z "$deplibs_check_method" && deplibs_check_method=unknown
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-if test -n "$ac_tool_prefix"; then
+-  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+-set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_DLLTOOL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$DLLTOOL"; then
+-  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-DLLTOOL=$ac_cv_prog_DLLTOOL
+-if test -n "$DLLTOOL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+-printf "%s\n" "$DLLTOOL" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-
+-fi
+-if test -z "$ac_cv_prog_DLLTOOL"; then
+-  ac_ct_DLLTOOL=$DLLTOOL
+-  # Extract the first word of "dlltool", so it can be a program name with args.
+-set dummy dlltool; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$ac_ct_DLLTOOL"; then
+-  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+-if test -n "$ac_ct_DLLTOOL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+-printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-  if test "x$ac_ct_DLLTOOL" = x; then
+-    DLLTOOL="false"
+-  else
+-    case $cross_compiling:$ac_tool_warned in
+-yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+-ac_tool_warned=yes ;;
+-esac
+-    DLLTOOL=$ac_ct_DLLTOOL
+-  fi
+-else
+-  DLLTOOL="$ac_cv_prog_DLLTOOL"
+-fi
+-
+-test -z "$DLLTOOL" && DLLTOOL=dlltool
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+-printf %s "checking how to associate runtime and link libraries... " >&6; }
+-if test ${lt_cv_sharedlib_from_linklib_cmd+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  lt_cv_sharedlib_from_linklib_cmd='unknown'
+-
+-case $host_os in
+-cygwin* | mingw* | pw32* | cegcc*)
+-  # two different shell functions defined in ltmain.sh;
+-  # decide which one to use based on capabilities of $DLLTOOL
+-  case `$DLLTOOL --help 2>&1` in
+-  *--identify-strict*)
+-    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+-    ;;
+-  *)
+-    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
++  sequent)
++    lt_cv_file_magic_cmd='/bin/file'
++    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
++    ;;
++  sni)
++    lt_cv_file_magic_cmd='/bin/file'
++    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
++    lt_cv_file_magic_test_file=/lib/libc.so
++    ;;
++  siemens)
++    lt_cv_deplibs_check_method=pass_all
++    ;;
++  pc)
++    lt_cv_deplibs_check_method=pass_all
+     ;;
+   esac
+   ;;
+-*)
+-  # fallback: assume linklib IS sharedlib
+-  lt_cv_sharedlib_from_linklib_cmd=$ECHO
++
++tpf*)
++  lt_cv_deplibs_check_method=pass_all
+   ;;
+ esac
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+-printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+-sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+-test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
++$as_echo "$lt_cv_deplibs_check_method" >&6; }
++file_magic_cmd=$lt_cv_file_magic_cmd
++deplibs_check_method=$lt_cv_deplibs_check_method
++test -z "$deplibs_check_method" && deplibs_check_method=unknown
++
++
++
++
++
+ 
+ 
+ 
+@@ -8555,16 +7350,13 @@ test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+ 
+ 
+ if test -n "$ac_tool_prefix"; then
+-  for ac_prog in ar
+-  do
+-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_AR+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
++set dummy ${ac_tool_prefix}ar; ac_word=$2
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_AR+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$AR"; then
+   ac_cv_prog_AR="$AR" # Let the user override the test.
+ else
+@@ -8572,15 +7364,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    ac_cv_prog_AR="${ac_tool_prefix}ar"
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8591,29 +7379,24 @@ fi
+ fi
+ AR=$ac_cv_prog_AR
+ if test -n "$AR"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+-printf "%s\n" "$AR" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
++$as_echo "$AR" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+-    test -n "$AR" && break
+-  done
+ fi
+-if test -z "$AR"; then
++if test -z "$ac_cv_prog_AR"; then
+   ac_ct_AR=$AR
+-  for ac_prog in ar
+-do
+-  # Extract the first word of "$ac_prog", so it can be a program name with args.
+-set dummy $ac_prog; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_AR+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  # Extract the first word of "ar", so it can be a program name with args.
++set dummy ar; ac_word=$2
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_AR+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_AR"; then
+   ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+ else
+@@ -8621,15 +7404,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_AR="$ac_prog"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    ac_cv_prog_ac_ct_AR="ar"
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8640,112 +7419,34 @@ fi
+ fi
+ ac_ct_AR=$ac_cv_prog_ac_ct_AR
+ if test -n "$ac_ct_AR"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+-printf "%s\n" "$ac_ct_AR" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
++$as_echo "$ac_ct_AR" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+-
+-  test -n "$ac_ct_AR" && break
+-done
+-
+   if test "x$ac_ct_AR" = x; then
+     AR="false"
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     AR=$ac_ct_AR
+   fi
++else
++  AR="$ac_cv_prog_AR"
+ fi
+ 
+-: ${AR=ar}
+-
+-
+-
+-
+-
+-
+-# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+-# Automake.  If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+-# higher priority because thats what people were doing historically (setting
+-# ARFLAGS for automake and AR_FLAGS for libtool).  FIXME: Make the AR_FLAGS
+-# variable obsoleted/removed.
+-
+-test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+-lt_ar_flags=$AR_FLAGS
+-
+-
+-
+-
+-
+-
+-# Make AR_FLAGS overridable by 'make ARFLAGS='.  Don't try to run-time override
+-# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+-
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+-printf %s "checking for archiver @FILE support... " >&6; }
+-if test ${lt_cv_ar_at_file+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  lt_cv_ar_at_file=no
+-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h.  */
+-
+-int
+-main (void)
+-{
++test -z "$AR" && AR=ar
++test -z "$AR_FLAGS" && AR_FLAGS=cru
+ 
+-  ;
+-  return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
+-  echo conftest.$ac_objext > conftest.lst
+-      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+-      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+-  (eval $lt_ar_try) 2>&5
+-  ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }
+-      if test 0 -eq "$ac_status"; then
+-	# Ensure the archiver fails upon bogus file names.
+-	rm -f conftest.$ac_objext libconftest.a
+-	{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+-  (eval $lt_ar_try) 2>&5
+-  ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }
+-	if test 0 -ne "$ac_status"; then
+-          lt_cv_ar_at_file=@
+-        fi
+-      fi
+-      rm -f conftest.* libconftest.a
+ 
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ 
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+-printf "%s\n" "$lt_cv_ar_at_file" >&6; }
+ 
+-if test no = "$lt_cv_ar_at_file"; then
+-  archiver_list_spec=
+-else
+-  archiver_list_spec=$lt_cv_ar_at_file
+-fi
+ 
+ 
+ 
+@@ -8756,12 +7457,11 @@ fi
+ if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}strip; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_STRIP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_STRIP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$STRIP"; then
+   ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+ else
+@@ -8769,15 +7469,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8788,11 +7484,11 @@ fi
+ fi
+ STRIP=$ac_cv_prog_STRIP
+ if test -n "$STRIP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+-printf "%s\n" "$STRIP" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
++$as_echo "$STRIP" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -8801,12 +7497,11 @@ if test -z "$ac_cv_prog_STRIP"; then
+   ac_ct_STRIP=$STRIP
+   # Extract the first word of "strip", so it can be a program name with args.
+ set dummy strip; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_STRIP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_STRIP"; then
+   ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+ else
+@@ -8814,15 +7509,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_STRIP="strip"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8833,11 +7524,11 @@ fi
+ fi
+ ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+ if test -n "$ac_ct_STRIP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+-printf "%s\n" "$ac_ct_STRIP" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
++$as_echo "$ac_ct_STRIP" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_STRIP" = x; then
+@@ -8845,8 +7536,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     STRIP=$ac_ct_STRIP
+@@ -8865,12 +7556,11 @@ test -z "$STRIP" && STRIP=:
+ if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_RANLIB+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_RANLIB+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$RANLIB"; then
+   ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+ else
+@@ -8878,15 +7568,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8897,11 +7583,11 @@ fi
+ fi
+ RANLIB=$ac_cv_prog_RANLIB
+ if test -n "$RANLIB"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+-printf "%s\n" "$RANLIB" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
++$as_echo "$RANLIB" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -8910,12 +7596,11 @@ if test -z "$ac_cv_prog_RANLIB"; then
+   ac_ct_RANLIB=$RANLIB
+   # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_RANLIB+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_RANLIB"; then
+   ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+ else
+@@ -8923,15 +7608,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_RANLIB="ranlib"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -8942,11 +7623,11 @@ fi
+ fi
+ ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+ if test -n "$ac_ct_RANLIB"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+-printf "%s\n" "$ac_ct_RANLIB" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
++$as_echo "$ac_ct_RANLIB" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_RANLIB" = x; then
+@@ -8954,8 +7635,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     RANLIB=$ac_ct_RANLIB
+@@ -8978,14 +7659,14 @@ old_postuninstall_cmds=
+ 
+ if test -n "$RANLIB"; then
+   case $host_os in
+-  bitrig* | openbsd*)
+-    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
++  openbsd*)
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+     ;;
+   *)
+-    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
++    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+     ;;
+   esac
+-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
++  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+ fi
+ 
+ case $host_os in
+@@ -9044,12 +7725,11 @@ compiler=$CC
+ 
+ 
+ # Check for command to grab the raw symbol name followed by C symbol from nm.
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+-printf %s "checking command to parse $NM output from $compiler object... " >&6; }
+-if test ${lt_cv_sys_global_symbol_pipe+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
++$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
++if ${lt_cv_sys_global_symbol_pipe+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+ 
+ # These are sane defaults that work on at least a few old systems.
+ # [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+@@ -9069,7 +7749,7 @@ cygwin* | mingw* | pw32* | cegcc*)
+   symcode='[ABCDGISTW]'
+   ;;
+ hpux*)
+-  if test ia64 = "$host_cpu"; then
++  if test "$host_cpu" = ia64; then
+     symcode='[ABCDEGRST]'
+   fi
+   ;;
+@@ -9102,44 +7782,14 @@ case `$NM -V 2>&1` in
+   symcode='[ABCDGIRSTW]' ;;
+ esac
+ 
+-if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+-  # Gets list of data symbols to import.
+-  lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+-  # Adjust the below global symbol transforms to fixup imported variables.
+-  lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+-  lt_c_name_hook=" -e 's/^I .* \(.*\)$/  {\"\1\", (void *) 0},/p'"
+-  lt_c_name_lib_hook="\
+-  -e 's/^I .* \(lib.*\)$/  {\"\1\", (void *) 0},/p'\
+-  -e 's/^I .* \(.*\)$/  {\"lib\1\", (void *) 0},/p'"
+-else
+-  # Disable hooks by default.
+-  lt_cv_sys_global_symbol_to_import=
+-  lt_cdecl_hook=
+-  lt_c_name_hook=
+-  lt_c_name_lib_hook=
+-fi
+-
+ # Transform an extracted symbol line into a proper C declaration.
+ # Some systems (esp. on ia64) link data and code symbols differently,
+ # so use this general approach.
+-lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+-$lt_cdecl_hook\
+-" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+-" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
++lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ 
+ # Transform an extracted symbol line into symbol name and symbol address
+-lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+-$lt_c_name_hook\
+-" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+-" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/p'"
+-
+-# Transform an extracted symbol line into symbol name with lib prefix and
+-# symbol address.
+-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+-$lt_c_name_lib_hook\
+-" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+-" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+-" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
++lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
++lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+ 
+ # Handle CRLF in mingw tool chain
+ opt_cr=
+@@ -9157,29 +7807,24 @@ for ac_symprfx in "" "_"; do
+ 
+   # Write the raw and C identifiers.
+   if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+-    # Fake it for dumpbin and say T for any non-static function,
+-    # D for any global variable and I for any imported variable.
+-    # Also find C++ and __fastcall symbols from MSVC++ or ICC,
++    # Fake it for dumpbin and say T for any non-static function
++    # and D for any global variable.
++    # Also find C++ and __fastcall symbols from MSVC++,
+     # which start with @ or ?.
+     lt_cv_sys_global_symbol_pipe="$AWK '"\
+ "     {last_section=section; section=\$ 3};"\
+-"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+ "     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+-"     /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+-"     /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+-"     /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+ "     \$ 0!~/External *\|/{next};"\
+ "     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+ "     {if(hide[section]) next};"\
+-"     {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+-"     {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+-"     s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+-"     s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
++"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
++"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
++"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
++"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+ "     ' prfx=^$ac_symprfx"
+   else
+-    lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
++    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[	 ]\($symcode$symcode*\)[	 ][	 ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+   fi
+-  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+ 
+   # Check to see that the pipe works correctly.
+   pipe_works=no
+@@ -9201,14 +7846,14 @@ _LT_EOF
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+     # Now try to grab the symbols.
+     nlist=conftest.nm
+     if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+   (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } && test -s "$nlist"; then
+       # Try sorting and uniquifying the output.
+       if sort "$nlist" | uniq > "$nlist"T; then
+@@ -9221,18 +7866,6 @@ _LT_EOF
+       if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ 	if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ 	  cat <<_LT_EOF > conftest.$ac_ext
+-/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+-#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+-/* DATA imports from DLLs on WIN32 can't be const, because runtime
+-   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+-# define LT_DLSYM_CONST
+-#elif defined __osf__
+-/* This system does not cope well with relocations in const data.  */
+-# define LT_DLSYM_CONST
+-#else
+-# define LT_DLSYM_CONST const
+-#endif
+-
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+@@ -9244,7 +7877,7 @@ _LT_EOF
+ 	  cat <<_LT_EOF >> conftest.$ac_ext
+ 
+ /* The mapping between symbol names and symbols.  */
+-LT_DLSYM_CONST struct {
++const struct {
+   const char *name;
+   void       *address;
+ }
+@@ -9252,7 +7885,7 @@ lt__PROGRAM__LTX_preloaded_symbols[] =
+ {
+   { "@PROGRAM@", (void *) 0 },
+ _LT_EOF
+-	  $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
++	  $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ 	  cat <<\_LT_EOF >> conftest.$ac_ext
+   {0, (void *) 0}
+ };
+@@ -9270,19 +7903,19 @@ static const void *lt_preloaded_setup() {
+ _LT_EOF
+ 	  # Now try linking the two files.
+ 	  mv conftest.$ac_objext conftstm.$ac_objext
+-	  lt_globsym_save_LIBS=$LIBS
+-	  lt_globsym_save_CFLAGS=$CFLAGS
+-	  LIBS=conftstm.$ac_objext
++	  lt_save_LIBS="$LIBS"
++	  lt_save_CFLAGS="$CFLAGS"
++	  LIBS="conftstm.$ac_objext"
+ 	  CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ 	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+   (eval $ac_link) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; } && test -s conftest$ac_exeext; then
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+ 	    pipe_works=yes
+ 	  fi
+-	  LIBS=$lt_globsym_save_LIBS
+-	  CFLAGS=$lt_globsym_save_CFLAGS
++	  LIBS="$lt_save_LIBS"
++	  CFLAGS="$lt_save_CFLAGS"
+ 	else
+ 	  echo "cannot find nm_test_func in $nlist" >&5
+ 	fi
+@@ -9299,7 +7932,7 @@ _LT_EOF
+   rm -rf conftest* conftst*
+ 
+   # Do not use the global_symbol_pipe unless it works.
+-  if test yes = "$pipe_works"; then
++  if test "$pipe_works" = yes; then
+     break
+   else
+     lt_cv_sys_global_symbol_pipe=
+@@ -9312,18 +7945,11 @@ if test -z "$lt_cv_sys_global_symbol_pipe"; then
+   lt_cv_sys_global_symbol_to_cdecl=
+ fi
+ if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+-printf "%s\n" "failed" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
++$as_echo "failed" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+-printf "%s\n" "ok" >&6; }
+-fi
+-
+-# Response file support.
+-if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+-  nm_file_list_spec='@'
+-elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+-  nm_file_list_spec='@'
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
++$as_echo "ok" >&6; }
+ fi
+ 
+ 
+@@ -9346,189 +7972,46 @@ fi
+ 
+ 
+ 
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+-printf %s "checking for sysroot... " >&6; }
+-
+-# Check whether --with-sysroot was given.
+-if test ${with_sysroot+y}
+-then :
+-  withval=$with_sysroot;
+-else $as_nop
+-  with_sysroot=no
+-fi
+-
+-
+-lt_sysroot=
+-case $with_sysroot in #(
+- yes)
+-   if test yes = "$GCC"; then
+-     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+-   fi
+-   ;; #(
+- /*)
+-   lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+-   ;; #(
+- no|'')
+-   ;; #(
+- *)
+-   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
+-printf "%s\n" "$with_sysroot" >&6; }
+-   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+-   ;;
+-esac
+-
+- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+-printf "%s\n" "${lt_sysroot:-no}" >&6; }
+-
+-
+-
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+-printf %s "checking for a working dd... " >&6; }
+-if test ${ac_cv_path_lt_DD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  printf 0123456789abcdef0123456789abcdef >conftest.i
+-cat conftest.i conftest.i >conftest2.i
+-: ${lt_DD:=$DD}
+-if test -z "$lt_DD"; then
+-  ac_path_lt_DD_found=false
+-  # Loop through the user's path and test for each of PROGNAME-LIST
+-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_prog in dd
+-   do
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-      ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext"
+-      as_fn_executable_p "$ac_path_lt_DD" || continue
+-if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+-  cmp -s conftest.i conftest.out \
+-  && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+-fi
+-      $ac_path_lt_DD_found && break 3
+-    done
+-  done
+-  done
+-IFS=$as_save_IFS
+-  if test -z "$ac_cv_path_lt_DD"; then
+-    :
+-  fi
+-else
+-  ac_cv_path_lt_DD=$lt_DD
+-fi
+-
+-rm -f conftest.i conftest2.i conftest.out
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+-printf "%s\n" "$ac_cv_path_lt_DD" >&6; }
+-
+-
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+-printf %s "checking how to truncate binary pipes... " >&6; }
+-if test ${lt_cv_truncate_bin+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  printf 0123456789abcdef0123456789abcdef >conftest.i
+-cat conftest.i conftest.i >conftest2.i
+-lt_cv_truncate_bin=
+-if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+-  cmp -s conftest.i conftest.out \
+-  && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+-fi
+-rm -f conftest.i conftest2.i conftest.out
+-test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+-printf "%s\n" "$lt_cv_truncate_bin" >&6; }
+-
+-
+-
+-
+-
+-
+-
+-# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+-func_cc_basename ()
+-{
+-    for cc_temp in $*""; do
+-      case $cc_temp in
+-        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+-        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+-        \-*) ;;
+-        *) break;;
+-      esac
+-    done
+-    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+-}
+ 
+ # Check whether --enable-libtool-lock was given.
+-if test ${enable_libtool_lock+y}
+-then :
++if test "${enable_libtool_lock+set}" = set; then :
+   enableval=$enable_libtool_lock;
+ fi
+ 
+-test no = "$enable_libtool_lock" || enable_libtool_lock=yes
++test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+ 
+ # Some flags need to be propagated to the compiler or linker for good
+ # libtool support.
+ case $host in
+ ia64-*-hpux*)
+-  # Find out what ABI is being produced by ac_compile, and set mode
+-  # options accordingly.
++  # Find out which ABI we are using.
+   echo 'int i;' > conftest.$ac_ext
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+-    case `$FILECMD conftest.$ac_objext` in
++    case `/usr/bin/file conftest.$ac_objext` in
+       *ELF-32*)
+-	HPUX_IA64_MODE=32
++	HPUX_IA64_MODE="32"
+ 	;;
+       *ELF-64*)
+-	HPUX_IA64_MODE=64
++	HPUX_IA64_MODE="64"
+ 	;;
+     esac
+   fi
+   rm -rf conftest*
+   ;;
+ *-*-irix6*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.
++  # Find out which ABI we are using.
+   echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+-    if test yes = "$lt_cv_prog_gnu_ld"; then
+-      case `$FILECMD conftest.$ac_objext` in
++    if test "$lt_cv_prog_gnu_ld" = yes; then
++      case `/usr/bin/file conftest.$ac_objext` in
+ 	*32-bit*)
+ 	  LD="${LD-ld} -melf32bsmip"
+ 	  ;;
+@@ -9540,7 +8023,7 @@ ia64-*-hpux*)
+ 	;;
+       esac
+     else
+-      case `$FILECMD conftest.$ac_objext` in
++      case `/usr/bin/file conftest.$ac_objext` in
+ 	*32-bit*)
+ 	  LD="${LD-ld} -32"
+ 	  ;;
+@@ -9556,64 +8039,23 @@ ia64-*-hpux*)
+   rm -rf conftest*
+   ;;
+ 
+-mips64*-*linux*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.
+-  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+-  (eval $ac_compile) 2>&5
+-  ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }; then
+-    emul=elf
+-    case `$FILECMD conftest.$ac_objext` in
+-      *32-bit*)
+-	emul="${emul}32"
+-	;;
+-      *64-bit*)
+-	emul="${emul}64"
+-	;;
+-    esac
+-    case `$FILECMD conftest.$ac_objext` in
+-      *MSB*)
+-	emul="${emul}btsmip"
+-	;;
+-      *LSB*)
+-	emul="${emul}ltsmip"
+-	;;
+-    esac
+-    case `$FILECMD conftest.$ac_objext` in
+-      *N32*)
+-	emul="${emul}n32"
+-	;;
+-    esac
+-    LD="${LD-ld} -m $emul"
+-  fi
+-  rm -rf conftest*
+-  ;;
+-
+ x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.  Note that the listed cases only cover the
+-  # situations where additional linker options are needed (such as when
+-  # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+-  # vice versa); the common cases where no linker options are needed do
+-  # not appear in the list.
++  # Find out which ABI we are using.
+   echo 'int i;' > conftest.$ac_ext
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+-    case `$FILECMD conftest.o` in
++    case `/usr/bin/file conftest.o` in
+       *32-bit*)
+ 	case $host in
+ 	  x86_64-*kfreebsd*-gnu)
+ 	    LD="${LD-ld} -m elf_i386_fbsd"
+ 	    ;;
+ 	  x86_64-*linux*)
+-	    case `$FILECMD conftest.o` in
++	    case `/usr/bin/file conftest.o` in
+ 	      *x86-64*)
+ 		LD="${LD-ld} -m elf32_x86_64"
+ 		;;
+@@ -9665,14 +8107,13 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ 
+ *-*-sco3.2v5*)
+   # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+-  SAVE_CFLAGS=$CFLAGS
++  SAVE_CFLAGS="$CFLAGS"
+   CFLAGS="$CFLAGS -belf"
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+-printf %s "checking whether the C compiler needs -belf... " >&6; }
+-if test ${lt_cv_cc_needs_belf+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
++$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
++if ${lt_cv_cc_needs_belf+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+@@ -9683,20 +8124,19 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   lt_cv_cc_needs_belf=yes
+-else $as_nop
++else
+   lt_cv_cc_needs_belf=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+      ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+@@ -9705,39 +8145,25 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+-printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
+-  if test yes != "$lt_cv_cc_needs_belf"; then
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
++$as_echo "$lt_cv_cc_needs_belf" >&6; }
++  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+     # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+-    CFLAGS=$SAVE_CFLAGS
++    CFLAGS="$SAVE_CFLAGS"
+   fi
+   ;;
+-*-*solaris*)
+-  # Find out what ABI is being produced by ac_compile, and set linker
+-  # options accordingly.
++sparc*-*solaris*)
++  # Find out which ABI we are using.
+   echo 'int i;' > conftest.$ac_ext
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+-    case `$FILECMD conftest.o` in
++    case `/usr/bin/file conftest.o` in
+     *64-bit*)
+       case $lt_cv_prog_gnu_ld in
+-      yes*)
+-        case $host in
+-        i?86-*-solaris*|x86_64-*-solaris*)
+-          LD="${LD-ld} -m elf_x86_64"
+-          ;;
+-        sparc*-*-solaris*)
+-          LD="${LD-ld} -m elf64_sparc"
+-          ;;
+-        esac
+-        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+-        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+-          LD=${LD-ld}_sol2
+-        fi
+-        ;;
++      yes*) LD="${LD-ld} -m elf64_sparc" ;;
+       *)
+ 	if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ 	  LD="${LD-ld} -64"
+@@ -9751,135 +8177,7 @@ printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
+   ;;
+ esac
+ 
+-need_locks=$enable_libtool_lock
+-
+-if test -n "$ac_tool_prefix"; then
+-  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+-set dummy ${ac_tool_prefix}mt; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_MANIFEST_TOOL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$MANIFEST_TOOL"; then
+-  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+-if test -n "$MANIFEST_TOOL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+-printf "%s\n" "$MANIFEST_TOOL" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-
+-fi
+-if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+-  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+-  # Extract the first word of "mt", so it can be a program name with args.
+-set dummy mt; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  if test -n "$ac_ct_MANIFEST_TOOL"; then
+-  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+-else
+-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+-for as_dir in $PATH
+-do
+-  IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+-    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+-    break 2
+-  fi
+-done
+-  done
+-IFS=$as_save_IFS
+-
+-fi
+-fi
+-ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+-if test -n "$ac_ct_MANIFEST_TOOL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+-printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; }
+-else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-fi
+-
+-  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+-    MANIFEST_TOOL=":"
+-  else
+-    case $cross_compiling:$ac_tool_warned in
+-yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+-ac_tool_warned=yes ;;
+-esac
+-    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+-  fi
+-else
+-  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+-fi
+-
+-test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+-printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+-if test ${lt_cv_path_mainfest_tool+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  lt_cv_path_mainfest_tool=no
+-  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+-  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+-  cat conftest.err >&5
+-  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+-    lt_cv_path_mainfest_tool=yes
+-  fi
+-  rm -f conftest*
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+-printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; }
+-if test yes != "$lt_cv_path_mainfest_tool"; then
+-  MANIFEST_TOOL=:
+-fi
+-
+-
+-
+-
++need_locks="$enable_libtool_lock"
+ 
+ 
+   case $host_os in
+@@ -9887,12 +8185,11 @@ fi
+     if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_DSYMUTIL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_DSYMUTIL+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$DSYMUTIL"; then
+   ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+ else
+@@ -9900,15 +8197,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -9919,11 +8212,11 @@ fi
+ fi
+ DSYMUTIL=$ac_cv_prog_DSYMUTIL
+ if test -n "$DSYMUTIL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+-printf "%s\n" "$DSYMUTIL" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
++$as_echo "$DSYMUTIL" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -9932,12 +8225,11 @@ if test -z "$ac_cv_prog_DSYMUTIL"; then
+   ac_ct_DSYMUTIL=$DSYMUTIL
+   # Extract the first word of "dsymutil", so it can be a program name with args.
+ set dummy dsymutil; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_DSYMUTIL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_DSYMUTIL"; then
+   ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+ else
+@@ -9945,15 +8237,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -9964,11 +8252,11 @@ fi
+ fi
+ ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+ if test -n "$ac_ct_DSYMUTIL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+-printf "%s\n" "$ac_ct_DSYMUTIL" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
++$as_echo "$ac_ct_DSYMUTIL" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_DSYMUTIL" = x; then
+@@ -9976,8 +8264,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     DSYMUTIL=$ac_ct_DSYMUTIL
+@@ -9989,12 +8277,11 @@ fi
+     if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_NMEDIT+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_NMEDIT+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$NMEDIT"; then
+   ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+ else
+@@ -10002,15 +8289,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10021,11 +8304,11 @@ fi
+ fi
+ NMEDIT=$ac_cv_prog_NMEDIT
+ if test -n "$NMEDIT"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+-printf "%s\n" "$NMEDIT" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
++$as_echo "$NMEDIT" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -10034,12 +8317,11 @@ if test -z "$ac_cv_prog_NMEDIT"; then
+   ac_ct_NMEDIT=$NMEDIT
+   # Extract the first word of "nmedit", so it can be a program name with args.
+ set dummy nmedit; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_NMEDIT+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_NMEDIT"; then
+   ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+ else
+@@ -10047,15 +8329,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_NMEDIT="nmedit"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10066,11 +8344,11 @@ fi
+ fi
+ ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+ if test -n "$ac_ct_NMEDIT"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+-printf "%s\n" "$ac_ct_NMEDIT" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
++$as_echo "$ac_ct_NMEDIT" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_NMEDIT" = x; then
+@@ -10078,8 +8356,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     NMEDIT=$ac_ct_NMEDIT
+@@ -10091,12 +8369,11 @@ fi
+     if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}lipo; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_LIPO+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_LIPO+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$LIPO"; then
+   ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+ else
+@@ -10104,15 +8381,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10123,11 +8396,11 @@ fi
+ fi
+ LIPO=$ac_cv_prog_LIPO
+ if test -n "$LIPO"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+-printf "%s\n" "$LIPO" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
++$as_echo "$LIPO" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -10136,12 +8409,11 @@ if test -z "$ac_cv_prog_LIPO"; then
+   ac_ct_LIPO=$LIPO
+   # Extract the first word of "lipo", so it can be a program name with args.
+ set dummy lipo; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_LIPO+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_LIPO"; then
+   ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+ else
+@@ -10149,15 +8421,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_LIPO="lipo"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10168,11 +8436,11 @@ fi
+ fi
+ ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+ if test -n "$ac_ct_LIPO"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+-printf "%s\n" "$ac_ct_LIPO" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
++$as_echo "$ac_ct_LIPO" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_LIPO" = x; then
+@@ -10180,8 +8448,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     LIPO=$ac_ct_LIPO
+@@ -10193,12 +8461,11 @@ fi
+     if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}otool; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_OTOOL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_OTOOL+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$OTOOL"; then
+   ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+ else
+@@ -10206,15 +8473,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10225,11 +8488,11 @@ fi
+ fi
+ OTOOL=$ac_cv_prog_OTOOL
+ if test -n "$OTOOL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+-printf "%s\n" "$OTOOL" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
++$as_echo "$OTOOL" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -10238,12 +8501,11 @@ if test -z "$ac_cv_prog_OTOOL"; then
+   ac_ct_OTOOL=$OTOOL
+   # Extract the first word of "otool", so it can be a program name with args.
+ set dummy otool; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_OTOOL+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_OTOOL"; then
+   ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+ else
+@@ -10251,15 +8513,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_OTOOL="otool"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10270,11 +8528,11 @@ fi
+ fi
+ ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+ if test -n "$ac_ct_OTOOL"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+-printf "%s\n" "$ac_ct_OTOOL" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
++$as_echo "$ac_ct_OTOOL" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_OTOOL" = x; then
+@@ -10282,8 +8540,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     OTOOL=$ac_ct_OTOOL
+@@ -10295,12 +8553,11 @@ fi
+     if test -n "$ac_tool_prefix"; then
+   # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}otool64; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_OTOOL64+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_OTOOL64+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$OTOOL64"; then
+   ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+ else
+@@ -10308,15 +8565,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10327,11 +8580,11 @@ fi
+ fi
+ OTOOL64=$ac_cv_prog_OTOOL64
+ if test -n "$OTOOL64"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+-printf "%s\n" "$OTOOL64" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
++$as_echo "$OTOOL64" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -10340,12 +8593,11 @@ if test -z "$ac_cv_prog_OTOOL64"; then
+   ac_ct_OTOOL64=$OTOOL64
+   # Extract the first word of "otool64", so it can be a program name with args.
+ set dummy otool64; ac_word=$2
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+-printf %s "checking for $ac_word... " >&6; }
+-if test ${ac_cv_prog_ac_ct_OTOOL64+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -n "$ac_ct_OTOOL64"; then
+   ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+ else
+@@ -10353,15 +8605,11 @@ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
++  test -z "$as_dir" && as_dir=.
+     for ac_exec_ext in '' $ac_executable_extensions; do
+-  if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+     ac_cv_prog_ac_ct_OTOOL64="otool64"
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+     break 2
+   fi
+ done
+@@ -10372,11 +8620,11 @@ fi
+ fi
+ ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+ if test -n "$ac_ct_OTOOL64"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+-printf "%s\n" "$ac_ct_OTOOL64" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
++$as_echo "$ac_ct_OTOOL64" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+   if test "x$ac_ct_OTOOL64" = x; then
+@@ -10384,8 +8632,8 @@ fi
+   else
+     case $cross_compiling:$ac_tool_warned in
+ yes:)
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+-printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
++$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ ac_tool_warned=yes ;;
+ esac
+     OTOOL64=$ac_ct_OTOOL64
+@@ -10420,14 +8668,13 @@ fi
+ 
+ 
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+-printf %s "checking for -single_module linker flag... " >&6; }
+-if test ${lt_cv_apple_cc_single_mod+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
++$as_echo_n "checking for -single_module linker flag... " >&6; }
++if ${lt_cv_apple_cc_single_mod+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_apple_cc_single_mod=no
+-      if test -z "$LT_MULTI_MODULE"; then
++      if test -z "${LT_MULTI_MODULE}"; then
+ 	# By default we will add the -single_module flag. You can override
+ 	# by either setting the environment variable LT_MULTI_MODULE
+ 	# non-empty at configure time, or by adding -multi_module to the
+@@ -10439,13 +8686,7 @@ else $as_nop
+ 	$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ 	  -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+         _lt_result=$?
+-	# If there is a non-empty error log, and "single_module"
+-	# appears in it, assume the flag caused a linker warning
+-        if test -s conftest.err && $GREP single_module conftest.err; then
+-	  cat conftest.err >&5
+-	# Otherwise, if the output was created with a 0 exit code from
+-	# the compiler, it worked.
+-	elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
++	if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+ 	  lt_cv_apple_cc_single_mod=yes
+ 	else
+ 	  cat conftest.err >&5
+@@ -10454,15 +8695,13 @@ else $as_nop
+ 	rm -f conftest.*
+       fi
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+-printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; }
+-
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+-printf %s "checking for -exported_symbols_list linker flag... " >&6; }
+-if test ${lt_cv_ld_exported_symbols_list+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
++$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
++$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
++if ${lt_cv_ld_exported_symbols_list+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_ld_exported_symbols_list=no
+       save_LDFLAGS=$LDFLAGS
+       echo "_main" > conftest.sym
+@@ -10471,52 +8710,45 @@ else $as_nop
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   lt_cv_ld_exported_symbols_list=yes
+-else $as_nop
++else
+   lt_cv_ld_exported_symbols_list=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+-	LDFLAGS=$save_LDFLAGS
++	LDFLAGS="$save_LDFLAGS"
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+-printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; }
+-
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+-printf %s "checking for -force_load linker flag... " >&6; }
+-if test ${lt_cv_ld_force_load+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
++$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
++$as_echo_n "checking for -force_load linker flag... " >&6; }
++if ${lt_cv_ld_force_load+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_ld_force_load=no
+       cat > conftest.c << _LT_EOF
+ int forced_loaded() { return 2;}
+ _LT_EOF
+       echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+       $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+-      echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
+-      $AR $AR_FLAGS libconftest.a conftest.o 2>&5
+-      echo "$RANLIB libconftest.a" >&5
+-      $RANLIB libconftest.a 2>&5
++      echo "$AR cru libconftest.a conftest.o" >&5
++      $AR cru libconftest.a conftest.o 2>&5
+       cat > conftest.c << _LT_EOF
+ int main() { return 0;}
+ _LT_EOF
+       echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+       $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+       _lt_result=$?
+-      if test -s conftest.err && $GREP force_load conftest.err; then
+-	cat conftest.err >&5
+-      elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
++      if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+ 	lt_cv_ld_force_load=yes
+       else
+ 	cat conftest.err >&5
+@@ -10525,31 +8757,38 @@ _LT_EOF
+         rm -rf conftest.dSYM
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+-printf "%s\n" "$lt_cv_ld_force_load" >&6; }
+-    case $host_os in
+-    rhapsody* | darwin1.[012])
+-      _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+-    darwin1.*)
+-      _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+-    darwin*)
+-      case $MACOSX_DEPLOYMENT_TARGET,$host in
+-        10.[012],*|,*powerpc*-darwin[5-8]*)
+-          _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+-        *)
+-          _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+-      esac
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
++$as_echo "$lt_cv_ld_force_load" >&6; }
++    # Allow for Darwin 4-7 (macOS 10.0-10.3) although these are not expect to
++    # build without first building modern cctools / linker.
++    case $host_cpu-$host_os in
++    *-rhapsody* | *-darwin1.[012])
++      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
++    *-darwin1.*)
++      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
++    *-darwin*)
++      # darwin 5.x (macOS 10.1) onwards we only need to adjust when the
++      # deployment target is forced to an earlier version.
++      case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host in
++	UNSET,*-darwin[89]*|UNSET,*-darwin[12][0123456789]*)
++	  ;;
++	10.[012][,.]*)
++	  _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
++	  ;;
++	*)
++	  ;;
++     esac
+     ;;
+   esac
+-    if test yes = "$lt_cv_apple_cc_single_mod"; then
++    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+       _lt_dar_single_mod='$single_module'
+     fi
+-    if test yes = "$lt_cv_ld_exported_symbols_list"; then
+-      _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
++    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
++      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+     else
+-      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
++      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+     fi
+-    if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
++    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+       _lt_dsymutil='~$DSYMUTIL $lib || :'
+     else
+       _lt_dsymutil=
+@@ -10557,61 +8796,21 @@ printf "%s\n" "$lt_cv_ld_force_load" >&6; }
+     ;;
+   esac
+ 
+-# func_munge_path_list VARIABLE PATH
+-# -----------------------------------
+-# VARIABLE is name of variable containing _space_ separated list of
+-# directories to be munged by the contents of PATH, which is string
+-# having a format:
+-# "DIR[:DIR]:"
+-#       string "DIR[ DIR]" will be prepended to VARIABLE
+-# ":DIR[:DIR]"
+-#       string "DIR[ DIR]" will be appended to VARIABLE
+-# "DIRP[:DIRP]::[DIRA:]DIRA"
+-#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+-#       "DIRA[ DIRA]" will be appended to VARIABLE
+-# "DIR[:DIR]"
+-#       VARIABLE will be replaced by "DIR[ DIR]"
+-func_munge_path_list ()
+-{
+-    case x$2 in
+-    x)
+-        ;;
+-    *:)
+-        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+-        ;;
+-    x:*)
+-        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+-        ;;
+-    *::*)
+-        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+-        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+-        ;;
+-    *)
+-        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+-        ;;
+-    esac
+-}
+-
+-ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
++for ac_header in dlfcn.h
++do :
++  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+ "
+-if test "x$ac_cv_header_dlfcn_h" = xyes
+-then :
+-  printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
++if test "x$ac_cv_header_dlfcn_h" = xyes; then :
++  cat >>confdefs.h <<_ACEOF
++#define HAVE_DLFCN_H 1
++_ACEOF
+ 
+ fi
+ 
++done
+ 
+ 
+ 
+-func_stripname_cnf ()
+-{
+-  case $2 in
+-  .*) func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%\\\\$2\$%%"`;;
+-  *)  func_stripname_result=`$ECHO "$3" | $SED "s%^$1%%; s%$2\$%%"`;;
+-  esac
+-} # func_stripname_cnf
+-
+-
+ 
+ 
+ 
+@@ -10626,8 +8825,7 @@ func_stripname_cnf ()
+ 
+ 
+             # Check whether --enable-shared was given.
+-if test ${enable_shared+y}
+-then :
++if test "${enable_shared+set}" = set; then :
+   enableval=$enable_shared; p=${PACKAGE-default}
+     case $enableval in
+     yes) enable_shared=yes ;;
+@@ -10635,17 +8833,17 @@ then :
+     *)
+       enable_shared=no
+       # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+       for pkg in $enableval; do
+-	IFS=$lt_save_ifs
++	IFS="$lt_save_ifs"
+ 	if test "X$pkg" = "X$p"; then
+ 	  enable_shared=yes
+ 	fi
+       done
+-      IFS=$lt_save_ifs
++      IFS="$lt_save_ifs"
+       ;;
+     esac
+-else $as_nop
++else
+   enable_shared=yes
+ fi
+ 
+@@ -10658,8 +8856,7 @@ fi
+ 
+ 
+   # Check whether --enable-static was given.
+-if test ${enable_static+y}
+-then :
++if test "${enable_static+set}" = set; then :
+   enableval=$enable_static; p=${PACKAGE-default}
+     case $enableval in
+     yes) enable_static=yes ;;
+@@ -10667,17 +8864,17 @@ then :
+     *)
+      enable_static=no
+       # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+       for pkg in $enableval; do
+-	IFS=$lt_save_ifs
++	IFS="$lt_save_ifs"
+ 	if test "X$pkg" = "X$p"; then
+ 	  enable_static=yes
+ 	fi
+       done
+-      IFS=$lt_save_ifs
++      IFS="$lt_save_ifs"
+       ;;
+     esac
+-else $as_nop
++else
+   enable_static=yes
+ fi
+ 
+@@ -10691,29 +8888,15 @@ fi
+ 
+ 
+ # Check whether --with-pic was given.
+-if test ${with_pic+y}
+-then :
+-  withval=$with_pic; lt_p=${PACKAGE-default}
+-    case $withval in
+-    yes|no) pic_mode=$withval ;;
+-    *)
+-      pic_mode=default
+-      # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+-      for lt_pkg in $withval; do
+-	IFS=$lt_save_ifs
+-	if test "X$lt_pkg" = "X$lt_p"; then
+-	  pic_mode=yes
+-	fi
+-      done
+-      IFS=$lt_save_ifs
+-      ;;
+-    esac
+-else $as_nop
++if test "${with_pic+set}" = set; then :
++  withval=$with_pic; pic_mode="$withval"
++else
+   pic_mode=default
+ fi
+ 
+ 
++test -z "$pic_mode" && pic_mode=default
++
+ 
+ 
+ 
+@@ -10721,8 +8904,7 @@ fi
+ 
+ 
+   # Check whether --enable-fast-install was given.
+-if test ${enable_fast_install+y}
+-then :
++if test "${enable_fast_install+set}" = set; then :
+   enableval=$enable_fast_install; p=${PACKAGE-default}
+     case $enableval in
+     yes) enable_fast_install=yes ;;
+@@ -10730,17 +8912,17 @@ then :
+     *)
+       enable_fast_install=no
+       # Look at the argument we got.  We use all the common list separators.
+-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
++      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+       for pkg in $enableval; do
+-	IFS=$lt_save_ifs
++	IFS="$lt_save_ifs"
+ 	if test "X$pkg" = "X$p"; then
+ 	  enable_fast_install=yes
+ 	fi
+       done
+-      IFS=$lt_save_ifs
++      IFS="$lt_save_ifs"
+       ;;
+     esac
+-else $as_nop
++else
+   enable_fast_install=yes
+ fi
+ 
+@@ -10751,65 +8933,11 @@ fi
+ 
+ 
+ 
+-  shared_archive_member_spec=
+-case $host,$enable_shared in
+-power*-*-aix[5-9]*,yes)
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+-printf %s "checking which variant of shared library versioning to provide... " >&6; }
+-
+-# Check whether --with-aix-soname was given.
+-if test ${with_aix_soname+y}
+-then :
+-  withval=$with_aix_soname; case $withval in
+-    aix|svr4|both)
+-      ;;
+-    *)
+-      as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+-      ;;
+-    esac
+-    lt_cv_with_aix_soname=$with_aix_soname
+-else $as_nop
+-  if test ${lt_cv_with_aix_soname+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  lt_cv_with_aix_soname=aix
+-fi
+-
+-    with_aix_soname=$lt_cv_with_aix_soname
+-fi
+-
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+-printf "%s\n" "$with_aix_soname" >&6; }
+-  if test aix != "$with_aix_soname"; then
+-    # For the AIX way of multilib, we name the shared archive member
+-    # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+-    # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+-    # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+-    # the AIX toolchain works better with OBJECT_MODE set (default 32).
+-    if test 64 = "${OBJECT_MODE-32}"; then
+-      shared_archive_member_spec=shr_64
+-    else
+-      shared_archive_member_spec=shr
+-    fi
+-  fi
+-  ;;
+-*)
+-  with_aix_soname=aix
+-  ;;
+-esac
+-
+-
+-
+-
+-
+-
+-
+ 
+ 
+ 
+ # This can be used to rebuild libtool when needed
+-LIBTOOL_DEPS=$ltmain
++LIBTOOL_DEPS="$ltmain"
+ 
+ # Always use our own libtool.
+ LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+@@ -10834,10 +8962,6 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+ 
+ 
+ 
+-
+-
+-
+-
+ 
+ 
+ 
+@@ -10858,16 +8982,15 @@ test -z "$LN_S" && LN_S="ln -s"
+ 
+ 
+ 
+-if test -n "${ZSH_VERSION+set}"; then
++if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+ fi
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+-printf %s "checking for objdir... " >&6; }
+-if test ${lt_cv_objdir+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
++$as_echo_n "checking for objdir... " >&6; }
++if ${lt_cv_objdir+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   rm -f .libs 2>/dev/null
+ mkdir .libs 2>/dev/null
+ if test -d .libs; then
+@@ -10878,15 +9001,17 @@ else
+ fi
+ rmdir .libs 2>/dev/null
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+-printf "%s\n" "$lt_cv_objdir" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
++$as_echo "$lt_cv_objdir" >&6; }
+ objdir=$lt_cv_objdir
+ 
+ 
+ 
+ 
+ 
+-printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define LT_OBJDIR "$lt_cv_objdir/"
++_ACEOF
+ 
+ 
+ 
+@@ -10896,7 +9021,7 @@ aix3*)
+   # AIX sometimes has problems with the GCC collect2 program.  For some
+   # reason, if we set the COLLECT_NAMES environment variable, the problems
+   # vanish in a puff of smoke.
+-  if test set != "${COLLECT_NAMES+set}"; then
++  if test "X${COLLECT_NAMES+set}" != Xset; then
+     COLLECT_NAMES=
+     export COLLECT_NAMES
+   fi
+@@ -10907,14 +9032,14 @@ esac
+ ofile=libtool
+ can_build_shared=yes
+ 
+-# All known linkers require a '.a' archive for static linking (except MSVC and
+-# ICC, which need '.lib').
++# All known linkers require a `.a' archive for static linking (except MSVC,
++# which needs '.lib').
+ libext=a
+ 
+-with_gnu_ld=$lt_cv_prog_gnu_ld
++with_gnu_ld="$lt_cv_prog_gnu_ld"
+ 
+-old_CC=$CC
+-old_CFLAGS=$CFLAGS
++old_CC="$CC"
++old_CFLAGS="$CFLAGS"
+ 
+ # Set sane defaults for various variables
+ test -z "$CC" && CC=cc
+@@ -10923,8 +9048,15 @@ test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+ test -z "$LD" && LD=ld
+ test -z "$ac_objext" && ac_objext=o
+ 
+-func_cc_basename $compiler
+-cc_basename=$func_cc_basename_result
++for cc_temp in $compiler""; do
++  case $cc_temp in
++    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
++    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
++    \-*) ;;
++    *) break;;
++  esac
++done
++cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+ 
+ 
+ # Only perform the check for file, if the check method requires it
+@@ -10932,30 +9064,29 @@ test -z "$MAGIC_CMD" && MAGIC_CMD=file
+ case $deplibs_check_method in
+ file_magic*)
+   if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+-printf %s "checking for ${ac_tool_prefix}file... " >&6; }
+-if test ${lt_cv_path_MAGIC_CMD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
++$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
++if ${lt_cv_path_MAGIC_CMD+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   case $MAGIC_CMD in
+ [\\/*] |  ?:[\\/]*)
+-  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
++  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+   ;;
+ *)
+-  lt_save_MAGIC_CMD=$MAGIC_CMD
+-  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  lt_save_MAGIC_CMD="$MAGIC_CMD"
++  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+   ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+   for ac_dir in $ac_dummy; do
+-    IFS=$lt_save_ifs
++    IFS="$lt_save_ifs"
+     test -z "$ac_dir" && ac_dir=.
+-    if test -f "$ac_dir/${ac_tool_prefix}file"; then
+-      lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
++    if test -f $ac_dir/${ac_tool_prefix}file; then
++      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+       if test -n "$file_magic_test_file"; then
+ 	case $deplibs_check_method in
+ 	"file_magic "*)
+ 	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+-	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ 	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ 	    $EGREP "$file_magic_regex" > /dev/null; then
+ 	    :
+@@ -10978,19 +9109,19 @@ _LT_EOF
+       break
+     fi
+   done
+-  IFS=$lt_save_ifs
+-  MAGIC_CMD=$lt_save_MAGIC_CMD
++  IFS="$lt_save_ifs"
++  MAGIC_CMD="$lt_save_MAGIC_CMD"
+   ;;
+ esac
+ fi
+ 
+-MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if test -n "$MAGIC_CMD"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+-printf "%s\n" "$MAGIC_CMD" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
++$as_echo "$MAGIC_CMD" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -10999,30 +9130,29 @@ fi
+ 
+ if test -z "$lt_cv_path_MAGIC_CMD"; then
+   if test -n "$ac_tool_prefix"; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+-printf %s "checking for file... " >&6; }
+-if test ${lt_cv_path_MAGIC_CMD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
++$as_echo_n "checking for file... " >&6; }
++if ${lt_cv_path_MAGIC_CMD+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   case $MAGIC_CMD in
+ [\\/*] |  ?:[\\/]*)
+-  lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
++  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+   ;;
+ *)
+-  lt_save_MAGIC_CMD=$MAGIC_CMD
+-  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  lt_save_MAGIC_CMD="$MAGIC_CMD"
++  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+   ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+   for ac_dir in $ac_dummy; do
+-    IFS=$lt_save_ifs
++    IFS="$lt_save_ifs"
+     test -z "$ac_dir" && ac_dir=.
+-    if test -f "$ac_dir/file"; then
+-      lt_cv_path_MAGIC_CMD=$ac_dir/"file"
++    if test -f $ac_dir/file; then
++      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+       if test -n "$file_magic_test_file"; then
+ 	case $deplibs_check_method in
+ 	"file_magic "*)
+ 	  file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+-	  MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++	  MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ 	  if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ 	    $EGREP "$file_magic_regex" > /dev/null; then
+ 	    :
+@@ -11045,19 +9175,19 @@ _LT_EOF
+       break
+     fi
+   done
+-  IFS=$lt_save_ifs
+-  MAGIC_CMD=$lt_save_MAGIC_CMD
++  IFS="$lt_save_ifs"
++  MAGIC_CMD="$lt_save_MAGIC_CMD"
+   ;;
+ esac
+ fi
+ 
+-MAGIC_CMD=$lt_cv_path_MAGIC_CMD
++MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if test -n "$MAGIC_CMD"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+-printf "%s\n" "$MAGIC_CMD" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
++$as_echo "$MAGIC_CMD" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ 
+ 
+@@ -11072,7 +9202,7 @@ esac
+ 
+ # Use C for the default configuration in the libtool script
+ 
+-lt_save_CC=$CC
++lt_save_CC="$CC"
+ ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+@@ -11126,11 +9256,15 @@ _lt_linker_boilerplate=`cat conftest.err`
+ $RM -r conftest*
+ 
+ 
++## CAVEAT EMPTOR:
++## There is no encapsulation within the following macros, do not change
++## the running order or otherwise move them around unless you know exactly
++## what you are doing...
+ if test -n "$compiler"; then
+ 
+ lt_prog_compiler_no_builtin_flag=
+ 
+-if test yes = "$GCC"; then
++if test "$GCC" = yes; then
+   case $cc_basename in
+   nvcc*)
+     lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+@@ -11138,16 +9272,15 @@ if test yes = "$GCC"; then
+     lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+   esac
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+-printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+-if test ${lt_cv_prog_compiler_rtti_exceptions+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
++$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
++if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_rtti_exceptions=no
+    ac_outfile=conftest.$ac_objext
+    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+-   lt_compiler_flag="-fno-rtti -fno-exceptions"  ## exclude from sc_useless_quotes_in_assignment
++   lt_compiler_flag="-fno-rtti -fno-exceptions"
+    # Insert the option either (1) after the last *FLAGS variable, or
+    # (2) before a word containing "conftest.", or (3) at the end.
+    # Note that $ac_compile itself does not contain backslashes and begins
+@@ -11174,10 +9307,10 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
++$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+ 
+-if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
++if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+     lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+ else
+     :
+@@ -11194,15 +9327,17 @@ fi
+ lt_prog_compiler_pic=
+ lt_prog_compiler_static=
+ 
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
++$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+ 
+-  if test yes = "$GCC"; then
++  if test "$GCC" = yes; then
+     lt_prog_compiler_wl='-Wl,'
+     lt_prog_compiler_static='-static'
+ 
+     case $host_os in
+       aix*)
+       # All AIX code is PIC.
+-      if test ia64 = "$host_cpu"; then
++      if test "$host_cpu" = ia64; then
+ 	# AIX 5 now supports IA64 processor
+ 	lt_prog_compiler_static='-Bstatic'
+       fi
+@@ -11217,8 +9352,8 @@ lt_prog_compiler_static=
+         ;;
+       m68k)
+             # FIXME: we need at least 68020 code to build shared libraries, but
+-            # adding the '-m68020' flag to GCC prevents building anything better,
+-            # like '-m68040'.
++            # adding the `-m68020' flag to GCC prevents building anything better,
++            # like `-m68040'.
+             lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+         ;;
+       esac
+@@ -11234,11 +9369,6 @@ lt_prog_compiler_static=
+       # Although the cygwin gcc ignores -fPIC, still need this for old-style
+       # (--disable-auto-import) libraries
+       lt_prog_compiler_pic='-DDLL_EXPORT'
+-      case $host_os in
+-      os2*)
+-	lt_prog_compiler_static='$wl-static'
+-	;;
+-      esac
+       ;;
+ 
+     darwin* | rhapsody*)
+@@ -11299,9 +9429,7 @@ lt_prog_compiler_static=
+     case $cc_basename in
+     nvcc*) # Cuda Compiler Driver 2.2
+       lt_prog_compiler_wl='-Xlinker '
+-      if test -n "$lt_prog_compiler_pic"; then
+-        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+-      fi
++      lt_prog_compiler_pic='-Xcompiler -fPIC'
+       ;;
+     esac
+   else
+@@ -11309,7 +9437,7 @@ lt_prog_compiler_static=
+     case $host_os in
+     aix*)
+       lt_prog_compiler_wl='-Wl,'
+-      if test ia64 = "$host_cpu"; then
++      if test "$host_cpu" = ia64; then
+ 	# AIX 5 now supports IA64 processor
+ 	lt_prog_compiler_static='-Bstatic'
+       else
+@@ -11317,29 +9445,10 @@ lt_prog_compiler_static=
+       fi
+       ;;
+ 
+-    darwin* | rhapsody*)
+-      # PIC is the default on this platform
+-      # Common symbols not allowed in MH_DYLIB files
+-      lt_prog_compiler_pic='-fno-common'
+-      case $cc_basename in
+-      nagfor*)
+-        # NAG Fortran compiler
+-        lt_prog_compiler_wl='-Wl,-Wl,,'
+-        lt_prog_compiler_pic='-PIC'
+-        lt_prog_compiler_static='-Bstatic'
+-        ;;
+-      esac
+-      ;;
+-
+     mingw* | cygwin* | pw32* | os2* | cegcc*)
+       # This hack is so that the source file can tell whether it is being
+       # built for inclusion in a dll (and should export symbols for example).
+       lt_prog_compiler_pic='-DDLL_EXPORT'
+-      case $host_os in
+-      os2*)
+-	lt_prog_compiler_static='$wl-static'
+-	;;
+-      esac
+       ;;
+ 
+     hpux9* | hpux10* | hpux11*)
+@@ -11355,7 +9464,7 @@ lt_prog_compiler_static=
+ 	;;
+       esac
+       # Is there a better lt_prog_compiler_static that works with the bundled CC?
+-      lt_prog_compiler_static='$wl-a ${wl}archive'
++      lt_prog_compiler_static='${wl}-a ${wl}archive'
+       ;;
+ 
+     irix5* | irix6* | nonstopux*)
+@@ -11364,9 +9473,9 @@ lt_prog_compiler_static=
+       lt_prog_compiler_static='-non_shared'
+       ;;
+ 
+-    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++    linux* | k*bsd*-gnu | kopensolaris*-gnu)
+       case $cc_basename in
+-      # old Intel for x86_64, which still supported -KPIC.
++      # old Intel for x86_64 which still supported -KPIC.
+       ecc*)
+ 	lt_prog_compiler_wl='-Wl,'
+ 	lt_prog_compiler_pic='-KPIC'
+@@ -11385,18 +9494,6 @@ lt_prog_compiler_static=
+ 	lt_prog_compiler_pic='--shared'
+ 	lt_prog_compiler_static='--static'
+ 	;;
+-      nagfor*)
+-	# NAG Fortran compiler
+-	lt_prog_compiler_wl='-Wl,-Wl,,'
+-	lt_prog_compiler_pic='-PIC'
+-	lt_prog_compiler_static='-Bstatic'
+-	;;
+-      tcc*)
+-	# Fabrice Bellard et al's Tiny C Compiler
+-	lt_prog_compiler_wl='-Wl,'
+-	lt_prog_compiler_pic='-fPIC'
+-	lt_prog_compiler_static='-static'
+-	;;
+       pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+         # Portland Group compilers (*not* the Pentium gcc compiler,
+ 	# which looks to be a dead project)
+@@ -11416,34 +9513,19 @@ lt_prog_compiler_static=
+ 	lt_prog_compiler_static='-qstaticlink'
+ 	;;
+       *)
+-	case `$CC -V 2>&1 | $SED 5q` in
+-	*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
++	case `$CC -V 2>&1 | sed 5q` in
++	*Sun\ F* | *Sun*Fortran*)
+ 	  # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ 	  lt_prog_compiler_pic='-KPIC'
+ 	  lt_prog_compiler_static='-Bstatic'
+ 	  lt_prog_compiler_wl=''
+ 	  ;;
+-	*Sun\ F* | *Sun*Fortran*)
+-	  lt_prog_compiler_pic='-KPIC'
+-	  lt_prog_compiler_static='-Bstatic'
+-	  lt_prog_compiler_wl='-Qoption ld '
+-	  ;;
+ 	*Sun\ C*)
+ 	  # Sun C 5.9
+ 	  lt_prog_compiler_pic='-KPIC'
+ 	  lt_prog_compiler_static='-Bstatic'
+ 	  lt_prog_compiler_wl='-Wl,'
+ 	  ;;
+-        *Intel*\ [CF]*Compiler*)
+-	  lt_prog_compiler_wl='-Wl,'
+-	  lt_prog_compiler_pic='-fPIC'
+-	  lt_prog_compiler_static='-static'
+-	  ;;
+-	*Portland\ Group*)
+-	  lt_prog_compiler_wl='-Wl,'
+-	  lt_prog_compiler_pic='-fpic'
+-	  lt_prog_compiler_static='-Bstatic'
+-	  ;;
+ 	esac
+ 	;;
+       esac
+@@ -11474,7 +9556,7 @@ lt_prog_compiler_static=
+       lt_prog_compiler_pic='-KPIC'
+       lt_prog_compiler_static='-Bstatic'
+       case $cc_basename in
+-      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
++      f77* | f90* | f95*)
+ 	lt_prog_compiler_wl='-Qoption ld ';;
+       *)
+ 	lt_prog_compiler_wl='-Wl,';;
+@@ -11494,7 +9576,7 @@ lt_prog_compiler_static=
+       ;;
+ 
+     sysv4*MP*)
+-      if test -d /usr/nec; then
++      if test -d /usr/nec ;then
+ 	lt_prog_compiler_pic='-Kconform_pic'
+ 	lt_prog_compiler_static='-Bstatic'
+       fi
+@@ -11523,7 +9605,7 @@ lt_prog_compiler_static=
+   fi
+ 
+ case $host_os in
+-  # For platforms that do not support PIC, -DPIC is meaningless:
++  # For platforms which do not support PIC, -DPIC is meaningless:
+   *djgpp*)
+     lt_prog_compiler_pic=
+     ;;
+@@ -11531,33 +9613,27 @@ case $host_os in
+     lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+     ;;
+ esac
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
++$as_echo "$lt_prog_compiler_pic" >&6; }
++
++
++
++
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+-printf %s "checking for $compiler option to produce PIC... " >&6; }
+-if test ${lt_cv_prog_compiler_pic+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
+-lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+ 
+ #
+ # Check to make sure the PIC flag actually works.
+ #
+ if test -n "$lt_prog_compiler_pic"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+-printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+-if test ${lt_cv_prog_compiler_pic_works+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
++$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
++if ${lt_cv_prog_compiler_pic_works+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_pic_works=no
+    ac_outfile=conftest.$ac_objext
+    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+-   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"  ## exclude from sc_useless_quotes_in_assignment
++   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+    # Insert the option either (1) after the last *FLAGS variable, or
+    # (2) before a word containing "conftest.", or (3) at the end.
+    # Note that $ac_compile itself does not contain backslashes and begins
+@@ -11584,10 +9660,10 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
++$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+ 
+-if test yes = "$lt_cv_prog_compiler_pic_works"; then
++if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+     case $lt_prog_compiler_pic in
+      "" | " "*) ;;
+      *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+@@ -11604,23 +9680,17 @@ fi
+ 
+ 
+ 
+-
+-
+-
+-
+-
+ #
+ # Check to make sure the static flag actually works.
+ #
+ wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+-printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+-if test ${lt_cv_prog_compiler_static_works+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
++$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
++if ${lt_cv_prog_compiler_static_works+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_static_works=no
+-   save_LDFLAGS=$LDFLAGS
++   save_LDFLAGS="$LDFLAGS"
+    LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+    echo "$lt_simple_link_test_code" > conftest.$ac_ext
+    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+@@ -11639,13 +9709,13 @@ else $as_nop
+      fi
+    fi
+    $RM -r conftest*
+-   LDFLAGS=$save_LDFLAGS
++   LDFLAGS="$save_LDFLAGS"
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
++$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+ 
+-if test yes = "$lt_cv_prog_compiler_static_works"; then
++if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+     :
+ else
+     lt_prog_compiler_static=
+@@ -11657,12 +9727,11 @@ fi
+ 
+ 
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+-printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+-if test ${lt_cv_prog_compiler_c_o+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if ${lt_cv_prog_compiler_c_o+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_c_o=no
+    $RM -r conftest 2>/dev/null
+    mkdir conftest
+@@ -11705,20 +9774,19 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
++$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+ 
+ 
+ 
+ 
+ 
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+-printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+-if test ${lt_cv_prog_compiler_c_o+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if ${lt_cv_prog_compiler_c_o+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_c_o=no
+    $RM -r conftest 2>/dev/null
+    mkdir conftest
+@@ -11761,28 +9829,28 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
++$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+ 
+ 
+ 
+ 
+-hard_links=nottested
+-if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
++hard_links="nottested"
++if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+   # do not overwrite the value of need_locks provided by the user
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+-printf %s "checking if we can lock with hard links... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
++$as_echo_n "checking if we can lock with hard links... " >&6; }
+   hard_links=yes
+   $RM conftest*
+   ln conftest.a conftest.b 2>/dev/null && hard_links=no
+   touch conftest.a
+   ln conftest.a conftest.b 2>&5 || hard_links=no
+   ln conftest.a conftest.b 2>/dev/null && hard_links=no
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+-printf "%s\n" "$hard_links" >&6; }
+-  if test no = "$hard_links"; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+-printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
++$as_echo "$hard_links" >&6; }
++  if test "$hard_links" = no; then
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
++$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+     need_locks=warn
+   fi
+ else
+@@ -11794,8 +9862,8 @@ fi
+ 
+ 
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+-printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
++$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+ 
+   runpath_var=
+   allow_undefined_flag=
+@@ -11810,6 +9878,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+   hardcode_direct=no
+   hardcode_direct_absolute=no
+   hardcode_libdir_flag_spec=
++  hardcode_libdir_flag_spec_ld=
+   hardcode_libdir_separator=
+   hardcode_minus_L=no
+   hardcode_shlibpath_var=unsupported
+@@ -11825,9 +9894,9 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+   # included in the symbol list
+   include_expsyms=
+   # exclude_expsyms can be an extended regexp of symbols to exclude
+-  # it will be wrapped by ' (' and ')$', so one must not match beginning or
+-  # end of line.  Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+-  # as well as any symbol that contains 'd'.
++  # it will be wrapped by ` (' and `)$', so one must not match beginning or
++  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
++  # as well as any symbol that contains `d'.
+   exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+   # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+   # platforms (ab)use it in PIC code, but their linkers get confused if
+@@ -11839,18 +9908,18 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+ 
+   case $host_os in
+   cygwin* | mingw* | pw32* | cegcc*)
+-    # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
++    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+     # When not using gcc, we currently assume that we are using
+-    # Microsoft Visual C++ or Intel C++ Compiler.
+-    if test yes != "$GCC"; then
++    # Microsoft Visual C++.
++    if test "$GCC" != yes; then
+       with_gnu_ld=no
+     fi
+     ;;
+   interix*)
+-    # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
++    # we just hope/assume this is gcc and not c89 (= MSVC++)
+     with_gnu_ld=yes
+     ;;
+-  openbsd* | bitrig*)
++  openbsd*)
+     with_gnu_ld=no
+     ;;
+   esac
+@@ -11860,7 +9929,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+   # On some targets, GNU ld is compatible enough with the native linker
+   # that we're better off using the native interface for both.
+   lt_use_gnu_ld_interface=no
+-  if test yes = "$with_gnu_ld"; then
++  if test "$with_gnu_ld" = yes; then
+     case $host_os in
+       aix*)
+ 	# The AIX port of GNU ld has always aspired to compatibility
+@@ -11882,24 +9951,24 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+     esac
+   fi
+ 
+-  if test yes = "$lt_use_gnu_ld_interface"; then
++  if test "$lt_use_gnu_ld_interface" = yes; then
+     # If archive_cmds runs LD, not CC, wlarc should be empty
+-    wlarc='$wl'
++    wlarc='${wl}'
+ 
+     # Set some defaults for GNU ld with shared library support. These
+     # are reset later if shared libraries are not supported. Putting them
+     # here allows them to be overridden if necessary.
+     runpath_var=LD_RUN_PATH
+-    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+-    export_dynamic_flag_spec='$wl--export-dynamic'
++    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
++    export_dynamic_flag_spec='${wl}--export-dynamic'
+     # ancient GNU ld didn't support --whole-archive et. al.
+     if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+-      whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+     else
+       whole_archive_flag_spec=
+     fi
+     supports_anon_versioning=no
+-    case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
++    case `$LD -v 2>&1` in
+       *GNU\ gold*) supports_anon_versioning=yes ;;
+       *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+       *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+@@ -11912,7 +9981,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+     case $host_os in
+     aix[3-9]*)
+       # On AIX/PPC, the GNU linker is very broken
+-      if test ia64 != "$host_cpu"; then
++      if test "$host_cpu" != ia64; then
+ 	ld_shlibs=no
+ 	cat <<_LT_EOF 1>&2
+ 
+@@ -11931,7 +10000,7 @@ _LT_EOF
+       case $host_cpu in
+       powerpc)
+             # see comment about AmigaOS4 .so support
+-            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+             archive_expsym_cmds=''
+         ;;
+       m68k)
+@@ -11947,7 +10016,7 @@ _LT_EOF
+ 	allow_undefined_flag=unsupported
+ 	# Joseph Beckenbach  says some releases of gcc
+ 	# support --undefined.  This deserves some investigation.  FIXME
+-	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       else
+ 	ld_shlibs=no
+       fi
+@@ -11957,98 +10026,68 @@ _LT_EOF
+       # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+       # as there is no search path for DLLs.
+       hardcode_libdir_flag_spec='-L$libdir'
+-      export_dynamic_flag_spec='$wl--export-all-symbols'
++      export_dynamic_flag_spec='${wl}--export-all-symbols'
+       allow_undefined_flag=unsupported
+       always_export_symbols=no
+       enable_shared_with_static_runtimes=yes
+-      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+-      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
++      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+ 
+       if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+-        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-	# If the export-symbols file already is a .def file, use it as
+-	# is; otherwise, prepend EXPORTS...
+-	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+-          cp $export_symbols $output_objdir/$soname.def;
+-        else
+-          echo EXPORTS > $output_objdir/$soname.def;
+-          cat $export_symbols >> $output_objdir/$soname.def;
+-        fi~
+-        $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++	# If the export-symbols file already is a .def file (1st line
++	# is EXPORTS), use it as is; otherwise, prepend...
++	archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
++	  cp $export_symbols $output_objdir/$soname.def;
++	else
++	  echo EXPORTS > $output_objdir/$soname.def;
++	  cat $export_symbols >> $output_objdir/$soname.def;
++	fi~
++	$CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       else
+ 	ld_shlibs=no
+       fi
+       ;;
+ 
+     haiku*)
+-      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       link_all_deplibs=yes
+       ;;
+ 
+-    os2*)
+-      hardcode_libdir_flag_spec='-L$libdir'
+-      hardcode_minus_L=yes
+-      allow_undefined_flag=unsupported
+-      shrext_cmds=.dll
+-      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	prefix_cmds="$SED"~
+-	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+-	  prefix_cmds="$prefix_cmds -e 1d";
+-	fi~
+-	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+-	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+-      enable_shared_with_static_runtimes=yes
+-      file_list_spec='@'
+-      ;;
+-
+     interix[3-9]*)
+       hardcode_direct=no
+       hardcode_shlibpath_var=no
+-      hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+-      export_dynamic_flag_spec='$wl-E'
++      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++      export_dynamic_flag_spec='${wl}-E'
+       # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+       # Instead, shared libraries are loaded at an image base (0x10000000 by
+       # default) and relocated if they conflict, which is a slow very memory
+       # consuming and fragmenting process.  To avoid this, we pick a random,
+       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+-      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+-      archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       ;;
+ 
+-    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
++    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)
+       tmp_diet=no
+-      if test linux-dietlibc = "$host_os"; then
++      if test "$host_os" = linux-dietlibc; then
+ 	case $cc_basename in
+ 	  diet\ *) tmp_diet=yes;;	# linux-dietlibc with static linking (!diet-dyn)
+ 	esac
+       fi
+       if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+-	 && test no = "$tmp_diet"
++	 && test "$tmp_diet" = no
+       then
+ 	tmp_addflag=' $pic_flag'
+ 	tmp_sharedflag='-shared'
+ 	case $cc_basename,$host_cpu in
+         pgcc*)				# Portland Group C compiler
+-	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ 	  tmp_addflag=' $pic_flag'
+ 	  ;;
+ 	pgf77* | pgf90* | pgf95* | pgfortran*)
+ 					# Portland Group f77 and f90 compilers
+-	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ 	  tmp_addflag=' $pic_flag -Mnomain' ;;
+ 	ecc*,ia64* | icc*,ia64*)	# Intel C compiler on ia64
+ 	  tmp_addflag=' -i_dynamic' ;;
+@@ -12059,47 +10098,43 @@ _LT_EOF
+ 	lf95*)				# Lahey Fortran 8.1
+ 	  whole_archive_flag_spec=
+ 	  tmp_sharedflag='--shared' ;;
+-        nagfor*)                        # NAGFOR 5.3
+-          tmp_sharedflag='-Wl,-shared' ;;
+ 	xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ 	  tmp_sharedflag='-qmkshrobj'
+ 	  tmp_addflag= ;;
+ 	nvcc*)	# Cuda Compiler Driver 2.2
+-	  whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ 	  compiler_needs_object=yes
+ 	  ;;
+ 	esac
+-	case `$CC -V 2>&1 | $SED 5q` in
++	case `$CC -V 2>&1 | sed 5q` in
+ 	*Sun\ C*)			# Sun C 5.9
+-	  whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	  whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ 	  compiler_needs_object=yes
+ 	  tmp_sharedflag='-G' ;;
+ 	*Sun\ F*)			# Sun Fortran 8.3
+ 	  tmp_sharedflag='-G' ;;
+ 	esac
+-	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ 
+-        if test yes = "$supports_anon_versioning"; then
++        if test "x$supports_anon_versioning" = xyes; then
+           archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+-            cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+-            echo "local: *; };" >> $output_objdir/$libname.ver~
+-            $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++	    cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++	    echo "local: *; };" >> $output_objdir/$libname.ver~
++	    $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+         fi
+ 
+ 	case $cc_basename in
+-	tcc*)
+-	  export_dynamic_flag_spec='-rdynamic'
+-	  ;;
+ 	xlf* | bgf* | bgxlf* | mpixlf*)
+ 	  # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ 	  whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+-	  hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+-	  archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+-	  if test yes = "$supports_anon_versioning"; then
++	  hardcode_libdir_flag_spec=
++	  hardcode_libdir_flag_spec_ld='-rpath $libdir'
++	  archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
++	  if test "x$supports_anon_versioning" = xyes; then
+ 	    archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+-              cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+-              echo "local: *; };" >> $output_objdir/$libname.ver~
+-              $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
++	      cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++	      echo "local: *; };" >> $output_objdir/$libname.ver~
++	      $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ 	  fi
+ 	  ;;
+ 	esac
+@@ -12113,8 +10148,8 @@ _LT_EOF
+ 	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ 	wlarc=
+       else
+-	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+       fi
+       ;;
+ 
+@@ -12132,8 +10167,8 @@ _LT_EOF
+ 
+ _LT_EOF
+       elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+       else
+ 	ld_shlibs=no
+       fi
+@@ -12145,7 +10180,7 @@ _LT_EOF
+ 	ld_shlibs=no
+ 	cat <<_LT_EOF 1>&2
+ 
+-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
++*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+ *** reliably create shared libraries on SCO systems.  Therefore, libtool
+ *** is disabling shared libraries support.  We urge you to upgrade GNU
+ *** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+@@ -12160,9 +10195,9 @@ _LT_EOF
+ 	  # DT_RUNPATH tag from executables and libraries.  But doing so
+ 	  # requires that you compile everything twice, which is a pain.
+ 	  if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	    hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+-	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
++	    archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++	    archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ 	  else
+ 	    ld_shlibs=no
+ 	  fi
+@@ -12179,15 +10214,15 @@ _LT_EOF
+ 
+     *)
+       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+-	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+       else
+ 	ld_shlibs=no
+       fi
+       ;;
+     esac
+ 
+-    if test no = "$ld_shlibs"; then
++    if test "$ld_shlibs" = no; then
+       runpath_var=
+       hardcode_libdir_flag_spec=
+       export_dynamic_flag_spec=
+@@ -12203,7 +10238,7 @@ _LT_EOF
+       # Note: this linker hardcodes the directories in LIBPATH if there
+       # are no directories specified by -L.
+       hardcode_minus_L=yes
+-      if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
++      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ 	# Neither direct hardcoding nor static linking is supported with a
+ 	# broken collect2.
+ 	hardcode_direct=unsupported
+@@ -12211,57 +10246,34 @@ _LT_EOF
+       ;;
+ 
+     aix[4-9]*)
+-      if test ia64 = "$host_cpu"; then
++      if test "$host_cpu" = ia64; then
+ 	# On IA64, the linker does run time linking by default, so we don't
+ 	# have to do anything special.
+ 	aix_use_runtimelinking=no
+ 	exp_sym_flag='-Bexport'
+-	no_entry_flag=
++	no_entry_flag=""
+       else
+ 	# If we're using GNU nm, then we don't want the "-C" option.
+-	# -C means demangle to GNU nm, but means don't demangle to AIX nm.
+-	# Without the "-l" option, or with the "-B" option, AIX nm treats
+-	# weak defined symbols like other global defined symbols, whereas
+-	# GNU nm marks them as "W".
+-	# While the 'weak' keyword is ignored in the Export File, we need
+-	# it in the Import File for the 'aix-soname' feature, so we have
+-	# to replace the "-B" option with "-P" for AIX nm.
++	# -C means demangle to AIX nm, but means don't demangle with GNU nm
++	# Also, AIX nm treats weak defined symbols like other global
++	# defined symbols, whereas GNU nm marks them as "W".
+ 	if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+-	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++	  export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ 	else
+-	  export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++	  export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ 	fi
+ 	aix_use_runtimelinking=no
+ 
+ 	# Test if we are trying to use run time linking or normal
+ 	# AIX style linking. If -brtl is somewhere in LDFLAGS, we
+-	# have runtime linking enabled, and use it for executables.
+-	# For shared libraries, we enable/disable runtime linking
+-	# depending on the kind of the shared library created -
+-	# when "with_aix_soname,aix_use_runtimelinking" is:
+-	# "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+-	# "aix,yes"  lib.so          shared, rtl:yes, for executables
+-	#            lib.a           static archive
+-	# "both,no"  lib.so.V(shr.o) shared, rtl:yes
+-	#            lib.a(lib.so.V) shared, rtl:no,  for executables
+-	# "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+-	#            lib.a(lib.so.V) shared, rtl:no
+-	# "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+-	#            lib.a           static archive
++	# need to do runtime linking.
+ 	case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ 	  for ld_flag in $LDFLAGS; do
+-	  if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
++	  if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ 	    aix_use_runtimelinking=yes
+ 	    break
+ 	  fi
+ 	  done
+-	  if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+-	    # With aix-soname=svr4, we create the lib.so.V shared archives only,
+-	    # so we don't have lib.a shared libs to link our executables.
+-	    # We have to force runtime linking in this case.
+-	    aix_use_runtimelinking=yes
+-	    LDFLAGS="$LDFLAGS -Wl,-brtl"
+-	  fi
+ 	  ;;
+ 	esac
+ 
+@@ -12280,21 +10292,13 @@ _LT_EOF
+       hardcode_direct_absolute=yes
+       hardcode_libdir_separator=':'
+       link_all_deplibs=yes
+-      file_list_spec='$wl-f,'
+-      case $with_aix_soname,$aix_use_runtimelinking in
+-      aix,*) ;; # traditional, no import file
+-      svr4,* | *,yes) # use import file
+-	# The Import File defines what to hardcode.
+-	hardcode_direct=no
+-	hardcode_direct_absolute=no
+-	;;
+-      esac
++      file_list_spec='${wl}-f,'
+ 
+-      if test yes = "$GCC"; then
++      if test "$GCC" = yes; then
+ 	case $host_os in aix4.[012]|aix4.[012].*)
+ 	# We only want to do this on AIX 4.2 and lower, the check
+ 	# below for broken collect2 doesn't work under 4.3+
+-	  collect2name=`$CC -print-prog-name=collect2`
++	  collect2name=`${CC} -print-prog-name=collect2`
+ 	  if test -f "$collect2name" &&
+ 	   strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ 	  then
+@@ -12313,168 +10317,119 @@ _LT_EOF
+ 	  ;;
+ 	esac
+ 	shared_flag='-shared'
+-	if test yes = "$aix_use_runtimelinking"; then
+-	  shared_flag="$shared_flag "'$wl-G'
++	if test "$aix_use_runtimelinking" = yes; then
++	  shared_flag="$shared_flag "'${wl}-G'
+ 	fi
+-	# Need to ensure runtime linking is disabled for the traditional
+-	# shared library, or the linker may eventually find shared libraries
+-	# /with/ Import File - we do not want to mix them.
+-	shared_flag_aix='-shared'
+-	shared_flag_svr4='-shared $wl-G'
+       else
+ 	# not using gcc
+-	if test ia64 = "$host_cpu"; then
++	if test "$host_cpu" = ia64; then
+ 	# VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ 	# chokes on -Wl,-G. The following line is correct:
+ 	  shared_flag='-G'
+ 	else
+-	  if test yes = "$aix_use_runtimelinking"; then
+-	    shared_flag='$wl-G'
++	  if test "$aix_use_runtimelinking" = yes; then
++	    shared_flag='${wl}-G'
+ 	  else
+-	    shared_flag='$wl-bM:SRE'
++	    shared_flag='${wl}-bM:SRE'
+ 	  fi
+-	  shared_flag_aix='$wl-bM:SRE'
+-	  shared_flag_svr4='$wl-G'
+ 	fi
+       fi
+ 
+-      export_dynamic_flag_spec='$wl-bexpall'
++      export_dynamic_flag_spec='${wl}-bexpall'
+       # It seems that -bexpall does not export symbols beginning with
+       # underscore (_), so it is better to generate a list of symbols to export.
+       always_export_symbols=yes
+-      if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++      if test "$aix_use_runtimelinking" = yes; then
+ 	# Warning - without using the other runtime loading flags (-brtl),
+ 	# -berok will link without error, but may produce a broken library.
+ 	allow_undefined_flag='-berok'
+         # Determine the default libpath from the value encoded in an
+         # empty executable.
+-        if test set = "${lt_cv_aix_libpath+set}"; then
+-  aix_libpath=$lt_cv_aix_libpath
+-else
+-  if test ${lt_cv_aix_libpath_+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
+-
+-  lt_aix_libpath_sed='
+-      /Import File Strings/,/^$/ {
+-	  /^0/ {
+-	      s/^0  *\([^ ]*\) *$/\1/
+-	      p
+-	  }
+-      }'
+-  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  # Check for a 64-bit object if we didn't find anything.
+-  if test -z "$lt_cv_aix_libpath_"; then
+-    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  fi
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
+-    conftest$ac_exeext conftest.$ac_ext
+-  if test -z "$lt_cv_aix_libpath_"; then
+-    lt_cv_aix_libpath_=/usr/lib:/lib
+-  fi
++if ac_fn_c_try_link "$LINENO"; then :
+ 
++lt_aix_libpath_sed='
++    /Import File Strings/,/^$/ {
++	/^0/ {
++	    s/^0  *\(.*\)$/\1/
++	    p
++	}
++    }'
++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++# Check for a 64-bit object if we didn't find anything.
++if test -z "$aix_libpath"; then
++  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+-
+-  aix_libpath=$lt_cv_aix_libpath_
+ fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+ 
+-        hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+-        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
++        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+-	if test ia64 = "$host_cpu"; then
+-	  hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
++	if test "$host_cpu" = ia64; then
++	  hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ 	  allow_undefined_flag="-z nodefs"
+-	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ 	else
+ 	 # Determine the default libpath from the value encoded in an
+ 	 # empty executable.
+-	 if test set = "${lt_cv_aix_libpath+set}"; then
+-  aix_libpath=$lt_cv_aix_libpath
+-else
+-  if test ${lt_cv_aix_libpath_+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
+-
+-  lt_aix_libpath_sed='
+-      /Import File Strings/,/^$/ {
+-	  /^0/ {
+-	      s/^0  *\([^ ]*\) *$/\1/
+-	      p
+-	  }
+-      }'
+-  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  # Check for a 64-bit object if we didn't find anything.
+-  if test -z "$lt_cv_aix_libpath_"; then
+-    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  fi
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
+-    conftest$ac_exeext conftest.$ac_ext
+-  if test -z "$lt_cv_aix_libpath_"; then
+-    lt_cv_aix_libpath_=/usr/lib:/lib
+-  fi
++if ac_fn_c_try_link "$LINENO"; then :
+ 
++lt_aix_libpath_sed='
++    /Import File Strings/,/^$/ {
++	/^0/ {
++	    s/^0  *\(.*\)$/\1/
++	    p
++	}
++    }'
++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++# Check for a 64-bit object if we didn't find anything.
++if test -z "$aix_libpath"; then
++  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+-
+-  aix_libpath=$lt_cv_aix_libpath_
+ fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+ 
+-	 hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
++	 hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ 	  # Warning - without using the other run time loading flags,
+ 	  # -berok will link without error, but may produce a broken library.
+-	  no_undefined_flag=' $wl-bernotok'
+-	  allow_undefined_flag=' $wl-berok'
+-	  if test yes = "$with_gnu_ld"; then
++	  no_undefined_flag=' ${wl}-bernotok'
++	  allow_undefined_flag=' ${wl}-berok'
++	  if test "$with_gnu_ld" = yes; then
+ 	    # We only use this code for GNU lds that support --whole-archive.
+-	    whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
++	    whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ 	  else
+ 	    # Exported symbols can be pulled into shared objects from archives
+ 	    whole_archive_flag_spec='$convenience'
+ 	  fi
+ 	  archive_cmds_need_lc=yes
+-	  archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+-	  # -brtl affects multiple linker settings, -berok does not and is overridden later
+-	  compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+-	  if test svr4 != "$with_aix_soname"; then
+-	    # This is similar to how AIX traditionally builds its shared libraries.
+-	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+-	  fi
+-	  if test aix != "$with_aix_soname"; then
+-	    archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+-	  else
+-	    # used by -dlpreopen to get the symbols
+-	    archive_expsym_cmds="$archive_expsym_cmds"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+-	  fi
+-	  archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
++	  # This is similar to how AIX traditionally builds its shared libraries.
++	  archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ 	fi
+       fi
+       ;;
+@@ -12483,7 +10438,7 @@ fi
+       case $host_cpu in
+       powerpc)
+             # see comment about AmigaOS4 .so support
+-            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+             archive_expsym_cmds=''
+         ;;
+       m68k)
+@@ -12500,68 +10455,23 @@ fi
+ 
+     cygwin* | mingw* | pw32* | cegcc*)
+       # When not using gcc, we currently assume that we are using
+-      # Microsoft Visual C++ or Intel C++ Compiler.
++      # Microsoft Visual C++.
+       # hardcode_libdir_flag_spec is actually meaningless, as there is
+       # no search path for DLLs.
+-      case $cc_basename in
+-      cl* | icl*)
+-	# Native MSVC or ICC
+-	hardcode_libdir_flag_spec=' '
+-	allow_undefined_flag=unsupported
+-	always_export_symbols=yes
+-	file_list_spec='@'
+-	# Tell ltmain to make .lib files, not .a files.
+-	libext=lib
+-	# Tell ltmain to make .dll files, not .so files.
+-	shrext_cmds=.dll
+-	# FIXME: Setting linknames here is a bad hack.
+-	archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+-	archive_expsym_cmds='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+-            cp "$export_symbols" "$output_objdir/$soname.def";
+-            echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+-          else
+-            $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+-          fi~
+-          $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+-          linknames='
+-	# The linker will not automatically build a static lib if we build a DLL.
+-	# _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+-	enable_shared_with_static_runtimes=yes
+-	exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+-	export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+-	# Don't use ranlib
+-	old_postinstall_cmds='chmod 644 $oldlib'
+-	postlink_cmds='lt_outputfile="@OUTPUT@"~
+-          lt_tool_outputfile="@TOOL_OUTPUT@"~
+-          case $lt_outputfile in
+-            *.exe|*.EXE) ;;
+-            *)
+-              lt_outputfile=$lt_outputfile.exe
+-              lt_tool_outputfile=$lt_tool_outputfile.exe
+-              ;;
+-          esac~
+-          if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+-            $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+-            $RM "$lt_outputfile.manifest";
+-          fi'
+-	;;
+-      *)
+-	# Assume MSVC and ICC wrapper
+-	hardcode_libdir_flag_spec=' '
+-	allow_undefined_flag=unsupported
+-	# Tell ltmain to make .lib files, not .a files.
+-	libext=lib
+-	# Tell ltmain to make .dll files, not .so files.
+-	shrext_cmds=.dll
+-	# FIXME: Setting linknames here is a bad hack.
+-	archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+-	# The linker will automatically build a .lib file if we build a DLL.
+-	old_archive_from_new_cmds='true'
+-	# FIXME: Should let the user specify the lib program.
+-	old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+-	enable_shared_with_static_runtimes=yes
+-	;;
+-      esac
++      hardcode_libdir_flag_spec=' '
++      allow_undefined_flag=unsupported
++      # Tell ltmain to make .lib files, not .a files.
++      libext=lib
++      # Tell ltmain to make .dll files, not .so files.
++      shrext_cmds=".dll"
++      # FIXME: Setting linknames here is a bad hack.
++      archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
++      # The linker will automatically build a .lib file if we build a DLL.
++      old_archive_from_new_cmds='true'
++      # FIXME: Should let the user specify the lib program.
++      old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
++      fix_srcfile_path='`cygpath -w "$srcfile"`'
++      enable_shared_with_static_runtimes=yes
+       ;;
+ 
+     darwin* | rhapsody*)
+@@ -12571,24 +10481,23 @@ fi
+   hardcode_direct=no
+   hardcode_automatic=yes
+   hardcode_shlibpath_var=unsupported
+-  if test yes = "$lt_cv_ld_force_load"; then
+-    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+-
++  if test "$lt_cv_ld_force_load" = "yes"; then
++    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+   else
+     whole_archive_flag_spec=''
+   fi
+   link_all_deplibs=yes
+-  allow_undefined_flag=$_lt_dar_allow_undefined
++  allow_undefined_flag="$_lt_dar_allow_undefined"
+   case $cc_basename in
+-     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
++     ifort*) _lt_dar_can_shared=yes ;;
+      *) _lt_dar_can_shared=$GCC ;;
+   esac
+-  if test yes = "$_lt_dar_can_shared"; then
++  if test "$_lt_dar_can_shared" = "yes"; then
+     output_verbose_link_cmd=func_echo_all
+-    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+-    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+-    archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+-    module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
++    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
++    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
++    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
++    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ 
+   else
+   ld_shlibs=no
+@@ -12622,41 +10531,42 @@ fi
+       ;;
+ 
+     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+-    freebsd* | dragonfly* | midnightbsd*)
+-      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++    freebsd* | dragonfly*)
++      archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+       hardcode_libdir_flag_spec='-R$libdir'
+       hardcode_direct=yes
+       hardcode_shlibpath_var=no
+       ;;
+ 
+     hpux9*)
+-      if test yes = "$GCC"; then
+-	archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++      if test "$GCC" = yes; then
++	archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+       else
+-	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++	archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+       fi
+-      hardcode_libdir_flag_spec='$wl+b $wl$libdir'
++      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+       hardcode_direct=yes
+ 
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L=yes
+-      export_dynamic_flag_spec='$wl-E'
++      export_dynamic_flag_spec='${wl}-E'
+       ;;
+ 
+     hpux10*)
+-      if test yes,no = "$GCC,$with_gnu_ld"; then
+-	archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
++	archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+       else
+ 	archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+       fi
+-      if test no = "$with_gnu_ld"; then
+-	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
++      if test "$with_gnu_ld" = no; then
++	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
++	hardcode_libdir_flag_spec_ld='+b $libdir'
+ 	hardcode_libdir_separator=:
+ 	hardcode_direct=yes
+ 	hardcode_direct_absolute=yes
+-	export_dynamic_flag_spec='$wl-E'
++	export_dynamic_flag_spec='${wl}-E'
+ 	# hardcode_minus_L: Not really in the search PATH,
+ 	# but as the default location of the library.
+ 	hardcode_minus_L=yes
+@@ -12664,38 +10574,37 @@ fi
+       ;;
+ 
+     hpux11*)
+-      if test yes,no = "$GCC,$with_gnu_ld"; then
++      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+ 	case $host_cpu in
+ 	hppa*64*)
+-	  archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+ 	ia64*)
+-	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+ 	*)
+-	  archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+ 	esac
+       else
+ 	case $host_cpu in
+ 	hppa*64*)
+-	  archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+ 	ia64*)
+-	  archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+ 	*)
+ 
+ 	  # Older versions of the 11.00 compiler do not understand -b yet
+ 	  # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+-	  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+-printf %s "checking if $CC understands -b... " >&6; }
+-if test ${lt_cv_prog_compiler__b+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++	  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
++$as_echo_n "checking if $CC understands -b... " >&6; }
++if ${lt_cv_prog_compiler__b+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler__b=no
+-   save_LDFLAGS=$LDFLAGS
++   save_LDFLAGS="$LDFLAGS"
+    LDFLAGS="$LDFLAGS -b"
+    echo "$lt_simple_link_test_code" > conftest.$ac_ext
+    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+@@ -12714,14 +10623,14 @@ else $as_nop
+      fi
+    fi
+    $RM -r conftest*
+-   LDFLAGS=$save_LDFLAGS
++   LDFLAGS="$save_LDFLAGS"
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+-printf "%s\n" "$lt_cv_prog_compiler__b" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
++$as_echo "$lt_cv_prog_compiler__b" >&6; }
+ 
+-if test yes = "$lt_cv_prog_compiler__b"; then
+-    archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
++if test x"$lt_cv_prog_compiler__b" = xyes; then
++    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+     archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+@@ -12729,8 +10638,8 @@ fi
+ 	  ;;
+ 	esac
+       fi
+-      if test no = "$with_gnu_ld"; then
+-	hardcode_libdir_flag_spec='$wl+b $wl$libdir'
++      if test "$with_gnu_ld" = no; then
++	hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ 	hardcode_libdir_separator=:
+ 
+ 	case $host_cpu in
+@@ -12741,7 +10650,7 @@ fi
+ 	*)
+ 	  hardcode_direct=yes
+ 	  hardcode_direct_absolute=yes
+-	  export_dynamic_flag_spec='$wl-E'
++	  export_dynamic_flag_spec='${wl}-E'
+ 
+ 	  # hardcode_minus_L: Not really in the search PATH,
+ 	  # but as the default location of the library.
+@@ -12752,60 +10661,35 @@ fi
+       ;;
+ 
+     irix5* | irix6* | nonstopux*)
+-      if test yes = "$GCC"; then
+-	archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++      if test "$GCC" = yes; then
++	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ 	# Try to use the -exported_symbol ld option, if it does not
+ 	# work, assume that -exports_file does not work either and
+ 	# implicitly export all symbols.
+-	# This should be the same for all languages, so no per-tag cache variable.
+-	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+-printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+-if test ${lt_cv_irix_exported_symbol+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  save_LDFLAGS=$LDFLAGS
+-	   LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+-	   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++        save_LDFLAGS="$LDFLAGS"
++        LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
++        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+-int foo (void) { return 0; }
++int foo(void) {}
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
+-  lt_cv_irix_exported_symbol=yes
+-else $as_nop
+-  lt_cv_irix_exported_symbol=no
++if ac_fn_c_try_link "$LINENO"; then :
++  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
++
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+-           LDFLAGS=$save_LDFLAGS
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+-printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+-	if test yes = "$lt_cv_irix_exported_symbol"; then
+-          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+-	fi
++        LDFLAGS="$save_LDFLAGS"
+       else
+-	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
++	archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
++	archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+       fi
+       archive_cmds_need_lc='no'
+-      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+       hardcode_libdir_separator=:
+       inherit_rpath=yes
+       link_all_deplibs=yes
+       ;;
+ 
+-    linux*)
+-      case $cc_basename in
+-      tcc*)
+-	# Fabrice Bellard et al's Tiny C Compiler
+-	ld_shlibs=yes
+-	archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-	;;
+-      esac
+-      ;;
+-
+     netbsd*)
+       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ 	archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+@@ -12820,7 +10704,7 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+     newsos6)
+       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_direct=yes
+-      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+       hardcode_libdir_separator=:
+       hardcode_shlibpath_var=no
+       ;;
+@@ -12828,19 +10712,27 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+     *nto* | *qnx*)
+       ;;
+ 
+-    openbsd* | bitrig*)
++    openbsd*)
+       if test -f /usr/libexec/ld.so; then
+ 	hardcode_direct=yes
+ 	hardcode_shlibpath_var=no
+ 	hardcode_direct_absolute=yes
+-	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
++	if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ 	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+-	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+-	  export_dynamic_flag_spec='$wl-E'
++	  archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
++	  hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++	  export_dynamic_flag_spec='${wl}-E'
+ 	else
+-	  archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+-	  hardcode_libdir_flag_spec='$wl-rpath,$libdir'
++	  case $host_os in
++	   openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
++	     archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
++	     hardcode_libdir_flag_spec='-R$libdir'
++	     ;;
++	   *)
++	     archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
++	     hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
++	     ;;
++	  esac
+ 	fi
+       else
+ 	ld_shlibs=no
+@@ -12851,54 +10743,33 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+       hardcode_libdir_flag_spec='-L$libdir'
+       hardcode_minus_L=yes
+       allow_undefined_flag=unsupported
+-      shrext_cmds=.dll
+-      archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	$ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	$ECHO EXPORTS >> $output_objdir/$libname.def~
+-	prefix_cmds="$SED"~
+-	if test EXPORTS = "`$SED 1q $export_symbols`"; then
+-	  prefix_cmds="$prefix_cmds -e 1d";
+-	fi~
+-	prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+-	cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+-	$CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	emximp -o $lib $output_objdir/$libname.def'
+-      old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+-      enable_shared_with_static_runtimes=yes
+-      file_list_spec='@'
++      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
++      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+       ;;
+ 
+     osf3*)
+-      if test yes = "$GCC"; then
+-	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+-	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++      if test "$GCC" = yes; then
++	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
++	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       else
+ 	allow_undefined_flag=' -expect_unresolved \*'
+-	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       fi
+       archive_cmds_need_lc='no'
+-      hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+       hardcode_libdir_separator=:
+       ;;
+ 
+     osf4* | osf5*)	# as osf3* with the addition of -msym flag
+-      if test yes = "$GCC"; then
+-	allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+-	archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+-	hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
++      if test "$GCC" = yes; then
++	allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
++	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
++	hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+       else
+ 	allow_undefined_flag=' -expect_unresolved \*'
+-	archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ 	archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+-          $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
++	$CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+ 
+ 	# Both c and cxx compiler support -rpath directly
+ 	hardcode_libdir_flag_spec='-rpath $libdir'
+@@ -12909,24 +10780,24 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+ 
+     solaris*)
+       no_undefined_flag=' -z defs'
+-      if test yes = "$GCC"; then
+-	wlarc='$wl'
+-	archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
++      if test "$GCC" = yes; then
++	wlarc='${wl}'
++	archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ 	archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-          $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++	  $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+       else
+ 	case `$CC -V 2>&1` in
+ 	*"Compilers 5.0"*)
+ 	  wlarc=''
+-	  archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
++	  archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ 	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-            $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
++	  $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ 	  ;;
+ 	*)
+-	  wlarc='$wl'
+-	  archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
++	  wlarc='${wl}'
++	  archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ 	  archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-            $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
++	  $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ 	  ;;
+ 	esac
+       fi
+@@ -12936,11 +10807,11 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+       solaris2.[0-5] | solaris2.[0-5].*) ;;
+       *)
+ 	# The compiler driver will combine and reorder linker options,
+-	# but understands '-z linker_flag'.  GCC discards it without '$wl',
++	# but understands `-z linker_flag'.  GCC discards it without `$wl',
+ 	# but is careful enough not to reorder.
+ 	# Supported since Solaris 2.6 (maybe 2.5.1?)
+-	if test yes = "$GCC"; then
+-	  whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++	if test "$GCC" = yes; then
++	  whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ 	else
+ 	  whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+ 	fi
+@@ -12950,10 +10821,10 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+       ;;
+ 
+     sunos4*)
+-      if test sequent = "$host_vendor"; then
++      if test "x$host_vendor" = xsequent; then
+ 	# Use $CC to link under sequent, because it throws in some extra .o
+ 	# files that make .init and .fini sections work.
+-	archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+       else
+ 	archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+       fi
+@@ -13002,43 +10873,43 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+       ;;
+ 
+     sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+-      no_undefined_flag='$wl-z,text'
++      no_undefined_flag='${wl}-z,text'
+       archive_cmds_need_lc=no
+       hardcode_shlibpath_var=no
+       runpath_var='LD_RUN_PATH'
+ 
+-      if test yes = "$GCC"; then
+-	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      if test "$GCC" = yes; then
++	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       else
+-	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       fi
+       ;;
+ 
+     sysv5* | sco3.2v5* | sco5v6*)
+-      # Note: We CANNOT use -z defs as we might desire, because we do not
++      # Note: We can NOT use -z defs as we might desire, because we do not
+       # link with -lc, and that would cause any symbols used from libc to
+       # always be unresolved, which means just about no library would
+       # ever link correctly.  If we're not using GNU ld we use -z text
+       # though, which does catch some bad symbols but isn't as heavy-handed
+       # as -z defs.
+-      no_undefined_flag='$wl-z,text'
+-      allow_undefined_flag='$wl-z,nodefs'
++      no_undefined_flag='${wl}-z,text'
++      allow_undefined_flag='${wl}-z,nodefs'
+       archive_cmds_need_lc=no
+       hardcode_shlibpath_var=no
+-      hardcode_libdir_flag_spec='$wl-R,$libdir'
++      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+       hardcode_libdir_separator=':'
+       link_all_deplibs=yes
+-      export_dynamic_flag_spec='$wl-Bexport'
++      export_dynamic_flag_spec='${wl}-Bexport'
+       runpath_var='LD_RUN_PATH'
+ 
+-      if test yes = "$GCC"; then
+-	archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++      if test "$GCC" = yes; then
++	archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       else
+-	archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       fi
+       ;;
+ 
+@@ -13053,18 +10924,18 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+       ;;
+     esac
+ 
+-    if test sni = "$host_vendor"; then
++    if test x$host_vendor = xsni; then
+       case $host in
+       sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+-	export_dynamic_flag_spec='$wl-Blargedynsym'
++	export_dynamic_flag_spec='${wl}-Blargedynsym'
+ 	;;
+       esac
+     fi
+   fi
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+-printf "%s\n" "$ld_shlibs" >&6; }
+-test no = "$ld_shlibs" && can_build_shared=no
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
++$as_echo "$ld_shlibs" >&6; }
++test "$ld_shlibs" = no && can_build_shared=no
+ 
+ with_gnu_ld=$with_gnu_ld
+ 
+@@ -13090,7 +10961,7 @@ x|xyes)
+   # Assume -lc should be added
+   archive_cmds_need_lc=yes
+ 
+-  if test yes,yes = "$GCC,$enable_shared"; then
++  if test "$enable_shared" = yes && test "$GCC" = yes; then
+     case $archive_cmds in
+     *'~'*)
+       # FIXME: we may have to deal with multi-command sequences.
+@@ -13099,19 +10970,18 @@ x|xyes)
+       # Test whether the compiler implicitly links with -lc since on some
+       # systems, -lgcc has to come before -lc. If gcc already passes -lc
+       # to ld, don't add -lc before -lgcc.
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+-printf %s "checking whether -lc should be explicitly linked in... " >&6; }
+-if test ${lt_cv_archive_cmds_need_lc+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
++$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
++if ${lt_cv_archive_cmds_need_lc+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   $RM conftest*
+ 	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ 
+ 	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } 2>conftest.err; then
+ 	  soname=conftest
+ 	  lib=conftest
+@@ -13129,7 +10999,7 @@ else $as_nop
+ 	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+   (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }
+ 	  then
+ 	    lt_cv_archive_cmds_need_lc=no
+@@ -13143,8 +11013,8 @@ else $as_nop
+ 	$RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+-printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
++$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+       archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+       ;;
+     esac
+@@ -13303,17 +11173,22 @@ esac
+ 
+ 
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+-printf %s "checking dynamic linker characteristics... " >&6; }
+ 
+-if test yes = "$GCC"; then
++
++
++
++
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
++$as_echo_n "checking dynamic linker characteristics... " >&6; }
++
++if test "$GCC" = yes; then
+   case $host_os in
+-    darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+-    *) lt_awk_arg='/^libraries:/' ;;
++    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
++    *) lt_awk_arg="/^libraries:/" ;;
+   esac
+   case $host_os in
+-    mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
+-    *) lt_sed_strip_eq='s|=/|/|g' ;;
++    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
++    *) lt_sed_strip_eq="s,=/,/,g" ;;
+   esac
+   lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+   case $lt_search_path_spec in
+@@ -13329,35 +11204,28 @@ if test yes = "$GCC"; then
+     ;;
+   esac
+   # Ok, now we have the path, separated by spaces, we can step through it
+-  # and add multilib dir if necessary...
++  # and add multilib dir if necessary.
+   lt_tmp_lt_search_path_spec=
+-  lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+-  # ...but if some path component already ends with the multilib dir we assume
+-  # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+-  case "$lt_multi_os_dir; $lt_search_path_spec " in
+-  "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+-    lt_multi_os_dir=
+-    ;;
+-  esac
++  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+   for lt_sys_path in $lt_search_path_spec; do
+-    if test -d "$lt_sys_path$lt_multi_os_dir"; then
+-      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+-    elif test -n "$lt_multi_os_dir"; then
++    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
++      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
++    else
+       test -d "$lt_sys_path" && \
+ 	lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+     fi
+   done
+   lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+-BEGIN {RS = " "; FS = "/|\n";} {
+-  lt_foo = "";
+-  lt_count = 0;
++BEGIN {RS=" "; FS="/|\n";} {
++  lt_foo="";
++  lt_count=0;
+   for (lt_i = NF; lt_i > 0; lt_i--) {
+     if ($lt_i != "" && $lt_i != ".") {
+       if ($lt_i == "..") {
+         lt_count++;
+       } else {
+         if (lt_count == 0) {
+-          lt_foo = "/" $lt_i lt_foo;
++          lt_foo="/" $lt_i lt_foo;
+         } else {
+           lt_count--;
+         }
+@@ -13371,7 +11239,7 @@ BEGIN {RS = " "; FS = "/|\n";} {
+   # for these hosts.
+   case $host_os in
+     mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+-      $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
++      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+   esac
+   sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+ else
+@@ -13380,7 +11248,7 @@ fi
+ library_names_spec=
+ libname_spec='lib$name'
+ soname_spec=
+-shrext_cmds=.so
++shrext_cmds=".so"
+ postinstall_cmds=
+ postuninstall_cmds=
+ finish_cmds=
+@@ -13397,108 +11265,56 @@ hardcode_into_libs=no
+ # flags to be left without arguments
+ need_version=unknown
+ 
+-
+-
+ case $host_os in
+ aix3*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+   shlibpath_var=LIBPATH
+ 
+   # AIX 3 has no versioning support, so we append a major version to the name.
+-  soname_spec='$libname$release$shared_ext$major'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   ;;
+ 
+ aix[4-9]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+   hardcode_into_libs=yes
+-  if test ia64 = "$host_cpu"; then
++  if test "$host_cpu" = ia64; then
+     # AIX 5 supports IA64
+-    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
++    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+     shlibpath_var=LD_LIBRARY_PATH
+   else
+     # With GCC up to 2.95.x, collect2 would create an import file
+     # for dependence libraries.  The import file would start with
+-    # the line '#! .'.  This would cause the generated library to
+-    # depend on '.', always an invalid library.  This was fixed in
++    # the line `#! .'.  This would cause the generated library to
++    # depend on `.', always an invalid library.  This was fixed in
+     # development snapshots of GCC prior to 3.0.
+     case $host_os in
+       aix4 | aix4.[01] | aix4.[01].*)
+       if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ 	   echo ' yes '
+-	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
++	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ 	:
+       else
+ 	can_build_shared=no
+       fi
+       ;;
+     esac
+-    # Using Import Files as archive members, it is possible to support
+-    # filename-based versioning of shared library archives on AIX. While
+-    # this would work for both with and without runtime linking, it will
+-    # prevent static linking of such archives. So we do filename-based
+-    # shared library versioning with .so extension only, which is used
+-    # when both runtime linking and shared linking is enabled.
+-    # Unfortunately, runtime linking may impact performance, so we do
+-    # not want this to be the default eventually. Also, we use the
+-    # versioned .so libs for executables only if there is the -brtl
+-    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+-    # To allow for filename-based versioning support, we need to create
+-    # libNAME.so.V as an archive file, containing:
+-    # *) an Import File, referring to the versioned filename of the
+-    #    archive as well as the shared archive member, telling the
+-    #    bitwidth (32 or 64) of that shared object, and providing the
+-    #    list of exported symbols of that shared object, eventually
+-    #    decorated with the 'weak' keyword
+-    # *) the shared object with the F_LOADONLY flag set, to really avoid
+-    #    it being seen by the linker.
+-    # At run time we better use the real file rather than another symlink,
+-    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+-
+-    case $with_aix_soname,$aix_use_runtimelinking in
+-    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
++    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+     # soname into executable. Probably we can add versioning support to
+     # collect2, so additional links can be useful in future.
+-    aix,yes) # traditional libtool
+-      dynamic_linker='AIX unversionable lib.so'
++    if test "$aix_use_runtimelinking" = yes; then
+       # If using run time linking (on AIX 4.2 or later) use lib.so
+       # instead of lib.a to let people know that these are not
+       # typical AIX shared libraries.
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-      ;;
+-    aix,no) # traditional AIX only
+-      dynamic_linker='AIX lib.a(lib.so.V)'
++      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    else
+       # We preserve .a as extension for shared libraries through AIX4.2
+       # and later when we are not doing run time linking.
+-      library_names_spec='$libname$release.a $libname.a'
+-      soname_spec='$libname$release$shared_ext$major'
+-      ;;
+-    svr4,*) # full svr4 only
+-      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+-      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+-      # We do not specify a path in Import Files, so LIBPATH fires.
+-      shlibpath_overrides_runpath=yes
+-      ;;
+-    *,yes) # both, prefer svr4
+-      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+-      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+-      # unpreferred sharedlib libNAME.a needs extra handling
+-      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+-      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+-      # We do not specify a path in Import Files, so LIBPATH fires.
+-      shlibpath_overrides_runpath=yes
+-      ;;
+-    *,no) # both, prefer aix
+-      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+-      library_names_spec='$libname$release.a $libname.a'
+-      soname_spec='$libname$release$shared_ext$major'
+-      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+-      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+-      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+-      ;;
+-    esac
++      library_names_spec='${libname}${release}.a $libname.a'
++      soname_spec='${libname}${release}${shared_ext}$major'
++    fi
+     shlibpath_var=LIBPATH
+   fi
+   ;;
+@@ -13508,27 +11324,27 @@ amigaos*)
+   powerpc)
+     # Since July 2007 AmigaOS4 officially supports .so libraries.
+     # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     ;;
+   m68k)
+     library_names_spec='$libname.ixlibrary $libname.a'
+     # Create ${libname}_ixlibrary.a entries in /sys/libs.
+-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+     ;;
+   esac
+   ;;
+ 
+ beos*)
+-  library_names_spec='$libname$shared_ext'
++  library_names_spec='${libname}${shared_ext}'
+   dynamic_linker="$host_os ld.so"
+   shlibpath_var=LIBRARY_PATH
+   ;;
+ 
+ bsdi[45]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+   sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+@@ -13540,17 +11356,16 @@ bsdi[45]*)
+ 
+ cygwin* | mingw* | pw32* | cegcc*)
+   version_type=windows
+-  shrext_cmds=.dll
++  shrext_cmds=".dll"
+   need_version=no
+   need_lib_prefix=no
+ 
+-  case $GCC,$cc_basename in
+-  yes,*)
+-    # gcc
++  case $GCC,$host_os in
++  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+     library_names_spec='$libname.dll.a'
+     # DLL is installed to $(libdir)/../bin by postinstall_cmds
+-    postinstall_cmds='base_file=`basename \$file`~
+-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++    postinstall_cmds='base_file=`basename \${file}`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+       dldir=$destdir/`dirname \$dlpath`~
+       test -d \$dldir || mkdir -p \$dldir~
+       $install_prog $dir/$dlname \$dldir/$dlname~
+@@ -13566,84 +11381,26 @@ cygwin* | mingw* | pw32* | cegcc*)
+     case $host_os in
+     cygwin*)
+       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+-      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ 
+       sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+       ;;
+     mingw* | cegcc*)
+       # MinGW DLLs use traditional 'lib' prefix
+-      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+       ;;
+     pw32*)
+       # pw32 DLLs use 'pw' prefix rather than 'lib'
+-      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+-      ;;
+-    esac
+-    dynamic_linker='Win32 ld.exe'
+-    ;;
+-
+-  *,cl* | *,icl*)
+-    # Native MSVC or ICC
+-    libname_spec='$name'
+-    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+-    library_names_spec='$libname.dll.lib'
+-
+-    case $build_os in
+-    mingw*)
+-      sys_lib_search_path_spec=
+-      lt_save_ifs=$IFS
+-      IFS=';'
+-      for lt_path in $LIB
+-      do
+-        IFS=$lt_save_ifs
+-        # Let DOS variable expansion print the short 8.3 style file name.
+-        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+-        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+-      done
+-      IFS=$lt_save_ifs
+-      # Convert to MSYS style.
+-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+-      ;;
+-    cygwin*)
+-      # Convert to unix form, then to dos form, then back to unix form
+-      # but this time dos style (no spaces!) so that the unix form looks
+-      # like /cygdrive/c/PROGRA~1:/cygdr...
+-      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+-      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+-      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+-      ;;
+-    *)
+-      sys_lib_search_path_spec=$LIB
+-      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+-        # It is most probably a Windows format PATH.
+-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+-      else
+-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+-      fi
+-      # FIXME: find the short name or the path components, as spaces are
+-      # common. (e.g. "Program Files" -> "PROGRA~1")
++      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+       ;;
+     esac
+-
+-    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+-    postinstall_cmds='base_file=`basename \$file`~
+-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+-      dldir=$destdir/`dirname \$dlpath`~
+-      test -d \$dldir || mkdir -p \$dldir~
+-      $install_prog $dir/$dlname \$dldir/$dlname'
+-    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+-      dlpath=$dir/\$dldll~
+-       $RM \$dlpath'
+-    shlibpath_overrides_runpath=yes
+-    dynamic_linker='Win32 link.exe'
+     ;;
+ 
+   *)
+-    # Assume MSVC and ICC wrapper
+-    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+-    dynamic_linker='Win32 ld.exe'
++    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+     ;;
+   esac
++  dynamic_linker='Win32 ld.exe'
+   # FIXME: first we should search . and the directory the executable is in
+   shlibpath_var=PATH
+   ;;
+@@ -13653,8 +11410,8 @@ darwin* | rhapsody*)
+   version_type=darwin
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+-  soname_spec='$libname$release$major$shared_ext'
++  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
++  soname_spec='${libname}${release}${major}$shared_ext'
+   shlibpath_overrides_runpath=yes
+   shlibpath_var=DYLD_LIBRARY_PATH
+   shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+@@ -13664,15 +11421,15 @@ darwin* | rhapsody*)
+   ;;
+ 
+ dgux*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   ;;
+ 
+-freebsd* | dragonfly* | midnightbsd*)
++freebsd* | dragonfly*)
+   # DragonFly does not have aout.  When/if they implement a new
+   # versioning mechanism, adjust this.
+   if test -x /usr/bin/objformat; then
+@@ -13686,13 +11443,12 @@ freebsd* | dragonfly* | midnightbsd*)
+   version_type=freebsd-$objformat
+   case $version_type in
+     freebsd-elf*)
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-      soname_spec='$libname$release$shared_ext$major'
++      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+       need_version=no
+       need_lib_prefix=no
+       ;;
+     freebsd-*)
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+       need_version=yes
+       ;;
+   esac
+@@ -13718,15 +11474,15 @@ freebsd* | dragonfly* | midnightbsd*)
+   ;;
+ 
+ haiku*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+   dynamic_linker="$host_os runtime_loader"
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
++  shlibpath_overrides_runpath=yes
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+   hardcode_into_libs=yes
+   ;;
+ 
+@@ -13743,15 +11499,14 @@ hpux9* | hpux10* | hpux11*)
+     dynamic_linker="$host_os dld.so"
+     shlibpath_var=LD_LIBRARY_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
+-    if test 32 = "$HPUX_IA64_MODE"; then
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
++    if test "X$HPUX_IA64_MODE" = X32; then
+       sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+-      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+     else
+       sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+-      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+     fi
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+@@ -13759,8 +11514,8 @@ hpux9* | hpux10* | hpux11*)
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+@@ -13769,8 +11524,8 @@ hpux9* | hpux10* | hpux11*)
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=SHLIB_PATH
+     shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
+     ;;
+   esac
+   # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+@@ -13780,11 +11535,11 @@ hpux9* | hpux10* | hpux11*)
+   ;;
+ 
+ interix[3-9]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+@@ -13795,16 +11550,16 @@ irix5* | irix6* | nonstopux*)
+   case $host_os in
+     nonstopux*) version_type=nonstopux ;;
+     *)
+-	if test yes = "$lt_cv_prog_gnu_ld"; then
+-		version_type=linux # correct to gnu/linux during the next big refactor
++	if test "$lt_cv_prog_gnu_ld" = yes; then
++		version_type=linux
+ 	else
+ 		version_type=irix
+ 	fi ;;
+   esac
+   need_lib_prefix=no
+   need_version=no
+-  soname_spec='$libname$release$shared_ext$major'
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
++  soname_spec='${libname}${release}${shared_ext}$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+   case $host_os in
+   irix5* | nonstopux*)
+     libsuff= shlibsuff=
+@@ -13823,8 +11578,8 @@ irix5* | irix6* | nonstopux*)
+   esac
+   shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+   shlibpath_overrides_runpath=no
+-  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+-  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
++  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
++  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+   hardcode_into_libs=yes
+   ;;
+ 
+@@ -13833,42 +11588,26 @@ linux*oldld* | linux*aout* | linux*coff*)
+   dynamic_linker=no
+   ;;
+ 
+-linux*android*)
+-  version_type=none # Android doesn't support versioned libraries.
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext'
+-  soname_spec='$libname$release$shared_ext'
+-  finish_cmds=
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-
+-  # This implies no fast_install, which is unacceptable.
+-  # Some rework will be needed to allow for fast_install
+-  # before this can be enabled.
+-  hardcode_into_libs=yes
+-
+-  dynamic_linker='Android linker'
+-  # Don't embed -rpath directories since the linker doesn't support them.
+-  hardcode_libdir_flag_spec='-L$libdir'
+-  ;;
++# This must be Linux ELF.
+ 
+-# This must be glibc/ELF.
+-linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++# uclinux* changes (here and below) have been submitted to the libtool
++# project, but have not yet been accepted: they are GCC-local changes
++# for the time being.  (See
++# https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html)
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi)
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+ 
+   # Some binutils ld are patched to set DT_RUNPATH
+-  if test ${lt_cv_shlibpath_overrides_runpath+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_shlibpath_overrides_runpath=no
+     save_LDFLAGS=$LDFLAGS
+     save_libdir=$libdir
+@@ -13878,21 +11617,19 @@ else $as_nop
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
+-  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
++  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+   lt_cv_shlibpath_overrides_runpath=yes
+ fi
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+     LDFLAGS=$save_LDFLAGS
+     libdir=$save_libdir
+@@ -13906,18 +11643,10 @@ fi
+   # before this can be enabled.
+   hardcode_into_libs=yes
+ 
+-  # Add ABI-specific directories to the system library path.
+-  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+-
+-  # Ideally, we could use ldconfig to report *all* directores which are
+-  # searched for libraries, however this is still not possible.  Aside from not
+-  # being certain /sbin/ldconfig is available, command
+-  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+-  # even though it is searched at run-time.  Try to do the best guess by
+-  # appending ld.so.conf contents (and includes) to the search path.
++  # Append ld.so.conf contents to the search path
+   if test -f /etc/ld.so.conf; then
+     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+-    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
++    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+   fi
+ 
+   # We used to test for /lib/ld.so.1 and disable shared libraries on
+@@ -13934,12 +11663,12 @@ netbsd*)
+   need_lib_prefix=no
+   need_version=no
+   if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+     finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+     dynamic_linker='NetBSD (a.out) ld.so'
+   else
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
+     dynamic_linker='NetBSD ld.elf_so'
+   fi
+   shlibpath_var=LD_LIBRARY_PATH
+@@ -13948,8 +11677,8 @@ netbsd*)
+   ;;
+ 
+ newsos6)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+   ;;
+@@ -13958,68 +11687,58 @@ newsos6)
+   version_type=qnx
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+   hardcode_into_libs=yes
+   dynamic_linker='ldqnx.so'
+   ;;
+ 
+-openbsd* | bitrig*)
++openbsd*)
+   version_type=sunos
+-  sys_lib_dlsearch_path_spec=/usr/lib
++  sys_lib_dlsearch_path_spec="/usr/lib"
+   need_lib_prefix=no
+-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+-    need_version=no
++  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
++  case $host_os in
++    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
++    *)				need_version=no  ;;
++  esac
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
++  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
++  shlibpath_var=LD_LIBRARY_PATH
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++    case $host_os in
++      openbsd2.[89] | openbsd2.[89].*)
++	shlibpath_overrides_runpath=no
++	;;
++      *)
++	shlibpath_overrides_runpath=yes
++	;;
++      esac
+   else
+-    need_version=yes
++    shlibpath_overrides_runpath=yes
+   fi
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+   ;;
+ 
+ os2*)
+   libname_spec='$name'
+-  version_type=windows
+-  shrext_cmds=.dll
+-  need_version=no
++  shrext_cmds=".dll"
+   need_lib_prefix=no
+-  # OS/2 can only load a DLL with a base name of 8 characters or less.
+-  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+-    v=$($ECHO $release$versuffix | tr -d .-);
+-    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+-    $ECHO $n$v`$shared_ext'
+-  library_names_spec='${libname}_dll.$libext'
++  library_names_spec='$libname${shared_ext} $libname.a'
+   dynamic_linker='OS/2 ld.exe'
+-  shlibpath_var=BEGINLIBPATH
+-  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+-  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+-  postinstall_cmds='base_file=`basename \$file`~
+-    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+-    dldir=$destdir/`dirname \$dlpath`~
+-    test -d \$dldir || mkdir -p \$dldir~
+-    $install_prog $dir/$dlname \$dldir/$dlname~
+-    chmod a+x \$dldir/$dlname~
+-    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+-      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+-    fi'
+-  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+-    dlpath=$dir/\$dldll~
+-    $RM \$dlpath'
++  shlibpath_var=LIBPATH
+   ;;
+ 
+ osf3* | osf4* | osf5*)
+   version_type=osf
+   need_lib_prefix=no
+   need_version=no
+-  soname_spec='$libname$release$shared_ext$major'
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='${libname}${release}${shared_ext}$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   shlibpath_var=LD_LIBRARY_PATH
+   sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+-  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+   ;;
+ 
+ rdos*)
+@@ -14027,11 +11746,11 @@ rdos*)
+   ;;
+ 
+ solaris*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+   hardcode_into_libs=yes
+@@ -14041,20 +11760,20 @@ solaris*)
+ 
+ sunos4*)
+   version_type=sunos
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+   finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+-  if test yes = "$with_gnu_ld"; then
++  if test "$with_gnu_ld" = yes; then
+     need_lib_prefix=no
+   fi
+   need_version=yes
+   ;;
+ 
+ sysv4 | sysv4.3*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   case $host_vendor in
+     sni)
+@@ -14075,24 +11794,24 @@ sysv4 | sysv4.3*)
+   ;;
+ 
+ sysv4*MP*)
+-  if test -d /usr/nec; then
+-    version_type=linux # correct to gnu/linux during the next big refactor
+-    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+-    soname_spec='$libname$shared_ext.$major'
++  if test -d /usr/nec ;then
++    version_type=linux
++    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
++    soname_spec='$libname${shared_ext}.$major'
+     shlibpath_var=LD_LIBRARY_PATH
+   fi
+   ;;
+ 
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+-  version_type=sco
++  version_type=freebsd-elf
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+   hardcode_into_libs=yes
+-  if test yes = "$with_gnu_ld"; then
++  if test "$with_gnu_ld" = yes; then
+     sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+   else
+     sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+@@ -14107,19 +11826,19 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ 
+ tpf*)
+   # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+   hardcode_into_libs=yes
+   ;;
+ 
+ uts4*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   ;;
+ 
+@@ -14127,33 +11846,22 @@ uts4*)
+   dynamic_linker=no
+   ;;
+ esac
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+-printf "%s\n" "$dynamic_linker" >&6; }
+-test no = "$dynamic_linker" && can_build_shared=no
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
++$as_echo "$dynamic_linker" >&6; }
++test "$dynamic_linker" = no && can_build_shared=no
+ 
+ variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+-if test yes = "$GCC"; then
++if test "$GCC" = yes; then
+   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+ fi
+ 
+-if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+-  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
++if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
++  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+ fi
+-
+-if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+-  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
++if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
++  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+ fi
+ 
+-# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+-configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+-
+-# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+-func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+-
+-# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+-configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+-
+-
+ 
+ 
+ 
+@@ -14245,24 +11953,20 @@ configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+ 
+ 
+ 
+-
+-
+-
+-
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+-printf %s "checking how to hardcode library paths into programs... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
++$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+ hardcode_action=
+ if test -n "$hardcode_libdir_flag_spec" ||
+    test -n "$runpath_var" ||
+-   test yes = "$hardcode_automatic"; then
++   test "X$hardcode_automatic" = "Xyes" ; then
+ 
+   # We can hardcode non-existent directories.
+-  if test no != "$hardcode_direct" &&
++  if test "$hardcode_direct" != no &&
+      # If the only mechanism to avoid hardcoding is shlibpath_var, we
+      # have to relink, otherwise we might link with an installed library
+      # when we should be linking with a yet-to-be-installed one
+-     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+-     test no != "$hardcode_minus_L"; then
++     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
++     test "$hardcode_minus_L" != no; then
+     # Linking always hardcodes the temporary library directory.
+     hardcode_action=relink
+   else
+@@ -14274,15 +11978,15 @@ else
+   # directories.
+   hardcode_action=unsupported
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+-printf "%s\n" "$hardcode_action" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
++$as_echo "$hardcode_action" >&6; }
+ 
+-if test relink = "$hardcode_action" ||
+-   test yes = "$inherit_rpath"; then
++if test "$hardcode_action" = relink ||
++   test "$inherit_rpath" = yes; then
+   # Fast installation is not supported
+   enable_fast_install=no
+-elif test yes = "$shlibpath_overrides_runpath" ||
+-     test no = "$enable_shared"; then
++elif test "$shlibpath_overrides_runpath" = yes ||
++     test "$enable_shared" = no; then
+   # Fast installation is not necessary
+   enable_fast_install=needless
+ fi
+@@ -14292,7 +11996,7 @@ fi
+ 
+ 
+ 
+-  if test yes != "$enable_dlopen"; then
++  if test "x$enable_dlopen" != xyes; then
+   enable_dlopen=unknown
+   enable_dlopen_self=unknown
+   enable_dlopen_self_static=unknown
+@@ -14302,29 +12006,28 @@ else
+ 
+   case $host_os in
+   beos*)
+-    lt_cv_dlopen=load_add_on
++    lt_cv_dlopen="load_add_on"
+     lt_cv_dlopen_libs=
+     lt_cv_dlopen_self=yes
+     ;;
+ 
+   mingw* | pw32* | cegcc*)
+-    lt_cv_dlopen=LoadLibrary
++    lt_cv_dlopen="LoadLibrary"
+     lt_cv_dlopen_libs=
+     ;;
+ 
+   cygwin*)
+-    lt_cv_dlopen=dlopen
++    lt_cv_dlopen="dlopen"
+     lt_cv_dlopen_libs=
+     ;;
+ 
+   darwin*)
+-    # if libdl is installed we need to link against it
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+-printf %s "checking for dlopen in -ldl... " >&6; }
+-if test ${ac_cv_lib_dl_dlopen+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  # if libdl is installed we need to link against it
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
++$as_echo_n "checking for dlopen in -ldl... " >&6; }
++if ${ac_cv_lib_dl_dlopen+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldl  $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+@@ -14333,33 +12036,34 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* Override any GCC internal prototype to avoid an error.
+    Use char because int might match the return type of a GCC
+    builtin and then its argument prototype would still apply.  */
++#ifdef __cplusplus
++extern "C"
++#endif
+ char dlopen ();
+ int
+-main (void)
++main ()
+ {
+ return dlopen ();
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_lib_dl_dlopen=yes
+-else $as_nop
++else
+   ac_cv_lib_dl_dlopen=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+-printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+-if test "x$ac_cv_lib_dl_dlopen" = xyes
+-then :
+-  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
++$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
++if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
++  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
++else
+ 
+-    lt_cv_dlopen=dyld
++    lt_cv_dlopen="dyld"
+     lt_cv_dlopen_libs=
+     lt_cv_dlopen_self=yes
+ 
+@@ -14367,26 +12071,16 @@ fi
+ 
+     ;;
+ 
+-  tpf*)
+-    # Don't try to run any link tests for TPF.  We know it's impossible
+-    # because TPF is a cross-compiler, and we know how we open DSOs.
+-    lt_cv_dlopen=dlopen
+-    lt_cv_dlopen_libs=
+-    lt_cv_dlopen_self=no
+-    ;;
+-
+   *)
+     ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+-if test "x$ac_cv_func_shl_load" = xyes
+-then :
+-  lt_cv_dlopen=shl_load
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+-printf %s "checking for shl_load in -ldld... " >&6; }
+-if test ${ac_cv_lib_dld_shl_load+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++if test "x$ac_cv_func_shl_load" = xyes; then :
++  lt_cv_dlopen="shl_load"
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
++$as_echo_n "checking for shl_load in -ldld... " >&6; }
++if ${ac_cv_lib_dld_shl_load+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldld  $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+@@ -14395,42 +12089,41 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* Override any GCC internal prototype to avoid an error.
+    Use char because int might match the return type of a GCC
+    builtin and then its argument prototype would still apply.  */
++#ifdef __cplusplus
++extern "C"
++#endif
+ char shl_load ();
+ int
+-main (void)
++main ()
+ {
+ return shl_load ();
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_lib_dld_shl_load=yes
+-else $as_nop
++else
+   ac_cv_lib_dld_shl_load=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+-printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
+-if test "x$ac_cv_lib_dld_shl_load" = xyes
+-then :
+-  lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
++$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
++if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
++  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
++else
+   ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+-if test "x$ac_cv_func_dlopen" = xyes
+-then :
+-  lt_cv_dlopen=dlopen
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+-printf %s "checking for dlopen in -ldl... " >&6; }
+-if test ${ac_cv_lib_dl_dlopen+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++if test "x$ac_cv_func_dlopen" = xyes; then :
++  lt_cv_dlopen="dlopen"
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
++$as_echo_n "checking for dlopen in -ldl... " >&6; }
++if ${ac_cv_lib_dl_dlopen+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldl  $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+@@ -14439,37 +12132,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* Override any GCC internal prototype to avoid an error.
+    Use char because int might match the return type of a GCC
+    builtin and then its argument prototype would still apply.  */
++#ifdef __cplusplus
++extern "C"
++#endif
+ char dlopen ();
+ int
+-main (void)
++main ()
+ {
+ return dlopen ();
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_lib_dl_dlopen=yes
+-else $as_nop
++else
+   ac_cv_lib_dl_dlopen=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+-printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+-if test "x$ac_cv_lib_dl_dlopen" = xyes
+-then :
+-  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+-printf %s "checking for dlopen in -lsvld... " >&6; }
+-if test ${ac_cv_lib_svld_dlopen+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
++$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
++if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
++  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
++$as_echo_n "checking for dlopen in -lsvld... " >&6; }
++if ${ac_cv_lib_svld_dlopen+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_check_lib_save_LIBS=$LIBS
+ LIBS="-lsvld  $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+@@ -14478,37 +12171,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* Override any GCC internal prototype to avoid an error.
+    Use char because int might match the return type of a GCC
+    builtin and then its argument prototype would still apply.  */
++#ifdef __cplusplus
++extern "C"
++#endif
+ char dlopen ();
+ int
+-main (void)
++main ()
+ {
+ return dlopen ();
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_lib_svld_dlopen=yes
+-else $as_nop
++else
+   ac_cv_lib_svld_dlopen=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+-printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; }
+-if test "x$ac_cv_lib_svld_dlopen" = xyes
+-then :
+-  lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
+-else $as_nop
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+-printf %s "checking for dld_link in -ldld... " >&6; }
+-if test ${ac_cv_lib_dld_dld_link+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
++$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
++if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
++  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
++$as_echo_n "checking for dld_link in -ldld... " >&6; }
++if ${ac_cv_lib_dld_dld_link+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   ac_check_lib_save_LIBS=$LIBS
+ LIBS="-ldld  $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+@@ -14517,30 +12210,31 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* Override any GCC internal prototype to avoid an error.
+    Use char because int might match the return type of a GCC
+    builtin and then its argument prototype would still apply.  */
++#ifdef __cplusplus
++extern "C"
++#endif
+ char dld_link ();
+ int
+-main (void)
++main ()
+ {
+ return dld_link ();
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_link "$LINENO"
+-then :
++if ac_fn_c_try_link "$LINENO"; then :
+   ac_cv_lib_dld_dld_link=yes
+-else $as_nop
++else
+   ac_cv_lib_dld_dld_link=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_lib_save_LIBS
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+-printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; }
+-if test "x$ac_cv_lib_dld_dld_link" = xyes
+-then :
+-  lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
++$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
++if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
++  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+ fi
+ 
+ 
+@@ -14561,36 +12255,35 @@ fi
+     ;;
+   esac
+ 
+-  if test no = "$lt_cv_dlopen"; then
+-    enable_dlopen=no
+-  else
++  if test "x$lt_cv_dlopen" != xno; then
+     enable_dlopen=yes
++  else
++    enable_dlopen=no
+   fi
+ 
+   case $lt_cv_dlopen in
+   dlopen)
+-    save_CPPFLAGS=$CPPFLAGS
+-    test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
++    save_CPPFLAGS="$CPPFLAGS"
++    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+ 
+-    save_LDFLAGS=$LDFLAGS
++    save_LDFLAGS="$LDFLAGS"
+     wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+ 
+-    save_LIBS=$LIBS
++    save_LIBS="$LIBS"
+     LIBS="$lt_cv_dlopen_libs $LIBS"
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+-printf %s "checking whether a program can dlopen itself... " >&6; }
+-if test ${lt_cv_dlopen_self+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  	  if test yes = "$cross_compiling"; then :
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
++$as_echo_n "checking whether a program can dlopen itself... " >&6; }
++if ${lt_cv_dlopen_self+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  	  if test "$cross_compiling" = yes; then :
+   lt_cv_dlopen_self=cross
+ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line $LINENO "configure"
++#line 12286 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -14631,13 +12324,13 @@ else
+ #  endif
+ #endif
+ 
+-/* When -fvisibility=hidden is used, assume the code has been annotated
++/* When -fvisbility=hidden is used, assume the code has been annotated
+    correspondingly for the symbols needed.  */
+-#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+-int fnord () __attribute__((visibility("default")));
++#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
++void fnord () __attribute__((visibility("default")));
+ #endif
+ 
+-int fnord () { return 42; }
++void fnord () { int i=42; }
+ int main ()
+ {
+   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+@@ -14662,8 +12355,8 @@ _LT_EOF
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+   (eval $ac_link) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+     (./conftest; exit; ) >&5 2>/dev/null
+     lt_status=$?
+     case x$lt_status in
+@@ -14680,24 +12373,23 @@ rm -fr conftest*
+ 
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+-printf "%s\n" "$lt_cv_dlopen_self" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
++$as_echo "$lt_cv_dlopen_self" >&6; }
+ 
+-    if test yes = "$lt_cv_dlopen_self"; then
++    if test "x$lt_cv_dlopen_self" = xyes; then
+       wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+-printf %s "checking whether a statically linked program can dlopen itself... " >&6; }
+-if test ${lt_cv_dlopen_self_static+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  	  if test yes = "$cross_compiling"; then :
++      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
++$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
++if ${lt_cv_dlopen_self_static+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  	  if test "$cross_compiling" = yes; then :
+   lt_cv_dlopen_self_static=cross
+ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line $LINENO "configure"
++#line 12392 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -14738,13 +12430,13 @@ else
+ #  endif
+ #endif
+ 
+-/* When -fvisibility=hidden is used, assume the code has been annotated
++/* When -fvisbility=hidden is used, assume the code has been annotated
+    correspondingly for the symbols needed.  */
+-#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+-int fnord () __attribute__((visibility("default")));
++#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
++void fnord () __attribute__((visibility("default")));
+ #endif
+ 
+-int fnord () { return 42; }
++void fnord () { int i=42; }
+ int main ()
+ {
+   void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+@@ -14769,8 +12461,8 @@ _LT_EOF
+   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+   (eval $ac_link) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+     (./conftest; exit; ) >&5 2>/dev/null
+     lt_status=$?
+     case x$lt_status in
+@@ -14787,13 +12479,13 @@ rm -fr conftest*
+ 
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+-printf "%s\n" "$lt_cv_dlopen_self_static" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
++$as_echo "$lt_cv_dlopen_self_static" >&6; }
+     fi
+ 
+-    CPPFLAGS=$save_CPPFLAGS
+-    LDFLAGS=$save_LDFLAGS
+-    LIBS=$save_LIBS
++    CPPFLAGS="$save_CPPFLAGS"
++    LDFLAGS="$save_LDFLAGS"
++    LIBS="$save_LIBS"
+     ;;
+   esac
+ 
+@@ -14826,43 +12518,32 @@ fi
+ 
+ striplib=
+ old_striplib=
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+-printf %s "checking whether stripping libraries is possible... " >&6; }
+-if test -z "$STRIP"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-else
+-  if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+-    old_striplib="$STRIP --strip-debug"
+-    striplib="$STRIP --strip-unneeded"
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
+-  else
+-    case $host_os in
+-    darwin*)
+-      # FIXME - insert some real tests, host_os isn't really good enough
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
++$as_echo_n "checking whether stripping libraries is possible... " >&6; }
++if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
++  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
++  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++else
++# FIXME - insert some real tests, host_os isn't really good enough
++  case $host_os in
++  darwin*)
++    if test -n "$STRIP" ; then
+       striplib="$STRIP -x"
+       old_striplib="$STRIP -S"
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
+-      ;;
+-    freebsd*)
+-      if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+-        old_striplib="$STRIP --strip-debug"
+-        striplib="$STRIP --strip-unneeded"
+-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-printf "%s\n" "yes" >&6; }
+-      else
+-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-      fi
+-      ;;
+-    *)
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
+-      ;;
+-    esac
+-  fi
++      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
++$as_echo "yes" >&6; }
++    else
++      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++    fi
++    ;;
++  *)
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++    ;;
++  esac
+ fi
+ 
+ 
+@@ -14876,21 +12557,21 @@ fi
+ 
+ 
+ 
+-  # Report what library types will actually be built
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+-printf %s "checking if libtool supports shared libraries... " >&6; }
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+-printf "%s\n" "$can_build_shared" >&6; }
++  # Report which library types will actually be built
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
++$as_echo_n "checking if libtool supports shared libraries... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
++$as_echo "$can_build_shared" >&6; }
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+-printf %s "checking whether to build shared libraries... " >&6; }
+-  test no = "$can_build_shared" && enable_shared=no
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
++$as_echo_n "checking whether to build shared libraries... " >&6; }
++  test "$can_build_shared" = "no" && enable_shared=no
+ 
+   # On AIX, shared libraries and static libraries use the same namespace, and
+   # are all built from PIC.
+   case $host_os in
+   aix3*)
+-    test yes = "$enable_shared" && enable_static=no
++    test "$enable_shared" = yes && enable_static=no
+     if test -n "$RANLIB"; then
+       archive_cmds="$archive_cmds~\$RANLIB \$lib"
+       postinstall_cmds='$RANLIB $lib'
+@@ -14898,24 +12579,20 @@ printf %s "checking whether to build shared libraries... " >&6; }
+     ;;
+ 
+   aix[4-9]*)
+-    if test ia64 != "$host_cpu"; then
+-      case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+-      yes,aix,yes) ;;			# shared object as lib.so file only
+-      yes,svr4,*) ;;			# shared object as lib.so archive member only
+-      yes,*) enable_static=no ;;	# shared object in lib.a archive as well
+-      esac
++    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
++      test "$enable_shared" = yes && enable_static=no
+     fi
+     ;;
+   esac
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+-printf "%s\n" "$enable_shared" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
++$as_echo "$enable_shared" >&6; }
+ 
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+-printf %s "checking whether to build static libraries... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
++$as_echo_n "checking whether to build static libraries... " >&6; }
+   # Make sure either enable_shared or enable_static is yes.
+-  test yes = "$enable_shared" || enable_static=yes
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+-printf "%s\n" "$enable_static" >&6; }
++  test "$enable_shared" = yes || enable_static=yes
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
++$as_echo "$enable_static" >&6; }
+ 
+ 
+ 
+@@ -14927,42 +12604,46 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+-CC=$lt_save_CC
++CC="$lt_save_CC"
+ 
+-      if test -n "$CXX" && ( test no != "$CXX" &&
+-    ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+-    (test g++ != "$CXX"))); then
++      if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
++    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
++    (test "X$CXX" != "Xg++"))) ; then
+   ac_ext=cpp
+ ac_cpp='$CXXCPP $CPPFLAGS'
+ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+-printf %s "checking how to run the C++ preprocessor... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
++$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+ if test -z "$CXXCPP"; then
+-  if test ${ac_cv_prog_CXXCPP+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-      # Double quotes because $CXX needs to be expanded
+-    for CXXCPP in "$CXX -E" cpp /lib/cpp
++  if ${ac_cv_prog_CXXCPP+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++      # Double quotes because CXXCPP needs to be expanded
++    for CXXCPP in "$CXX -E" "/lib/cpp"
+     do
+       ac_preproc_ok=false
+ for ac_cxx_preproc_warn_flag in '' yes
+ do
+   # Use a header file that comes with gcc, so configuring glibc
+   # with a fresh cross-compiler works.
++  # Prefer  to  if __STDC__ is defined, since
++  #  exists even on freestanding compilers.
+   # On the NeXT, cc -E runs the code through the compiler's parser,
+   # not just through cpp. "Syntax error" is here to catch this case.
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+-#include 
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
+ 		     Syntax error
+ _ACEOF
+-if ac_fn_cxx_try_cpp "$LINENO"
+-then :
++if ac_fn_cxx_try_cpp "$LINENO"; then :
+ 
+-else $as_nop
++else
+   # Broken: fails on valid input.
+ continue
+ fi
+@@ -14974,11 +12655,10 @@ rm -f conftest.err conftest.i conftest.$ac_ext
+ /* end confdefs.h.  */
+ #include 
+ _ACEOF
+-if ac_fn_cxx_try_cpp "$LINENO"
+-then :
++if ac_fn_cxx_try_cpp "$LINENO"; then :
+   # Broken: success on invalid input.
+ continue
+-else $as_nop
++else
+   # Passes both tests.
+ ac_preproc_ok=:
+ break
+@@ -14988,8 +12668,7 @@ rm -f conftest.err conftest.i conftest.$ac_ext
+ done
+ # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+ rm -f conftest.i conftest.err conftest.$ac_ext
+-if $ac_preproc_ok
+-then :
++if $ac_preproc_ok; then :
+   break
+ fi
+ 
+@@ -15001,24 +12680,29 @@ fi
+ else
+   ac_cv_prog_CXXCPP=$CXXCPP
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+-printf "%s\n" "$CXXCPP" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
++$as_echo "$CXXCPP" >&6; }
+ ac_preproc_ok=false
+ for ac_cxx_preproc_warn_flag in '' yes
+ do
+   # Use a header file that comes with gcc, so configuring glibc
+   # with a fresh cross-compiler works.
++  # Prefer  to  if __STDC__ is defined, since
++  #  exists even on freestanding compilers.
+   # On the NeXT, cc -E runs the code through the compiler's parser,
+   # not just through cpp. "Syntax error" is here to catch this case.
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+-#include 
++#ifdef __STDC__
++# include 
++#else
++# include 
++#endif
+ 		     Syntax error
+ _ACEOF
+-if ac_fn_cxx_try_cpp "$LINENO"
+-then :
++if ac_fn_cxx_try_cpp "$LINENO"; then :
+ 
+-else $as_nop
++else
+   # Broken: fails on valid input.
+ continue
+ fi
+@@ -15030,11 +12714,10 @@ rm -f conftest.err conftest.i conftest.$ac_ext
+ /* end confdefs.h.  */
+ #include 
+ _ACEOF
+-if ac_fn_cxx_try_cpp "$LINENO"
+-then :
++if ac_fn_cxx_try_cpp "$LINENO"; then :
+   # Broken: success on invalid input.
+ continue
+-else $as_nop
++else
+   # Passes both tests.
+ ac_preproc_ok=:
+ break
+@@ -15044,12 +12727,11 @@ rm -f conftest.err conftest.i conftest.$ac_ext
+ done
+ # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+ rm -f conftest.i conftest.err conftest.$ac_ext
+-if $ac_preproc_ok
+-then :
++if $ac_preproc_ok; then :
+ 
+-else $as_nop
+-  { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++else
++  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+ See \`config.log' for more details" "$LINENO" 5; }
+ fi
+@@ -15079,6 +12761,7 @@ export_dynamic_flag_spec_CXX=
+ hardcode_direct_CXX=no
+ hardcode_direct_absolute_CXX=no
+ hardcode_libdir_flag_spec_CXX=
++hardcode_libdir_flag_spec_ld_CXX=
+ hardcode_libdir_separator_CXX=
+ hardcode_minus_L_CXX=no
+ hardcode_shlibpath_var_CXX=unsupported
+@@ -15105,7 +12788,7 @@ objext_CXX=$objext
+ # the CXX compiler isn't working.  Some variables (like enable_shared)
+ # are currently assumed to apply to all compilers on this platform,
+ # and will be corrupted by setting them based on a non-working compiler.
+-if test yes != "$_lt_caught_CXX_error"; then
++if test "$_lt_caught_CXX_error" != yes; then
+   # Code to be used in simple compile tests
+   lt_simple_compile_test_code="int some_variable = 0;"
+ 
+@@ -15145,7 +12828,6 @@ $RM -r conftest*
+ 
+   # Allow CC to be a program name with arguments.
+   lt_save_CC=$CC
+-  lt_save_CFLAGS=$CFLAGS
+   lt_save_LD=$LD
+   lt_save_GCC=$GCC
+   GCC=$GXX
+@@ -15163,43 +12845,48 @@ $RM -r conftest*
+   fi
+   test -z "${LDCXX+set}" || LD=$LDCXX
+   CC=${CXX-"c++"}
+-  CFLAGS=$CXXFLAGS
+   compiler=$CC
+   compiler_CXX=$CC
+-  func_cc_basename $compiler
+-cc_basename=$func_cc_basename_result
++  for cc_temp in $compiler""; do
++  case $cc_temp in
++    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
++    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
++    \-*) ;;
++    *) break;;
++  esac
++done
++cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+ 
+ 
+   if test -n "$compiler"; then
+     # We don't want -fno-exception when compiling C++ code, so set the
+     # no_builtin_flag separately
+-    if test yes = "$GXX"; then
++    if test "$GXX" = yes; then
+       lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+     else
+       lt_prog_compiler_no_builtin_flag_CXX=
+     fi
+ 
+-    if test yes = "$GXX"; then
++    if test "$GXX" = yes; then
+       # Set up default GNU C++ configuration
+ 
+ 
+ 
+ # Check whether --with-gnu-ld was given.
+-if test ${with_gnu_ld+y}
+-then :
+-  withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+-else $as_nop
++if test "${with_gnu_ld+set}" = set; then :
++  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
++else
+   with_gnu_ld=no
+ fi
+ 
+ ac_prog=ld
+-if test yes = "$GCC"; then
++if test "$GCC" = yes; then
+   # Check if gcc -print-prog-name=ld gives a path.
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+-printf %s "checking for ld used by $CC... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
++$as_echo_n "checking for ld used by $CC... " >&6; }
+   case $host in
+   *-*-mingw*)
+-    # gcc leaves a trailing carriage return, which upsets mingw
++    # gcc leaves a trailing carriage return which upsets mingw
+     ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+   *)
+     ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+@@ -15213,7 +12900,7 @@ printf %s "checking for ld used by $CC... " >&6; }
+       while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ 	ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+       done
+-      test -z "$LD" && LD=$ac_prog
++      test -z "$LD" && LD="$ac_prog"
+       ;;
+   "")
+     # If it fails, then pretend we aren't using GCC.
+@@ -15224,58 +12911,56 @@ printf %s "checking for ld used by $CC... " >&6; }
+     with_gnu_ld=unknown
+     ;;
+   esac
+-elif test yes = "$with_gnu_ld"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+-printf %s "checking for GNU ld... " >&6; }
++elif test "$with_gnu_ld" = yes; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
++$as_echo_n "checking for GNU ld... " >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+-printf %s "checking for non-GNU ld... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
++$as_echo_n "checking for non-GNU ld... " >&6; }
+ fi
+-if test ${lt_cv_path_LD+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++if ${lt_cv_path_LD+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   if test -z "$LD"; then
+-  lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
++  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+   for ac_dir in $PATH; do
+-    IFS=$lt_save_ifs
++    IFS="$lt_save_ifs"
+     test -z "$ac_dir" && ac_dir=.
+     if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+-      lt_cv_path_LD=$ac_dir/$ac_prog
++      lt_cv_path_LD="$ac_dir/$ac_prog"
+       # Check to see if the program is GNU ld.  I'd rather use --version,
+       # but apparently some variants of GNU ld only accept -v.
+       # Break only if it was the GNU/non-GNU ld that we prefer.
+       case `"$lt_cv_path_LD" -v 2>&1 &5
+-printf "%s\n" "$LD" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
++$as_echo "$LD" >&6; }
+ else
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-printf "%s\n" "no" >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
+ fi
+ test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+-printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
+-if test ${lt_cv_prog_gnu_ld+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
++$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
++if ${lt_cv_prog_gnu_ld+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   # I'd rather use --version here, but apparently some GNU lds only accept -v.
+ case `$LD -v 2>&1 &1 &5
+-printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
++$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+ with_gnu_ld=$lt_cv_prog_gnu_ld
+ 
+ 
+@@ -15298,22 +12983,22 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
+ 
+       # Check if GNU C++ uses GNU ld as the underlying linker, since the
+       # archiving commands below assume that GNU ld is being used.
+-      if test yes = "$with_gnu_ld"; then
+-        archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-        archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++      if test "$with_gnu_ld" = yes; then
++        archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
++        archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ 
+-        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+-        export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
++        export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ 
+         # If archive_cmds runs LD, not CC, wlarc should be empty
+         # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+         #     investigate it a little bit more. (MM)
+-        wlarc='$wl'
++        wlarc='${wl}'
+ 
+         # ancient GNU ld didn't support --whole-archive et. al.
+         if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ 	  $GREP 'no-whole-archive' > /dev/null; then
+-          whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++          whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+         else
+           whole_archive_flag_spec_CXX=
+         fi
+@@ -15341,8 +13026,8 @@ with_gnu_ld=$lt_cv_prog_gnu_ld
+     fi
+ 
+     # PORTME: fill in a description of your system's C++ link characteristics
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+-printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
++$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+     ld_shlibs_CXX=yes
+     case $host_os in
+       aix3*)
+@@ -15350,30 +13035,18 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+         ld_shlibs_CXX=no
+         ;;
+       aix[4-9]*)
+-        if test ia64 = "$host_cpu"; then
++        if test "$host_cpu" = ia64; then
+           # On IA64, the linker does run time linking by default, so we don't
+           # have to do anything special.
+           aix_use_runtimelinking=no
+           exp_sym_flag='-Bexport'
+-          no_entry_flag=
++          no_entry_flag=""
+         else
+           aix_use_runtimelinking=no
+ 
+           # Test if we are trying to use run time linking or normal
+           # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+-          # have runtime linking enabled, and use it for executables.
+-          # For shared libraries, we enable/disable runtime linking
+-          # depending on the kind of the shared library created -
+-          # when "with_aix_soname,aix_use_runtimelinking" is:
+-          # "aix,no"   lib.a(lib.so.V) shared, rtl:no,  for executables
+-          # "aix,yes"  lib.so          shared, rtl:yes, for executables
+-          #            lib.a           static archive
+-          # "both,no"  lib.so.V(shr.o) shared, rtl:yes
+-          #            lib.a(lib.so.V) shared, rtl:no,  for executables
+-          # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+-          #            lib.a(lib.so.V) shared, rtl:no
+-          # "svr4,*"   lib.so.V(shr.o) shared, rtl:yes, for executables
+-          #            lib.a           static archive
++          # need to do runtime linking.
+           case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ 	    for ld_flag in $LDFLAGS; do
+ 	      case $ld_flag in
+@@ -15383,13 +13056,6 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+ 	        ;;
+ 	      esac
+ 	    done
+-	    if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+-	      # With aix-soname=svr4, we create the lib.so.V shared archives only,
+-	      # so we don't have lib.a shared libs to link our executables.
+-	      # We have to force runtime linking in this case.
+-	      aix_use_runtimelinking=yes
+-	      LDFLAGS="$LDFLAGS -Wl,-brtl"
+-	    fi
+ 	    ;;
+           esac
+ 
+@@ -15408,21 +13074,13 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+         hardcode_direct_absolute_CXX=yes
+         hardcode_libdir_separator_CXX=':'
+         link_all_deplibs_CXX=yes
+-        file_list_spec_CXX='$wl-f,'
+-        case $with_aix_soname,$aix_use_runtimelinking in
+-        aix,*) ;;	# no import file
+-        svr4,* | *,yes) # use import file
+-          # The Import File defines what to hardcode.
+-          hardcode_direct_CXX=no
+-          hardcode_direct_absolute_CXX=no
+-          ;;
+-        esac
++        file_list_spec_CXX='${wl}-f,'
+ 
+-        if test yes = "$GXX"; then
++        if test "$GXX" = yes; then
+           case $host_os in aix4.[012]|aix4.[012].*)
+           # We only want to do this on AIX 4.2 and lower, the check
+           # below for broken collect2 doesn't work under 4.3+
+-	  collect2name=`$CC -print-prog-name=collect2`
++	  collect2name=`${CC} -print-prog-name=collect2`
+ 	  if test -f "$collect2name" &&
+ 	     strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ 	  then
+@@ -15440,172 +13098,122 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries
+ 	  fi
+           esac
+           shared_flag='-shared'
+-	  if test yes = "$aix_use_runtimelinking"; then
+-	    shared_flag=$shared_flag' $wl-G'
++	  if test "$aix_use_runtimelinking" = yes; then
++	    shared_flag="$shared_flag "'${wl}-G'
+ 	  fi
+-	  # Need to ensure runtime linking is disabled for the traditional
+-	  # shared library, or the linker may eventually find shared libraries
+-	  # /with/ Import File - we do not want to mix them.
+-	  shared_flag_aix='-shared'
+-	  shared_flag_svr4='-shared $wl-G'
+         else
+           # not using gcc
+-          if test ia64 = "$host_cpu"; then
++          if test "$host_cpu" = ia64; then
+ 	  # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ 	  # chokes on -Wl,-G. The following line is correct:
+ 	  shared_flag='-G'
+           else
+-	    if test yes = "$aix_use_runtimelinking"; then
+-	      shared_flag='$wl-G'
++	    if test "$aix_use_runtimelinking" = yes; then
++	      shared_flag='${wl}-G'
+ 	    else
+-	      shared_flag='$wl-bM:SRE'
++	      shared_flag='${wl}-bM:SRE'
+ 	    fi
+-	    shared_flag_aix='$wl-bM:SRE'
+-	    shared_flag_svr4='$wl-G'
+           fi
+         fi
+ 
+-        export_dynamic_flag_spec_CXX='$wl-bexpall'
++        export_dynamic_flag_spec_CXX='${wl}-bexpall'
+         # It seems that -bexpall does not export symbols beginning with
+         # underscore (_), so it is better to generate a list of symbols to
+ 	# export.
+         always_export_symbols_CXX=yes
+-	if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
++        if test "$aix_use_runtimelinking" = yes; then
+           # Warning - without using the other runtime loading flags (-brtl),
+           # -berok will link without error, but may produce a broken library.
+-          # The "-G" linker flag allows undefined symbols.
+-          no_undefined_flag_CXX='-bernotok'
++          allow_undefined_flag_CXX='-berok'
+           # Determine the default libpath from the value encoded in an empty
+           # executable.
+-          if test set = "${lt_cv_aix_libpath+set}"; then
+-  aix_libpath=$lt_cv_aix_libpath
+-else
+-  if test ${lt_cv_aix_libpath__CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_link "$LINENO"
+-then :
+-
+-  lt_aix_libpath_sed='
+-      /Import File Strings/,/^$/ {
+-	  /^0/ {
+-	      s/^0  *\([^ ]*\) *$/\1/
+-	      p
+-	  }
+-      }'
+-  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  # Check for a 64-bit object if we didn't find anything.
+-  if test -z "$lt_cv_aix_libpath__CXX"; then
+-    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  fi
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
+-    conftest$ac_exeext conftest.$ac_ext
+-  if test -z "$lt_cv_aix_libpath__CXX"; then
+-    lt_cv_aix_libpath__CXX=/usr/lib:/lib
+-  fi
++if ac_fn_cxx_try_link "$LINENO"; then :
+ 
++lt_aix_libpath_sed='
++    /Import File Strings/,/^$/ {
++	/^0/ {
++	    s/^0  *\(.*\)$/\1/
++	    p
++	}
++    }'
++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++# Check for a 64-bit object if we didn't find anything.
++if test -z "$aix_libpath"; then
++  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+-
+-  aix_libpath=$lt_cv_aix_libpath__CXX
+ fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+ 
+-          hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
++          hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ 
+-          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
++          archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+         else
+-          if test ia64 = "$host_cpu"; then
+-	    hardcode_libdir_flag_spec_CXX='$wl-R $libdir:/usr/lib:/lib'
++          if test "$host_cpu" = ia64; then
++	    hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ 	    allow_undefined_flag_CXX="-z nodefs"
+-	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
++	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+           else
+ 	    # Determine the default libpath from the value encoded in an
+ 	    # empty executable.
+-	    if test set = "${lt_cv_aix_libpath+set}"; then
+-  aix_libpath=$lt_cv_aix_libpath
+-else
+-  if test ${lt_cv_aix_libpath__CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_link "$LINENO"
+-then :
+-
+-  lt_aix_libpath_sed='
+-      /Import File Strings/,/^$/ {
+-	  /^0/ {
+-	      s/^0  *\([^ ]*\) *$/\1/
+-	      p
+-	  }
+-      }'
+-  lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  # Check for a 64-bit object if we didn't find anything.
+-  if test -z "$lt_cv_aix_libpath__CXX"; then
+-    lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+-  fi
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
+-    conftest$ac_exeext conftest.$ac_ext
+-  if test -z "$lt_cv_aix_libpath__CXX"; then
+-    lt_cv_aix_libpath__CXX=/usr/lib:/lib
+-  fi
++if ac_fn_cxx_try_link "$LINENO"; then :
+ 
++lt_aix_libpath_sed='
++    /Import File Strings/,/^$/ {
++	/^0/ {
++	    s/^0  *\(.*\)$/\1/
++	    p
++	}
++    }'
++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
++# Check for a 64-bit object if we didn't find anything.
++if test -z "$aix_libpath"; then
++  aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+-
+-  aix_libpath=$lt_cv_aix_libpath__CXX
+ fi
++rm -f core conftest.err conftest.$ac_objext \
++    conftest$ac_exeext conftest.$ac_ext
++if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+ 
+-	    hardcode_libdir_flag_spec_CXX='$wl-blibpath:$libdir:'"$aix_libpath"
++	    hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ 	    # Warning - without using the other run time loading flags,
+ 	    # -berok will link without error, but may produce a broken library.
+-	    no_undefined_flag_CXX=' $wl-bernotok'
+-	    allow_undefined_flag_CXX=' $wl-berok'
+-	    if test yes = "$with_gnu_ld"; then
++	    no_undefined_flag_CXX=' ${wl}-bernotok'
++	    allow_undefined_flag_CXX=' ${wl}-berok'
++	    if test "$with_gnu_ld" = yes; then
+ 	      # We only use this code for GNU lds that support --whole-archive.
+-	      whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
++	      whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ 	    else
+ 	      # Exported symbols can be pulled into shared objects from archives
+ 	      whole_archive_flag_spec_CXX='$convenience'
+ 	    fi
+ 	    archive_cmds_need_lc_CXX=yes
+-	    archive_expsym_cmds_CXX='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+-	    # -brtl affects multiple linker settings, -berok does not and is overridden later
+-	    compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+-	    if test svr4 != "$with_aix_soname"; then
+-	      # This is similar to how AIX traditionally builds its shared
+-	      # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+-	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+-	    fi
+-	    if test aix != "$with_aix_soname"; then
+-	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+-	    else
+-	      # used by -dlpreopen to get the symbols
+-	      archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$MV  $output_objdir/$realname.d/$soname $output_objdir'
+-	    fi
+-	    archive_expsym_cmds_CXX="$archive_expsym_cmds_CXX"'~$RM -r $output_objdir/$realname.d'
++	    # This is similar to how AIX traditionally builds its shared
++	    # libraries.
++	    archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+           fi
+         fi
+         ;;
+@@ -15615,7 +13223,7 @@ fi
+ 	  allow_undefined_flag_CXX=unsupported
+ 	  # Joseph Beckenbach  says some releases of gcc
+ 	  # support --undefined.  This deserves some investigation.  FIXME
+-	  archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++	  archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ 	else
+ 	  ld_shlibs_CXX=no
+ 	fi
+@@ -15631,76 +13239,29 @@ fi
+         ;;
+ 
+       cygwin* | mingw* | pw32* | cegcc*)
+-	case $GXX,$cc_basename in
+-	,cl* | no,cl* | ,icl* | no,icl*)
+-	  # Native MSVC or ICC
+-	  # hardcode_libdir_flag_spec is actually meaningless, as there is
+-	  # no search path for DLLs.
+-	  hardcode_libdir_flag_spec_CXX=' '
+-	  allow_undefined_flag_CXX=unsupported
+-	  always_export_symbols_CXX=yes
+-	  file_list_spec_CXX='@'
+-	  # Tell ltmain to make .lib files, not .a files.
+-	  libext=lib
+-	  # Tell ltmain to make .dll files, not .so files.
+-	  shrext_cmds=.dll
+-	  # FIXME: Setting linknames here is a bad hack.
+-	  archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+-	  archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+-              cp "$export_symbols" "$output_objdir/$soname.def";
+-              echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+-            else
+-              $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+-            fi~
+-            $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+-            linknames='
+-	  # The linker will not automatically build a static lib if we build a DLL.
+-	  # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true'
+-	  enable_shared_with_static_runtimes_CXX=yes
+-	  # Don't use ranlib
+-	  old_postinstall_cmds_CXX='chmod 644 $oldlib'
+-	  postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~
+-            lt_tool_outputfile="@TOOL_OUTPUT@"~
+-            case $lt_outputfile in
+-              *.exe|*.EXE) ;;
+-              *)
+-                lt_outputfile=$lt_outputfile.exe
+-                lt_tool_outputfile=$lt_tool_outputfile.exe
+-                ;;
+-            esac~
+-            func_to_tool_file "$lt_outputfile"~
+-            if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+-              $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+-              $RM "$lt_outputfile.manifest";
+-            fi'
+-	  ;;
+-	*)
+-	  # g++
+-	  # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+-	  # as there is no search path for DLLs.
+-	  hardcode_libdir_flag_spec_CXX='-L$libdir'
+-	  export_dynamic_flag_spec_CXX='$wl--export-all-symbols'
+-	  allow_undefined_flag_CXX=unsupported
+-	  always_export_symbols_CXX=no
+-	  enable_shared_with_static_runtimes_CXX=yes
+-
+-	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+-	    archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-	    # If the export-symbols file already is a .def file, use it as
+-	    # is; otherwise, prepend EXPORTS...
+-	    archive_expsym_cmds_CXX='if   test DEF = "`$SED -n     -e '\''s/^[	 ]*//'\''     -e '\''/^\(;.*\)*$/d'\''     -e '\''s/^\(EXPORTS\|LIBRARY\)\([	 ].*\)*$/DEF/p'\''     -e q     $export_symbols`" ; then
+-              cp $export_symbols $output_objdir/$soname.def;
+-            else
+-              echo EXPORTS > $output_objdir/$soname.def;
+-              cat $export_symbols >> $output_objdir/$soname.def;
+-            fi~
+-            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+-	  else
+-	    ld_shlibs_CXX=no
+-	  fi
+-	  ;;
+-	esac
+-	;;
++        # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
++        # as there is no search path for DLLs.
++        hardcode_libdir_flag_spec_CXX='-L$libdir'
++        export_dynamic_flag_spec_CXX='${wl}--export-all-symbols'
++        allow_undefined_flag_CXX=unsupported
++        always_export_symbols_CXX=no
++        enable_shared_with_static_runtimes_CXX=yes
++
++        if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
++          archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++          # If the export-symbols file already is a .def file (1st line
++          # is EXPORTS), use it as is; otherwise, prepend...
++          archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
++	    cp $export_symbols $output_objdir/$soname.def;
++          else
++	    echo EXPORTS > $output_objdir/$soname.def;
++	    cat $export_symbols >> $output_objdir/$soname.def;
++          fi~
++          $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
++        else
++          ld_shlibs_CXX=no
++        fi
++        ;;
+       darwin* | rhapsody*)
+ 
+ 
+@@ -15708,27 +13269,26 @@ fi
+   hardcode_direct_CXX=no
+   hardcode_automatic_CXX=yes
+   hardcode_shlibpath_var_CXX=unsupported
+-  if test yes = "$lt_cv_ld_force_load"; then
+-    whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+-
++  if test "$lt_cv_ld_force_load" = "yes"; then
++    whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+   else
+     whole_archive_flag_spec_CXX=''
+   fi
+   link_all_deplibs_CXX=yes
+-  allow_undefined_flag_CXX=$_lt_dar_allow_undefined
++  allow_undefined_flag_CXX="$_lt_dar_allow_undefined"
+   case $cc_basename in
+-     ifort*|nagfor*) _lt_dar_can_shared=yes ;;
++     ifort*) _lt_dar_can_shared=yes ;;
+      *) _lt_dar_can_shared=$GCC ;;
+   esac
+-  if test yes = "$_lt_dar_can_shared"; then
++  if test "$_lt_dar_can_shared" = "yes"; then
+     output_verbose_link_cmd=func_echo_all
+-    archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+-    module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+-    archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+-    module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+-       if test yes != "$lt_cv_apple_cc_single_mod"; then
+-      archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+-      archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
++    archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
++    module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
++    archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
++    module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
++       if test "$lt_cv_apple_cc_single_mod" != "yes"; then
++      archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
++      archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+     fi
+ 
+   else
+@@ -15737,35 +13297,6 @@ fi
+ 
+ 	;;
+ 
+-      os2*)
+-	hardcode_libdir_flag_spec_CXX='-L$libdir'
+-	hardcode_minus_L_CXX=yes
+-	allow_undefined_flag_CXX=unsupported
+-	shrext_cmds=.dll
+-	archive_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+-	  emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+-	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	  emximp -o $lib $output_objdir/$libname.def'
+-	archive_expsym_cmds_CXX='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+-	  $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+-	  $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+-	  $ECHO EXPORTS >> $output_objdir/$libname.def~
+-	  prefix_cmds="$SED"~
+-	  if test EXPORTS = "`$SED 1q $export_symbols`"; then
+-	    prefix_cmds="$prefix_cmds -e 1d";
+-	  fi~
+-	  prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+-	  cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+-	  $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+-	  emximp -o $lib $output_objdir/$libname.def'
+-	old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+-	enable_shared_with_static_runtimes_CXX=yes
+-	file_list_spec_CXX='@'
+-	;;
+-
+       dgux*)
+         case $cc_basename in
+           ec++*)
+@@ -15794,21 +13325,24 @@ fi
+         archive_cmds_need_lc_CXX=no
+         ;;
+ 
+-      freebsd* | dragonfly* | midnightbsd*)
++      freebsd* | dragonfly*)
+         # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+         # conventions
+         ld_shlibs_CXX=yes
+         ;;
+ 
++      gnu*)
++        ;;
++
+       haiku*)
+-        archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
++        archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+         link_all_deplibs_CXX=yes
+         ;;
+ 
+       hpux9*)
+-        hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
++        hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+         hardcode_libdir_separator_CXX=:
+-        export_dynamic_flag_spec_CXX='$wl-E'
++        export_dynamic_flag_spec_CXX='${wl}-E'
+         hardcode_direct_CXX=yes
+         hardcode_minus_L_CXX=yes # Not in the search PATH,
+ 				             # but as the default
+@@ -15820,7 +13354,7 @@ fi
+             ld_shlibs_CXX=no
+             ;;
+           aCC*)
+-            archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++            archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+             # Commands to make compiler produce verbose output that lists
+             # what "hidden" libraries, object files and flags are used when
+             # linking a shared library.
+@@ -15829,11 +13363,11 @@ fi
+             # explicitly linking system object files so we need to strip them
+             # from the output so that they don't get included in the library
+             # dependencies.
+-            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+             ;;
+           *)
+-            if test yes = "$GXX"; then
+-              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
++            if test "$GXX" = yes; then
++              archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+             else
+               # FIXME: insert proper C++ library support
+               ld_shlibs_CXX=no
+@@ -15843,15 +13377,15 @@ fi
+         ;;
+ 
+       hpux10*|hpux11*)
+-        if test no = "$with_gnu_ld"; then
+-	  hardcode_libdir_flag_spec_CXX='$wl+b $wl$libdir'
++        if test $with_gnu_ld = no; then
++	  hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ 	  hardcode_libdir_separator_CXX=:
+ 
+           case $host_cpu in
+             hppa*64*|ia64*)
+               ;;
+             *)
+-	      export_dynamic_flag_spec_CXX='$wl-E'
++	      export_dynamic_flag_spec_CXX='${wl}-E'
+               ;;
+           esac
+         fi
+@@ -15877,13 +13411,13 @@ fi
+           aCC*)
+ 	    case $host_cpu in
+ 	      hppa*64*)
+-	        archive_cmds_CXX='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	        ;;
+ 	      ia64*)
+-	        archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	        ;;
+ 	      *)
+-	        archive_cmds_CXX='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	        archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	        ;;
+ 	    esac
+ 	    # Commands to make compiler produce verbose output that lists
+@@ -15894,20 +13428,20 @@ fi
+ 	    # explicitly linking system object files so we need to strip them
+ 	    # from the output so that they don't get included in the library
+ 	    # dependencies.
+-	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ 	    ;;
+           *)
+-	    if test yes = "$GXX"; then
+-	      if test no = "$with_gnu_ld"; then
++	    if test "$GXX" = yes; then
++	      if test $with_gnu_ld = no; then
+ 	        case $host_cpu in
+ 	          hppa*64*)
+-	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	            ;;
+ 	          ia64*)
+-	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	            ;;
+ 	          *)
+-	            archive_cmds_CXX='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	            archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	            ;;
+ 	        esac
+ 	      fi
+@@ -15922,22 +13456,22 @@ fi
+       interix[3-9]*)
+ 	hardcode_direct_CXX=no
+ 	hardcode_shlibpath_var_CXX=no
+-	hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+-	export_dynamic_flag_spec_CXX='$wl-E'
++	hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
++	export_dynamic_flag_spec_CXX='${wl}-E'
+ 	# Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ 	# Instead, shared libraries are loaded at an image base (0x10000000 by
+ 	# default) and relocated if they conflict, which is a slow very memory
+ 	# consuming and fragmenting process.  To avoid this, we pick a random,
+ 	# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ 	# time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+-	archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+-	archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++	archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
++	archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ 	;;
+       irix5* | irix6*)
+         case $cc_basename in
+           CC*)
+ 	    # SGI C++
+-	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	    archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ 
+ 	    # Archives containing C++ object files must be created using
+ 	    # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+@@ -15946,22 +13480,22 @@ fi
+ 	    old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ 	    ;;
+           *)
+-	    if test yes = "$GXX"; then
+-	      if test no = "$with_gnu_ld"; then
+-	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	    if test "$GXX" = yes; then
++	      if test "$with_gnu_ld" = no; then
++	        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ 	      else
+-	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
++	        archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+ 	      fi
+ 	    fi
+ 	    link_all_deplibs_CXX=yes
+ 	    ;;
+         esac
+-        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+         hardcode_libdir_separator_CXX=:
+         inherit_rpath_CXX=yes
+         ;;
+ 
+-      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++      linux* | k*bsd*-gnu | kopensolaris*-gnu)
+         case $cc_basename in
+           KCC*)
+ 	    # Kuck and Associates, Inc. (KAI) C++ Compiler
+@@ -15969,8 +13503,8 @@ fi
+ 	    # KCC will only create a shared library if the output file
+ 	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ 	    # to its proper name (with version) after linking.
+-	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+-	    archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
++	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++	    archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ 	    # Commands to make compiler produce verbose output that lists
+ 	    # what "hidden" libraries, object files and flags are used when
+ 	    # linking a shared library.
+@@ -15979,10 +13513,10 @@ fi
+ 	    # explicitly linking system object files so we need to strip them
+ 	    # from the output so that they don't get included in the library
+ 	    # dependencies.
+-	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ 
+-	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+-	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
++	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
++	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ 
+ 	    # Archives containing C++ object files must be created using
+ 	    # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+@@ -15996,59 +13530,59 @@ fi
+ 	    # earlier do not add the objects themselves.
+ 	    case `$CC -V 2>&1` in
+ 	      *"Version 7."*)
+-	        archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-		archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	        archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
++		archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ 		;;
+ 	      *)  # Version 8.0 or newer
+ 	        tmp_idyn=
+ 	        case $host_cpu in
+ 		  ia64*) tmp_idyn=' -i_dynamic';;
+ 		esac
+-	        archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-		archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	        archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++		archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ 		;;
+ 	    esac
+ 	    archive_cmds_need_lc_CXX=no
+-	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+-	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+-	    whole_archive_flag_spec_CXX='$wl--whole-archive$convenience $wl--no-whole-archive'
++	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
++	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
++	    whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ 	    ;;
+           pgCC* | pgcpp*)
+             # Portland Group C++ compiler
+ 	    case `$CC -V` in
+ 	    *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
+ 	      prelink_cmds_CXX='tpldir=Template.dir~
+-               rm -rf $tpldir~
+-               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+-               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
++		rm -rf $tpldir~
++		$CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
++		compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+ 	      old_archive_cmds_CXX='tpldir=Template.dir~
+-                rm -rf $tpldir~
+-                $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+-                $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+-                $RANLIB $oldlib'
++		rm -rf $tpldir~
++		$CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
++		$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
++		$RANLIB $oldlib'
+ 	      archive_cmds_CXX='tpldir=Template.dir~
+-                rm -rf $tpldir~
+-                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+-                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
++		rm -rf $tpldir~
++		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ 	      archive_expsym_cmds_CXX='tpldir=Template.dir~
+-                rm -rf $tpldir~
+-                $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+-                $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++		rm -rf $tpldir~
++		$CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
++		$CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ 	      ;;
+ 	    *) # Version 6 and above use weak symbols
+-	      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-	      archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
++	      archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
++	      archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ 	      ;;
+ 	    esac
+ 
+-	    hardcode_libdir_flag_spec_CXX='$wl--rpath $wl$libdir'
+-	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+-	    whole_archive_flag_spec_CXX='$wl--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	    hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
++	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
++	    whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+             ;;
+ 	  cxx*)
+ 	    # Compaq C++
+-	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+-	    archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname  -o $lib $wl-retain-symbols-file $wl$export_symbols'
++	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
++	    archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+ 
+ 	    runpath_var=LD_RUN_PATH
+ 	    hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+@@ -16062,29 +13596,29 @@ fi
+ 	    # explicitly linking system object files so we need to strip them
+ 	    # from the output so that they don't get included in the library
+ 	    # dependencies.
+-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
++	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+ 	    ;;
+ 	  xl* | mpixl* | bgxl*)
+ 	    # IBM XL 8.0 on PPC, with GNU ld
+-	    hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
+-	    export_dynamic_flag_spec_CXX='$wl--export-dynamic'
+-	    archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+-	    if test yes = "$supports_anon_versioning"; then
++	    hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
++	    export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
++	    archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
++	    if test "x$supports_anon_versioning" = xyes; then
+ 	      archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
+-                cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+-                echo "local: *; };" >> $output_objdir/$libname.ver~
+-                $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
++		cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
++		echo "local: *; };" >> $output_objdir/$libname.ver~
++		$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ 	    fi
+ 	    ;;
+ 	  *)
+-	    case `$CC -V 2>&1 | $SED 5q` in
++	    case `$CC -V 2>&1 | sed 5q` in
+ 	    *Sun\ C*)
+ 	      # Sun C++ 5.9
+ 	      no_undefined_flag_CXX=' -zdefs'
+-	      archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+-	      archive_expsym_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
++	      archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	      archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ 	      hardcode_libdir_flag_spec_CXX='-R$libdir'
+-	      whole_archive_flag_spec_CXX='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
++	      whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ 	      compiler_needs_object_CXX=yes
+ 
+ 	      # Not sure whether something based on
+@@ -16142,17 +13676,22 @@ fi
+         ld_shlibs_CXX=yes
+ 	;;
+ 
+-      openbsd* | bitrig*)
++      openbsd2*)
++        # C++ shared libraries are fairly broken
++	ld_shlibs_CXX=no
++	;;
++
++      openbsd*)
+ 	if test -f /usr/libexec/ld.so; then
+ 	  hardcode_direct_CXX=yes
+ 	  hardcode_shlibpath_var_CXX=no
+ 	  hardcode_direct_absolute_CXX=yes
+ 	  archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+-	  hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
+-	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+-	    archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+-	    export_dynamic_flag_spec_CXX='$wl-E'
+-	    whole_archive_flag_spec_CXX=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
++	  hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
++	  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++	    archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
++	    export_dynamic_flag_spec_CXX='${wl}-E'
++	    whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ 	  fi
+ 	  output_verbose_link_cmd=func_echo_all
+ 	else
+@@ -16168,9 +13707,9 @@ fi
+ 	    # KCC will only create a shared library if the output file
+ 	    # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ 	    # to its proper name (with version) after linking.
+-	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
++	    archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ 
+-	    hardcode_libdir_flag_spec_CXX='$wl-rpath,$libdir'
++	    hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ 	    hardcode_libdir_separator_CXX=:
+ 
+ 	    # Archives containing C++ object files must be created using
+@@ -16188,17 +13727,17 @@ fi
+           cxx*)
+ 	    case $host in
+ 	      osf3*)
+-	        allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
+-	        archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+-	        hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++	        allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
++	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
++	        hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ 		;;
+ 	      *)
+ 	        allow_undefined_flag_CXX=' -expect_unresolved \*'
+-	        archive_cmds_CXX='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
++	        archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ 	        archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+-                  echo "-hidden">> $lib.exp~
+-                  $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+-                  $RM $lib.exp'
++	          echo "-hidden">> $lib.exp~
++	          $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
++	          $RM $lib.exp'
+ 	        hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ 		;;
+ 	    esac
+@@ -16213,21 +13752,21 @@ fi
+ 	    # explicitly linking system object files so we need to strip them
+ 	    # from the output so that they don't get included in the library
+ 	    # dependencies.
+-	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
++	    output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ 	    ;;
+ 	  *)
+-	    if test yes,no = "$GXX,$with_gnu_ld"; then
+-	      allow_undefined_flag_CXX=' $wl-expect_unresolved $wl\*'
++	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
++	      allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ 	      case $host in
+ 	        osf3*)
+-	          archive_cmds_CXX='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ 		  ;;
+ 	        *)
+-	          archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
++	          archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ 		  ;;
+ 	      esac
+ 
+-	      hardcode_libdir_flag_spec_CXX='$wl-rpath $wl$libdir'
++	      hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ 	      hardcode_libdir_separator_CXX=:
+ 
+ 	      # Commands to make compiler produce verbose output that lists
+@@ -16269,13 +13808,13 @@ fi
+ 
+       solaris*)
+         case $cc_basename in
+-          CC* | sunCC*)
++          CC*)
+ 	    # Sun C++ 4.2, 5.x and Centerline C++
+             archive_cmds_need_lc_CXX=yes
+ 	    no_undefined_flag_CXX=' -zdefs'
+-	    archive_cmds_CXX='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
++	    archive_cmds_CXX='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ 	    archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-              $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++	      $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+ 
+ 	    hardcode_libdir_flag_spec_CXX='-R$libdir'
+ 	    hardcode_shlibpath_var_CXX=no
+@@ -16283,7 +13822,7 @@ fi
+ 	      solaris2.[0-5] | solaris2.[0-5].*) ;;
+ 	      *)
+ 		# The compiler driver will combine and reorder linker options,
+-		# but understands '-z linker_flag'.
++		# but understands `-z linker_flag'.
+ 	        # Supported since Solaris 2.6 (maybe 2.5.1?)
+ 		whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+ 	        ;;
+@@ -16300,30 +13839,30 @@ fi
+ 	    ;;
+           gcx*)
+ 	    # Green Hills C++ Compiler
+-	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	    archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ 
+ 	    # The C++ compiler must be used to create the archive.
+ 	    old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ 	    ;;
+           *)
+ 	    # GNU C++ compiler with Solaris linker
+-	    if test yes,no = "$GXX,$with_gnu_ld"; then
+-	      no_undefined_flag_CXX=' $wl-z ${wl}defs'
++	    if test "$GXX" = yes && test "$with_gnu_ld" = no; then
++	      no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ 	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+-	        archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	        archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ 	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++		  $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+ 
+ 	        # Commands to make compiler produce verbose output that lists
+ 	        # what "hidden" libraries, object files and flags are used when
+ 	        # linking a shared library.
+ 	        output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ 	      else
+-	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
++	        # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ 	        # platform.
+-	        archive_cmds_CXX='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
++	        archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ 	        archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+-                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
++		  $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+ 
+ 	        # Commands to make compiler produce verbose output that lists
+ 	        # what "hidden" libraries, object files and flags are used when
+@@ -16331,11 +13870,11 @@ fi
+ 	        output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ 	      fi
+ 
+-	      hardcode_libdir_flag_spec_CXX='$wl-R $wl$libdir'
++	      hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ 	      case $host_os in
+ 		solaris2.[0-5] | solaris2.[0-5].*) ;;
+ 		*)
+-		  whole_archive_flag_spec_CXX='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
++		  whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ 		  ;;
+ 	      esac
+ 	    fi
+@@ -16344,52 +13883,52 @@ fi
+         ;;
+ 
+     sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+-      no_undefined_flag_CXX='$wl-z,text'
++      no_undefined_flag_CXX='${wl}-z,text'
+       archive_cmds_need_lc_CXX=no
+       hardcode_shlibpath_var_CXX=no
+       runpath_var='LD_RUN_PATH'
+ 
+       case $cc_basename in
+         CC*)
+-	  archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+ 	*)
+-	  archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	  archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	  archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ 	  ;;
+       esac
+       ;;
+ 
+       sysv5* | sco3.2v5* | sco5v6*)
+-	# Note: We CANNOT use -z defs as we might desire, because we do not
++	# Note: We can NOT use -z defs as we might desire, because we do not
+ 	# link with -lc, and that would cause any symbols used from libc to
+ 	# always be unresolved, which means just about no library would
+ 	# ever link correctly.  If we're not using GNU ld we use -z text
+ 	# though, which does catch some bad symbols but isn't as heavy-handed
+ 	# as -z defs.
+-	no_undefined_flag_CXX='$wl-z,text'
+-	allow_undefined_flag_CXX='$wl-z,nodefs'
++	no_undefined_flag_CXX='${wl}-z,text'
++	allow_undefined_flag_CXX='${wl}-z,nodefs'
+ 	archive_cmds_need_lc_CXX=no
+ 	hardcode_shlibpath_var_CXX=no
+-	hardcode_libdir_flag_spec_CXX='$wl-R,$libdir'
++	hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir'
+ 	hardcode_libdir_separator_CXX=':'
+ 	link_all_deplibs_CXX=yes
+-	export_dynamic_flag_spec_CXX='$wl-Bexport'
++	export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ 	runpath_var='LD_RUN_PATH'
+ 
+ 	case $cc_basename in
+           CC*)
+-	    archive_cmds_CXX='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	    archive_expsym_cmds_CXX='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ 	    old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
+-              '"$old_archive_cmds_CXX"
++	      '"$old_archive_cmds_CXX"
+ 	    reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
+-              '"$reload_cmds_CXX"
++	      '"$reload_cmds_CXX"
+ 	    ;;
+ 	  *)
+-	    archive_cmds_CXX='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+-	    archive_expsym_cmds_CXX='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
++	    archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ 	    ;;
+ 	esac
+       ;;
+@@ -16419,12 +13958,12 @@ fi
+         ;;
+     esac
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+-printf "%s\n" "$ld_shlibs_CXX" >&6; }
+-    test no = "$ld_shlibs_CXX" && can_build_shared=no
++    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
++$as_echo "$ld_shlibs_CXX" >&6; }
++    test "$ld_shlibs_CXX" = no && can_build_shared=no
+ 
+-    GCC_CXX=$GXX
+-    LD_CXX=$LD
++    GCC_CXX="$GXX"
++    LD_CXX="$LD"
+ 
+     ## CAVEAT EMPTOR:
+     ## There is no encapsulation within the following macros, do not change
+@@ -16447,18 +13986,10 @@ private:
+ };
+ _LT_EOF
+ 
+-
+-_lt_libdeps_save_CFLAGS=$CFLAGS
+-case "$CC $CFLAGS " in #(
+-*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+-*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+-*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+-esac
+-
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }; then
+   # Parse the compiler output and extract the necessary
+   # objects, libraries and library flags.
+@@ -16468,38 +13999,29 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   pre_test_object_deps_done=no
+ 
+   for p in `eval "$output_verbose_link_cmd"`; do
+-    case $prev$p in
++    case $p in
+ 
+     -L* | -R* | -l*)
+        # Some compilers place space between "-{L,R}" and the path.
+        # Remove the space.
+-       if test x-L = "$p" ||
+-          test x-R = "$p"; then
++       if test $p = "-L" ||
++          test $p = "-R"; then
+ 	 prev=$p
+ 	 continue
++       else
++	 prev=
+        fi
+ 
+-       # Expand the sysroot to ease extracting the directories later.
+-       if test -z "$prev"; then
+-         case $p in
+-         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+-         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+-         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+-         esac
+-       fi
+-       case $p in
+-       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+-       esac
+-       if test no = "$pre_test_object_deps_done"; then
+-	 case $prev in
+-	 -L | -R)
++       if test "$pre_test_object_deps_done" = no; then
++	 case $p in
++	 -L* | -R*)
+ 	   # Internal compiler library paths should come after those
+ 	   # provided the user.  The postdeps already come after the
+ 	   # user supplied libs so there is no need to process them.
+ 	   if test -z "$compiler_lib_search_path_CXX"; then
+-	     compiler_lib_search_path_CXX=$prev$p
++	     compiler_lib_search_path_CXX="${prev}${p}"
+ 	   else
+-	     compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} $prev$p"
++	     compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ 	   fi
+ 	   ;;
+ 	 # The "-l" case would never come before the object being
+@@ -16507,15 +14029,13 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ 	 esac
+        else
+ 	 if test -z "$postdeps_CXX"; then
+-	   postdeps_CXX=$prev$p
++	   postdeps_CXX="${prev}${p}"
+ 	 else
+-	   postdeps_CXX="${postdeps_CXX} $prev$p"
++	   postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ 	 fi
+        fi
+-       prev=
+        ;;
+ 
+-    *.lto.$objext) ;; # Ignore GCC LTO objects
+     *.$objext)
+        # This assumes that the test object file only shows up
+        # once in the compiler output.
+@@ -16524,15 +14044,15 @@ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ 	 continue
+        fi
+ 
+-       if test no = "$pre_test_object_deps_done"; then
++       if test "$pre_test_object_deps_done" = no; then
+ 	 if test -z "$predep_objects_CXX"; then
+-	   predep_objects_CXX=$p
++	   predep_objects_CXX="$p"
+ 	 else
+ 	   predep_objects_CXX="$predep_objects_CXX $p"
+ 	 fi
+        else
+ 	 if test -z "$postdep_objects_CXX"; then
+-	   postdep_objects_CXX=$p
++	   postdep_objects_CXX="$p"
+ 	 else
+ 	   postdep_objects_CXX="$postdep_objects_CXX $p"
+ 	 fi
+@@ -16551,7 +14071,6 @@ else
+ fi
+ 
+ $RM -f confest.$objext
+-CFLAGS=$_lt_libdeps_save_CFLAGS
+ 
+ # PORTME: override above test on systems where it is broken
+ case $host_os in
+@@ -16562,6 +14081,51 @@ interix[3-9]*)
+   postdep_objects_CXX=
+   postdeps_CXX=
+   ;;
++
++linux*)
++  case `$CC -V 2>&1 | sed 5q` in
++  *Sun\ C*)
++    # Sun C++ 5.9
++
++    # The more standards-conforming stlport4 library is
++    # incompatible with the Cstd library. Avoid specifying
++    # it if it's in CXXFLAGS. Ignore libCrun as
++    # -library=stlport4 depends on it.
++    case " $CXX $CXXFLAGS " in
++    *" -library=stlport4 "*)
++      solaris_use_stlport4=yes
++      ;;
++    esac
++
++    if test "$solaris_use_stlport4" != yes; then
++      postdeps_CXX='-library=Cstd -library=Crun'
++    fi
++    ;;
++  esac
++  ;;
++
++solaris*)
++  case $cc_basename in
++  CC*)
++    # The more standards-conforming stlport4 library is
++    # incompatible with the Cstd library. Avoid specifying
++    # it if it's in CXXFLAGS. Ignore libCrun as
++    # -library=stlport4 depends on it.
++    case " $CXX $CXXFLAGS " in
++    *" -library=stlport4 "*)
++      solaris_use_stlport4=yes
++      ;;
++    esac
++
++    # Adding this requires a known-good setup of shared libraries for
++    # Sun compiler versions before 5.6, else PIC objects from an old
++    # archive will be linked into the output, leading to subtle bugs.
++    if test "$solaris_use_stlport4" != yes; then
++      postdeps_CXX='-library=Cstd -library=Crun'
++    fi
++    ;;
++  esac
++  ;;
+ esac
+ 
+ 
+@@ -16570,7 +14134,7 @@ case " $postdeps_CXX " in
+ esac
+  compiler_lib_search_dirs_CXX=
+ if test -n "${compiler_lib_search_path_CXX}"; then
+- compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | $SED -e 's! -L! !g' -e 's!^ !!'`
++ compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+ fi
+ 
+ 
+@@ -16607,16 +14171,18 @@ fi
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX=
+ 
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
++$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+ 
+   # C++ specific cases for pic, static, wl, etc.
+-  if test yes = "$GXX"; then
++  if test "$GXX" = yes; then
+     lt_prog_compiler_wl_CXX='-Wl,'
+     lt_prog_compiler_static_CXX='-static'
+ 
+     case $host_os in
+     aix*)
+       # All AIX code is PIC.
+-      if test ia64 = "$host_cpu"; then
++      if test "$host_cpu" = ia64; then
+ 	# AIX 5 now supports IA64 processor
+ 	lt_prog_compiler_static_CXX='-Bstatic'
+       fi
+@@ -16631,8 +14197,8 @@ lt_prog_compiler_static_CXX=
+         ;;
+       m68k)
+             # FIXME: we need at least 68020 code to build shared libraries, but
+-            # adding the '-m68020' flag to GCC prevents building anything better,
+-            # like '-m68040'.
++            # adding the `-m68020' flag to GCC prevents building anything better,
++            # like `-m68040'.
+             lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+         ;;
+       esac
+@@ -16647,11 +14213,6 @@ lt_prog_compiler_static_CXX=
+       # Although the cygwin gcc ignores -fPIC, still need this for old-style
+       # (--disable-auto-import) libraries
+       lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+-      case $host_os in
+-      os2*)
+-	lt_prog_compiler_static_CXX='$wl-static'
+-	;;
+-      esac
+       ;;
+     darwin* | rhapsody*)
+       # PIC is the default on this platform
+@@ -16701,7 +14262,7 @@ lt_prog_compiler_static_CXX=
+     case $host_os in
+       aix[4-9]*)
+ 	# All AIX code is PIC.
+-	if test ia64 = "$host_cpu"; then
++	if test "$host_cpu" = ia64; then
+ 	  # AIX 5 now supports IA64 processor
+ 	  lt_prog_compiler_static_CXX='-Bstatic'
+ 	else
+@@ -16716,11 +14277,6 @@ lt_prog_compiler_static_CXX=
+ 	  ;;
+ 	esac
+ 	;;
+-      mingw* | cygwin* | os2* | pw32* | cegcc*)
+-	# This hack is so that the source file can tell whether it is being
+-	# built for inclusion in a dll (and should export symbols for example).
+-	lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+-	;;
+       dgux*)
+ 	case $cc_basename in
+ 	  ec++*)
+@@ -16734,21 +14290,21 @@ lt_prog_compiler_static_CXX=
+ 	    ;;
+ 	esac
+ 	;;
+-      freebsd* | dragonfly* | midnightbsd*)
++      freebsd* | dragonfly*)
+ 	# FreeBSD uses GNU C++
+ 	;;
+       hpux9* | hpux10* | hpux11*)
+ 	case $cc_basename in
+ 	  CC*)
+ 	    lt_prog_compiler_wl_CXX='-Wl,'
+-	    lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
+-	    if test ia64 != "$host_cpu"; then
++	    lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
++	    if test "$host_cpu" != ia64; then
+ 	      lt_prog_compiler_pic_CXX='+Z'
+ 	    fi
+ 	    ;;
+ 	  aCC*)
+ 	    lt_prog_compiler_wl_CXX='-Wl,'
+-	    lt_prog_compiler_static_CXX='$wl-a ${wl}archive'
++	    lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ 	    case $host_cpu in
+ 	    hppa*64*|ia64*)
+ 	      # +Z the default
+@@ -16777,7 +14333,7 @@ lt_prog_compiler_static_CXX=
+ 	    ;;
+ 	esac
+ 	;;
+-      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
++      linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ 	case $cc_basename in
+ 	  KCC*)
+ 	    # KAI C++ Compiler
+@@ -16785,7 +14341,7 @@ lt_prog_compiler_static_CXX=
+ 	    lt_prog_compiler_pic_CXX='-fPIC'
+ 	    ;;
+ 	  ecpc* )
+-	    # old Intel C++ for x86_64, which still supported -KPIC.
++	    # old Intel C++ for x86_64 which still supported -KPIC.
+ 	    lt_prog_compiler_wl_CXX='-Wl,'
+ 	    lt_prog_compiler_pic_CXX='-KPIC'
+ 	    lt_prog_compiler_static_CXX='-static'
+@@ -16817,7 +14373,7 @@ lt_prog_compiler_static_CXX=
+ 	    lt_prog_compiler_static_CXX='-qstaticlink'
+ 	    ;;
+ 	  *)
+-	    case `$CC -V 2>&1 | $SED 5q` in
++	    case `$CC -V 2>&1 | sed 5q` in
+ 	    *Sun\ C*)
+ 	      # Sun C++ 5.9
+ 	      lt_prog_compiler_pic_CXX='-KPIC'
+@@ -16873,7 +14429,7 @@ lt_prog_compiler_static_CXX=
+ 	;;
+       solaris*)
+ 	case $cc_basename in
+-	  CC* | sunCC*)
++	  CC*)
+ 	    # Sun C++ 4.2, 5.x and Centerline C++
+ 	    lt_prog_compiler_pic_CXX='-KPIC'
+ 	    lt_prog_compiler_static_CXX='-Bstatic'
+@@ -16930,7 +14486,7 @@ lt_prog_compiler_static_CXX=
+   fi
+ 
+ case $host_os in
+-  # For platforms that do not support PIC, -DPIC is meaningless:
++  # For platforms which do not support PIC, -DPIC is meaningless:
+   *djgpp*)
+     lt_prog_compiler_pic_CXX=
+     ;;
+@@ -16938,33 +14494,24 @@ case $host_os in
+     lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+     ;;
+ esac
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5
++$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
++
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+-printf %s "checking for $compiler option to produce PIC... " >&6; }
+-if test ${lt_cv_prog_compiler_pic_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
+-  lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX
+-fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_pic_CXX" >&6; }
+-lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX
+ 
+ #
+ # Check to make sure the PIC flag actually works.
+ #
+ if test -n "$lt_prog_compiler_pic_CXX"; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+-printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
+-if test ${lt_cv_prog_compiler_pic_works_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
++$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
++if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_pic_works_CXX=no
+    ac_outfile=conftest.$ac_objext
+    echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+-   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"  ## exclude from sc_useless_quotes_in_assignment
++   lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+    # Insert the option either (1) after the last *FLAGS variable, or
+    # (2) before a word containing "conftest.", or (3) at the end.
+    # Note that $ac_compile itself does not contain backslashes and begins
+@@ -16991,10 +14538,10 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
++$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
+ 
+-if test yes = "$lt_cv_prog_compiler_pic_works_CXX"; then
++if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then
+     case $lt_prog_compiler_pic_CXX in
+      "" | " "*) ;;
+      *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+@@ -17008,20 +14555,17 @@ fi
+ 
+ 
+ 
+-
+-
+ #
+ # Check to make sure the static flag actually works.
+ #
+ wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+-printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+-if test ${lt_cv_prog_compiler_static_works_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
++$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
++if ${lt_cv_prog_compiler_static_works_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_static_works_CXX=no
+-   save_LDFLAGS=$LDFLAGS
++   save_LDFLAGS="$LDFLAGS"
+    LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+    echo "$lt_simple_link_test_code" > conftest.$ac_ext
+    if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+@@ -17040,13 +14584,13 @@ else $as_nop
+      fi
+    fi
+    $RM -r conftest*
+-   LDFLAGS=$save_LDFLAGS
++   LDFLAGS="$save_LDFLAGS"
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_static_works_CXX" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
++$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; }
+ 
+-if test yes = "$lt_cv_prog_compiler_static_works_CXX"; then
++if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then
+     :
+ else
+     lt_prog_compiler_static_CXX=
+@@ -17055,12 +14599,11 @@ fi
+ 
+ 
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+-printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+-if test ${lt_cv_prog_compiler_c_o_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_c_o_CXX=no
+    $RM -r conftest 2>/dev/null
+    mkdir conftest
+@@ -17103,17 +14646,16 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
++$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+ 
+ 
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+-printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+-if test ${lt_cv_prog_compiler_c_o_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
++$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
++if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_prog_compiler_c_o_CXX=no
+    $RM -r conftest 2>/dev/null
+    mkdir conftest
+@@ -17156,28 +14698,28 @@ else $as_nop
+    $RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+-printf "%s\n" "$lt_cv_prog_compiler_c_o_CXX" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
++$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+ 
+ 
+ 
+ 
+-hard_links=nottested
+-if test no = "$lt_cv_prog_compiler_c_o_CXX" && test no != "$need_locks"; then
++hard_links="nottested"
++if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+   # do not overwrite the value of need_locks provided by the user
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+-printf %s "checking if we can lock with hard links... " >&6; }
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
++$as_echo_n "checking if we can lock with hard links... " >&6; }
+   hard_links=yes
+   $RM conftest*
+   ln conftest.a conftest.b 2>/dev/null && hard_links=no
+   touch conftest.a
+   ln conftest.a conftest.b 2>&5 || hard_links=no
+   ln conftest.a conftest.b 2>/dev/null && hard_links=no
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+-printf "%s\n" "$hard_links" >&6; }
+-  if test no = "$hard_links"; then
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+-printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
++$as_echo "$hard_links" >&6; }
++  if test "$hard_links" = no; then
++    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
++$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+     need_locks=warn
+   fi
+ else
+@@ -17186,49 +14728,37 @@ fi
+ 
+ 
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+-printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
++$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+ 
+   export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+-  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+   case $host_os in
+   aix[4-9]*)
+     # If we're using GNU nm, then we don't want the "-C" option.
+-    # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+-    # Without the "-l" option, or with the "-B" option, AIX nm treats
+-    # weak defined symbols like other global defined symbols, whereas
+-    # GNU nm marks them as "W".
+-    # While the 'weak' keyword is ignored in the Export File, we need
+-    # it in the Import File for the 'aix-soname' feature, so we have
+-    # to replace the "-B" option with "-P" for AIX nm.
++    # -C means demangle to AIX nm, but means don't demangle with GNU nm
++    # Also, AIX nm treats weak defined symbols like other global defined
++    # symbols, whereas GNU nm marks them as "W".
+     if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+-      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
++      export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+     else
+-      export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
++      export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+     fi
+     ;;
+   pw32*)
+-    export_symbols_cmds_CXX=$ltdll_cmds
+-    ;;
++    export_symbols_cmds_CXX="$ltdll_cmds"
++  ;;
+   cygwin* | mingw* | cegcc*)
+-    case $cc_basename in
+-    cl* | icl*)
+-      exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+-      ;;
+-    *)
+-      export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+-      exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+-      ;;
+-    esac
+-    ;;
++    export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
++  ;;
+   *)
+     export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+-    ;;
++  ;;
+   esac
++  exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+-printf "%s\n" "$ld_shlibs_CXX" >&6; }
+-test no = "$ld_shlibs_CXX" && can_build_shared=no
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
++$as_echo "$ld_shlibs_CXX" >&6; }
++test "$ld_shlibs_CXX" = no && can_build_shared=no
+ 
+ with_gnu_ld_CXX=$with_gnu_ld
+ 
+@@ -17245,7 +14775,7 @@ x|xyes)
+   # Assume -lc should be added
+   archive_cmds_need_lc_CXX=yes
+ 
+-  if test yes,yes = "$GCC,$enable_shared"; then
++  if test "$enable_shared" = yes && test "$GCC" = yes; then
+     case $archive_cmds_CXX in
+     *'~'*)
+       # FIXME: we may have to deal with multi-command sequences.
+@@ -17254,19 +14784,18 @@ x|xyes)
+       # Test whether the compiler implicitly links with -lc since on some
+       # systems, -lgcc has to come before -lc. If gcc already passes -lc
+       # to ld, don't add -lc before -lgcc.
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+-printf %s "checking whether -lc should be explicitly linked in... " >&6; }
+-if test ${lt_cv_archive_cmds_need_lc_CXX+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
++$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
++if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   $RM conftest*
+ 	echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ 
+ 	if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+   (eval $ac_compile) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; } 2>conftest.err; then
+ 	  soname=conftest
+ 	  lib=conftest
+@@ -17284,7 +14813,7 @@ else $as_nop
+ 	  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+   (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+   ac_status=$?
+-  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+   test $ac_status = 0; }
+ 	  then
+ 	    lt_cv_archive_cmds_need_lc_CXX=no
+@@ -17298,8 +14827,8 @@ else $as_nop
+ 	$RM conftest*
+ 
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
+-printf "%s\n" "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
++$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
+       archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
+       ;;
+     esac
+@@ -17368,13 +14897,15 @@ esac
+ 
+ 
+ 
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+-printf %s "checking dynamic linker characteristics... " >&6; }
++
++
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
++$as_echo_n "checking dynamic linker characteristics... " >&6; }
+ 
+ library_names_spec=
+ libname_spec='lib$name'
+ soname_spec=
+-shrext_cmds=.so
++shrext_cmds=".so"
+ postinstall_cmds=
+ postuninstall_cmds=
+ finish_cmds=
+@@ -17391,108 +14922,56 @@ hardcode_into_libs=no
+ # flags to be left without arguments
+ need_version=unknown
+ 
+-
+-
+ case $host_os in
+ aix3*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+   shlibpath_var=LIBPATH
+ 
+   # AIX 3 has no versioning support, so we append a major version to the name.
+-  soname_spec='$libname$release$shared_ext$major'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   ;;
+ 
+ aix[4-9]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+   hardcode_into_libs=yes
+-  if test ia64 = "$host_cpu"; then
++  if test "$host_cpu" = ia64; then
+     # AIX 5 supports IA64
+-    library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
++    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+     shlibpath_var=LD_LIBRARY_PATH
+   else
+     # With GCC up to 2.95.x, collect2 would create an import file
+     # for dependence libraries.  The import file would start with
+-    # the line '#! .'.  This would cause the generated library to
+-    # depend on '.', always an invalid library.  This was fixed in
++    # the line `#! .'.  This would cause the generated library to
++    # depend on `.', always an invalid library.  This was fixed in
+     # development snapshots of GCC prior to 3.0.
+     case $host_os in
+       aix4 | aix4.[01] | aix4.[01].*)
+       if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ 	   echo ' yes '
+-	   echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
++	   echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ 	:
+       else
+ 	can_build_shared=no
+       fi
+       ;;
+     esac
+-    # Using Import Files as archive members, it is possible to support
+-    # filename-based versioning of shared library archives on AIX. While
+-    # this would work for both with and without runtime linking, it will
+-    # prevent static linking of such archives. So we do filename-based
+-    # shared library versioning with .so extension only, which is used
+-    # when both runtime linking and shared linking is enabled.
+-    # Unfortunately, runtime linking may impact performance, so we do
+-    # not want this to be the default eventually. Also, we use the
+-    # versioned .so libs for executables only if there is the -brtl
+-    # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+-    # To allow for filename-based versioning support, we need to create
+-    # libNAME.so.V as an archive file, containing:
+-    # *) an Import File, referring to the versioned filename of the
+-    #    archive as well as the shared archive member, telling the
+-    #    bitwidth (32 or 64) of that shared object, and providing the
+-    #    list of exported symbols of that shared object, eventually
+-    #    decorated with the 'weak' keyword
+-    # *) the shared object with the F_LOADONLY flag set, to really avoid
+-    #    it being seen by the linker.
+-    # At run time we better use the real file rather than another symlink,
+-    # but for link time we create the symlink libNAME.so -> libNAME.so.V
+-
+-    case $with_aix_soname,$aix_use_runtimelinking in
+-    # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
++    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+     # soname into executable. Probably we can add versioning support to
+     # collect2, so additional links can be useful in future.
+-    aix,yes) # traditional libtool
+-      dynamic_linker='AIX unversionable lib.so'
++    if test "$aix_use_runtimelinking" = yes; then
+       # If using run time linking (on AIX 4.2 or later) use lib.so
+       # instead of lib.a to let people know that these are not
+       # typical AIX shared libraries.
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-      ;;
+-    aix,no) # traditional AIX only
+-      dynamic_linker='AIX lib.a(lib.so.V)'
++      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    else
+       # We preserve .a as extension for shared libraries through AIX4.2
+       # and later when we are not doing run time linking.
+-      library_names_spec='$libname$release.a $libname.a'
+-      soname_spec='$libname$release$shared_ext$major'
+-      ;;
+-    svr4,*) # full svr4 only
+-      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+-      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+-      # We do not specify a path in Import Files, so LIBPATH fires.
+-      shlibpath_overrides_runpath=yes
+-      ;;
+-    *,yes) # both, prefer svr4
+-      dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+-      library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+-      # unpreferred sharedlib libNAME.a needs extra handling
+-      postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+-      postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+-      # We do not specify a path in Import Files, so LIBPATH fires.
+-      shlibpath_overrides_runpath=yes
+-      ;;
+-    *,no) # both, prefer aix
+-      dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+-      library_names_spec='$libname$release.a $libname.a'
+-      soname_spec='$libname$release$shared_ext$major'
+-      # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+-      postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+-      postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+-      ;;
+-    esac
++      library_names_spec='${libname}${release}.a $libname.a'
++      soname_spec='${libname}${release}${shared_ext}$major'
++    fi
+     shlibpath_var=LIBPATH
+   fi
+   ;;
+@@ -17502,27 +14981,27 @@ amigaos*)
+   powerpc)
+     # Since July 2007 AmigaOS4 officially supports .so libraries.
+     # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     ;;
+   m68k)
+     library_names_spec='$libname.ixlibrary $libname.a'
+     # Create ${libname}_ixlibrary.a entries in /sys/libs.
+-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
++    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+     ;;
+   esac
+   ;;
+ 
+ beos*)
+-  library_names_spec='$libname$shared_ext'
++  library_names_spec='${libname}${shared_ext}'
+   dynamic_linker="$host_os ld.so"
+   shlibpath_var=LIBRARY_PATH
+   ;;
+ 
+ bsdi[45]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+   sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+@@ -17534,17 +15013,16 @@ bsdi[45]*)
+ 
+ cygwin* | mingw* | pw32* | cegcc*)
+   version_type=windows
+-  shrext_cmds=.dll
++  shrext_cmds=".dll"
+   need_version=no
+   need_lib_prefix=no
+ 
+-  case $GCC,$cc_basename in
+-  yes,*)
+-    # gcc
++  case $GCC,$host_os in
++  yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+     library_names_spec='$libname.dll.a'
+     # DLL is installed to $(libdir)/../bin by postinstall_cmds
+-    postinstall_cmds='base_file=`basename \$file`~
+-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
++    postinstall_cmds='base_file=`basename \${file}`~
++      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+       dldir=$destdir/`dirname \$dlpath`~
+       test -d \$dldir || mkdir -p \$dldir~
+       $install_prog $dir/$dlname \$dldir/$dlname~
+@@ -17560,83 +15038,25 @@ cygwin* | mingw* | pw32* | cegcc*)
+     case $host_os in
+     cygwin*)
+       # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+-      soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ 
+       ;;
+     mingw* | cegcc*)
+       # MinGW DLLs use traditional 'lib' prefix
+-      soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
++      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+       ;;
+     pw32*)
+       # pw32 DLLs use 'pw' prefix rather than 'lib'
+-      library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+-      ;;
+-    esac
+-    dynamic_linker='Win32 ld.exe'
+-    ;;
+-
+-  *,cl* | *,icl*)
+-    # Native MSVC or ICC
+-    libname_spec='$name'
+-    soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+-    library_names_spec='$libname.dll.lib'
+-
+-    case $build_os in
+-    mingw*)
+-      sys_lib_search_path_spec=
+-      lt_save_ifs=$IFS
+-      IFS=';'
+-      for lt_path in $LIB
+-      do
+-        IFS=$lt_save_ifs
+-        # Let DOS variable expansion print the short 8.3 style file name.
+-        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+-        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+-      done
+-      IFS=$lt_save_ifs
+-      # Convert to MSYS style.
+-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+-      ;;
+-    cygwin*)
+-      # Convert to unix form, then to dos form, then back to unix form
+-      # but this time dos style (no spaces!) so that the unix form looks
+-      # like /cygdrive/c/PROGRA~1:/cygdr...
+-      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+-      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+-      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+-      ;;
+-    *)
+-      sys_lib_search_path_spec=$LIB
+-      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+-        # It is most probably a Windows format PATH.
+-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+-      else
+-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+-      fi
+-      # FIXME: find the short name or the path components, as spaces are
+-      # common. (e.g. "Program Files" -> "PROGRA~1")
++      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+       ;;
+     esac
+-
+-    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+-    postinstall_cmds='base_file=`basename \$file`~
+-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+-      dldir=$destdir/`dirname \$dlpath`~
+-      test -d \$dldir || mkdir -p \$dldir~
+-      $install_prog $dir/$dlname \$dldir/$dlname'
+-    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+-      dlpath=$dir/\$dldll~
+-       $RM \$dlpath'
+-    shlibpath_overrides_runpath=yes
+-    dynamic_linker='Win32 link.exe'
+     ;;
+ 
+   *)
+-    # Assume MSVC and ICC wrapper
+-    library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+-    dynamic_linker='Win32 ld.exe'
++    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+     ;;
+   esac
++  dynamic_linker='Win32 ld.exe'
+   # FIXME: first we should search . and the directory the executable is in
+   shlibpath_var=PATH
+   ;;
+@@ -17646,8 +15066,8 @@ darwin* | rhapsody*)
+   version_type=darwin
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+-  soname_spec='$libname$release$major$shared_ext'
++  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
++  soname_spec='${libname}${release}${major}$shared_ext'
+   shlibpath_overrides_runpath=yes
+   shlibpath_var=DYLD_LIBRARY_PATH
+   shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+@@ -17656,15 +15076,15 @@ darwin* | rhapsody*)
+   ;;
+ 
+ dgux*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   ;;
+ 
+-freebsd* | dragonfly* | midnightbsd*)
++freebsd* | dragonfly*)
+   # DragonFly does not have aout.  When/if they implement a new
+   # versioning mechanism, adjust this.
+   if test -x /usr/bin/objformat; then
+@@ -17678,13 +15098,12 @@ freebsd* | dragonfly* | midnightbsd*)
+   version_type=freebsd-$objformat
+   case $version_type in
+     freebsd-elf*)
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-      soname_spec='$libname$release$shared_ext$major'
++      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+       need_version=no
+       need_lib_prefix=no
+       ;;
+     freebsd-*)
+-      library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+       need_version=yes
+       ;;
+   esac
+@@ -17710,15 +15129,15 @@ freebsd* | dragonfly* | midnightbsd*)
+   ;;
+ 
+ haiku*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+   dynamic_linker="$host_os runtime_loader"
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LIBRARY_PATH
+-  shlibpath_overrides_runpath=no
+-  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
++  shlibpath_overrides_runpath=yes
++  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+   hardcode_into_libs=yes
+   ;;
+ 
+@@ -17735,15 +15154,14 @@ hpux9* | hpux10* | hpux11*)
+     dynamic_linker="$host_os dld.so"
+     shlibpath_var=LD_LIBRARY_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
+-    if test 32 = "$HPUX_IA64_MODE"; then
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
++    if test "X$HPUX_IA64_MODE" = X32; then
+       sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+-      sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+     else
+       sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+-      sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+     fi
++    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   hppa*64*)
+     shrext_cmds='.sl'
+@@ -17751,8 +15169,8 @@ hpux9* | hpux10* | hpux11*)
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+@@ -17761,8 +15179,8 @@ hpux9* | hpux10* | hpux11*)
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=SHLIB_PATH
+     shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
+     ;;
+   esac
+   # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+@@ -17772,11 +15190,11 @@ hpux9* | hpux10* | hpux11*)
+   ;;
+ 
+ interix[3-9]*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+@@ -17787,16 +15205,16 @@ irix5* | irix6* | nonstopux*)
+   case $host_os in
+     nonstopux*) version_type=nonstopux ;;
+     *)
+-	if test yes = "$lt_cv_prog_gnu_ld"; then
+-		version_type=linux # correct to gnu/linux during the next big refactor
++	if test "$lt_cv_prog_gnu_ld" = yes; then
++		version_type=linux
+ 	else
+ 		version_type=irix
+ 	fi ;;
+   esac
+   need_lib_prefix=no
+   need_version=no
+-  soname_spec='$libname$release$shared_ext$major'
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
++  soname_spec='${libname}${release}${shared_ext}$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+   case $host_os in
+   irix5* | nonstopux*)
+     libsuff= shlibsuff=
+@@ -17811,56 +15229,40 @@ irix5* | irix6* | nonstopux*)
+       libsuff=64 shlibsuff=64 libmagic=64-bit;;
+     *) libsuff= shlibsuff= libmagic=never-match;;
+     esac
+-    ;;
+-  esac
+-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+-  shlibpath_overrides_runpath=no
+-  sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+-  sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+-  hardcode_into_libs=yes
+-  ;;
+-
+-# No shared lib support for Linux oldld, aout, or coff.
+-linux*oldld* | linux*aout* | linux*coff*)
+-  dynamic_linker=no
+-  ;;
+-
+-linux*android*)
+-  version_type=none # Android doesn't support versioned libraries.
+-  need_lib_prefix=no
+-  need_version=no
+-  library_names_spec='$libname$release$shared_ext'
+-  soname_spec='$libname$release$shared_ext'
+-  finish_cmds=
+-  shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
+-
+-  # This implies no fast_install, which is unacceptable.
+-  # Some rework will be needed to allow for fast_install
+-  # before this can be enabled.
++    ;;
++  esac
++  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
++  shlibpath_overrides_runpath=no
++  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
++  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+   hardcode_into_libs=yes
++  ;;
+ 
+-  dynamic_linker='Android linker'
+-  # Don't embed -rpath directories since the linker doesn't support them.
+-  hardcode_libdir_flag_spec_CXX='-L$libdir'
++# No shared lib support for Linux oldld, aout, or coff.
++linux*oldld* | linux*aout* | linux*coff*)
++  dynamic_linker=no
+   ;;
+ 
+-# This must be glibc/ELF.
+-linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++# This must be Linux ELF.
++
++# uclinux* changes (here and below) have been submitted to the libtool
++# project, but have not yet been accepted: they are GCC-local changes
++# for the time being.  (See
++# https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html)
++linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi)
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+ 
+   # Some binutils ld are patched to set DT_RUNPATH
+-  if test ${lt_cv_shlibpath_overrides_runpath+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   lt_cv_shlibpath_overrides_runpath=no
+     save_LDFLAGS=$LDFLAGS
+     save_libdir=$libdir
+@@ -17870,21 +15272,19 @@ else $as_nop
+ /* end confdefs.h.  */
+ 
+ int
+-main (void)
++main ()
+ {
+ 
+   ;
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_cxx_try_link "$LINENO"
+-then :
+-  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
+-then :
++if ac_fn_cxx_try_link "$LINENO"; then :
++  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+   lt_cv_shlibpath_overrides_runpath=yes
+ fi
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam \
++rm -f core conftest.err conftest.$ac_objext \
+     conftest$ac_exeext conftest.$ac_ext
+     LDFLAGS=$save_LDFLAGS
+     libdir=$save_libdir
+@@ -17898,18 +15298,10 @@ fi
+   # before this can be enabled.
+   hardcode_into_libs=yes
+ 
+-  # Add ABI-specific directories to the system library path.
+-  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+-
+-  # Ideally, we could use ldconfig to report *all* directores which are
+-  # searched for libraries, however this is still not possible.  Aside from not
+-  # being certain /sbin/ldconfig is available, command
+-  # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+-  # even though it is searched at run-time.  Try to do the best guess by
+-  # appending ld.so.conf contents (and includes) to the search path.
++  # Append ld.so.conf contents to the search path
+   if test -f /etc/ld.so.conf; then
+     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[	 ]*hwcap[	 ]/d;s/[:,	]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+-    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
++    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+   fi
+ 
+   # We used to test for /lib/ld.so.1 and disable shared libraries on
+@@ -17926,12 +15318,12 @@ netbsd*)
+   need_lib_prefix=no
+   need_version=no
+   if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+     finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+     dynamic_linker='NetBSD (a.out) ld.so'
+   else
+-    library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-    soname_spec='$libname$release$shared_ext$major'
++    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
++    soname_spec='${libname}${release}${shared_ext}$major'
+     dynamic_linker='NetBSD ld.elf_so'
+   fi
+   shlibpath_var=LD_LIBRARY_PATH
+@@ -17940,8 +15332,8 @@ netbsd*)
+   ;;
+ 
+ newsos6)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+   ;;
+@@ -17950,68 +15342,58 @@ newsos6)
+   version_type=qnx
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+   hardcode_into_libs=yes
+   dynamic_linker='ldqnx.so'
+   ;;
+ 
+-openbsd* | bitrig*)
++openbsd*)
+   version_type=sunos
+-  sys_lib_dlsearch_path_spec=/usr/lib
++  sys_lib_dlsearch_path_spec="/usr/lib"
+   need_lib_prefix=no
+-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+-    need_version=no
+-  else
+-    need_version=yes
+-  fi
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
++  case $host_os in
++    openbsd3.3 | openbsd3.3.*)	need_version=yes ;;
++    *)				need_version=no  ;;
++  esac
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+   finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+-  shlibpath_overrides_runpath=yes
++  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
++    case $host_os in
++      openbsd2.[89] | openbsd2.[89].*)
++	shlibpath_overrides_runpath=no
++	;;
++      *)
++	shlibpath_overrides_runpath=yes
++	;;
++      esac
++  else
++    shlibpath_overrides_runpath=yes
++  fi
+   ;;
+ 
+ os2*)
+   libname_spec='$name'
+-  version_type=windows
+-  shrext_cmds=.dll
+-  need_version=no
++  shrext_cmds=".dll"
+   need_lib_prefix=no
+-  # OS/2 can only load a DLL with a base name of 8 characters or less.
+-  soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+-    v=$($ECHO $release$versuffix | tr -d .-);
+-    n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+-    $ECHO $n$v`$shared_ext'
+-  library_names_spec='${libname}_dll.$libext'
++  library_names_spec='$libname${shared_ext} $libname.a'
+   dynamic_linker='OS/2 ld.exe'
+-  shlibpath_var=BEGINLIBPATH
+-  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+-  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+-  postinstall_cmds='base_file=`basename \$file`~
+-    dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+-    dldir=$destdir/`dirname \$dlpath`~
+-    test -d \$dldir || mkdir -p \$dldir~
+-    $install_prog $dir/$dlname \$dldir/$dlname~
+-    chmod a+x \$dldir/$dlname~
+-    if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+-      eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+-    fi'
+-  postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+-    dlpath=$dir/\$dldll~
+-    $RM \$dlpath'
++  shlibpath_var=LIBPATH
+   ;;
+ 
+ osf3* | osf4* | osf5*)
+   version_type=osf
+   need_lib_prefix=no
+   need_version=no
+-  soname_spec='$libname$release$shared_ext$major'
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  soname_spec='${libname}${release}${shared_ext}$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   shlibpath_var=LD_LIBRARY_PATH
+   sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+-  sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
++  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+   ;;
+ 
+ rdos*)
+@@ -18019,11 +15401,11 @@ rdos*)
+   ;;
+ 
+ solaris*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+   hardcode_into_libs=yes
+@@ -18033,20 +15415,20 @@ solaris*)
+ 
+ sunos4*)
+   version_type=sunos
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+   finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+-  if test yes = "$with_gnu_ld"; then
++  if test "$with_gnu_ld" = yes; then
+     need_lib_prefix=no
+   fi
+   need_version=yes
+   ;;
+ 
+ sysv4 | sysv4.3*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   case $host_vendor in
+     sni)
+@@ -18067,24 +15449,24 @@ sysv4 | sysv4.3*)
+   ;;
+ 
+ sysv4*MP*)
+-  if test -d /usr/nec; then
+-    version_type=linux # correct to gnu/linux during the next big refactor
+-    library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+-    soname_spec='$libname$shared_ext.$major'
++  if test -d /usr/nec ;then
++    version_type=linux
++    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
++    soname_spec='$libname${shared_ext}.$major'
+     shlibpath_var=LD_LIBRARY_PATH
+   fi
+   ;;
+ 
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+-  version_type=sco
++  version_type=freebsd-elf
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=yes
+   hardcode_into_libs=yes
+-  if test yes = "$with_gnu_ld"; then
++  if test "$with_gnu_ld" = yes; then
+     sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+   else
+     sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+@@ -18099,19 +15481,19 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ 
+ tpf*)
+   # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+-  version_type=linux # correct to gnu/linux during the next big refactor
++  version_type=linux
+   need_lib_prefix=no
+   need_version=no
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+   shlibpath_var=LD_LIBRARY_PATH
+   shlibpath_overrides_runpath=no
+   hardcode_into_libs=yes
+   ;;
+ 
+ uts4*)
+-  version_type=linux # correct to gnu/linux during the next big refactor
+-  library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+-  soname_spec='$libname$release$shared_ext$major'
++  version_type=linux
++  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
++  soname_spec='${libname}${release}${shared_ext}$major'
+   shlibpath_var=LD_LIBRARY_PATH
+   ;;
+ 
+@@ -18119,32 +15501,22 @@ uts4*)
+   dynamic_linker=no
+   ;;
+ esac
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+-printf "%s\n" "$dynamic_linker" >&6; }
+-test no = "$dynamic_linker" && can_build_shared=no
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
++$as_echo "$dynamic_linker" >&6; }
++test "$dynamic_linker" = no && can_build_shared=no
+ 
+ variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+-if test yes = "$GCC"; then
++if test "$GCC" = yes; then
+   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+ fi
+ 
+-if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+-  sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
++if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
++  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+ fi
+-
+-if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+-  sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
++if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
++  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+ fi
+ 
+-# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+-configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+-
+-# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+-func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+-
+-# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+-configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+-
+ 
+ 
+ 
+@@ -18182,22 +15554,20 @@ configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+ 
+ 
+ 
+-
+-
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+-printf %s "checking how to hardcode library paths into programs... " >&6; }
++    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
++$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+ hardcode_action_CXX=
+ if test -n "$hardcode_libdir_flag_spec_CXX" ||
+    test -n "$runpath_var_CXX" ||
+-   test yes = "$hardcode_automatic_CXX"; then
++   test "X$hardcode_automatic_CXX" = "Xyes" ; then
+ 
+   # We can hardcode non-existent directories.
+-  if test no != "$hardcode_direct_CXX" &&
++  if test "$hardcode_direct_CXX" != no &&
+      # If the only mechanism to avoid hardcoding is shlibpath_var, we
+      # have to relink, otherwise we might link with an installed library
+      # when we should be linking with a yet-to-be-installed one
+-     ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" &&
+-     test no != "$hardcode_minus_L_CXX"; then
++     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
++     test "$hardcode_minus_L_CXX" != no; then
+     # Linking always hardcodes the temporary library directory.
+     hardcode_action_CXX=relink
+   else
+@@ -18209,15 +15579,15 @@ else
+   # directories.
+   hardcode_action_CXX=unsupported
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
+-printf "%s\n" "$hardcode_action_CXX" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
++$as_echo "$hardcode_action_CXX" >&6; }
+ 
+-if test relink = "$hardcode_action_CXX" ||
+-   test yes = "$inherit_rpath_CXX"; then
++if test "$hardcode_action_CXX" = relink ||
++   test "$inherit_rpath_CXX" = yes; then
+   # Fast installation is not supported
+   enable_fast_install=no
+-elif test yes = "$shlibpath_overrides_runpath" ||
+-     test no = "$enable_shared"; then
++elif test "$shlibpath_overrides_runpath" = yes ||
++     test "$enable_shared" = no; then
+   # Fast installation is not necessary
+   enable_fast_install=needless
+ fi
+@@ -18231,7 +15601,6 @@ fi
+   fi # test -n "$compiler"
+ 
+   CC=$lt_save_CC
+-  CFLAGS=$lt_save_CFLAGS
+   LDCXX=$LD
+   LD=$lt_save_LD
+   GCC=$lt_save_GCC
+@@ -18240,7 +15609,7 @@ fi
+   lt_cv_path_LD=$lt_save_path_LD
+   lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+   lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+-fi # test yes != "$_lt_caught_CXX_error"
++fi # test "$_lt_caught_CXX_error" != yes
+ 
+ ac_ext=c
+ ac_cpp='$CPP $CPPFLAGS'
+@@ -18260,8 +15629,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ 
+ 
+ 
+-
+-
+         ac_config_commands="$ac_config_commands libtool"
+ 
+ 
+@@ -18270,14 +15637,38 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ # Only expand once:
+ 
+ 
+-ACX_LT_HOST_FLAGS
++
++
++
++
++case $host in
++  *-cygwin* | *-mingw*)
++    # 'host' will be top-level target in the case of a target lib,
++    # we must compare to with_cross_host to decide if this is a native
++    # or cross-compiler and select where to install dlls appropriately.
++    if test -n "$with_cross_host" &&
++	test x"$with_cross_host" != x"no"; then
++      lt_host_flags='-no-undefined -bindir "$(toolexeclibdir)"';
++    else
++      lt_host_flags='-no-undefined -bindir "$(bindir)"';
++    fi
++    ;;
++  *)
++    lt_host_flags=
++    ;;
++esac
++
++
++
+ 
+ ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
+ case $ac_cv_c_int64_t in #(
+   no|yes) ;; #(
+   *)
+ 
+-printf "%s\n" "#define int64_t $ac_cv_c_int64_t" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define int64_t $ac_cv_c_int64_t
++_ACEOF
+ ;;
+ esac
+ 
+@@ -18286,19 +15677,20 @@ case $ac_cv_c_uint64_t in #(
+   no|yes) ;; #(
+   *)
+ 
+-printf "%s\n" "#define _UINT64_T 1" >>confdefs.h
++$as_echo "#define _UINT64_T 1" >>confdefs.h
+ 
+ 
+-printf "%s\n" "#define uint64_t $ac_cv_c_uint64_t" >>confdefs.h
++cat >>confdefs.h <<_ACEOF
++#define uint64_t $ac_cv_c_uint64_t
++_ACEOF
+ ;;
+   esac
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+-printf %s "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+-if test ${ac_cv_header_sys_wait_h+y}
+-then :
+-  printf %s "(cached) " >&6
+-else $as_nop
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
++$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
++if ${ac_cv_header_sys_wait_h+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #include 
+@@ -18311,7 +15703,7 @@ else $as_nop
+ #endif
+ 
+ int
+-main (void)
++main ()
+ {
+   int s;
+   wait (&s);
+@@ -18320,19 +15712,18 @@ main (void)
+   return 0;
+ }
+ _ACEOF
+-if ac_fn_c_try_compile "$LINENO"
+-then :
++if ac_fn_c_try_compile "$LINENO"; then :
+   ac_cv_header_sys_wait_h=yes
+-else $as_nop
++else
+   ac_cv_header_sys_wait_h=no
+ fi
+-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+-printf "%s\n" "$ac_cv_header_sys_wait_h" >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
++$as_echo "$ac_cv_header_sys_wait_h" >&6; }
+ if test $ac_cv_header_sys_wait_h = yes; then
+ 
+-printf "%s\n" "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
++$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+ 
+ fi
+ 
+@@ -18367,8 +15758,8 @@ _ACEOF
+     case $ac_val in #(
+     *${as_nl}*)
+       case $ac_var in #(
+-      *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+-printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
++      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
++$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+       esac
+       case $ac_var in #(
+       _ | IFS | as_nl) ;; #(
+@@ -18398,15 +15789,15 @@ printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;}
+      /^ac_cv_env_/b end
+      t clear
+      :clear
+-     s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
++     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+      t end
+      s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+      :end' >>confcache
+ if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+   if test -w "$cache_file"; then
+     if test "x$cache_file" != "x/dev/null"; then
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+-printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
++      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
++$as_echo "$as_me: updating cache $cache_file" >&6;}
+       if test ! -f "$cache_file" || test -h "$cache_file"; then
+ 	cat confcache >"$cache_file"
+       else
+@@ -18420,8 +15811,8 @@ printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
+       fi
+     fi
+   else
+-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+-printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
++    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
++$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+   fi
+ fi
+ rm -f confcache
+@@ -18438,7 +15829,7 @@ U=
+ for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+   # 1. Remove the extension, and $U if already installed.
+   ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+-  ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
++  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+   # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+   #    will be set to the directory where LIBOBJS objects are built.
+   as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+@@ -18449,14 +15840,14 @@ LIBOBJS=$ac_libobjs
+ LTLIBOBJS=$ac_ltlibobjs
+ 
+ 
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+-printf %s "checking that generated files are newer than configure... " >&6; }
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
++$as_echo_n "checking that generated files are newer than configure... " >&6; }
+    if test -n "$am_sleep_pid"; then
+      # Hide warnings about reused PIDs.
+      wait $am_sleep_pid 2>/dev/null
+    fi
+-   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5
+-printf "%s\n" "done" >&6; }
++   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
++$as_echo "done" >&6; }
+  if test -n "$EXEEXT"; then
+   am__EXEEXT_TRUE=
+   am__EXEEXT_FALSE='#'
+@@ -18490,8 +15881,8 @@ fi
+ ac_write_fail=0
+ ac_clean_files_save=$ac_clean_files
+ ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+-printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
++{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
++$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+ as_write_fail=0
+ cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+ #! $SHELL
+@@ -18514,16 +15905,14 @@ cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+ 
+ # Be more Bourne compatible
+ DUALCASE=1; export DUALCASE # for MKS sh
+-as_nop=:
+-if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+-then :
++if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+   emulate sh
+   NULLCMD=:
+   # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+   # is contrary to our usage.  Disable this feature.
+   alias -g '${1+"$@"}'='"$@"'
+   setopt NO_GLOB_SUBST
+-else $as_nop
++else
+   case `(set -o) 2>/dev/null` in #(
+   *posix*) :
+     set -o posix ;; #(
+@@ -18533,46 +15922,46 @@ esac
+ fi
+ 
+ 
+-
+-# Reset variables that may have inherited troublesome values from
+-# the environment.
+-
+-# IFS needs to be set, to space, tab, and newline, in precisely that order.
+-# (If _AS_PATH_WALK were called with IFS unset, it would have the
+-# side effect of setting IFS to empty, thus disabling word splitting.)
+-# Quoting is to prevent editors from complaining about space-tab.
+ as_nl='
+ '
+ export as_nl
+-IFS=" ""	$as_nl"
+-
+-PS1='$ '
+-PS2='> '
+-PS4='+ '
+-
+-# Ensure predictable behavior from utilities with locale-dependent output.
+-LC_ALL=C
+-export LC_ALL
+-LANGUAGE=C
+-export LANGUAGE
+-
+-# We cannot yet rely on "unset" to work, but we need these variables
+-# to be unset--not just set to an empty or harmless value--now, to
+-# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct
+-# also avoids known problems related to "unset" and subshell syntax
+-# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+-for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+-do eval test \${$as_var+y} \
+-  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+-done
+-
+-# Ensure that fds 0, 1, and 2 are open.
+-if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+-if (exec 3>&2)            ; then :; else exec 2>/dev/null; fi
++# Printing a long string crashes Solaris 7 /usr/bin/printf.
++as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
++as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
++# Prefer a ksh shell builtin over an external printf program on Solaris,
++# but without wasting forks for bash or zsh.
++if test -z "$BASH_VERSION$ZSH_VERSION" \
++    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
++  as_echo='print -r --'
++  as_echo_n='print -rn --'
++elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
++  as_echo='printf %s\n'
++  as_echo_n='printf %s'
++else
++  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
++    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
++    as_echo_n='/usr/ucb/echo -n'
++  else
++    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
++    as_echo_n_body='eval
++      arg=$1;
++      case $arg in #(
++      *"$as_nl"*)
++	expr "X$arg" : "X\\(.*\\)$as_nl";
++	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
++      esac;
++      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
++    '
++    export as_echo_n_body
++    as_echo_n='sh -c $as_echo_n_body as_echo'
++  fi
++  export as_echo_body
++  as_echo='sh -c $as_echo_body as_echo'
++fi
+ 
+ # The user is always right.
+-if ${PATH_SEPARATOR+false} :; then
++if test "${PATH_SEPARATOR+set}" != set; then
+   PATH_SEPARATOR=:
+   (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+     (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+@@ -18581,6 +15970,13 @@ if ${PATH_SEPARATOR+false} :; then
+ fi
+ 
+ 
++# IFS
++# We need space, tab and new line, in precisely that order.  Quoting is
++# there to prevent editors from complaining about space-tab.
++# (If _AS_PATH_WALK were called with IFS unset, it would disable word
++# splitting by setting IFS to empty value.)
++IFS=" ""	$as_nl"
++
+ # Find who we are.  Look in the path if we contain no directory separator.
+ as_myself=
+ case $0 in #((
+@@ -18589,12 +15985,8 @@ case $0 in #((
+ for as_dir in $PATH
+ do
+   IFS=$as_save_IFS
+-  case $as_dir in #(((
+-    '') as_dir=./ ;;
+-    */) ;;
+-    *) as_dir=$as_dir/ ;;
+-  esac
+-    test -r "$as_dir$0" && as_myself=$as_dir$0 && break
++  test -z "$as_dir" && as_dir=.
++    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+   done
+ IFS=$as_save_IFS
+ 
+@@ -18606,10 +15998,30 @@ if test "x$as_myself" = x; then
+   as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+-  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
++  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+   exit 1
+ fi
+ 
++# Unset variables that we do not need and which cause bugs (e.g. in
++# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
++# suppresses any "Segmentation fault" message there.  '((' could
++# trigger a bug in pdksh 5.2.14.
++for as_var in BASH_ENV ENV MAIL MAILPATH
++do eval test x\${$as_var+set} = xset \
++  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
++done
++PS1='$ '
++PS2='> '
++PS4='+ '
++
++# NLS nuisances.
++LC_ALL=C
++export LC_ALL
++LANGUAGE=C
++export LANGUAGE
++
++# CDPATH.
++(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+ 
+ 
+ # as_fn_error STATUS ERROR [LINENO LOG_FD]
+@@ -18622,14 +16034,13 @@ as_fn_error ()
+   as_status=$1; test $as_status -eq 0 && as_status=1
+   if test "$4"; then
+     as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+-    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
++    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+   fi
+-  printf "%s\n" "$as_me: error: $2" >&2
++  $as_echo "$as_me: error: $2" >&2
+   as_fn_exit $as_status
+ } # as_fn_error
+ 
+ 
+-
+ # as_fn_set_status STATUS
+ # -----------------------
+ # Set $? to STATUS, without forking.
+@@ -18656,20 +16067,18 @@ as_fn_unset ()
+   { eval $1=; unset $1;}
+ }
+ as_unset=as_fn_unset
+-
+ # as_fn_append VAR VALUE
+ # ----------------------
+ # Append the text in VALUE to the end of the definition contained in VAR. Take
+ # advantage of any shell optimizations that allow amortized linear growth over
+ # repeated appends, instead of the typical quadratic growth present in naive
+ # implementations.
+-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+-then :
++if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+   eval 'as_fn_append ()
+   {
+     eval $1+=\$2
+   }'
+-else $as_nop
++else
+   as_fn_append ()
+   {
+     eval $1=\$$1\$2
+@@ -18681,13 +16090,12 @@ fi # as_fn_append
+ # Perform arithmetic evaluation on the ARGs, and store the result in the
+ # global $as_val. Take advantage of shells that can avoid forks. The arguments
+ # must be portable across $(()) and expr.
+-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+-then :
++if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+   eval 'as_fn_arith ()
+   {
+     as_val=$(( $* ))
+   }'
+-else $as_nop
++else
+   as_fn_arith ()
+   {
+     as_val=`expr "$@" || test $? -eq 1`
+@@ -18718,7 +16126,7 @@ as_me=`$as_basename -- "$0" ||
+ $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ 	 X"$0" : 'X\(//\)$' \| \
+ 	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X/"$0" |
++$as_echo X/"$0" |
+     sed '/^.*\/\([^/][^/]*\)\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -18740,10 +16148,6 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+ as_cr_digits='0123456789'
+ as_cr_alnum=$as_cr_Letters$as_cr_digits
+ 
+-
+-# Determine whether it's possible to make 'echo' print without a newline.
+-# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+-# for compatibility with existing Makefiles.
+ ECHO_C= ECHO_N= ECHO_T=
+ case `echo -n x` in #(((((
+ -n*)
+@@ -18757,12 +16161,6 @@ case `echo -n x` in #(((((
+   ECHO_N='-n';;
+ esac
+ 
+-# For backward compatibility with old third-party macros, we provide
+-# the shell variables $as_echo and $as_echo_n.  New code should use
+-# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+-as_echo='printf %s\n'
+-as_echo_n='printf %s'
+-
+ rm -f conf$$ conf$$.exe conf$$.file
+ if test -d conf$$.dir; then
+   rm -f conf$$.dir/conf$$.file
+@@ -18804,7 +16202,7 @@ as_fn_mkdir_p ()
+     as_dirs=
+     while :; do
+       case $as_dir in #(
+-      *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
++      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+       *) as_qdir=$as_dir;;
+       esac
+       as_dirs="'$as_qdir' $as_dirs"
+@@ -18813,7 +16211,7 @@ $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ 	 X"$as_dir" : 'X\(//\)[^/]' \| \
+ 	 X"$as_dir" : 'X\(//\)$' \| \
+ 	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X"$as_dir" |
++$as_echo X"$as_dir" |
+     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -18876,7 +16274,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ # values after options handling.
+ ac_log="
+ This file was extended by bolt plugin for ld $as_me 0.1, which was
+-generated by GNU Autoconf 2.71.  Invocation command line was
++generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+   CONFIG_HEADERS  = $CONFIG_HEADERS
+@@ -18938,16 +16336,14 @@ $config_commands
+ Report bugs to the package provider."
+ 
+ _ACEOF
+-ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+-ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+-ac_cs_config='$ac_cs_config_escaped'
++ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+ bolt plugin for ld config.status 0.1
+-configured by $0, generated by GNU Autoconf 2.71,
++configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+-Copyright (C) 2021 Free Software Foundation, Inc.
++Copyright (C) 2012 Free Software Foundation, Inc.
+ This config.status script is free software; the Free Software Foundation
+ gives unlimited permission to copy, distribute and modify it."
+ 
+@@ -18987,15 +16383,15 @@ do
+   -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+     ac_cs_recheck=: ;;
+   --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+-    printf "%s\n" "$ac_cs_version"; exit ;;
++    $as_echo "$ac_cs_version"; exit ;;
+   --config | --confi | --conf | --con | --co | --c )
+-    printf "%s\n" "$ac_cs_config"; exit ;;
++    $as_echo "$ac_cs_config"; exit ;;
+   --debug | --debu | --deb | --de | --d | -d )
+     debug=: ;;
+   --file | --fil | --fi | --f )
+     $ac_shift
+     case $ac_optarg in
+-    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
++    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+     '') as_fn_error $? "missing file argument" ;;
+     esac
+     as_fn_append CONFIG_FILES " '$ac_optarg'"
+@@ -19003,7 +16399,7 @@ do
+   --header | --heade | --head | --hea )
+     $ac_shift
+     case $ac_optarg in
+-    *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
++    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+     esac
+     as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+     ac_need_defaults=false;;
+@@ -19012,7 +16408,7 @@ do
+     as_fn_error $? "ambiguous option: \`$1'
+ Try \`$0 --help' for more information.";;
+   --help | --hel | -h )
+-    printf "%s\n" "$ac_cs_usage"; exit ;;
++    $as_echo "$ac_cs_usage"; exit ;;
+   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+   | -silent | --silent | --silen | --sile | --sil | --si | --s)
+     ac_cs_silent=: ;;
+@@ -19040,7 +16436,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ if \$ac_cs_recheck; then
+   set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+   shift
+-  \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
++  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+   CONFIG_SHELL='$SHELL'
+   export CONFIG_SHELL
+   exec "\$@"
+@@ -19054,7 +16450,7 @@ exec 5>>config.log
+   sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+ ## Running $as_me. ##
+ _ASBOX
+-  printf "%s\n" "$ac_log"
++  $as_echo "$ac_log"
+ } >&5
+ 
+ _ACEOF
+@@ -19078,10 +16474,8 @@ enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+ enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+ pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+ enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+-shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+ SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+-PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+ host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+ host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+ host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+@@ -19102,22 +16496,13 @@ exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+ lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+ lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+ lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+-lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+-lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+ reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+ reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+-FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
+ OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+ deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+ file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+-file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+-want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+-DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+-sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+ AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+-lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
+ AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+-archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+ STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+ RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+ old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+@@ -19130,22 +16515,16 @@ compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+ GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+ lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+ lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+-lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+ lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+-lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+-nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+-lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+-lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+ objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+ MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+ lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+-lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+ lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+ lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+ lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+ need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+-MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+ DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+ NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+ LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+@@ -19169,6 +16548,7 @@ with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+ allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+ no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+ hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
++hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`'
+ hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+ hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+ hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+@@ -19177,12 +16557,12 @@ hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_q
+ hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+ inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+ link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
++fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`'
+ always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+ export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+ exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+ include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+ prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+-postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+ file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+ variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+ need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+@@ -19201,8 +16581,7 @@ finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+ finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+ hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+ sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+-configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+-configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
++sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+ hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+ enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+ enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+@@ -19222,8 +16601,8 @@ old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote
+ compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`'
+ GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`'
+ lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`'
+-lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
+ lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`'
++lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`'
+ lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`'
+ lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`'
+ archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`'
+@@ -19241,6 +16620,7 @@ with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`'
+ allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+ no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`'
+ hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`'
++hardcode_libdir_flag_spec_ld_CXX='`$ECHO "$hardcode_libdir_flag_spec_ld_CXX" | $SED "$delay_single_quote_subst"`'
+ hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`'
+ hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`'
+ hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`'
+@@ -19249,12 +16629,12 @@ hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_
+ hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`'
+ inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`'
+ link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`'
++fix_srcfile_path_CXX='`$ECHO "$fix_srcfile_path_CXX" | $SED "$delay_single_quote_subst"`'
+ always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`'
+ export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+ exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+ include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`'
+ prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+-postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`'
+ file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`'
+ hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`'
+ compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`'
+@@ -19279,7 +16659,6 @@ _LTECHO_EOF'
+ # Quote evaled strings.
+ for var in SHELL \
+ ECHO \
+-PATH_SEPARATOR \
+ SED \
+ GREP \
+ EGREP \
+@@ -19290,16 +16669,11 @@ LN_S \
+ lt_SP2NL \
+ lt_NL2SP \
+ reload_flag \
+-FILECMD \
+ OBJDUMP \
+ deplibs_check_method \
+ file_magic_cmd \
+-file_magic_glob \
+-want_nocaseglob \
+-DLLTOOL \
+-sharedlib_from_linklib_cmd \
+ AR \
+-archiver_list_spec \
++AR_FLAGS \
+ STRIP \
+ RANLIB \
+ CC \
+@@ -19307,19 +16681,14 @@ CFLAGS \
+ compiler \
+ lt_cv_sys_global_symbol_pipe \
+ lt_cv_sys_global_symbol_to_cdecl \
+-lt_cv_sys_global_symbol_to_import \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+-lt_cv_nm_interface \
+-nm_file_list_spec \
+-lt_cv_truncate_bin \
+ lt_prog_compiler_no_builtin_flag \
+-lt_prog_compiler_pic \
+ lt_prog_compiler_wl \
++lt_prog_compiler_pic \
+ lt_prog_compiler_static \
+ lt_cv_prog_compiler_c_o \
+ need_locks \
+-MANIFEST_TOOL \
+ DSYMUTIL \
+ NMEDIT \
+ LIPO \
+@@ -19333,7 +16702,9 @@ with_gnu_ld \
+ allow_undefined_flag \
+ no_undefined_flag \
+ hardcode_libdir_flag_spec \
++hardcode_libdir_flag_spec_ld \
+ hardcode_libdir_separator \
++fix_srcfile_path \
+ exclude_expsyms \
+ include_expsyms \
+ file_list_spec \
+@@ -19355,8 +16726,8 @@ LD_CXX \
+ reload_flag_CXX \
+ compiler_CXX \
+ lt_prog_compiler_no_builtin_flag_CXX \
+-lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_wl_CXX \
++lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_static_CXX \
+ lt_cv_prog_compiler_c_o_CXX \
+ export_dynamic_flag_spec_CXX \
+@@ -19366,7 +16737,9 @@ with_gnu_ld_CXX \
+ allow_undefined_flag_CXX \
+ no_undefined_flag_CXX \
+ hardcode_libdir_flag_spec_CXX \
++hardcode_libdir_flag_spec_ld_CXX \
+ hardcode_libdir_separator_CXX \
++fix_srcfile_path_CXX \
+ exclude_expsyms_CXX \
+ include_expsyms_CXX \
+ file_list_spec_CXX \
+@@ -19378,7 +16751,7 @@ postdeps_CXX \
+ compiler_lib_search_path_CXX; do
+     case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+     *[\\\\\\\`\\"\\\$]*)
+-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+       ;;
+     *)
+       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+@@ -19400,13 +16773,11 @@ module_cmds \
+ module_expsym_cmds \
+ export_symbols_cmds \
+ prelink_cmds \
+-postlink_cmds \
+ postinstall_cmds \
+ postuninstall_cmds \
+ finish_cmds \
+ sys_lib_search_path_spec \
+-configure_time_dlsearch_path \
+-configure_time_lt_sys_library_path \
++sys_lib_dlsearch_path_spec \
+ reload_cmds_CXX \
+ old_archive_cmds_CXX \
+ old_archive_from_new_cmds_CXX \
+@@ -19416,11 +16787,10 @@ archive_expsym_cmds_CXX \
+ module_cmds_CXX \
+ module_expsym_cmds_CXX \
+ export_symbols_cmds_CXX \
+-prelink_cmds_CXX \
+-postlink_cmds_CXX; do
++prelink_cmds_CXX; do
+     case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+     *[\\\\\\\`\\"\\\$]*)
+-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
++      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+       ;;
+     *)
+       eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+@@ -19429,16 +16799,19 @@ postlink_cmds_CXX; do
+ done
+ 
+ ac_aux_dir='$ac_aux_dir'
++xsi_shell='$xsi_shell'
++lt_shell_append='$lt_shell_append'
+ 
+-# See if we are running on zsh, and set the options that allow our
++# See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes INIT.
+-if test -n "\${ZSH_VERSION+set}"; then
++if test -n "\${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+ fi
+ 
+ 
+     PACKAGE='$PACKAGE'
+     VERSION='$VERSION'
++    TIMESTAMP='$TIMESTAMP'
+     RM='$RM'
+     ofile='$ofile'
+ 
+@@ -19470,9 +16843,9 @@ done
+ # We use the long form for the default assignment because of an extremely
+ # bizarre bug on SunOS 4.1.3.
+ if $ac_need_defaults; then
+-  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+-  test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
+-  test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
++  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
++  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
++  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+ fi
+ 
+ # Have a temporary directory for convenience.  Make it in the build tree
+@@ -19808,7 +17181,7 @@ do
+ 	   esac ||
+ 	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+       esac
+-      case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
++      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+       as_fn_append ac_file_inputs " '$ac_f'"
+     done
+ 
+@@ -19816,17 +17189,17 @@ do
+     # use $as_me), people would be surprised to read:
+     #    /* config.h.  Generated by config.status.  */
+     configure_input='Generated from '`
+-	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
++	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ 	`' by configure.'
+     if test x"$ac_file" != x-; then
+       configure_input="$ac_file.  $configure_input"
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+-printf "%s\n" "$as_me: creating $ac_file" >&6;}
++      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
++$as_echo "$as_me: creating $ac_file" >&6;}
+     fi
+     # Neutralize special characters interpreted by sed in replacement strings.
+     case $configure_input in #(
+     *\&* | *\|* | *\\* )
+-       ac_sed_conf_input=`printf "%s\n" "$configure_input" |
++       ac_sed_conf_input=`$as_echo "$configure_input" |
+        sed 's/[\\\\&|]/\\\\&/g'`;; #(
+     *) ac_sed_conf_input=$configure_input;;
+     esac
+@@ -19843,7 +17216,7 @@ $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ 	 X"$ac_file" : 'X\(//\)[^/]' \| \
+ 	 X"$ac_file" : 'X\(//\)$' \| \
+ 	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X"$ac_file" |
++$as_echo X"$ac_file" |
+     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -19867,9 +17240,9 @@ printf "%s\n" X"$ac_file" |
+ case "$ac_dir" in
+ .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *)
+-  ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
++  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+   # A ".." for each directory in $ac_dir_suffix.
+-  ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
++  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+   case $ac_top_builddir_sub in
+   "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+   *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+@@ -19931,8 +17304,8 @@ ac_sed_dataroot='
+ case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+ *datarootdir*) ac_datarootdir_seen=yes;;
+ *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+-printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
++$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+   ac_datarootdir_hack='
+@@ -19976,9 +17349,9 @@ test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+   { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+   { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+       "$ac_tmp/out"`; test -z "$ac_out"; } &&
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
++  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ which seems to be undefined.  Please make sure it is defined" >&5
+-printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
++$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ which seems to be undefined.  Please make sure it is defined" >&2;}
+ 
+   rm -f "$ac_tmp/stdin"
+@@ -19994,20 +17367,20 @@ which seems to be undefined.  Please make sure it is defined" >&2;}
+   #
+   if test x"$ac_file" != x-; then
+     {
+-      printf "%s\n" "/* $configure_input  */" >&1 \
++      $as_echo "/* $configure_input  */" \
+       && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+     } >"$ac_tmp/config.h" \
+       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+     if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+-      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+-printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
++      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
++$as_echo "$as_me: $ac_file is unchanged" >&6;}
+     else
+       rm -f "$ac_file"
+       mv "$ac_tmp/config.h" "$ac_file" \
+ 	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+     fi
+   else
+-    printf "%s\n" "/* $configure_input  */" >&1 \
++    $as_echo "/* $configure_input  */" \
+       && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+       || as_fn_error $? "could not create -" "$LINENO" 5
+   fi
+@@ -20027,7 +17400,7 @@ $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ 	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+ 	 X"$_am_arg" : 'X\(//\)$' \| \
+ 	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X"$_am_arg" |
++$as_echo X"$_am_arg" |
+     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -20047,8 +17420,8 @@ printf "%s\n" X"$_am_arg" |
+ 	  s/.*/./; q'`/stamp-h$_am_stamp_count
+  ;;
+ 
+-  :C)  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+-printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
++  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
++$as_echo "$as_me: executing $ac_file commands" >&6;}
+  ;;
+   esac
+ 
+@@ -20074,7 +17447,7 @@ esac
+   for am_mf
+   do
+     # Strip MF so we end up with the name of the file.
+-    am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'`
++    am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
+     # Check whether this is an Automake generated Makefile which includes
+     # dependency-tracking related rules and includes.
+     # Grep'ing the whole file directly is not great: AIX grep has a line
+@@ -20086,7 +17459,7 @@ $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ 	 X"$am_mf" : 'X\(//\)[^/]' \| \
+ 	 X"$am_mf" : 'X\(//\)$' \| \
+ 	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X"$am_mf" |
++$as_echo X"$am_mf" |
+     sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -20108,7 +17481,7 @@ printf "%s\n" X"$am_mf" |
+ $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+ 	 X"$am_mf" : 'X\(//\)$' \| \
+ 	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+-printf "%s\n" X/"$am_mf" |
++$as_echo X/"$am_mf" |
+     sed '/^.*\/\([^/][^/]*\)\/*$/{
+ 	    s//\1/
+ 	    q
+@@ -20133,8 +17506,8 @@ printf "%s\n" X/"$am_mf" |
+    (exit $ac_status); } || am_rc=$?
+   done
+   if test $am_rc -ne 0; then
+-    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+-printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
++    { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
++$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ as_fn_error $? "Something went wrong bootstrapping makefile fragments
+     for automatic dependency tracking.  If GNU make was not used, consider
+     re-running the configure script with MAKE=\"gmake\" (or whatever is
+@@ -20152,53 +17525,54 @@ See \`config.log' for more details" "$LINENO" 5; }
+  ;;
+     "libtool":C)
+ 
+-    # See if we are running on zsh, and set the options that allow our
++    # See if we are running on zsh, and set the options which allow our
+     # commands through without removal of \ escapes.
+-    if test -n "${ZSH_VERSION+set}"; then
++    if test -n "${ZSH_VERSION+set}" ; then
+       setopt NO_GLOB_SUBST
+     fi
+ 
+-    cfgfile=${ofile}T
++    cfgfile="${ofile}T"
+     trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+     $RM "$cfgfile"
+ 
+     cat <<_LT_EOF >> "$cfgfile"
+ #! $SHELL
+-# Generated automatically by $as_me ($PACKAGE) $VERSION
++
++# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
++# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+ # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+ # NOTE: Changes made to this file will be lost: look at ltmain.sh.
+-
+-# Provide generalized library-building support services.
+-# Written by Gordon Matzigkeit, 1996
+-
+-# Copyright (C) 2014 Free Software Foundation, Inc.
+-# This is free software; see the source for copying conditions.  There is NO
+-# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+-
+-# GNU Libtool 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 2 of of the License, or
+-# (at your option) any later version.
+ #
+-# As a special exception to the GNU General Public License, if you
+-# distribute this file as part of a program or library that is built
+-# using GNU Libtool, you may include this file under the  same
+-# distribution terms that you use for the rest of that program.
++#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
++#                 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
++#   Written by Gordon Matzigkeit, 1996
+ #
+-# GNU Libtool is distributed in the hope that it will be useful, but
+-# WITHOUT ANY WARRANTY; without even the implied warranty of
++#   This file is part of GNU Libtool.
++#
++# GNU Libtool 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 2 of
++# the License, or (at your option) any later version.
++#
++# As a special exception to the GNU General Public License,
++# if you distribute this file as part of a program or library that
++# is built using GNU Libtool, you may include this file under the
++# same distribution terms that you use for the rest of that program.
++#
++# GNU Libtool is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+-# along with this program.  If not, see .
++# along with GNU Libtool; see the file COPYING.  If not, a copy
++# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
++# obtained by writing to the Free Software Foundation, Inc.,
++# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ 
+ 
+ # The names of the tagged configurations supported by this script.
+-available_tags='CXX '
+-
+-# Configured defaults for sys_lib_dlsearch_path munging.
+-: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
++available_tags="CXX "
+ 
+ # ### BEGIN LIBTOOL CONFIG
+ 
+@@ -20218,18 +17592,12 @@ pic_mode=$pic_mode
+ # Whether or not to optimize for fast installation.
+ fast_install=$enable_fast_install
+ 
+-# Shared archive member basename,for filename based shared library versioning on AIX.
+-shared_archive_member_spec=$shared_archive_member_spec
+-
+ # Shell to use when invoking shell scripts.
+ SHELL=$lt_SHELL
+ 
+ # An echo program that protects backslashes.
+ ECHO=$lt_ECHO
+ 
+-# The PATH separator for the build system.
+-PATH_SEPARATOR=$lt_PATH_SEPARATOR
+-
+ # The host system.
+ host_alias=$host_alias
+ host=$host
+@@ -20279,47 +17647,18 @@ SP2NL=$lt_lt_SP2NL
+ # turn newlines into spaces.
+ NL2SP=$lt_lt_NL2SP
+ 
+-# convert \$build file names to \$host format.
+-to_host_file_cmd=$lt_cv_to_host_file_cmd
+-
+-# convert \$build files to toolchain format.
+-to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+-
+-# A file(cmd) program that detects file types.
+-FILECMD=$lt_FILECMD
+-
+ # An object symbol dumper.
+ OBJDUMP=$lt_OBJDUMP
+ 
+ # Method to check whether dependent libraries are shared objects.
+ deplibs_check_method=$lt_deplibs_check_method
+ 
+-# Command to use when deplibs_check_method = "file_magic".
++# Command to use when deplibs_check_method == "file_magic".
+ file_magic_cmd=$lt_file_magic_cmd
+ 
+-# How to find potential files when deplibs_check_method = "file_magic".
+-file_magic_glob=$lt_file_magic_glob
+-
+-# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+-want_nocaseglob=$lt_want_nocaseglob
+-
+-# DLL creation program.
+-DLLTOOL=$lt_DLLTOOL
+-
+-# Command to associate shared and link libraries.
+-sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+-
+ # The archiver.
+ AR=$lt_AR
+-
+-# Flags to create an archive (by configure).
+-lt_ar_flags=$lt_ar_flags
+-
+-# Flags to create an archive.
+-AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
+-
+-# How to feed a file listing to the archiver.
+-archiver_list_spec=$lt_archiver_list_spec
++AR_FLAGS=$lt_AR_FLAGS
+ 
+ # A symbol stripping program.
+ STRIP=$lt_STRIP
+@@ -20344,27 +17683,12 @@ global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+ # Transform the output of nm in a proper C declaration.
+ global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+ 
+-# Transform the output of nm into a list of symbols to manually relocate.
+-global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+-
+ # Transform the output of nm in a C name address pair.
+ global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+ 
+ # Transform the output of nm in a C name address pair when lib prefix is needed.
+ global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+ 
+-# The name lister interface.
+-nm_interface=$lt_lt_cv_nm_interface
+-
+-# Specify filename containing input files for \$NM.
+-nm_file_list_spec=$lt_nm_file_list_spec
+-
+-# The root where to search for dependent libraries,and where our libraries should be installed.
+-lt_sysroot=$lt_sysroot
+-
+-# Command to truncate a binary pipe.
+-lt_truncate_bin=$lt_lt_cv_truncate_bin
+-
+ # The name of the directory that contains temporary libtool files.
+ objdir=$objdir
+ 
+@@ -20374,9 +17698,6 @@ MAGIC_CMD=$MAGIC_CMD
+ # Must we lock files when doing compilation?
+ need_locks=$lt_need_locks
+ 
+-# Manifest tool.
+-MANIFEST_TOOL=$lt_MANIFEST_TOOL
+-
+ # Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+ DSYMUTIL=$lt_DSYMUTIL
+ 
+@@ -20455,11 +17776,8 @@ hardcode_into_libs=$hardcode_into_libs
+ # Compile-time system search path for libraries.
+ sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+ 
+-# Detected run-time system search path for libraries.
+-sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+-
+-# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+-configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
++# Run-time system search path for libraries.
++sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+ 
+ # Whether dlopen is supported.
+ dlopen_support=$enable_dlopen
+@@ -20494,12 +17812,12 @@ with_gcc=$GCC
+ # Compiler flag to turn off builtin functions.
+ no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+ 
+-# Additional compiler flags for building library objects.
+-pic_flag=$lt_lt_prog_compiler_pic
+-
+ # How to pass a linker flag through the compiler.
+ wl=$lt_lt_prog_compiler_wl
+ 
++# Additional compiler flags for building library objects.
++pic_flag=$lt_lt_prog_compiler_pic
++
+ # Compiler flag to prevent dynamic linking.
+ link_static_flag=$lt_lt_prog_compiler_static
+ 
+@@ -20549,16 +17867,20 @@ no_undefined_flag=$lt_no_undefined_flag
+ # This must work even if \$libdir does not exist
+ hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+ 
++# If ld is used when linking, flag to hardcode \$libdir into a binary
++# during linking.  This must work even if \$libdir does not exist.
++hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
++
+ # Whether we need a single "-rpath" flag with a separated argument.
+ hardcode_libdir_separator=$lt_hardcode_libdir_separator
+ 
+-# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+ # DIR into the resulting binary.
+ hardcode_direct=$hardcode_direct
+ 
+-# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+ # DIR into the resulting binary and the resulting library dependency is
+-# "absolute",i.e impossible to change by setting \$shlibpath_var if the
++# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+ # library is relocated.
+ hardcode_direct_absolute=$hardcode_direct_absolute
+ 
+@@ -20582,6 +17904,9 @@ inherit_rpath=$inherit_rpath
+ # Whether libtool must link a program against all its dependency libraries.
+ link_all_deplibs=$link_all_deplibs
+ 
++# Fix the shell variable \$srcfile for the compiler.
++fix_srcfile_path=$lt_fix_srcfile_path
++
+ # Set to "yes" if exported symbols are required.
+ always_export_symbols=$always_export_symbols
+ 
+@@ -20597,9 +17922,6 @@ include_expsyms=$lt_include_expsyms
+ # Commands necessary for linking programs (against libraries) with templates.
+ prelink_cmds=$lt_prelink_cmds
+ 
+-# Commands necessary for finishing linking programs.
+-postlink_cmds=$lt_postlink_cmds
+-
+ # Specify filename containing input files.
+ file_list_spec=$lt_file_list_spec
+ 
+@@ -20622,65 +17944,6 @@ compiler_lib_search_path=$lt_compiler_lib_search_path
+ 
+ # ### END LIBTOOL CONFIG
+ 
+-_LT_EOF
+-
+-    cat <<'_LT_EOF' >> "$cfgfile"
+-
+-# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+-
+-# func_munge_path_list VARIABLE PATH
+-# -----------------------------------
+-# VARIABLE is name of variable containing _space_ separated list of
+-# directories to be munged by the contents of PATH, which is string
+-# having a format:
+-# "DIR[:DIR]:"
+-#       string "DIR[ DIR]" will be prepended to VARIABLE
+-# ":DIR[:DIR]"
+-#       string "DIR[ DIR]" will be appended to VARIABLE
+-# "DIRP[:DIRP]::[DIRA:]DIRA"
+-#       string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+-#       "DIRA[ DIRA]" will be appended to VARIABLE
+-# "DIR[:DIR]"
+-#       VARIABLE will be replaced by "DIR[ DIR]"
+-func_munge_path_list ()
+-{
+-    case x$2 in
+-    x)
+-        ;;
+-    *:)
+-        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+-        ;;
+-    x:*)
+-        eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+-        ;;
+-    *::*)
+-        eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+-        eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+-        ;;
+-    *)
+-        eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+-        ;;
+-    esac
+-}
+-
+-
+-# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+-func_cc_basename ()
+-{
+-    for cc_temp in $*""; do
+-      case $cc_temp in
+-        compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+-        distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+-        \-*) ;;
+-        *) break;;
+-      esac
+-    done
+-    func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+-}
+-
+-
+-# ### END FUNCTIONS SHARED WITH CONFIGURE
+-
+ _LT_EOF
+ 
+   case $host_os in
+@@ -20689,7 +17952,7 @@ _LT_EOF
+ # AIX sometimes has problems with the GCC collect2 program.  For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+-if test set != "${COLLECT_NAMES+set}"; then
++if test "X${COLLECT_NAMES+set}" != Xset; then
+   COLLECT_NAMES=
+   export COLLECT_NAMES
+ fi
+@@ -20698,18 +17961,217 @@ _LT_EOF
+   esac
+ 
+ 
+-
+-ltmain=$ac_aux_dir/ltmain.sh
++ltmain="$ac_aux_dir/ltmain.sh"
+ 
+ 
+   # We use sed instead of cat because bash on DJGPP gets confused if
+   # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+   # text mode, it properly converts lines to CR/LF.  This bash problem
+   # is reportedly fixed, but why not run on old versions too?
+-  $SED '$q' "$ltmain" >> "$cfgfile" \
+-     || (rm -f "$cfgfile"; exit 1)
++  sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
++    || (rm -f "$cfgfile"; exit 1)
++
++  case $xsi_shell in
++  yes)
++    cat << \_LT_EOF >> "$cfgfile"
++
++# func_dirname file append nondir_replacement
++# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
++# otherwise set result to NONDIR_REPLACEMENT.
++func_dirname ()
++{
++  case ${1} in
++    */*) func_dirname_result="${1%/*}${2}" ;;
++    *  ) func_dirname_result="${3}" ;;
++  esac
++}
++
++# func_basename file
++func_basename ()
++{
++  func_basename_result="${1##*/}"
++}
++
++# func_dirname_and_basename file append nondir_replacement
++# perform func_basename and func_dirname in a single function
++# call:
++#   dirname:  Compute the dirname of FILE.  If nonempty,
++#             add APPEND to the result, otherwise set result
++#             to NONDIR_REPLACEMENT.
++#             value returned in "$func_dirname_result"
++#   basename: Compute filename of FILE.
++#             value retuned in "$func_basename_result"
++# Implementation must be kept synchronized with func_dirname
++# and func_basename. For efficiency, we do not delegate to
++# those functions but instead duplicate the functionality here.
++func_dirname_and_basename ()
++{
++  case ${1} in
++    */*) func_dirname_result="${1%/*}${2}" ;;
++    *  ) func_dirname_result="${3}" ;;
++  esac
++  func_basename_result="${1##*/}"
++}
++
++# func_stripname prefix suffix name
++# strip PREFIX and SUFFIX off of NAME.
++# PREFIX and SUFFIX must not contain globbing or regex special
++# characters, hashes, percent signs, but SUFFIX may contain a leading
++# dot (in which case that matches only a dot).
++func_stripname ()
++{
++  # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
++  # positional parameters, so assign one to ordinary parameter first.
++  func_stripname_result=${3}
++  func_stripname_result=${func_stripname_result#"${1}"}
++  func_stripname_result=${func_stripname_result%"${2}"}
++}
++
++# func_opt_split
++func_opt_split ()
++{
++  func_opt_split_opt=${1%%=*}
++  func_opt_split_arg=${1#*=}
++}
++
++# func_lo2o object
++func_lo2o ()
++{
++  case ${1} in
++    *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
++    *)    func_lo2o_result=${1} ;;
++  esac
++}
++
++# func_xform libobj-or-source
++func_xform ()
++{
++  func_xform_result=${1%.*}.lo
++}
++
++# func_arith arithmetic-term...
++func_arith ()
++{
++  func_arith_result=$(( $* ))
++}
+ 
+-   mv -f "$cfgfile" "$ofile" ||
++# func_len string
++# STRING may not start with a hyphen.
++func_len ()
++{
++  func_len_result=${#1}
++}
++
++_LT_EOF
++    ;;
++  *) # Bourne compatible functions.
++    cat << \_LT_EOF >> "$cfgfile"
++
++# func_dirname file append nondir_replacement
++# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
++# otherwise set result to NONDIR_REPLACEMENT.
++func_dirname ()
++{
++  # Extract subdirectory from the argument.
++  func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
++  if test "X$func_dirname_result" = "X${1}"; then
++    func_dirname_result="${3}"
++  else
++    func_dirname_result="$func_dirname_result${2}"
++  fi
++}
++
++# func_basename file
++func_basename ()
++{
++  func_basename_result=`$ECHO "${1}" | $SED "$basename"`
++}
++
++
++# func_stripname prefix suffix name
++# strip PREFIX and SUFFIX off of NAME.
++# PREFIX and SUFFIX must not contain globbing or regex special
++# characters, hashes, percent signs, but SUFFIX may contain a leading
++# dot (in which case that matches only a dot).
++# func_strip_suffix prefix name
++func_stripname ()
++{
++  case ${2} in
++    .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
++    *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
++  esac
++}
++
++# sed scripts:
++my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
++my_sed_long_arg='1s/^-[^=]*=//'
++
++# func_opt_split
++func_opt_split ()
++{
++  func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"`
++  func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"`
++}
++
++# func_lo2o object
++func_lo2o ()
++{
++  func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
++}
++
++# func_xform libobj-or-source
++func_xform ()
++{
++  func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
++}
++
++# func_arith arithmetic-term...
++func_arith ()
++{
++  func_arith_result=`expr "$@"`
++}
++
++# func_len string
++# STRING may not start with a hyphen.
++func_len ()
++{
++  func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
++}
++
++_LT_EOF
++esac
++
++case $lt_shell_append in
++  yes)
++    cat << \_LT_EOF >> "$cfgfile"
++
++# func_append var value
++# Append VALUE to the end of shell variable VAR.
++func_append ()
++{
++  eval "$1+=\$2"
++}
++_LT_EOF
++    ;;
++  *)
++    cat << \_LT_EOF >> "$cfgfile"
++
++# func_append var value
++# Append VALUE to the end of shell variable VAR.
++func_append ()
++{
++  eval "$1=\$$1\$2"
++}
++
++_LT_EOF
++    ;;
++  esac
++
++
++  sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
++    || (rm -f "$cfgfile"; exit 1)
++
++  mv -f "$cfgfile" "$ofile" ||
+     (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+   chmod +x "$ofile"
+ 
+@@ -20737,12 +18199,12 @@ with_gcc=$GCC_CXX
+ # Compiler flag to turn off builtin functions.
+ no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+ 
+-# Additional compiler flags for building library objects.
+-pic_flag=$lt_lt_prog_compiler_pic_CXX
+-
+ # How to pass a linker flag through the compiler.
+ wl=$lt_lt_prog_compiler_wl_CXX
+ 
++# Additional compiler flags for building library objects.
++pic_flag=$lt_lt_prog_compiler_pic_CXX
++
+ # Compiler flag to prevent dynamic linking.
+ link_static_flag=$lt_lt_prog_compiler_static_CXX
+ 
+@@ -20792,16 +18254,20 @@ no_undefined_flag=$lt_no_undefined_flag_CXX
+ # This must work even if \$libdir does not exist
+ hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+ 
++# If ld is used when linking, flag to hardcode \$libdir into a binary
++# during linking.  This must work even if \$libdir does not exist.
++hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
++
+ # Whether we need a single "-rpath" flag with a separated argument.
+ hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+ 
+-# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+ # DIR into the resulting binary.
+ hardcode_direct=$hardcode_direct_CXX
+ 
+-# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
++# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+ # DIR into the resulting binary and the resulting library dependency is
+-# "absolute",i.e impossible to change by setting \$shlibpath_var if the
++# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+ # library is relocated.
+ hardcode_direct_absolute=$hardcode_direct_absolute_CXX
+ 
+@@ -20825,6 +18291,9 @@ inherit_rpath=$inherit_rpath_CXX
+ # Whether libtool must link a program against all its dependency libraries.
+ link_all_deplibs=$link_all_deplibs_CXX
+ 
++# Fix the shell variable \$srcfile for the compiler.
++fix_srcfile_path=$lt_fix_srcfile_path_CXX
++
+ # Set to "yes" if exported symbols are required.
+ always_export_symbols=$always_export_symbols_CXX
+ 
+@@ -20840,9 +18309,6 @@ include_expsyms=$lt_include_expsyms_CXX
+ # Commands necessary for linking programs (against libraries) with templates.
+ prelink_cmds=$lt_prelink_cmds_CXX
+ 
+-# Commands necessary for finishing linking programs.
+-postlink_cmds=$lt_postlink_cmds_CXX
+-
+ # Specify filename containing input files.
+ file_list_spec=$lt_file_list_spec_CXX
+ 
+@@ -20901,9 +18367,8 @@ if test "$no_create" != yes; then
+   $ac_cs_success || as_fn_exit 1
+ fi
+ if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+-printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
++  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
++$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ fi
+ 
+ 
+-
+-- 
+2.33.0
+
diff --git a/0089-StructReorderFields-Fix-gimple-call-not-rewritten.patch b/0089-StructReorderFields-Fix-gimple-call-not-rewritten.patch
new file mode 100644
index 0000000..76697e2
--- /dev/null
+++ b/0089-StructReorderFields-Fix-gimple-call-not-rewritten.patch
@@ -0,0 +1,48 @@
+From 302b7e15d6308c29c215db4c9901342e1106381a Mon Sep 17 00:00:00 2001
+From: huang-xiaoquan 
+Date: Mon, 29 Apr 2024 11:00:12 +0800
+Subject: [PATCH] [StructReorderFields] Fix gimple call not rewritten due to
+ empty function node
+
+Add parameter type escape for empty functions or inline functions.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index e08577c0c..2257d3528 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -4366,6 +4366,17 @@ ipa_struct_reorg::maybe_record_call (cgraph_node *node, gcall *stmt)
+ 
+       argtype = argtype ? TREE_CHAIN (argtype) : NULL_TREE;
+     }
++
++  /* Types escapes via a argument at empty or inlined function.  */
++  cgraph_node *callee = node->get_edge (stmt)->callee;
++  if (!gimple_call_builtin_p (stmt, BUILT_IN_FREE)
++      && gimple_call_num_args (stmt)
++      && callee && (!callee->has_gimple_body_p () || callee->inlined_to))
++    {
++      for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
++	mark_type_as_escape (TREE_TYPE (gimple_call_arg (stmt, i)),
++			      escape_var_arg_function);
++    }
+ }
+ 
+ void
+@@ -8068,6 +8079,11 @@ ipa_struct_reorg::rewrite_functions (void)
+ 	      if (dump_file && (dump_flags & TDF_DETAILS))
+ 		{
+ 		  fprintf (dump_file, "\nNo rewrite:\n");
++		  if (current_function_decl == NULL)
++		    {
++		      fprintf (dump_file, "\ncurrent_function_decl == NULL\n");
++		      continue;
++		    }
+ 		  if (current_function_decl)
+ 		    dump_function_to_file (current_function_decl, dump_file,
+ 					   dump_flags | TDF_VOPS);
+-- 
+2.33.0
+
diff --git a/0090-double-sized-mul-testsuite-Add-march-armv8.2-a-for-d.patch b/0090-double-sized-mul-testsuite-Add-march-armv8.2-a-for-d.patch
new file mode 100644
index 0000000..41ed921
--- /dev/null
+++ b/0090-double-sized-mul-testsuite-Add-march-armv8.2-a-for-d.patch
@@ -0,0 +1,40 @@
+From 01517aa2397f854ffa96128a0fb23dd5542be709 Mon Sep 17 00:00:00 2001
+From: Chernonog Viacheslav 
+Date: Tue, 30 Apr 2024 18:43:32 +0800
+Subject: [PATCH 1/4] [double-sized-mul][testsuite] Add march armv8.2-a for dg
+ tests
+
+---
+ gcc/testsuite/gcc.dg/double_sized_mul-1.c | 2 +-
+ gcc/testsuite/gcc.dg/double_sized_mul-2.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.dg/double_sized_mul-1.c b/gcc/testsuite/gcc.dg/double_sized_mul-1.c
+index 4d475cc8a..d32a25223 100644
+--- a/gcc/testsuite/gcc.dg/double_sized_mul-1.c
++++ b/gcc/testsuite/gcc.dg/double_sized_mul-1.c
+@@ -1,7 +1,7 @@
+ /* { dg-do compile } */
+ /* fif-conversion-gimple and fuaddsub-overflow-match-all are required for
+    proper overflow detection in some cases.  */
+-/* { dg-options "-O2 -fif-conversion-gimple -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++/* { dg-options "-O2 -fif-conversion-gimple -march=armv8.2-a -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
+ #include 
+ 
+ typedef unsigned __int128 uint128_t;
+diff --git a/gcc/testsuite/gcc.dg/double_sized_mul-2.c b/gcc/testsuite/gcc.dg/double_sized_mul-2.c
+index cc6e5af25..ff35902b7 100644
+--- a/gcc/testsuite/gcc.dg/double_sized_mul-2.c
++++ b/gcc/testsuite/gcc.dg/double_sized_mul-2.c
+@@ -1,7 +1,7 @@
+ /* { dg-do compile } */
+ /* fif-conversion-gimple is required for proper overflow detection
+    in some cases.  */
+-/* { dg-options "-O2 -fif-conversion-gimple -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++/* { dg-options "-O2 -fif-conversion-gimple -march=armv8.2-a -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
+ #include 
+ 
+ typedef unsigned __int128 uint128_t;
+-- 
+2.33.0
+
diff --git a/0091-IPA-Bugfix-Fix-fails-in-IPA-prefetch-src-openEuler-g.patch b/0091-IPA-Bugfix-Fix-fails-in-IPA-prefetch-src-openEuler-g.patch
new file mode 100644
index 0000000..5ed7248
--- /dev/null
+++ b/0091-IPA-Bugfix-Fix-fails-in-IPA-prefetch-src-openEuler-g.patch
@@ -0,0 +1,34 @@
+From b84a896e2df214b08d6519a097cc410d3e582add Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Wed, 8 May 2024 21:28:32 +0800
+Subject: [PATCH 2/4] [IPA][Bugfix] Fix fails in IPA prefetch
+ (src-openEuler/gcc: I9J6N6)
+
+---
+ gcc/ipa-prefetch.cc | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index 1ceb5137f..94290ea9c 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -1432,8 +1432,14 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
+ 	  TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
+ 	  TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
+ 	  TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+-	  /* TODO: maybe support this case.  */
+-	  gcc_assert (MR_DEPENDENCE_CLIQUE (old) == 0);
++	  if (MR_DEPENDENCE_CLIQUE (old) != 0)
++	    {
++	      MR_DEPENDENCE_CLIQUE (*tp) = MR_DEPENDENCE_CLIQUE (old);
++	      MR_DEPENDENCE_BASE (*tp) = MR_DEPENDENCE_BASE (old);
++	      if (dump_file)
++		fprintf (dump_file, "Copy clique=%d base=%d info.\n",
++			 MR_DEPENDENCE_CLIQUE (old), MR_DEPENDENCE_BASE (old));
++	    }
+ 	  /* We cannot propagate the TREE_THIS_NOTRAP flag if we have
+ 	     remapped a parameter as the property might be valid only
+ 	     for the parameter itself.  */
+-- 
+2.33.0
+
diff --git a/0092-AES-Bugfix-Change-set_of-to-reg_set_p-and-add-check-.patch b/0092-AES-Bugfix-Change-set_of-to-reg_set_p-and-add-check-.patch
new file mode 100644
index 0000000..c9bf39e
--- /dev/null
+++ b/0092-AES-Bugfix-Change-set_of-to-reg_set_p-and-add-check-.patch
@@ -0,0 +1,29 @@
+From acb6bbf0612aead00a879892ba8ed816c90fe788 Mon Sep 17 00:00:00 2001
+From: Chernonog Viacheslav 
+Date: Wed, 8 May 2024 19:24:27 +0800
+Subject: [PATCH 3/4] [AES][Bugfix] Change set_of to reg_set_p, and add check
+ for global_regs fix for I9JDHE
+
+---
+ gcc/rtl-matcher.h | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/rtl-matcher.h b/gcc/rtl-matcher.h
+index 6aed8d98d..5310f6266 100644
+--- a/gcc/rtl-matcher.h
++++ b/gcc/rtl-matcher.h
+@@ -56,8 +56,9 @@ check_def_chain_ref (df_ref ref, rtx reg)
+   if (!ref || !DF_REF_INSN_INFO (ref))
+     return false;
+ 
+-  return !global_regs[REGNO (reg)]
+-    || set_of (reg, DF_REF_INSN (ref));
++  return !(REGNO (reg) < FIRST_PSEUDO_REGISTER
++	   && global_regs[REGNO (reg)])
++    || reg_set_p (reg, DF_REF_INSN (ref));
+ }
+ 
+ /* Get the single def instruction of the reg being used in the insn.  */
+-- 
+2.33.0
+
diff --git a/0093-fix-bugs-within-pointer-compression-and-DFE.patch b/0093-fix-bugs-within-pointer-compression-and-DFE.patch
new file mode 100644
index 0000000..64b35fe
--- /dev/null
+++ b/0093-fix-bugs-within-pointer-compression-and-DFE.patch
@@ -0,0 +1,26 @@
+From 48724ee73cd58b67d59962ee4d56ac85db797e61 Mon Sep 17 00:00:00 2001
+From: tiancheng-bao 
+Date: Fri, 10 May 2024 17:52:27 +0800
+Subject: [PATCH 4/4] fix bugs within pointer compression and DFE
+
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index 2257d3528..1a169c635 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -7472,9 +7472,6 @@ ipa_struct_reorg::rewrite_assign (gassign *stmt, gimple_stmt_iterator *gsi)
+ 	    continue;
+ 	  tree lhs_expr = newlhs[i] ? newlhs[i] : lhs;
+ 	  tree rhs_expr = newrhs[i] ? newrhs[i] : rhs;
+-	  if (!useless_type_conversion_p (TREE_TYPE (lhs_expr),
+-					  TREE_TYPE (rhs_expr)))
+-	    rhs_expr = gimplify_build1 (gsi, NOP_EXPR, TREE_TYPE (lhs_expr), rhs_expr);  
+ 	  gimple *newstmt = gimple_build_assign (lhs_expr, rhs_expr);
+ 	  if (dump_file && (dump_flags & TDF_DETAILS))
+ 	    {
+-- 
+2.33.0
+
diff --git a/0094-BUGFIX-AutoBOLT-function-miss-bind-type.patch b/0094-BUGFIX-AutoBOLT-function-miss-bind-type.patch
new file mode 100644
index 0000000..4b0e6a5
--- /dev/null
+++ b/0094-BUGFIX-AutoBOLT-function-miss-bind-type.patch
@@ -0,0 +1,28 @@
+From 4861c3db991e947060de54a4d20c1a13747a6024 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Wed, 15 May 2024 14:41:45 +0800
+Subject: [PATCH] [BUGFIX] AutoBOLT function miss bind type
+
+---
+ gcc/final.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/final.cc b/gcc/final.cc
+index af4e529bb..c440846f7 100644
+--- a/gcc/final.cc
++++ b/gcc/final.cc
+@@ -4272,9 +4272,9 @@ leaf_renumber_regs_insn (rtx in_rtx)
+ 
+ #define ASM_FDO_CALLER_FLAG ".fdo.caller "
+ #define ASM_FDO_CALLER_SIZE_FLAG ".fdo.caller.size "
+-#define ASM_FDO_CALLER_BIND_FLAG ".fdo.caller.bind"
++#define ASM_FDO_CALLER_BIND_FLAG ".fdo.caller.bind "
+ 
+-#define ASM_FDO_CALLEE_FLAG ".fdo.callee"
++#define ASM_FDO_CALLEE_FLAG ".fdo.callee "
+ 
+ /* Return the relative offset address of the start instruction of BB,
+    return -1 if it is empty instruction.    */
+-- 
+2.33.0
+
diff --git a/0095-STABS-remove-gstabs-and-gxcoff-functionality.patch b/0095-STABS-remove-gstabs-and-gxcoff-functionality.patch
new file mode 100644
index 0000000..e76e8c3
--- /dev/null
+++ b/0095-STABS-remove-gstabs-and-gxcoff-functionality.patch
@@ -0,0 +1,9044 @@
+From 97b011574a0b4133c79f2f1ceea2f9ae1d42d044 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Thu, 16 May 2024 10:31:40 +0800
+Subject: [PATCH] STABS: remove -gstabs and -gxcoff functionality
+
+gcc/ChangeLog:
+
+	* Makefile.in: Remove -gstabs option support, DBX-related
+	  macros and DBX debugging info support.
+	* collect2.cc (scan_prog_file): Likewise.
+	* common.opt: Likewise.
+	* config.gcc: Likewise.
+	* config.in: Likewise.
+	* config/aarch64/aarch64-elf.h (DBX_DEBUGGING_INFO): Likewise.
+	* config/alpha/alpha.cc: Likewise.
+	* config/alpha/elf.h (ASM_SPEC): Likewise.
+	* config/arc/arc.h (DBX_DEBUGGING_INFO): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/arm/aout.h (DBX_DEBUGGING_INFO): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/arm/netbsd-elf.h (DBX_CONTIN_LENGTH): Likewise.
+	* config/darwin.h (DSYMUTIL_SPEC): Likewise.
+	(ASM_DEBUG_SPEC): Likewise.
+	(DBX_DEBUGGING_INFO): Likewise.
+	(DBX_USE_BINCL): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	(DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END): Likewise.
+	* config/epiphany/epiphany.h (DBX_DEBUGGING_INFO): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/i386/bsd.h (DBX_NO_XREFS): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/i386/gas.h (DBX_NO_XREFS): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/ia64/ia64.h: Likewise.
+	* config/ia64/sysv4.h (DBX_DEBUGGING_INFO): Likewise.
+	* config/m68k/linux.h (DBX_CONTIN_LENGTH): Likewise.
+	* config/m68k/openbsd.h (DBX_DEBUGGING_INFO): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	(DBX_CONTIN_CHAR): Likewise.
+	* config/mips/mips.cc (mips_output_filename): Likewise.
+	(mips_option_override): Likewise.
+	* config/mips/mips.h (SUBTARGET_ASM_DEBUGGING_SPEC): Likewise.
+	(DBX_DEBUGGING_INFO): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	(DBX_REGISTER_NUMBER): Likewise.
+	(GP_DBX_FIRST): Likewise.
+	(FP_DBX_FIRST): Likewise.
+	(MD_DBX_FIRST): Likewise.
+	* config/nvptx/nvptx.cc: Likewise.
+	* config/openbsd.h (DBX_NO_XREFS): Likewise.
+	* config/pa/pa-64.h (DBX_DEBUGGING_INFO): Likewise.
+	* config/pa/pa.h (ASSEMBLER_DIALECT): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/pa/som.h (PREFERRED_DEBUGGING_TYPE): Likewise.
+	(DBX_USE_BINCL): Likewise.
+	(DBX_LINES_FUNCTION_RELATIVE): Likewise.
+	(DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END): Likewise.
+	* config/pdp11/pdp11.cc: Likewise.
+	* config/pdp11/pdp11.h (DBX_DEBUGGING_INFO): Likewise.
+	(PREFERRED_DEBUGGING_TYPE): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	* config/rs6000/rs6000-builtin.cc: Likewise.
+	* config/rs6000/rs6000-call.cc: Likewise.
+	* config/rs6000/rs6000-logue.cc (defined): Likewise.
+	* config/rs6000/rs6000.cc (rs6000_option_override_internal): Likewise.
+	(HAVE_XCOFF_DWARF_EXTRAS): Likewise.
+	(rs6000_xcoff_declare_function_name): Likewise.
+	* config/rs6000/sysv4.h (DBX_DEBUGGING_INFO): Likewise.
+	(DBX_FUNCTION_FIRST): Likewise.
+	* config/rs6000/xcoff.h (XCOFF_DEBUGGING_INFO): Likewise.
+	* config/rx/rx.h (DBX_DEBUGGING_INFO): Likewise.
+	* config/sh/elf.h (DBX_LINES_FUNCTION_RELATIVE): Likewise.
+	(DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END): Likewise.
+	* config/sol2.h (NO_DBX_BNSYM_ENSYM): Likewise.
+	* config/sparc/freebsd.h (DBX_CONTIN_CHAR): Likewise.
+	* config/sparc/netbsd-elf.h (DBX_CONTIN_CHAR): Likewise.
+	* config/sparc/sparc.h (DBX_CONTIN_LENGTH): Likewise.
+	* config/vax/vax.cc (vax_file_start): Likewise.
+	* config/vax/vax.h (DBX_DEBUGGING_INFO): Likewise.
+	(DBX_CONTIN_LENGTH): Likewise.
+	(DBX_CONTIN_CHAR): Likewise.
+	(DBX_NO_XREFS): Likewise.
+	(DBX_STATIC_STAB_DATA_SECTION): Likewise.
+	* config/vx-common.h (DBX_DEBUGGING_INFO): Likewise.
+	(XCOFF_DEBUGGING_INFO): Likewise.
+	* configure: Regenerate. Likewise.
+	* configure.ac: Likewise.
+	* debug.h: Likewise.
+	* doc/install.texi: Likewise.
+	* doc/invoke.texi: Likewise.
+	* doc/passes.texi: Likewise.
+	* doc/tm.texi: Likewise.
+	* doc/tm.texi.in: Likewise.
+	* dwarf2asm.cc (XCOFF_DEBUGGING_INFO): Likewise.
+	(dw2_asm_output_nstring): Likewise.
+	(USE_LINKONCE_INDIRECT): Likewise.
+	* dwarf2out.cc (XCOFF_DEBUGGING_INFO): Likewise.
+	(HAVE_XCOFF_DWARF_EXTRAS): Likewise.
+	(output_fde): Likewise.
+	(output_call_frame_info): Likewise.
+	(have_macinfo): Likewise.
+	(add_AT_loc_list): Likewise.
+	(add_AT_view_list): Likewise.
+	(output_compilation_unit_header): Likewise.
+	(output_pubnames): Likewise.
+	(output_aranges): Likewise.
+	(output_line_info): Likewise.
+	(output_macinfo): Likewise.
+	(dwarf2out_finish): Likewise.
+	(dwarf2out_early_finish): Likewise.
+	* final.cc (final_scan_insn_1): Likewise.
+	(rest_of_handle_final): Likewise.
+	* flag-types.h (enum debug_info_type): Likewise.
+	(DBX_DEBUG): Likewise.
+	(XCOFF_DEBUG): Likewise.
+	* function.cc (defined): Likewise.
+	* gcc.cc (defined): Likewise.
+	(ASM_DEBUG_SPEC): Likewise.
+	(ASM_DEBUG_OPTION_SPEC): Likewise.
+	* opts.cc (common_handle_option): Likewise.
+	(set_debug_level): Likewise.
+	* system.h (fancy_abort): Likewise.
+	* target-def.h (TARGET_ASM_CONSTRUCTOR): Likewise.
+	(TARGET_ASM_DESTRUCTOR): Likewise.
+	* toplev.cc (defined): Likewise.
+	* varasm.cc: Likewise.
+	* config/dbxcoff.h: Removed.
+	* config/dbxelf.h: Removed.
+	* dbxout.cc: Removed.
+	* dbxout.h: Removed.
+	* gstab.h: Removed.
+	* stab.def: Removed.
+	* xcoffout.cc: Removed.
+	* xcoffout.h: Removed.
+
+gcc/go/ChangeLog:
+
+	* go-lang.cc (go_langhook_pushdecl): Remove -gstabs option support, DBX-related
+	  macros and DBX debugging info support.
+	* gospec.cc (lang_specific_driver): Likewise.
+
+gcc/testsuite/ChangeLog:
+
+	* lib/gcc-dg.exp: Remove -gstabs option support, DBX-related
+	  macros and DBX debugging info support.
+	* lib/gfortran-dg.exp: Likewise.
+	* lib/target-supports.exp: Likewise.
+	* g++.dg/cpp0x/alias-decl-debug-0.C: Removed.
+	* g++.dg/other/PR23205.C: Removed.
+	* g++.dg/other/pr23205-2.C: Removed.
+	* gcc.dg/20040813-1.c: Removed.
+	* gcc.dg/darwin-20040809-2.c: Removed.
+	* gcc.dg/debug/pr35154.c: Removed.
+	* gcc.dg/pr69471-2.c: Removed.
+	* gcc.target/powerpc/stabs-attrib-vect-darwin.c: Removed.
+	* gcc.target/s390/20041216-1.c: Removed.
+	* gfortran.dg/debug/pr35154-stabs.f: Removed.
+	* objc.dg/stabs-1.m: Removed.
+---
+ gcc/Makefile.in                               |    4 +-
+ gcc/collect2.cc                               |    7 -
+ gcc/common.opt                                |   26 +-
+ gcc/config.gcc                                |  232 +-
+ gcc/config.in                                 |   19 -
+ gcc/config/aarch64/aarch64-elf.h              |    3 -
+ gcc/config/alpha/alpha.cc                     |    4 -
+ gcc/config/alpha/elf.h                        |    2 +-
+ gcc/config/arc/arc.h                          |   10 +-
+ gcc/config/arm/aout.h                         |    9 -
+ gcc/config/arm/netbsd-elf.h                   |    3 -
+ gcc/config/darwin.h                           |   27 +-
+ gcc/config/dbxcoff.h                          |   56 -
+ gcc/config/dbxelf.h                           |   68 -
+ gcc/config/epiphany/epiphany.h                |    7 +-
+ gcc/config/i386/bsd.h                         |    6 -
+ gcc/config/i386/gas.h                         |    4 -
+ gcc/config/ia64/ia64.h                        |    2 -
+ gcc/config/ia64/sysv4.h                       |    3 -
+ gcc/config/m68k/linux.h                       |    4 -
+ gcc/config/m68k/openbsd.h                     |   12 -
+ gcc/config/mips/mips.cc                       |   16 -
+ gcc/config/mips/mips.h                        |   17 +-
+ gcc/config/nvptx/nvptx.cc                     |    1 -
+ gcc/config/openbsd.h                          |   11 -
+ gcc/config/pa/pa-64.h                         |    4 -
+ gcc/config/pa/pa.h                            |   10 -
+ gcc/config/pa/som.h                           |   15 -
+ gcc/config/pdp11/pdp11.cc                     |    1 -
+ gcc/config/pdp11/pdp11.h                      |    9 -
+ gcc/config/rs6000/rs6000-builtin.cc           |    3 -
+ gcc/config/rs6000/rs6000-call.cc              |    8 -
+ gcc/config/rs6000/rs6000-logue.cc             |   12 -
+ gcc/config/rs6000/rs6000.cc                   |   24 +-
+ gcc/config/rs6000/sysv4.h                     |    8 -
+ gcc/config/rs6000/xcoff.h                     |    3 -
+ gcc/config/rx/rx.h                            |    1 -
+ gcc/config/sh/elf.h                           |    3 -
+ gcc/config/sol2.h                             |    4 -
+ gcc/config/sparc/freebsd.h                    |    6 -
+ gcc/config/sparc/netbsd-elf.h                 |    5 -
+ gcc/config/sparc/sparc.h                      |    8 -
+ gcc/config/vax/vax.cc                         |    3 -
+ gcc/config/vax/vax.h                          |   21 -
+ gcc/config/vx-common.h                        |    2 -
+ gcc/configure                                 |   99 -
+ gcc/configure.ac                              |   20 -
+ gcc/dbxout.cc                                 | 3936 -----------------
+ gcc/dbxout.h                                  |   60 -
+ gcc/debug.h                                   |    1 -
+ gcc/doc/install.texi                          |    3 +-
+ gcc/doc/invoke.texi                           |   42 +-
+ gcc/doc/passes.texi                           |    2 +-
+ gcc/doc/tm.texi                               |  220 +-
+ gcc/doc/tm.texi.in                            |  220 +-
+ gcc/dwarf2asm.cc                              |   13 +-
+ gcc/dwarf2out.cc                              |  103 +-
+ gcc/final.cc                                  |   44 -
+ gcc/flag-types.h                              |   18 +-
+ gcc/function.cc                               |    8 -
+ gcc/gcc.cc                                    |   24 +-
+ gcc/go/go-lang.cc                             |    3 +-
+ gcc/go/gospec.cc                              |    4 -
+ gcc/gstab.h                                   |   35 -
+ gcc/opts.cc                                   |   18 +-
+ gcc/stab.def                                  |  239 -
+ gcc/system.h                                  |   14 +-
+ gcc/target-def.h                              |    4 -
+ .../g++.dg/cpp0x/alias-decl-debug-0.C         |   12 -
+ gcc/testsuite/g++.dg/other/PR23205.C          |   17 -
+ gcc/testsuite/g++.dg/other/pr23205-2.C        |   17 -
+ gcc/testsuite/gcc.dg/20040813-1.c             |   14 -
+ gcc/testsuite/gcc.dg/darwin-20040809-2.c      |   15 -
+ gcc/testsuite/gcc.dg/debug/pr35154.c          |   35 -
+ gcc/testsuite/gcc.dg/pr69471-2.c              |    8 -
+ .../powerpc/stabs-attrib-vect-darwin.c        |   12 -
+ gcc/testsuite/gcc.target/s390/20041216-1.c    |   23 -
+ .../gfortran.dg/debug/pr35154-stabs.f         |   35 -
+ gcc/testsuite/lib/gcc-dg.exp                  |    2 +-
+ gcc/testsuite/lib/gfortran-dg.exp             |    2 +-
+ gcc/testsuite/lib/target-supports.exp         |    9 -
+ gcc/testsuite/objc.dg/stabs-1.m               |   19 -
+ gcc/toplev.cc                                 |   21 -
+ gcc/varasm.cc                                 |    4 -
+ gcc/xcoffout.cc                               |  494 ---
+ gcc/xcoffout.h                                |  194 -
+ 86 files changed, 211 insertions(+), 6555 deletions(-)
+ delete mode 100644 gcc/config/dbxcoff.h
+ delete mode 100644 gcc/config/dbxelf.h
+ delete mode 100644 gcc/dbxout.cc
+ delete mode 100644 gcc/dbxout.h
+ delete mode 100644 gcc/gstab.h
+ delete mode 100644 gcc/stab.def
+ delete mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C
+ delete mode 100644 gcc/testsuite/g++.dg/other/PR23205.C
+ delete mode 100644 gcc/testsuite/g++.dg/other/pr23205-2.C
+ delete mode 100644 gcc/testsuite/gcc.dg/20040813-1.c
+ delete mode 100644 gcc/testsuite/gcc.dg/darwin-20040809-2.c
+ delete mode 100644 gcc/testsuite/gcc.dg/debug/pr35154.c
+ delete mode 100644 gcc/testsuite/gcc.dg/pr69471-2.c
+ delete mode 100644 gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c
+ delete mode 100644 gcc/testsuite/gcc.target/s390/20041216-1.c
+ delete mode 100644 gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f
+ delete mode 100644 gcc/testsuite/objc.dg/stabs-1.m
+ delete mode 100644 gcc/xcoffout.cc
+ delete mode 100644 gcc/xcoffout.h
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 298bc9c92..5cd838270 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1347,7 +1347,6 @@ OBJS = \
+ 	data-streamer.o \
+ 	data-streamer-in.o \
+ 	data-streamer-out.o \
+-	dbxout.o \
+ 	dbgcnt.o \
+ 	dce.o \
+ 	ddg.o \
+@@ -1720,7 +1719,6 @@ OBJS = \
+ 	web.o \
+ 	wide-int.o \
+ 	wide-int-print.o \
+-	xcoffout.o \
+ 	$(out_object_file) \
+ 	$(ANALYZER_OBJS) \
+ 	$(EXTRA_OBJS) \
+@@ -2665,7 +2663,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
+   $(srcdir)/reload.h $(srcdir)/caller-save.cc $(srcdir)/symtab.cc \
+   $(srcdir)/alias.cc $(srcdir)/bitmap.cc $(srcdir)/cselib.cc $(srcdir)/cgraph.cc \
+   $(srcdir)/ipa-prop.cc $(srcdir)/ipa-cp.cc $(srcdir)/ipa-utils.h \
+-  $(srcdir)/ipa-param-manipulation.h $(srcdir)/ipa-sra.cc $(srcdir)/dbxout.cc \
++  $(srcdir)/ipa-param-manipulation.h $(srcdir)/ipa-sra.cc \
+   $(srcdir)/ipa-modref.h $(srcdir)/ipa-modref.cc \
+   $(srcdir)/ipa-modref-tree.h \
+   $(srcdir)/signop.h \
+diff --git a/gcc/collect2.cc b/gcc/collect2.cc
+index d81c7f28f..9715e8eee 100644
+--- a/gcc/collect2.cc
++++ b/gcc/collect2.cc
+@@ -2784,13 +2784,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
+ 		      if ((name = ldgetname (ldptr, &symbol)) == NULL)
+ 			continue;		/* Should never happen.  */
+ 
+-#ifdef XCOFF_DEBUGGING_INFO
+-		      /* All AIX function names have a duplicate entry
+-			 beginning with a dot.  */
+-		      if (*name == '.')
+-			++name;
+-#endif
+-
+ 		      switch (is_ctor_dtor (name))
+ 			{
+ #if TARGET_AIX_VERSION
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 4367d458d..b18f0b944 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -122,12 +122,6 @@ uint32_t write_symbols = NO_DEBUG
+ Variable
+ enum debug_info_levels debug_info_level = DINFO_LEVEL_NONE
+ 
+-; Nonzero means use GNU-only extensions in the generated symbolic
+-; debugging information.  Currently, this only has an effect when
+-; write_symbols is set to DBX_DEBUG or XCOFF_DEBUG.
+-Variable
+-bool use_gnu_debug_info_extensions
+-
+ ; Level of CTF debugging information we are producing.  See flag-types.h
+ ; for the definitions of the different possible levels.
+ Variable
+@@ -3410,7 +3404,7 @@ Common Driver JoinedOrMissing Negative(gdwarf-)
+ Generate debug information in default version of DWARF format.
+ 
+ gdwarf-
+-Common Driver Joined UInteger Var(dwarf_version) Init(5) Negative(gstabs)
++Common Driver Joined UInteger Var(dwarf_version) Init(5)
+ Generate debug information in DWARF v2 (or later) format.
+ 
+ gdwarf32
+@@ -3458,12 +3452,12 @@ Common Driver Var(dwarf_split_debug_info) Init(0)
+ Generate debug information in separate .dwo files.
+ 
+ gstabs
+-Common Driver JoinedOrMissing Negative(gstabs+)
+-Generate debug information in STABS format.
++Common Driver WarnRemoved
++Does nothing.  Preserved for backward compatibility.
+ 
+ gstabs+
+-Common Driver JoinedOrMissing Negative(gvms)
+-Generate debug information in extended STABS format.
++Common Driver WarnRemoved
++Does nothing.  Preserved for backward compatibility.
+ 
+ gstatement-frontiers
+ Common Driver Var(debug_nonbind_markers_p) PerFunction
+@@ -3489,16 +3483,16 @@ gvariable-location-views=incompat5
+ Common Driver RejectNegative Var(debug_variable_location_views, -1) Init(2)
+ 
+ gvms
+-Common Driver JoinedOrMissing Negative(gxcoff)
++Common Driver JoinedOrMissing
+ Generate debug information in VMS format.
+ 
+ gxcoff
+-Common Driver JoinedOrMissing Negative(gxcoff+)
+-Generate debug information in XCOFF format.
++Common Driver WarnRemoved
++Does nothing.  Preserved for backward compatibility.
+ 
+ gxcoff+
+-Common Driver JoinedOrMissing Negative(gdwarf)
+-Generate debug information in extended XCOFF format.
++Common Driver JoinedOrMissing  WarnRemoved
++Does nothing.  Preserved for backward compatibility.
+ 
+ Enum
+ Name(compressed_debug_sections) Type(int)
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 3108ac4eb..8fdde1576 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -72,10 +72,10 @@
+ #  tm_file		A list of target macro files, if different from
+ #			"$cpu_type/$cpu_type.h". Usually it's constructed
+ #			per target in a way like this:
+-#			tm_file="${tm_file} dbxelf.h elfos.h ${cpu_type.h}/elf.h"
++#			tm_file="${tm_file} elfos.h ${cpu_type.h}/elf.h"
+ #			Note that the preferred order is:
+ #			- specific target header "${cpu_type}/${cpu_type.h}"
+-#			- generic headers like dbxelf.h elfos.h, etc.
++#			- generic headers like elfos.h, etc.
+ #			- specializing target headers like ${cpu_type.h}/elf.h
+ #			This helps to keep OS specific stuff out of the CPU
+ #			defining header ${cpu_type}/${cpu_type.h}.
+@@ -969,7 +969,7 @@ case ${target} in
+ *-*-solaris2*)
+   # i?86-*-solaris2* needs to insert headers between cpu default and
+   # Solaris 2 specific ones.
+-  sol2_tm_file_head="dbxelf.h elfos.h ${cpu_type}/sysv4.h"
++  sol2_tm_file_head="elfos.h ${cpu_type}/sysv4.h"
+   sol2_tm_file_tail="${cpu_type}/sol2.h sol2.h"
+   sol2_tm_file="${sol2_tm_file_head} ${sol2_tm_file_tail}"
+   case ${target} in
+@@ -1093,7 +1093,7 @@ esac
+ 
+ case ${target} in
+ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h"
+ 	tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-elf-raw.h"
+ 	tmake_file="${tmake_file} aarch64/t-aarch64"
+ 	case $target in
+@@ -1130,19 +1130,19 @@ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
+ 	TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'`
+ 	;;
+ aarch64*-*-freebsd*)
+-	tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file}"
++	tm_file="${tm_file} elfos.h ${fbsd_tm_file}"
+ 	tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-freebsd.h"
+ 	tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-freebsd"
+ 	tm_defines="${tm_defines}  TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1"
+ 	;;
+ aarch64*-*-netbsd*)
+-	tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file}"
++	tm_file="${tm_file} elfos.h ${nbsd_tm_file}"
+ 	tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-netbsd.h"
+ 	tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-netbsd"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	;;
+ aarch64*-*-linux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h"
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h"
+ 	tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-linux.h"
+ 	tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-linux"
+ 	tm_defines="${tm_defines}  TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1"
+@@ -1198,7 +1198,7 @@ alpha*-dec-*vms*)
+ 	tmake_file="${tmake_file} alpha/t-vms alpha/t-alpha"
+ 	;;
+ arc*-*-elf*)
+-	tm_file="arc/arc-arch.h dbxelf.h elfos.h newlib-stdint.h arc/elf.h ${tm_file}"
++	tm_file="arc/arc-arch.h elfos.h newlib-stdint.h arc/elf.h ${tm_file}"
+ 	tmake_file="arc/t-multilib arc/t-arc"
+ 	extra_gcc_objs="driver-arc.o"
+ 	if test "x$with_cpu" != x; then
+@@ -1219,7 +1219,7 @@ arc*-*-elf*)
+ 	esac
+ 	;;
+ arc*-*-linux*)
+-	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}"
++	tm_file="arc/arc-arch.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}"
+ 	tmake_file="${tmake_file} arc/t-multilib-linux arc/t-arc"
+ 	extra_gcc_objs="driver-arc.o"
+ 	if test "x$with_cpu" != x; then
+@@ -1255,7 +1255,7 @@ arm-wrs-vxworks7*)
+ 	need_64bit_hwint=yes
+ 	;;
+ arm*-*-freebsd*)                # ARM FreeBSD EABI
+-	tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h"
++	tm_file="elfos.h ${fbsd_tm_file} arm/elf.h"
+ 	case $target in
+ 	arm*b-*-freebsd*)
+ 	    tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+@@ -1283,7 +1283,7 @@ arm*-*-freebsd*)                # ARM FreeBSD EABI
+ arm*-*-netbsdelf*)
+ 	target_cpu_cname="strongarm"
+ 	tmake_file="${tmake_file} arm/t-arm"
+-	tm_file="dbxelf.h elfos.h ${nbsd_tm_file} arm/elf.h"
++	tm_file="elfos.h ${nbsd_tm_file} arm/elf.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	case ${target} in
+ 	arm*eb-*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" ;;
+@@ -1312,7 +1312,7 @@ arm*-*-netbsdelf*)
+ 	esac
+ 	;;
+ arm*-*-linux-* | arm*-*-uclinuxfdpiceabi)
+-	tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h"
++	tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h"
+ 	extra_options="${extra_options} linux-android.opt"
+ 	case $target in
+ 	arm*b-*-linux*)
+@@ -1343,7 +1343,7 @@ arm*-*-linux-* | arm*-*-uclinuxfdpiceabi)
+ 	with_tls=${with_tls:-gnu}
+ 	;;
+ arm*-*-uclinux*eabi*)		# ARM ucLinux
+-	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/linux-gas.h arm/uclinux-elf.h glibc-stdint.h"
++	tm_file="elfos.h arm/unknown-elf.h arm/elf.h arm/linux-gas.h arm/uclinux-elf.h glibc-stdint.h"
+ 	tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi"
+ 	tm_file="$tm_file arm/bpabi.h arm/uclinux-eabi.h arm/aout.h arm/arm.h"
+ 	target_cpu_cname="arm7tdmi"
+@@ -1363,7 +1363,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems* | arm*-*-fuchsia*)
+ 	  tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ 	esac
+ 	default_use_cxa_atexit=yes
+-	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
++	tm_file="elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
+ 	tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf"
+ 	target_cpu_cname="arm7tdmi"
+ 	case ${target} in
+@@ -1392,7 +1392,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems* | arm*-*-fuchsia*)
+ 	tm_file="${tm_file} arm/aout.h arm/arm.h"
+ 	;;
+ avr-*-*)
+-	tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h dbxelf.h avr/avr-stdint.h"
++	tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h avr/avr-stdint.h"
+ 	if test x${with_avrlibc} != xno; then
+ 	    tm_file="${tm_file} ${cpu_type}/avrlibc.h"
+ 	    tm_defines="${tm_defines} WITH_AVRLIBC"
+@@ -1525,26 +1525,26 @@ avr-*-*)
+ 	extra_objs="avr-devices.o avr-log.o"
+ 	;;
+ bfin*-elf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h bfin/elf.h"
+ 	tmake_file=bfin/t-bfin-elf
+ 	use_collect2=no
+ 	;;
+ bfin*-uclinux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/uclinux.h"
++	tm_file="${tm_file} elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/uclinux.h"
+ 	tmake_file=bfin/t-bfin-uclinux
+ 	use_collect2=no
+ 	;;
+ bfin*-linux-uclibc*)
+-	tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/linux.h ./linux-sysroot-suffix.h"
++	tm_file="${tm_file} elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/linux.h ./linux-sysroot-suffix.h"
+ 	tmake_file="${tmake_file} bfin/t-bfin-linux"
+ 	use_collect2=no
+ 	;;
+ bfin*-rtems*)
+-	tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h bfin/rtems.h rtems.h newlib-stdint.h"
++	tm_file="${tm_file} elfos.h bfin/elf.h bfin/rtems.h rtems.h newlib-stdint.h"
+ 	tmake_file="${tmake_file} bfin/t-rtems"
+ 	;;
+ bfin*-*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h bfin/elf.h"
+ 	use_collect2=no
+ 	use_gcc_stdint=wrap
+ 	;;
+@@ -1600,13 +1600,13 @@ csky-*-*)
+ 
+ 	case ${target} in
+ 	    csky-*-elf*)
+-		tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} csky/csky-elf.h"
++		tm_file="elfos.h newlib-stdint.h ${tm_file} csky/csky-elf.h"
+ 		tmake_file="csky/t-csky csky/t-csky-elf"
+ 		default_use_cxa_atexit=no
+ 		use_gcc_stdint=wrap
+ 		;;
+ 	    csky-*-linux*)
+-		tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} csky/csky-linux-elf.h"
++		tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} csky/csky-linux-elf.h"
+ 		tmake_file="${tmake_file} csky/t-csky csky/t-csky-linux"
+ 
+ 		case ${target} in
+@@ -1633,7 +1633,7 @@ csky-*-*)
+ 	esac
+ 	;;
+ epiphany-*-elf | epiphany-*-rtems*)
+-	tm_file="dbxelf.h elfos.h ${tm_file}"
++	tm_file="elfos.h ${tm_file}"
+ 	tmake_file="${tmake_file} epiphany/t-epiphany"
+ 	case ${target} in
+ 	epiphany-*-rtems*)
+@@ -1649,21 +1649,21 @@ epiphany-*-elf | epiphany-*-rtems*)
+ 	extra_headers="epiphany_intrinsics.h"
+ 	;;
+ fr30-*-elf)
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ 	;;
+ frv-*-elf)
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ 	tmake_file=frv/t-frv
+ 	;;
+ frv-*-*linux*)
+-	tm_file="dbxelf.h elfos.h ${tm_file} \
++	tm_file="elfos.h ${tm_file} \
+ 	         gnu-user.h linux.h glibc-stdint.h frv/linux.h"
+ 	tmake_file="${tmake_file} frv/t-frv frv/t-linux"
+ 	;;
+ ft32-*-elf)
+ 	gas=yes
+ 	gnu_ld=yes
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ 	tmake_file="${tmake_file} ft32/t-ft32"
+ 	;;
+ amdgcn-*-amdhsa)
+@@ -1691,23 +1691,23 @@ amdgcn-*-amdhsa)
+ moxie-*-elf)
+ 	gas=yes
+ 	gnu_ld=yes
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ 	tmake_file="${tmake_file} moxie/t-moxie"
+ 	;;
+ moxie-*-uclinux*)
+ 	gas=yes
+ 	gnu_ld=yes
+-	tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h moxie/uclinux.h"
++	tm_file="elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h moxie/uclinux.h"
+ 	tmake_file="${tmake_file} moxie/t-moxie"
+ 	;;
+ moxie-*-rtems*)
+ 	tmake_file="${tmake_file} moxie/t-moxie"
+-	tm_file="moxie/moxie.h dbxelf.h elfos.h moxie/rtems.h rtems.h newlib-stdint.h"
++	tm_file="moxie/moxie.h elfos.h moxie/rtems.h rtems.h newlib-stdint.h"
+ 	;;
+ moxie-*-moxiebox*)
+ 	gas=yes
+ 	gnu_ld=yes
+-	tm_file="${tm_file} dbxelf.h elfos.h moxie/moxiebox.h newlib-stdint.h"
++	tm_file="${tm_file} elfos.h moxie/moxiebox.h newlib-stdint.h"
+ 	tmake_file="${tmake_file} moxie/t-moxiebox"
+ 	;;
+ h8300-*-elf*)
+@@ -1720,7 +1720,7 @@ h8300-*-linux*)
+ 	;;
+ hppa*64*-*-linux*)
+ 	target_cpu_default="MASK_PA_11|MASK_PA_20"
+-	tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h gnu-user.h linux.h \
++	tm_file="pa/pa64-start.h ${tm_file} elfos.h gnu-user.h linux.h \
+ 		 glibc-stdint.h pa/pa-linux.h pa/pa64-regs.h pa/pa-64.h \
+ 		 pa/pa64-linux.h"
+ 	tmake_file="${tmake_file} pa/t-pa pa/t-linux"
+@@ -1729,14 +1729,14 @@ hppa*64*-*-linux*)
+ 	;;
+ hppa*-*-linux*)
+ 	target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS|MASK_CALLER_COPIES"
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h pa/pa-linux.h \
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h pa/pa-linux.h \
+ 		 pa/pa32-regs.h pa/pa32-linux.h"
+ 	tmake_file="${tmake_file} pa/t-pa pa/t-linux"
+ 	d_target_objs="${d_target_objs} pa-d.o"
+ 	;;
+ hppa*-*-openbsd*)
+ 	target_cpu_default="MASK_PA_11"
+-	tm_file="${tm_file} dbxelf.h elfos.h openbsd.h openbsd-stdint.h openbsd-libpthread.h \
++	tm_file="${tm_file} elfos.h openbsd.h openbsd-stdint.h openbsd-libpthread.h \
+ 		 pa/pa-openbsd.h pa/pa32-regs.h pa/pa32-openbsd.h"
+ 	extra_options="${extra_options} openbsd.opt"
+ 	tmake_file="pa/t-pa"
+@@ -1746,7 +1746,7 @@ hppa*-*-openbsd*)
+ 	;;
+ hppa*-*-netbsd*)
+ 	target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS"
+-	tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file} \
++	tm_file="${tm_file} elfos.h ${nbsd_tm_file} \
+ 		 pa/pa-netbsd.h pa/pa32-regs.h pa/pa32-netbsd.h"
+ 	tmake_file="${tmake_file}"
+ 	tm_defines="${tm_defines} CHAR_FAST8=1 SHORT_FAST16=1"
+@@ -1794,7 +1794,7 @@ hppa*64*-*-hpux11*)
+ 	then
+ 		target_cpu_default="${target_cpu_default}|MASK_GNU_LD"
+ 	fi
+-	tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h \
++	tm_file="pa/pa64-start.h ${tm_file} elfos.h \
+ 		 pa/pa64-regs.h pa/pa-hpux.h pa/pa-hpux1010.h \
+ 		 pa/pa-hpux11.h"
+ 	case ${target} in
+@@ -1898,55 +1898,55 @@ x86_64-*-darwin*)
+ 	tm_file="${cpu_type}/darwin64-biarch.h ${tm_file} "
+ 	;;
+ i[34567]86-*-elfiamcu)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/iamcu.h"
+ 	;;
+ i[34567]86-*-elf*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h"
+ 	;;
+ x86_64-*-elf*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h"
+ 	;;
+ x86_64-*-rtems*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h"
+ 	;;
+ i[34567]86-*-rdos*)
+-    tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/rdos.h"
++    tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/rdos.h"
+     ;;
+ x86_64-*-rdos*)
+-    tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rdos.h i386/rdos64.h"
++    tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rdos.h i386/rdos64.h"
+     tmake_file="i386/t-i386elf t-svr4"
+     ;;
+ i[34567]86-*-dragonfly*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h"
+ 	tmake_file="${tmake_file} i386/t-crtstuff"
+ 	;;
+ x86_64-*-dragonfly*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h dragonfly.h dragonfly-stdint.h i386/x86-64.h i386/dragonfly.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h dragonfly.h dragonfly-stdint.h i386/x86-64.h i386/dragonfly.h"
+ 	tmake_file="${tmake_file} i386/t-crtstuff"
+ 	;;
+ i[34567]86-*-freebsd*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
+ 	;;
+ x86_64-*-freebsd*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h"
+ 	;;
+ i[34567]86-*-netbsdelf*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${nbsd_tm_file} i386/netbsd-elf.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${nbsd_tm_file} i386/netbsd-elf.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	;;
+ x86_64-*-netbsd*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${nbsd_tm_file} i386/x86-64.h i386/netbsd64.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${nbsd_tm_file} i386/x86-64.h i386/netbsd64.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	;;
+ i[34567]86-*-openbsd*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h"
+ 	tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h i386/openbsdelf.h"
+ 	extra_options="${extra_options} openbsd.opt"
+ 	gas=yes
+ 	gnu_ld=yes
+ 	;;
+ x86_64-*-openbsd*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h"
+ 	tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h i386/x86-64.h i386/openbsdelf.h"
+ 	extra_options="${extra_options} openbsd.opt"
+ 	gas=yes
+@@ -1955,7 +1955,7 @@ x86_64-*-openbsd*)
+ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
+ 			# Intel 80386's running GNU/*
+ 			# with ELF format using glibc 2
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h gnu-user.h glibc-stdint.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h gnu-user.h glibc-stdint.h"
+ 	case ${target} in
+ 	i[34567]86-*-linux*)
+ 		tm_file="${tm_file} linux.h linux-android.h"
+@@ -2012,7 +2012,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]8
+ 	esac
+ 	;;
+ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h gnu-user.h glibc-stdint.h \
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h gnu-user.h glibc-stdint.h \
+ 		 i386/x86-64.h i386/gnu-user-common.h i386/gnu-user64.h"
+ 	case ${target} in
+ 	x86_64-*-linux*)
+@@ -2050,7 +2050,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu)
+ 	;;
+ i[34567]86-pc-msdosdjgpp*)
+ 	xm_file=i386/xm-djgpp.h
+-	tm_file="dbxcoff.h ${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h i386/djgpp-stdint.h"
++	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h i386/djgpp-stdint.h"
+ 	native_system_header_dir=/dev/env/DJDIR/include
+ 	extra_options="${extra_options} i386/djgpp.opt"
+ 	gnu_ld=yes
+@@ -2059,7 +2059,7 @@ i[34567]86-pc-msdosdjgpp*)
+ 	;;
+ i[34567]86-*-lynxos*)
+ 	xm_defines=POSIX
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/lynx.h lynx.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/lynx.h lynx.h"
+ 	tmake_file="${tmake_file} t-lynx"
+ 	extra_options="${extra_options} lynx.opt"
+ 	thread_file=lynx
+@@ -2067,13 +2067,13 @@ i[34567]86-*-lynxos*)
+ 	gas=yes
+ 	;;
+ i[34567]86-*-nto-qnx*)
+-	tm_file="${tm_file} i386/att.h dbxelf.h tm-dwarf2.h elfos.h i386/unix.h i386/nto.h"
++	tm_file="${tm_file} i386/att.h tm-dwarf2.h elfos.h i386/unix.h i386/nto.h"
+ 	extra_options="${extra_options} i386/nto.opt"
+ 	gnu_ld=yes
+ 	gas=yes
+ 	;;
+ i[34567]86-*-rtems*)
+-	tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h newlib-stdint.h"
++	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h newlib-stdint.h"
+ 	tmake_file="${tmake_file} i386/t-rtems"
+ 	;;
+ i[34567]86-*-solaris2* | x86_64-*-solaris2*)
+@@ -2122,7 +2122,7 @@ i[4567]86-wrs-vxworks*|x86_64-wrs-vxworks7*)
+ 	esac
+ 	;;
+ i[34567]86-*-cygwin*)
+-	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h i386/cygwin-stdint.h"
++	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/cygming.h i386/cygwin.h i386/cygwin-stdint.h"
+ 	xm_file=i386/xm-cygwin.h
+ 	tmake_file="${tmake_file} i386/t-cygming t-slibgcc"
+ 	target_gtfiles="$target_gtfiles \$(srcdir)/config/i386/winnt.cc"
+@@ -2140,7 +2140,7 @@ i[34567]86-*-cygwin*)
+ 	;;
+ x86_64-*-cygwin*)
+ 	need_64bit_isa=yes
+-	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h i386/cygwin-w64.h i386/cygwin-stdint.h"
++	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/cygming.h i386/cygwin.h i386/cygwin-w64.h i386/cygwin-stdint.h"
+ 	xm_file=i386/xm-cygwin.h
+ 	tmake_file="${tmake_file} i386/t-cygming t-slibgcc i386/t-cygwin-w64"
+ 	target_gtfiles="$target_gtfiles \$(srcdir)/config/i386/winnt.cc"
+@@ -2158,7 +2158,7 @@ x86_64-*-cygwin*)
+ 	tm_defines="${tm_defines} TARGET_CYGWIN64=1"
+ 	;;
+ i[34567]86-*-mingw* | x86_64-*-mingw*)
+-	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h"
++	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/cygming.h"
+ 	xm_file=i386/xm-mingw32.h
+ 	c_target_objs="${c_target_objs} winnt-c.o"
+ 	cxx_target_objs="${cxx_target_objs} winnt-c.o"
+@@ -2252,7 +2252,7 @@ x86_64-*-fuchsia*)
+ 	tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h fuchsia.h"
+ 	;;
+ ia64*-*-elf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h ia64/sysv4.h ia64/elf.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h ia64/sysv4.h ia64/elf.h"
+ 	tmake_file="ia64/t-ia64"
+ 	target_cpu_default="0"
+ 	if test x$gas = xyes
+@@ -2265,17 +2265,17 @@ ia64*-*-elf*)
+ 	fi
+ 	;;
+ ia64*-*-freebsd*)
+-	tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file} ia64/sysv4.h ia64/freebsd.h"
++	tm_file="${tm_file} elfos.h ${fbsd_tm_file} ia64/sysv4.h ia64/freebsd.h"
+ 	target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
+ 	tmake_file="${tmake_file} ia64/t-ia64"
+ 	;;
+ ia64*-*-linux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ia64/sysv4.h ia64/linux.h"
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h ia64/sysv4.h ia64/linux.h"
+ 	tmake_file="${tmake_file} ia64/t-ia64 ia64/t-linux t-libunwind"
+ 	target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
+ 	;;
+ ia64*-*-hpux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h ia64/sysv4.h ia64/hpux.h"
++	tm_file="${tm_file} elfos.h ia64/sysv4.h ia64/hpux.h"
+ 	tmake_file="ia64/t-ia64 ia64/t-hpux t-slibgcc"
+ 	target_cpu_default="MASK_GNU_AS"
+ 	case x$enable_threads in
+@@ -2311,16 +2311,16 @@ iq2000*-*-elf*)
+         md_file=iq2000/iq2000.md
+         ;;
+ lm32-*-elf*)
+-        tm_file="dbxelf.h elfos.h ${tm_file} newlib-stdint.h"
++        tm_file="elfos.h ${tm_file} newlib-stdint.h"
+ 	tmake_file="${tmake_file} lm32/t-lm32"
+         ;;
+ lm32-*-rtems*)
+-	tm_file="dbxelf.h elfos.h ${tm_file} lm32/rtems.h rtems.h newlib-stdint.h"
++	tm_file="elfos.h ${tm_file} lm32/rtems.h rtems.h newlib-stdint.h"
+ 	tmake_file="${tmake_file} lm32/t-lm32"
+ 	tmake_file="${tmake_file} lm32/t-rtems"
+          ;;
+ lm32-*-uclinux*)
+-        tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h lm32/uclinux-elf.h"
++        tm_file="elfos.h ${tm_file} gnu-user.h linux.h lm32/uclinux-elf.h"
+ 	tmake_file="${tmake_file} lm32/t-lm32"
+         ;;
+ m32r-*-elf*)
+@@ -2348,7 +2348,7 @@ m68k-*-elf* | fido-*-elf*)
+ 		default_cf_cpu=5206
+ 		;;
+ 	esac
+-	tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h"
++	tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h"
+ 	tm_defines="${tm_defines} MOTOROLA=1"
+ 	tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf"
+ 	# Add multilibs for targets other than fido.
+@@ -2363,7 +2363,7 @@ m68k-*-elf* | fido-*-elf*)
+ m68k*-*-netbsdelf*)
+ 	default_m68k_cpu=68020
+ 	default_cf_cpu=5475
+-	tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file} m68k/netbsd-elf.h"
++	tm_file="${tm_file} elfos.h ${nbsd_tm_file} m68k/netbsd-elf.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	tm_defines="${tm_defines} MOTOROLA=1 CHAR_FAST8=1 SHORT_FAST16=1"
+ 	;;
+@@ -2372,7 +2372,7 @@ m68k-*-uclinux*)		# Motorola m68k/ColdFire running uClinux
+ 				# ABI.
+ 	default_m68k_cpu=68020
+ 	default_cf_cpu=5206
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h flat.h m68k/linux.h m68k/uclinux.h ./sysroot-suffix.h"
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h flat.h m68k/linux.h m68k/uclinux.h ./sysroot-suffix.h"
+ 	extra_options="${extra_options} m68k/uclinux.opt"
+  	tm_defines="${tm_defines} MOTOROLA=1"
+ 	tmake_file="m68k/t-floatlib m68k/t-uclinux m68k/t-mlibs"
+@@ -2383,7 +2383,7 @@ m68k-*-linux*)			# Motorola m68k's running GNU/Linux
+ 	default_m68k_cpu=68020
+ 	default_cf_cpu=5475
+ 	with_arch=${with_arch:-m68k}
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h m68k/linux.h ./sysroot-suffix.h"
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h m68k/linux.h ./sysroot-suffix.h"
+ 	extra_options="${extra_options} m68k/ieee.opt"
+ 	tm_defines="${tm_defines} MOTOROLA=1"
+ 	tmake_file="${tmake_file} m68k/t-floatlib m68k/t-linux m68k/t-mlibs"
+@@ -2392,11 +2392,11 @@ m68k-*-rtems*)
+ 	default_m68k_cpu=68020
+ 	default_cf_cpu=5206
+ 	tmake_file="${tmake_file} m68k/t-floatlib m68k/t-m68kbare m68k/t-crtstuff m68k/t-rtems m68k/t-mlibs"
+-	tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/m68kemb.h m68k/m68020-elf.h m68k/rtemself.h rtems.h newlib-stdint.h"
++	tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h elfos.h m68k/m68kemb.h m68k/m68020-elf.h m68k/rtemself.h rtems.h newlib-stdint.h"
+ 	tm_defines="${tm_defines} MOTOROLA=1"
+ 	;;
+ mcore-*-elf)
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} mcore/mcore-elf.h"
++	tm_file="elfos.h newlib-stdint.h ${tm_file} mcore/mcore-elf.h"
+ 	tmake_file=mcore/t-mcore
+ 	inhibit_libc=true
+ 	;;
+@@ -2409,7 +2409,7 @@ microblaze*-linux*)
+ 			tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321"
+ 			;;
+ 	esac
+-	tm_file="${tm_file} dbxelf.h gnu-user.h linux.h microblaze/linux.h"
++	tm_file="${tm_file} gnu-user.h linux.h microblaze/linux.h"
+ 	tm_file="${tm_file} glibc-stdint.h"
+ 	c_target_objs="${c_target_objs} microblaze-c.o"
+ 	cxx_target_objs="${cxx_target_objs} microblaze-c.o"
+@@ -2425,7 +2425,7 @@ microblaze*-*-rtems*)
+ 			tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321"
+ 			;;
+ 	esac
+-	tm_file="${tm_file} dbxelf.h"
++	tm_file="${tm_file}"
+ 	tm_file="${tm_file} microblaze/rtems.h rtems.h newlib-stdint.h"
+ 	c_target_objs="${c_target_objs} microblaze-c.o"
+ 	cxx_target_objs="${cxx_target_objs} microblaze-c.o"
+@@ -2441,7 +2441,7 @@ microblaze*-*-elf)
+ 			tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321"
+ 			;;
+ 	esac
+-	tm_file="${tm_file} dbxelf.h newlib-stdint.h"
++	tm_file="${tm_file} newlib-stdint.h"
+ 	c_target_objs="${c_target_objs} microblaze-c.o"
+ 	cxx_target_objs="${cxx_target_objs} microblaze-c.o"
+ 	tmake_file="${tmake_file} microblaze/t-microblaze"
+@@ -2509,7 +2509,7 @@ riscv*-*-freebsd*)
+ 	;;
+ 
+ loongarch*-*-linux*)
+-	tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}"
++	tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}"
+ 	tm_file="${tm_file} loongarch/gnu-user.h loongarch/linux.h"
+ 	extra_options="${extra_options} linux-android.opt"
+ 	tmake_file="${tmake_file} loongarch/t-linux"
+@@ -2527,7 +2527,7 @@ mips*-*-netbsd*)			# NetBSD/mips, either endian.
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	;;
+ 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"
++	tm_file="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=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32"
+@@ -2537,7 +2537,7 @@ mips*-img-linux*)
+ 	gas=yes
+ 	;;
+ 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"
++	tm_file="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=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32"
+@@ -2547,7 +2547,7 @@ mips*-mti-linux*)
+ 	gas=yes
+ 	;;
+ mips*-*-linux*)				# Linux MIPS, either endian.
+-	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"
++	tm_file="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"
+ 	extra_options="${extra_options} linux-android.opt"
+ 	case ${target} in
+ 		mipsisa32r6*)
+@@ -2759,7 +2759,7 @@ mn10300-*-*)
+ 	use_gcc_stdint=wrap
+ 	;;
+ msp430-*-*)
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ 	c_target_objs="msp430-c.o"
+ 	cxx_target_objs="msp430-c.o"
+ 	tmake_file="${tmake_file} msp430/t-msp430"
+@@ -2797,11 +2797,11 @@ nds32*-*-*)
+ 	esac
+ 	case ${target} in
+ 	  nds32*-*-elf*)
+-	    tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/elf.h nds32/nds32_intrinsic.h"
++	    tm_file="elfos.h newlib-stdint.h ${tm_file} nds32/elf.h nds32/nds32_intrinsic.h"
+ 	    tmake_file="nds32/t-nds32 nds32/t-elf"
+ 	    ;;
+ 	  nds32*-*-linux*)
+-	    tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h nds32/linux.h nds32/nds32_intrinsic.h"
++	    tm_file="elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h nds32/linux.h nds32/nds32_intrinsic.h"
+ 	    tmake_file="${tmake_file} nds32/t-nds32 nds32/t-linux"
+ 	    gcc_cv_initfini_array=yes
+ 	    ;;
+@@ -2922,7 +2922,7 @@ powerpc64-*-darwin*)
+ 	tm_file="${tm_file} ${cpu_type}/darwin64-biarch.h"
+ 	;;
+ powerpc*-*-freebsd*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h ${fbsd_tm_file} rs6000/sysv4.h"
++	tm_file="${tm_file} elfos.h gnu-user.h ${fbsd_tm_file} rs6000/sysv4.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
+ 	case ${target} in
+@@ -2947,47 +2947,47 @@ powerpc*-*-freebsd*)
+ 	esac
+ 	;;
+ powerpc-*-netbsd*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h ${nbsd_tm_file} freebsd-spec.h rs6000/sysv4.h rs6000/netbsd.h"
++	tm_file="${tm_file} elfos.h gnu-user.h ${nbsd_tm_file} freebsd-spec.h rs6000/sysv4.h rs6000/netbsd.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	tmake_file="${tmake_file} rs6000/t-netbsd"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	;;
+ powerpc-*-eabisimaltivec*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h rs6000/eabialtivec.h"
++	tm_file="${tm_file} elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h rs6000/eabialtivec.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcendian rs6000/t-ppccomm"
+ 	use_gcc_stdint=wrap
+ 	;;
+ powerpc-*-eabisim*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h"
++	tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ 	use_gcc_stdint=wrap
+ 	;;
+ powerpc-*-elf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h"
++	tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ 	;;
+ powerpc-*-eabialtivec*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabialtivec.h"
++	tm_file="${tm_file} elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabialtivec.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcendian rs6000/t-ppccomm"
+ 	use_gcc_stdint=wrap
+ 	;;
+ powerpc-*-eabi*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h"
++	tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ 	use_gcc_stdint=wrap
+ 	;;
+ powerpc-*-rtems*)
+-	tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h"
++	tm_file="rs6000/biarch64.h ${tm_file} elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt rs6000/linux64.opt"
+ 	tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-rtems rs6000/t-ppccomm"
+ 	;;
+ powerpc*-*-linux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h freebsd-spec.h rs6000/sysv4.h"
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h freebsd-spec.h rs6000/sysv4.h"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-ppccomm"
+ 	extra_objs="$extra_objs rs6000-linux.o"
+@@ -3094,7 +3094,7 @@ powerpc-wrs-vxworks*)
+ 	;;
+ powerpc-*-lynxos*)
+ 	xm_defines=POSIX
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h rs6000/sysv4.h rs6000/lynx.h lynx.h"
++	tm_file="${tm_file} elfos.h gnu-user.h rs6000/sysv4.h rs6000/lynx.h lynx.h"
+ 	tmake_file="t-lynx rs6000/t-lynx"
+ 	extra_options="${extra_options} rs6000/sysv4.opt lynx.opt"
+ 	thread_file=lynx
+@@ -3102,18 +3102,18 @@ powerpc-*-lynxos*)
+ 	gas=yes
+ 	;;
+ powerpcle-*-elf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h"
++	tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	;;
+ powerpcle-*-eabisim*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h rs6000/eabisim.h"
++	tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h rs6000/eabisim.h"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	use_gcc_stdint=wrap
+ 	;;
+ powerpcle-*-eabi*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h"
++	tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h"
+ 	tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ 	extra_options="${extra_options} rs6000/sysv4.opt"
+ 	use_gcc_stdint=wrap
+@@ -3171,7 +3171,7 @@ rl78-*-elf*)
+ 	tmake_file="${tmake_file} rl78/t-rl78"
+ 	;;
+ rx-*-elf*)
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ 	tmake_file="${tmake_file} rx/t-rx"
+ 	extra_options="${extra_options} rx/elf.opt"
+ 	;;
+@@ -3180,7 +3180,7 @@ rx-*-linux*)
+ 	tmake_file="${tmake_file} rx/t-linux"
+ 	;;
+ s390-*-linux*)
+-	tm_file="s390/s390.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h"
++	tm_file="s390/s390.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h"
+ 	c_target_objs="${c_target_objs} s390-c.o"
+ 	cxx_target_objs="${cxx_target_objs} s390-c.o"
+ 	if test x$enable_targets = xall; then
+@@ -3189,7 +3189,7 @@ s390-*-linux*)
+ 	tmake_file="${tmake_file} s390/t-s390"
+ 	;;
+ s390x-*-linux*)
+-	tm_file="s390/s390x.h s390/s390.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h"
++	tm_file="s390/s390x.h s390/s390.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h"
+ 	tm_p_file="linux-protos.h s390/s390-protos.h"
+ 	c_target_objs="${c_target_objs} s390-c.o"
+ 	cxx_target_objs="${cxx_target_objs} s390-c.o"
+@@ -3199,7 +3199,7 @@ s390x-*-linux*)
+ 	tmake_file="${tmake_file} s390/t-linux64 s390/t-s390"
+ 	;;
+ s390x-ibm-tpf*)
+-	tm_file="s390/s390x.h s390/s390.h dbxelf.h elfos.h glibc-stdint.h s390/tpf.h"
++	tm_file="s390/s390x.h s390/s390.h elfos.h glibc-stdint.h s390/tpf.h"
+ 	tm_p_file=s390/s390-protos.h
+ 	c_target_objs="${c_target_objs} s390-c.o"
+ 	cxx_target_objs="${cxx_target_objs} s390-c.o"
+@@ -3238,7 +3238,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ 	case ${with_endian} in
+ 	little*)	tm_file="sh/little.h ${tm_file}" ;;
+ 	esac
+-	tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h"
++	tm_file="${tm_file} elfos.h sh/elf.h"
+ 	case ${target} in
+ 	sh*-*-linux*)	tmake_file="${tmake_file} sh/t-linux"
+ 			if test x$enable_fdpic = xyes; then
+@@ -3359,14 +3359,14 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
+ 	;;
+ sh-*-rtems*)
+ 	tmake_file="${tmake_file} sh/t-sh sh/t-rtems"
+-	tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h newlib-stdint.h"
++	tm_file="${tm_file} elfos.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h newlib-stdint.h"
+ 	;;
+ sh-wrs-vxworks)
+ 	tmake_file="$tmake_file sh/t-sh sh/t-vxworks"
+ 	tm_file="${tm_file} elfos.h sh/elf.h sh/embed-elf.h vx-common.h vxworks.h sh/vxworks.h"
+ 	;;
+ sparc-*-elf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp-elf.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp-elf.h"
+ 	case ${target} in
+ 	    *-leon-*)
+ 		tmake_file="sparc/t-sparc sparc/t-leon"
+@@ -3380,11 +3380,11 @@ sparc-*-elf*)
+ 	esac
+ 	;;
+ sparc-*-rtems*)
+-	tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h"
++	tm_file="${tm_file} elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h"
+ 	tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems"
+ 	;;
+ sparc-*-linux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h"
++	tm_file="${tm_file} elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h"
+ 	extra_options="${extra_options} sparc/long-double-switch.opt"
+ 	case ${target} in
+ 	    *-leon-*)
+@@ -3406,7 +3406,7 @@ sparc-*-linux*)
+ 	fi
+ 	;;
+ sparc-*-netbsdelf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h"
++	tm_file="${tm_file} elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	extra_options="${extra_options} sparc/long-double-switch.opt"
+ 	tmake_file="${tmake_file} sparc/t-sparc"
+@@ -3428,22 +3428,22 @@ sparc-wrs-vxworks)
+ 	tmake_file="${tmake_file} sparc/t-sparc sparc/t-vxworks"
+ 	;;
+ sparc64-*-elf*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h"
+ 	extra_options="${extra_options}"
+ 	tmake_file="${tmake_file} sparc/t-sparc"
+ 	;;
+ sparc64-*-rtems*)
+-	tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h sparc/rtemself.h rtems.h"
++	tm_file="${tm_file} elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h sparc/rtemself.h rtems.h"
+ 	extra_options="${extra_options}"
+ 	tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems-64"
+ 	;;
+ sparc64-*-linux*)
+-	tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default64.h sparc/linux64.h sparc/tso.h"
++	tm_file="sparc/biarch64.h ${tm_file} elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default64.h sparc/linux64.h sparc/tso.h"
+ 	extra_options="${extra_options} sparc/long-double-switch.opt"
+ 	tmake_file="${tmake_file} sparc/t-sparc sparc/t-linux64"
+ 	;;
+ sparc64-*-freebsd*|ultrasparc-*-freebsd*)
+-	tm_file="${tm_file} ${fbsd_tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/freebsd.h"
++	tm_file="${tm_file} ${fbsd_tm_file} elfos.h sparc/sysv4.h sparc/freebsd.h"
+ 	extra_options="${extra_options} sparc/long-double-switch.opt"
+ 	case "x$with_cpu" in
+ 		xultrasparc) ;;
+@@ -3454,13 +3454,13 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*)
+ 	;;
+ sparc64-*-netbsd*)
+ 	tm_file="sparc/biarch64.h ${tm_file}"
+-	tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h"
++	tm_file="${tm_file} elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h"
+ 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ 	extra_options="${extra_options} sparc/long-double-switch.opt"
+ 	tmake_file="${tmake_file} sparc/t-sparc sparc/t-netbsd64"
+ 	;;
+ sparc64-*-openbsd*)
+-	tm_file="sparc/openbsd1-64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp64-elf.h"
++	tm_file="sparc/openbsd1-64.h ${tm_file} elfos.h sparc/sysv4.h sparc/sp64-elf.h"
+ 	tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h sparc/openbsd64.h"
+ 	extra_options="${extra_options} openbsd.opt"
+ 	extra_options="${extra_options}"
+@@ -3470,13 +3470,13 @@ sparc64-*-openbsd*)
+ 	;;
+ tic6x-*-elf)
+ 	tm_file="elfos.h ${tm_file} c6x/elf-common.h c6x/elf.h"
+-	tm_file="${tm_file} dbxelf.h tm-dwarf2.h newlib-stdint.h"
++	tm_file="${tm_file} tm-dwarf2.h newlib-stdint.h"
+ 	tmake_file="c6x/t-c6x c6x/t-c6x-elf"
+ 	use_collect2=no
+ 	;;
+ tic6x-*-uclinux)
+ 	tm_file="elfos.h ${tm_file} gnu-user.h linux.h c6x/elf-common.h c6x/uclinux-elf.h"
+-	tm_file="${tm_file} dbxelf.h tm-dwarf2.h glibc-stdint.h"
++	tm_file="${tm_file} tm-dwarf2.h glibc-stdint.h"
+ 	tm_file="${tm_file} ./sysroot-suffix.h"
+ 	tmake_file="t-sysroot-suffix t-slibgcc"
+ 	tmake_file="${tmake_file} c6x/t-c6x c6x/t-c6x-elf c6x/t-c6x-uclinux"
+@@ -3541,7 +3541,7 @@ v850*-*-*)
+ 	use_gcc_stdint=wrap
+ 	;;
+ vax-*-linux*)
+-	tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h vax/elf.h vax/linux.h"
++	tm_file="${tm_file} elfos.h gnu-user.h linux.h vax/elf.h vax/linux.h"
+ 	extra_options="${extra_options} vax/elf.opt"
+ 	;;
+ vax-*-netbsdelf*)
+@@ -3550,12 +3550,12 @@ vax-*-netbsdelf*)
+ 	tm_defines="${tm_defines} CHAR_FAST8=1 SHORT_FAST16=1"
+ 	;;
+ visium-*-elf*)
+-	tm_file="dbxelf.h elfos.h ${tm_file} visium/elf.h newlib-stdint.h"
++	tm_file="elfos.h ${tm_file} visium/elf.h newlib-stdint.h"
+ 	tmake_file="visium/t-visium visium/t-crtstuff"
+ 	;;
+ xstormy16-*-elf)
+ 	# For historical reasons, the target files omit the 'x'.
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h stormy16/stormy16.h"
++	tm_file="elfos.h newlib-stdint.h stormy16/stormy16.h"
+ 	tm_p_file=stormy16/stormy16-protos.h
+ 	md_file=stormy16/stormy16.md
+ 	out_file=stormy16/stormy16.cc
+diff --git a/gcc/config.in b/gcc/config.in
+index 6bb25b25b..91328572b 100644
+--- a/gcc/config.in
++++ b/gcc/config.in
+@@ -453,12 +453,6 @@
+ #endif
+ 
+ 
+-/* Define if your assembler supports the --gstabs option. */
+-#ifndef USED_FOR_TARGET
+-#undef HAVE_AS_GSTABS_DEBUG_FLAG
+-#endif
+-
+-
+ /* Define if your assembler supports the Sun syntax for cmov. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_AS_IX86_CMOV_SUN_SYNTAX
+@@ -747,12 +741,6 @@
+ #endif
+ 
+ 
+-/* Define if your assembler supports .stabs. */
+-#ifndef USED_FOR_TARGET
+-#undef HAVE_AS_STABS_DIRECTIVE
+-#endif
+-
+-
+ /* Define if your assembler and linker support thread-local storage. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_AS_TLS
+@@ -2178,13 +2166,6 @@
+ #endif
+ 
+ 
+-/* Define if your assembler supports AIX debug frame section label reference.
+-   */
+-#ifndef USED_FOR_TARGET
+-#undef HAVE_XCOFF_DWARF_EXTRAS
+-#endif
+-
+-
+ /* Define if you have a working  header file. */
+ #ifndef USED_FOR_TARGET
+ #undef HAVE_ZSTD_H
+diff --git a/gcc/config/aarch64/aarch64-elf.h b/gcc/config/aarch64/aarch64-elf.h
+index 410a40b51..8e05b1f1c 100644
+--- a/gcc/config/aarch64/aarch64-elf.h
++++ b/gcc/config/aarch64/aarch64-elf.h
+@@ -144,7 +144,4 @@ ASM_MABI_SPEC
+ #undef TYPE_OPERAND_FMT
+ #define TYPE_OPERAND_FMT	"%%%s"
+ 
+-/* Stabs debug not required.  */
+-#undef DBX_DEBUGGING_INFO
+-
+ #endif /* GCC_AARCH64_ELF_H */
+diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
+index 0a85e66fa..66c17149d 100644
+--- a/gcc/config/alpha/alpha.cc
++++ b/gcc/config/alpha/alpha.cc
+@@ -8458,10 +8458,6 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ }
+ #endif /* TARGET_ABI_OSF */
+ 
+-/* Debugging support.  */
+-
+-#include "gstab.h"
+-
+ /* Name of the file containing the current function.  */
+ 
+ static const char *current_function_file = "";
+diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h
+index 4447a7f24..c9cd42e69 100644
+--- a/gcc/config/alpha/elf.h
++++ b/gcc/config/alpha/elf.h
+@@ -22,7 +22,7 @@ along with GCC; see the file COPYING3.  If not see
+ #define CC1_SPEC  "%{G*}"
+ 
+ #undef  ASM_SPEC
+-#define ASM_SPEC  "%{G*} %{relax:-relax} %{!gstabs*:-no-mdebug}%{gstabs*:-mdebug} %{mcpu=*:-m%*}"
++#define ASM_SPEC  "%{G*} %{relax:-relax} %{mcpu=*:-m%*}"
+ 
+ /* Do not output a .file directive at the beginning of the input file.  */
+  
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 539a16620..0cb560b8a 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1330,12 +1330,7 @@ do { \
+ 
+ /* Debugging information.  */
+ 
+-/* Generate DBX and DWARF debugging information.  */
+-#ifdef DBX_DEBUGGING_INFO
+-#undef DBX_DEBUGGING_INFO
+-#endif
+-#define DBX_DEBUGGING_INFO
+-
++/* Generate DWARF debugging information.  */
+ #ifdef DWARF2_DEBUGGING_INFO
+ #undef DWARF2_DEBUGGING_INFO
+ #endif
+@@ -1385,9 +1380,6 @@ do { \
+ 
+ #define EH_RETURN_STACKADJ_RTX   gen_rtx_REG (Pmode, 2)
+ 
+-/* Turn off splitting of long stabs.  */
+-#define DBX_CONTIN_LENGTH 0
+-
+ /* Miscellaneous.  */
+ 
+ /* Specify the machine mode that this machine uses
+diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
+index b918ad378..cfb8db52c 100644
+--- a/gcc/config/arm/aout.h
++++ b/gcc/config/arm/aout.h
+@@ -145,15 +145,6 @@
+ #define NO_DOLLAR_IN_LABEL 1
+ #endif
+ 
+-/* Generate DBX debugging information.  riscix.h will undefine this because
+-   the native assembler does not support stabs.  */
+-#define DBX_DEBUGGING_INFO 1
+-
+-/* Acorn dbx moans about continuation chars, so don't use any.  */
+-#ifndef DBX_CONTIN_LENGTH
+-#define DBX_CONTIN_LENGTH  0
+-#endif
+-
+ /* Output a function label definition.  */
+ #ifndef ASM_DECLARE_FUNCTION_NAME
+ #define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL)	\
+diff --git a/gcc/config/arm/netbsd-elf.h b/gcc/config/arm/netbsd-elf.h
+index d239c734c..ef1bba280 100644
+--- a/gcc/config/arm/netbsd-elf.h
++++ b/gcc/config/arm/netbsd-elf.h
+@@ -85,9 +85,6 @@
+ #undef PTRDIFF_TYPE
+ #define PTRDIFF_TYPE "long int"
+ 
+-/* We don't have any limit on the length as out debugger is GDB.  */
+-#undef DBX_CONTIN_LENGTH
+-
+ /* NetBSD does its profiling differently to the Acorn compiler. We
+    don't need a word following the mcount call; and to skip it
+    requires either an assembly stub or use of fomit-frame-pointer when
+diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
+index 51e257dc6..0485b6b45 100644
+--- a/gcc/config/darwin.h
++++ b/gcc/config/darwin.h
+@@ -396,10 +396,10 @@ extern GTY(()) int darwin_ms_struct;
+ 
+ #define DSYMUTIL_SPEC \
+   "%{!c:%{!E:%{!S:%{!r:%{!M:%{!MM:%{!fsyntax-only:%{!fdump=*:\
+-     %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -idsym \
++     %{g*:%{!gctf:%{!gbtf:%{%: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
+@@ -594,14 +594,7 @@ extern GTY(()) int darwin_ms_struct;
+ "%{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
+-   dwarf is not uniformly supported in the assemblers.  */
+-#define ASM_DEBUG_SPEC  "%{g*:%{%:debug-level-gt(0):%{!gdwarf*:--gstabs}}}"
+-#else
+ #define ASM_DEBUG_SPEC  ""
+-#endif
+-
+ #undef  ASM_DEBUG_OPTION_SPEC
+ #define ASM_DEBUG_OPTION_SPEC	""
+ 
+@@ -615,10 +608,6 @@ ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC
+ #define DWARF2_DEBUGGING_INFO 1
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+-#ifdef HAVE_AS_STABS_DIRECTIVE
+-#define DBX_DEBUGGING_INFO 1
+-#endif
+-
+ #define DEBUG_FRAME_SECTION	  "__DWARF,__debug_frame,regular,debug"
+ #define DEBUG_INFO_SECTION	  "__DWARF,__debug_info,regular,debug"
+ #define DEBUG_ABBREV_SECTION	  "__DWARF,__debug_abbrev,regular,debug"
+@@ -650,18 +639,6 @@ ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC
+                                ? "__DWARF,__debug_gnu_pubt,regular,debug" \
+                                : "__DWARF,__debug_pubtypes,regular,debug")
+ 
+-/* When generating stabs debugging, use N_BINCL entries.  */
+-
+-#define DBX_USE_BINCL
+-
+-/* There is no limit to the length of stabs strings.  */
+-
+-#define DBX_CONTIN_LENGTH 0
+-
+-/* gdb needs a null N_SO at the end of each file for scattered loading.  */
+-
+-#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-
+ /* GCC's definition of 'one_only' is the same as its definition of 'weak'.  */
+ #define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+ 
+diff --git a/gcc/config/dbxcoff.h b/gcc/config/dbxcoff.h
+deleted file mode 100644
+index 02b78c6bf..000000000
+--- a/gcc/config/dbxcoff.h
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/* Definitions needed when using stabs embedded in COFF sections.
+-   Copyright (C) 1996-2022 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
+-.  */
+-
+-/* This file may be included by any COFF target which wishes to
+-   support -gstabs generating stabs in sections, as produced by gas
+-   and understood by gdb.  */
+-
+-/* Output DBX (stabs) debugging information if doing -gstabs.  */
+-
+-#define DBX_DEBUGGING_INFO 1
+-
+-/* Be function-relative for block and source line stab directives.  */
+-
+-#define DBX_BLOCKS_FUNCTION_RELATIVE 1
+-
+-/* but, to make this work, functions must appear prior to line info.  */
+-
+-#define DBX_FUNCTION_FIRST
+-
+-/* Generate a blank trailing N_SO to mark the end of the .o file, since
+-   we can't depend upon the linker to mark .o file boundaries with
+-   embedded stabs.  */
+-
+-#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-
+-/* Like block addresses, stabs line numbers are relative to the
+-   current function.  */
+-
+-#define DBX_LINES_FUNCTION_RELATIVE 1
+-
+-/* When generating stabs debugging, use N_BINCL entries.  */
+-
+-#undef DBX_USE_BINCL
+-#define DBX_USE_BINCL
+-
+-/* There is no limit to the length of stabs strings.  */
+-
+-#ifndef DBX_CONTIN_LENGTH
+-#define DBX_CONTIN_LENGTH 0
+-#endif
+diff --git a/gcc/config/dbxelf.h b/gcc/config/dbxelf.h
+deleted file mode 100644
+index 4b90e95bc..000000000
+--- a/gcc/config/dbxelf.h
++++ /dev/null
+@@ -1,68 +0,0 @@
+-/* Definitions needed when using stabs embedded in ELF sections.
+-   Copyright (C) 1999-2022 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
+-.  */
+-
+-/* This file may be included by any ELF target which wishes to
+-   support -gstabs generating stabs in sections, as produced by gas
+-   and understood by gdb.  */
+-
+-#ifndef GCC_DBX_ELF_H
+-#define GCC_DBX_ELF_H
+-
+-/* Output DBX (stabs) debugging information if doing -gstabs.  */
+-
+-#define DBX_DEBUGGING_INFO 1
+-
+-/* Make LBRAC and RBRAC addresses relative to the start of the
+-   function.  The native Solaris stabs debugging format works this
+-   way, gdb expects it, and it reduces the number of relocation
+-   entries...  */
+-
+-#define DBX_BLOCKS_FUNCTION_RELATIVE 1
+-
+-/* ... but, to make this work, functions must appear prior to line info.  */
+-
+-#define DBX_FUNCTION_FIRST
+-
+-/* When generating stabs debugging, use N_BINCL entries.  */
+-
+-#define DBX_USE_BINCL
+-
+-/* There is no limit to the length of stabs strings.  */
+-
+-#ifndef DBX_CONTIN_LENGTH
+-#define DBX_CONTIN_LENGTH 0
+-#endif
+-
+-/* Like block addresses, stabs line numbers are relative to the
+-   current function.  */
+-
+-#define DBX_LINES_FUNCTION_RELATIVE 1
+-
+-/* Generate a blank trailing N_SO to mark the end of the .o file, since
+-   we can't depend upon the linker to mark .o file boundaries with
+-   embedded stabs.  */
+-
+-#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-
+-#endif /* ! GCC_DBX_ELF_H */
+diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h
+index 8c723845a..7c6a7f33d 100644
+--- a/gcc/config/epiphany/epiphany.h
++++ b/gcc/config/epiphany/epiphany.h
+@@ -795,14 +795,9 @@ do \
+ 
+ /* Debugging information.  */
+ 
+-/* Generate DBX and DWARF debugging information.  */
+-#define DBX_DEBUGGING_INFO 1
+-
++/* Generate DWARF debugging information.  */
+ #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/i386/bsd.h b/gcc/config/i386/bsd.h
+index d19ad2773..98d2810e9 100644
+--- a/gcc/config/i386/bsd.h
++++ b/gcc/config/i386/bsd.h
+@@ -91,9 +91,3 @@ along with GCC; see the file COPYING3.  If not see
+ /* The prefix to add to user-visible assembler symbols.  */
+ 
+ #define USER_LABEL_PREFIX "_"
+-
+-/* Sequent has some changes in the format of DBX symbols.  */
+-#define DBX_NO_XREFS 1
+-
+-/* Don't split DBX symbols into continuations.  */
+-#define DBX_CONTIN_LENGTH 0
+diff --git a/gcc/config/i386/gas.h b/gcc/config/i386/gas.h
+index 3bac8eb68..e0ffc75dc 100644
+--- a/gcc/config/i386/gas.h
++++ b/gcc/config/i386/gas.h
+@@ -36,10 +36,6 @@ along with GCC; see the file COPYING3.  If not see
+  * people who want both form will have to compile twice.
+  */
+ 
+-/* these come from i386/bsd.h, but are specific to sequent */
+-#undef DBX_NO_XREFS
+-#undef DBX_CONTIN_LENGTH
+-
+ /* Output #ident as a .ident.  */
+ 
+ #undef TARGET_ASM_OUTPUT_IDENT
+diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
+index bd0ef35e9..69646625e 100644
+--- a/gcc/config/ia64/ia64.h
++++ b/gcc/config/ia64/ia64.h
+@@ -1426,8 +1426,6 @@ do {									\
+ 
+ /* Specific Options for DBX Output.  */
+ 
+-/* This is handled by dbxelf.h.  */
+-
+ 
+ /* Open ended Hooks for DBX Output.  */
+ 
+diff --git a/gcc/config/ia64/sysv4.h b/gcc/config/ia64/sysv4.h
+index 045752af0..046c51101 100644
+--- a/gcc/config/ia64/sysv4.h
++++ b/gcc/config/ia64/sysv4.h
+@@ -30,9 +30,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ #undef PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+-/* Stabs does not work properly for 64-bit targets.  */
+-#undef DBX_DEBUGGING_INFO
+-
+ /* Various pseudo-ops for which the Intel assembler uses non-standard
+    definitions.  */
+ 
+diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h
+index 05661bf35..0c66c91f8 100644
+--- a/gcc/config/m68k/linux.h
++++ b/gcc/config/m68k/linux.h
+@@ -146,10 +146,6 @@ along with GCC; see the file COPYING3.  If not see
+     fprintf (FILE, "\tjbsr _mcount\n");					\
+ }
+ 
+-/* Do not break .stabs pseudos into continuations.  */
+-
+-#define DBX_CONTIN_LENGTH 0
+-
+ /* 1 if N is a possible register number for a function value.  For
+    m68k/SVR4 allow d0, a0, or fp0 as return registers, for integral,
+    pointer, or floating types, respectively.  Reject fp0 if not using
+diff --git a/gcc/config/m68k/openbsd.h b/gcc/config/m68k/openbsd.h
+index 63c57fdcc..ab998177d 100644
+--- a/gcc/config/m68k/openbsd.h
++++ b/gcc/config/m68k/openbsd.h
+@@ -60,18 +60,6 @@ along with GCC; see the file COPYING3.  If not see
+ /* Every structure or union's size must be a multiple of 2 bytes.  */
+ #define STRUCTURE_SIZE_BOUNDARY 16
+ 
+-/* Specific options for DBX Output.  */
+-
+-/* This is BSD, so it wants DBX format.  */
+-#define DBX_DEBUGGING_INFO 1
+-
+-/* Do not break .stabs pseudos into continuations.  */
+-#define DBX_CONTIN_LENGTH 0
+-
+-/* This is the char to use for continuation (in case we need to turn
+-   continuation back on).  */
+-#define DBX_CONTIN_CHAR '?'
+-
+ /* Stack & calling: aggregate returns.  */
+ 
+ /* ??? This is traditional, but quite possibly wrong.  It appears to
+diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
+index e64928f41..02d11ddbf 100644
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -445,7 +445,6 @@ int num_source_filenames;
+ const char *current_function_file = "";
+ 
+ /* Arrays that map GCC register numbers to debugger register numbers.  */
+-int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
+ int mips_dwarf_regno[FIRST_PSEUDO_REGISTER];
+ 
+ /* Information about the current function's epilogue, used only while
+@@ -9595,10 +9594,6 @@ mips_output_filename (FILE *stream, const char *name)
+       output_quoted_string (stream, name);
+       putc ('\n', stream);
+     }
+-  /* If we are emitting stabs, let dbxout.cc handle this (except for
+-     the mips_output_filename_first_time case).  */
+-  else if (write_symbols == DBX_DEBUG)
+-    return;
+   else if (name != current_function_file
+ 	   && strcmp (name, current_function_file) != 0)
+     {
+@@ -20505,24 +20500,13 @@ mips_option_override (void)
+ 
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     {
+-      mips_dbx_regno[i] = IGNORED_DWARF_REGNUM;
+       if (GP_REG_P (i) || FP_REG_P (i) || ALL_COP_REG_P (i))
+ 	mips_dwarf_regno[i] = i;
+       else
+ 	mips_dwarf_regno[i] = INVALID_REGNUM;
+     }
+ 
+-  start = GP_DBX_FIRST - GP_REG_FIRST;
+-  for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
+-    mips_dbx_regno[i] = i + start;
+-
+-  start = FP_DBX_FIRST - FP_REG_FIRST;
+-  for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
+-    mips_dbx_regno[i] = i + start;
+-
+   /* Accumulator debug registers use big-endian ordering.  */
+-  mips_dbx_regno[HI_REGNUM] = MD_DBX_FIRST + 0;
+-  mips_dbx_regno[LO_REGNUM] = MD_DBX_FIRST + 1;
+   mips_dwarf_regno[HI_REGNUM] = MD_REG_FIRST + 0;
+   mips_dwarf_regno[LO_REGNUM] = MD_REG_FIRST + 1;
+   for (i = DSP_ACC_REG_FIRST; i <= DSP_ACC_REG_LAST; i += 2)
+diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
+index 02562d3b6..fa0676acd 100644
+--- a/gcc/config/mips/mips.h
++++ b/gcc/config/mips/mips.h
+@@ -1380,9 +1380,7 @@ struct mips_cpu_info {
+ #ifndef SUBTARGET_ASM_DEBUGGING_SPEC
+ #define SUBTARGET_ASM_DEBUGGING_SPEC "\
+ %{g} %{g0} %{g1} %{g2} %{g3} \
+-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
+-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
+-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3}"
++%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3}"
+ #endif
+ 
+ /* FP_ASM_SPEC represents the floating-point options that must be passed
+@@ -1504,7 +1502,6 @@ FP_ASM_SPEC "\
+ #define SUBTARGET_EXTRA_SPECS
+ #endif
+ 
+-#define DBX_DEBUGGING_INFO 1		/* generate stabs (OSF/rose) */
+ #define DWARF2_DEBUGGING_INFO 1         /* dwarf2 debugging info */
+ 
+ #ifndef PREFERRED_DEBUGGING_TYPE
+@@ -1544,14 +1541,6 @@ FP_ASM_SPEC "\
+ #define USER_LABEL_PREFIX	""
+ #endif
+ 
+-/* On Sun 4, this limit is 2048.  We use 1500 to be safe,
+-   since the length can run past this up to a continuation point.  */
+-#undef DBX_CONTIN_LENGTH
+-#define DBX_CONTIN_LENGTH 1500
+-
+-/* How to renumber registers for dbx and gdb.  */
+-#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[REGNO]
+-
+ /* The mapping from gcc register number to DWARF 2 CFA column number.  */
+ #define DWARF_FRAME_REGNUM(REGNO) mips_dwarf_regno[REGNO]
+ 
+@@ -1865,7 +1854,6 @@ FP_ASM_SPEC "\
+ #define GP_REG_FIRST 0
+ #define GP_REG_LAST  31
+ #define GP_REG_NUM   (GP_REG_LAST - GP_REG_FIRST + 1)
+-#define GP_DBX_FIRST 0
+ #define K0_REG_NUM   (GP_REG_FIRST + 26)
+ #define K1_REG_NUM   (GP_REG_FIRST + 27)
+ #define KERNEL_REG_P(REGNO)	(IN_RANGE (REGNO, K0_REG_NUM, K1_REG_NUM))
+@@ -1873,12 +1861,10 @@ FP_ASM_SPEC "\
+ #define FP_REG_FIRST 32
+ #define FP_REG_LAST  63
+ #define FP_REG_NUM   (FP_REG_LAST - FP_REG_FIRST + 1)
+-#define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32)
+ 
+ #define MD_REG_FIRST 64
+ #define MD_REG_LAST  65
+ #define MD_REG_NUM   (MD_REG_LAST - MD_REG_FIRST + 1)
+-#define MD_DBX_FIRST (FP_DBX_FIRST + FP_REG_NUM)
+ 
+ #define MSA_REG_FIRST FP_REG_FIRST
+ #define MSA_REG_LAST  FP_REG_LAST
+@@ -3217,7 +3203,6 @@ extern int num_source_filenames;	/* current .file # */
+ extern struct mips_asm_switch mips_noreorder;
+ extern struct mips_asm_switch mips_nomacro;
+ extern struct mips_asm_switch mips_noat;
+-extern int mips_dbx_regno[];
+ extern int mips_dwarf_regno[];
+ extern bool mips_split_p[];
+ extern bool mips_split_hi_p[];
+diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
+index e4297e2d6..3634a49de 100644
+--- a/gcc/config/nvptx/nvptx.cc
++++ b/gcc/config/nvptx/nvptx.cc
+@@ -52,7 +52,6 @@
+ #include "tm-preds.h"
+ #include "tm-constrs.h"
+ #include "langhooks.h"
+-#include "dbxout.h"
+ #include "cfgrtl.h"
+ #include "gimple.h"
+ #include "stor-layout.h"
+diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h
+index 54be22254..aa90ef734 100644
+--- a/gcc/config/openbsd.h
++++ b/gcc/config/openbsd.h
+@@ -150,17 +150,6 @@ while (0)
+ #undef TARGET_LIBC_HAS_FUNCTION
+ #define TARGET_LIBC_HAS_FUNCTION default_libc_has_function
+ 
+-
+-/* Runtime target specification.  */
+-
+-/* Miscellaneous parameters.  */
+-
+-/* Controlling debugging info: dbx options.  */
+-
+-/* Don't use the `xsTAG;' construct in DBX output; OpenBSD systems that
+-   use DBX don't support it.  */
+-#define DBX_NO_XREFS
+-
+ 
+ /* - we use . - _func instead of a local label,
+    - we put extra spaces in expressions such as 
+diff --git a/gcc/config/pa/pa-64.h b/gcc/config/pa/pa-64.h
+index bf505768a..5157b7f30 100644
+--- a/gcc/config/pa/pa-64.h
++++ b/gcc/config/pa/pa-64.h
+@@ -65,10 +65,6 @@ along with GCC; see the file COPYING3.  If not see
+ #undef LONG_DOUBLE_TYPE_SIZE
+ #define LONG_DOUBLE_TYPE_SIZE 128
+ 
+-/* Temporary until we figure out what to do with those *(&@$ 32bit
+-   relocs which appear in stabs.  */
+-#undef DBX_DEBUGGING_INFO
+-
+ /* ?!? This needs to be made compile-time selectable.
+ 
+    The PA64 runtime model has arguments that grow to higher addresses
+diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
+index 1ce6635ae..bafdf6021 100644
+--- a/gcc/config/pa/pa.h
++++ b/gcc/config/pa/pa.h
+@@ -130,8 +130,6 @@ extern unsigned long total_code_bytes;
+    and the old mnemonics are dialect zero.  */
+ #define ASSEMBLER_DIALECT (TARGET_PA_20 ? 1 : 0)
+ 
+-/* Override some settings from dbxelf.h.  */
+-
+ /* We do not have to be compatible with dbx, so we enable gdb extensions
+    by default.  */
+ #define DEFAULT_GDB_EXTENSIONS 1
+@@ -139,14 +137,6 @@ extern unsigned long total_code_bytes;
+ /* Select dwarf2 as the preferred debug format.  */
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+-/* This used to be zero (no max length), but big enums and such can
+-   cause huge strings which killed gas.
+-
+-   We also have to avoid lossage in dbxout.cc -- it does not compute the
+-   string size accurately, so we are real conservative here.  */
+-#undef DBX_CONTIN_LENGTH
+-#define DBX_CONTIN_LENGTH 3000
+-
+ /* GDB always assumes the current function's frame begins at the value
+    of the stack pointer upon entry to the current function.  Accessing
+    local variables and parameters passed on the stack is done using the
+diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
+index d2510e9b9..3efae0e1f 100644
+--- a/gcc/config/pa/som.h
++++ b/gcc/config/pa/som.h
+@@ -21,21 +21,6 @@ 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.  */
+-#undef DBX_USE_BINCL
+-
+-#define DBX_LINES_FUNCTION_RELATIVE 1
+-
+-/* gdb needs a null N_SO at the end of each file for scattered loading.  */
+-
+-#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-
+ /* HPUX has a program 'chatr' to list the dependencies of dynamically
+    linked executables and shared libraries.  */
+ #define LDD_SUFFIX "chatr"
+diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
+index f7482df18..380223439 100644
+--- a/gcc/config/pdp11/pdp11.cc
++++ b/gcc/config/pdp11/pdp11.cc
+@@ -44,7 +44,6 @@ along with GCC; see the file COPYING3.  If not see
+ #include "calls.h"
+ #include "expr.h"
+ #include "builtins.h"
+-#include "dbxout.h"
+ #include "explow.h"
+ #include "expmed.h"
+ 
+diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h
+index b7d66c3bc..1fa52e8c7 100644
+--- a/gcc/config/pdp11/pdp11.h
++++ b/gcc/config/pdp11/pdp11.h
+@@ -51,12 +51,6 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ 
+ /* Generate DBX debugging information.  */
+-
+-#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)
+ 
+@@ -489,9 +483,6 @@ extern int current_first_parm_offset;
+ /* Nonzero if access to memory by byte is no faster than by word.  */
+ #define SLOW_BYTE_ACCESS 1
+ 
+-/* Do not break .stabs pseudos into continuations.  */
+-#define DBX_CONTIN_LENGTH 0
+-
+ /* Give a comparison code (EQ, NE etc) and the first operand of a COMPARE,
+    return the mode to be used for the comparison.  */
+ 
+diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc
+index cc385a2b2..3bf3b4779 100644
+--- a/gcc/config/rs6000/rs6000-builtin.cc
++++ b/gcc/config/rs6000/rs6000-builtin.cc
+@@ -51,9 +51,6 @@
+ #include "tree-ssa-propagate.h"
+ #include "builtins.h"
+ #include "tree-vector-builder.h"
+-#if TARGET_XCOFF
+-#include "xcoffout.h"  /* get declarations of xcoff_*_section_name */
+-#endif
+ #include "ppc-auxv.h"
+ #include "rs6000-internal.h"
+ 
+diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc
+index d27df7b25..4dfe033a4 100644
+--- a/gcc/config/rs6000/rs6000-call.cc
++++ b/gcc/config/rs6000/rs6000-call.cc
+@@ -61,20 +61,12 @@
+ #include "tree-ssa-propagate.h"
+ #include "builtins.h"
+ #include "tree-vector-builder.h"
+-#if TARGET_XCOFF
+-#include "xcoffout.h"  /* get declarations of xcoff_*_section_name */
+-#endif
+ #include "ppc-auxv.h"
+ #include "targhooks.h"
+ #include "opts.h"
+ 
+ #include "rs6000-internal.h"
+ 
+-#if TARGET_MACHO
+-#include "gstab.h"  /* for N_SLINE */
+-#include "dbxout.h" /* dbxout_ */
+-#endif
+-
+ #ifndef TARGET_PROFILE_KERNEL
+ #define TARGET_PROFILE_KERNEL 0
+ #endif
+diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc
+index a868ede24..a11d020cc 100644
+--- a/gcc/config/rs6000/rs6000-logue.cc
++++ b/gcc/config/rs6000/rs6000-logue.cc
+@@ -47,10 +47,6 @@
+ #include "diagnostic-core.h"
+ #include "alias.h"
+ #include "rs6000-internal.h"
+-#if TARGET_MACHO
+-#include "gstab.h"  /* for N_SLINE */
+-#include "dbxout.h" /* dbxout_ */
+-#endif
+ 
+ static int rs6000_ra_ever_killed (void);
+ static void is_altivec_return_reg (rtx, void *);
+@@ -5144,10 +5140,6 @@ macho_branch_islands (void)
+ 	}
+       strcpy (tmp_buf, "\n");
+       strcat (tmp_buf, label);
+-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+-      if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+-	dbxout_stabd (N_SLINE, bi->line_number);
+-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+       if (flag_pic)
+ 	{
+ 	  strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
+@@ -5181,10 +5173,6 @@ macho_branch_islands (void)
+ 	  strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
+ 	}
+       output_asm_insn (tmp_buf, 0);
+-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+-      if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+-	dbxout_stabd (N_SLINE, bi->line_number);
+-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+       branch_islands->pop ();
+     }
+ }
+diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
+index d9a4c3dff..0b75861bb 100644
+--- a/gcc/config/rs6000/rs6000.cc
++++ b/gcc/config/rs6000/rs6000.cc
+@@ -75,9 +75,6 @@
+ #include "ipa-prop.h"
+ #include "ipa-fnsummary.h"
+ #include "except.h"
+-#if TARGET_XCOFF
+-#include "xcoffout.h"  /* get declarations of xcoff_*_section_name */
+-#endif
+ #include "case-cfn-macros.h"
+ #include "ppc-auxv.h"
+ #include "rs6000-internal.h"
+@@ -3899,12 +3896,6 @@ rs6000_option_override_internal (bool global_init_p)
+   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
+     rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags);
+ 
+-#ifdef XCOFF_DEBUGGING_INFO
+-  /* For AIX default to 64-bit DWARF.  */
+-  if (!OPTION_SET_P (dwarf_offset_size))
+-    dwarf_offset_size = POINTER_SIZE_UNITS;
+-#endif
+-
+   /* Handle explicit -mno-{altivec,vsx,power8-vector,power9-vector} and turn
+      off all of the options that depend on those flags.  */
+   ignore_masks = rs6000_disable_incompatible_switches ();
+@@ -21022,9 +21013,14 @@ rs6000_elf_file_end (void)
+ 
+ #if TARGET_XCOFF
+ 
+-#ifndef HAVE_XCOFF_DWARF_EXTRAS
+-#define HAVE_XCOFF_DWARF_EXTRAS 0
+-#endif
++/* Names of bss and data sections.  These should be unique names for each
++   compilation unit.  */
++
++char *xcoff_bss_section_name;
++char *xcoff_private_data_section_name;
++char *xcoff_private_rodata_section_name;
++char *xcoff_tls_data_section_name;
++char *xcoff_read_only_section_name;
+ 
+ static enum unwind_info_type
+ rs6000_xcoff_debug_unwind_info (void)
+@@ -21539,9 +21535,7 @@ rs6000_xcoff_declare_function_name (FILE *file, const char *name, tree decl)
+ 							&data, true);
+   if (!DECL_IGNORED_P (decl))
+     {
+-      if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+-	xcoffout_declare_function (file, decl, buffer);
+-      else if (dwarf_debuginfo_p ())
++      if (dwarf_debuginfo_p ())
+ 	{
+ 	  name = (*targetm.strip_name_encoding) (name);
+ 	  fprintf (file, "\t.function .%s,.%s,2,0\n", name, name);
+diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
+index 7e2519de5..c8b7eb633 100644
+--- a/gcc/config/rs6000/sysv4.h
++++ b/gcc/config/rs6000/sysv4.h
+@@ -504,9 +504,6 @@ extern int fixuplabelno;
+ #undef  PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+-/* Historically we have also supported stabs debugging.  */
+-#define DBX_DEBUGGING_INFO 1
+-
+ #define TARGET_ENCODE_SECTION_INFO  rs6000_elf_encode_section_info
+ #define TARGET_IN_SMALL_DATA_P  rs6000_elf_in_small_data_p
+ 
+@@ -515,11 +512,6 @@ extern int fixuplabelno;
+ #define	RS6000_OUTPUT_BASENAME(FILE, NAME)	\
+     assemble_name (FILE, NAME)
+ 
+-/* We have to output the stabs for the function name *first*, before
+-   outputting its label.  */
+-
+-#define	DBX_FUNCTION_FIRST
+-
+ /* This is the end of what might become sysv4dbx.h.  */
+ 
+ #define TARGET_OS_SYSV_CPP_BUILTINS()		\
+diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h
+index cd0f99cb9..bafc57df5 100644
+--- a/gcc/config/rs6000/xcoff.h
++++ b/gcc/config/rs6000/xcoff.h
+@@ -21,9 +21,6 @@
+ 
+ #define TARGET_OBJECT_FORMAT OBJECT_XCOFF
+ 
+-/* The RS/6000 uses the XCOFF format.  */
+-#define XCOFF_DEBUGGING_INFO 1
+-
+ /* Define if the object format being used is COFF or a superset.  */
+ #define OBJECT_FORMAT_COFF
+ 
+diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
+index ce9c2ff12..77f84039c 100644
+--- a/gcc/config/rx/rx.h
++++ b/gcc/config/rx/rx.h
+@@ -623,7 +623,6 @@ typedef unsigned int CUMULATIVE_ARGS;
+ #undef  PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+-#define DBX_DEBUGGING_INFO 1
+ #define DWARF2_DEBUGGING_INFO 1
+ 
+ #define INCOMING_FRAME_SP_OFFSET		4
+diff --git a/gcc/config/sh/elf.h b/gcc/config/sh/elf.h
+index afb3bc353..f0fd19f88 100644
+--- a/gcc/config/sh/elf.h
++++ b/gcc/config/sh/elf.h
+@@ -67,9 +67,6 @@ along with GCC; see the file COPYING3.  If not see
+ #define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
+   sprintf ((STRING), "*%s%s%ld", LOCAL_LABEL_PREFIX, (PREFIX), (long)(NUM))
+ 
+-#define DBX_LINES_FUNCTION_RELATIVE 1
+-#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-
+ #undef STARTFILE_SPEC
+ #define STARTFILE_SPEC \
+   "%{!shared: crt1.o%s} crti.o%s \
+diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
+index e22c70c45..fc7033082 100644
+--- a/gcc/config/sol2.h
++++ b/gcc/config/sol2.h
+@@ -498,11 +498,7 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ #define AS_NEEDS_DASH_FOR_PIPED_INPUT
+ 
+-/* The Solaris assembler cannot grok .stabd directives.  */
+-#undef NO_DBX_BNSYM_ENSYM
+-#define NO_DBX_BNSYM_ENSYM 1
+ #endif
+-
+ /* Solaris has an implementation of __enable_execute_stack.  */
+ #define HAVE_ENABLE_EXECUTE_STACK
+ 
+diff --git a/gcc/config/sparc/freebsd.h b/gcc/config/sparc/freebsd.h
+index 98319c528..73850a31f 100644
+--- a/gcc/config/sparc/freebsd.h
++++ b/gcc/config/sparc/freebsd.h
+@@ -109,12 +109,6 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ /************************[  Debugger stuff  ]*********************************/
+ 
+-/* This is the char to use for continuation (in case we need to turn
+-   continuation back on).  */
+-
+-#undef  DBX_CONTIN_CHAR
+-#define DBX_CONTIN_CHAR	'?'
+-
+ /* DWARF bits.  */
+ 
+ /* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets. 
+diff --git a/gcc/config/sparc/netbsd-elf.h b/gcc/config/sparc/netbsd-elf.h
+index af194df3e..bee71fc18 100644
+--- a/gcc/config/sparc/netbsd-elf.h
++++ b/gcc/config/sparc/netbsd-elf.h
+@@ -46,11 +46,6 @@ along with GCC; see the file COPYING3.  If not see
+ #undef PTRDIFF_TYPE
+ #define PTRDIFF_TYPE "long int"
+ 
+-/* This is the char to use for continuation (in case we need to turn
+-   continuation back on).  */
+-#undef DBX_CONTIN_CHAR
+-#define DBX_CONTIN_CHAR '?'
+-
+ #undef  LOCAL_LABEL_PREFIX
+ #define LOCAL_LABEL_PREFIX  "."
+ 
+diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
+index 91917c3ea..155e1da7a 100644
+--- a/gcc/config/sparc/sparc.h
++++ b/gcc/config/sparc/sparc.h
+@@ -1506,14 +1506,6 @@ do {									   \
+ #define ADDITIONAL_REGISTER_NAMES \
+ {{"ccr", SPARC_ICC_REG}, {"cc", SPARC_ICC_REG}}
+ 
+-/* On Sun 4, this limit is 2048.  We use 1000 to be safe, since the length
+-   can run past this up to a continuation point.  Once we used 1500, but
+-   a single entry in C++ can run more than 500 bytes, due to the length of
+-   mangled symbol names.  dbxout.cc should really be fixed to do
+-   continuations when they are actually needed instead of trying to
+-   guess...  */
+-#define DBX_CONTIN_LENGTH 1000
+-
+ /* This is how to output a command to make the user-level label named NAME
+    defined for reference from other files.  */
+ 
+diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
+index f44e23d17..28c1af59a 100644
+--- a/gcc/config/vax/vax.cc
++++ b/gcc/config/vax/vax.cc
+@@ -247,9 +247,6 @@ static void
+ vax_file_start (void)
+ {
+   default_file_start ();
+-
+-  if (write_symbols == DBX_DEBUG)
+-    fprintf (asm_out_file, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR);
+ }
+ 
+ /* We can use the BSD C library routines for the libgcc calls that are
+diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
+index 45c0e7563..12c51e53d 100644
+--- a/gcc/config/vax/vax.h
++++ b/gcc/config/vax/vax.h
+@@ -508,27 +508,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
+     "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc",	\
+     "psl" }
+ 
+-/* This is BSD, so it wants DBX format.  */
+-
+-#define DBX_DEBUGGING_INFO 1
+-
+-/* Do not break .stabs pseudos into continuations.  */
+-
+-#define DBX_CONTIN_LENGTH 0
+-
+-/* This is the char to use for continuation (in case we need to turn
+-   continuation back on).  */
+-
+-#define DBX_CONTIN_CHAR '?'
+-
+-/* Don't use the `xsfoo;' construct in DBX output; this system
+-   doesn't support it.  */
+-
+-#define DBX_NO_XREFS
+-
+-/* Output the .stabs for a C `static' variable in the data section.  */
+-#define DBX_STATIC_STAB_DATA_SECTION
+-
+ /* VAX specific: which type character is used for type double?  */
+ 
+ #define ASM_DOUBLE_CHAR (TARGET_G_FLOAT ? 'g' : 'd')
+diff --git a/gcc/config/vx-common.h b/gcc/config/vx-common.h
+index aaae4f78b..bc2768437 100644
+--- a/gcc/config/vx-common.h
++++ b/gcc/config/vx-common.h
+@@ -94,8 +94,6 @@ along with GCC; see the file COPYING3.  If not see
+ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+ 
+ /* None of these other formats is supported.  */
+-#undef DBX_DEBUGGING_INFO
+-#undef XCOFF_DEBUGGING_INFO
+ #undef VMS_DEBUGGING_INFO
+ 
+ /* ------------------------ Misc configuration bits ----------------------  */
+diff --git a/gcc/configure b/gcc/configure
+index 30f386789..7e64599b0 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -25078,38 +25078,6 @@ cat >>confdefs.h <<_ACEOF
+ _ACEOF
+ 
+ 
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for stabs directive" >&5
+-$as_echo_n "checking assembler for stabs directive... " >&6; }
+-if ${gcc_cv_as_stabs_directive+:} false; then :
+-  $as_echo_n "(cached) " >&6
+-else
+-  gcc_cv_as_stabs_directive=no
+-  if test x$gcc_cv_as != x; then
+-    $as_echo '.stabs "gcc2_compiled.",60,0,0,0' > conftest.s
+-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+-  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+-  (eval $ac_try) 2>&5
+-  ac_status=$?
+-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }; }
+-    then
+-	gcc_cv_as_stabs_directive=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_stabs_directive" >&5
+-$as_echo "$gcc_cv_as_stabs_directive" >&6; }
+-if test $gcc_cv_as_stabs_directive = yes; then
+-
+-$as_echo "#define HAVE_AS_STABS_DIRECTIVE 1" >>confdefs.h
+-
+-fi
+-
+-
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for COMDAT group support (GNU as)" >&5
+ $as_echo_n "checking assembler for COMDAT group support (GNU as)... " >&6; }
+ if ${gcc_cv_as_comdat_group+:} false; then :
+@@ -28186,41 +28154,6 @@ if test $gcc_cv_as_aix_ref = yes; then
+ 
+ $as_echo "#define HAVE_AS_REF 1" >>confdefs.h
+ 
+-fi
+-
+-
+-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for AIX DWARF location lists section support" >&5
+-$as_echo_n "checking assembler for AIX DWARF location lists section support... " >&6; }
+-if ${gcc_cv_as_aix_dwloc+:} false; then :
+-  $as_echo_n "(cached) " >&6
+-else
+-  gcc_cv_as_aix_dwloc=no
+-  if test x$gcc_cv_as != x; then
+-    $as_echo '	.dwsect 0xA0000
+-	Lframe..0:
+-		.vbyte 4,Lframe..0
+-	  ' > conftest.s
+-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+-  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+-  (eval $ac_try) 2>&5
+-  ac_status=$?
+-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+-  test $ac_status = 0; }; }
+-    then
+-	gcc_cv_as_aix_dwloc=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_aix_dwloc" >&5
+-$as_echo "$gcc_cv_as_aix_dwloc" >&6; }
+-if test $gcc_cv_as_aix_dwloc = yes; then
+-
+-$as_echo "#define HAVE_XCOFF_DWARF_EXTRAS 1" >>confdefs.h
+-
+ fi
+ 
+ 	;;
+@@ -30008,38 +29941,6 @@ $as_echo "#define HAVE_AS_WORKING_DWARF_N_FLAG 1" >>confdefs.h
+    fi
+  fi
+ 
+- { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gstabs option" >&5
+-$as_echo_n "checking assembler for --gstabs option... " >&6; }
+-if ${gcc_cv_as_gstabs_flag+:} false; then :
+-  $as_echo_n "(cached) " >&6
+-else
+-  gcc_cv_as_gstabs_flag=no
+-  if test x$gcc_cv_as != x; then
+-    $as_echo "$insn" > conftest.s
+-    if { ac_try='$gcc_cv_as $gcc_cv_as_flags --gstabs -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_gstabs_flag=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_gstabs_flag" >&5
+-$as_echo "$gcc_cv_as_gstabs_flag" >&6; }
+-if test $gcc_cv_as_gstabs_flag = yes; then
+-
+-$as_echo "#define HAVE_AS_GSTABS_DEBUG_FLAG 1" >>confdefs.h
+-
+-fi
+-
+-
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --debug-prefix-map option" >&5
+ $as_echo_n "checking assembler for --debug-prefix-map option... " >&6; }
+ if ${gcc_cv_as_debug_prefix_map_flag+:} false; then :
+diff --git a/gcc/configure.ac b/gcc/configure.ac
+index dd6cd60f8..708ec3fd3 100644
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -3509,11 +3509,6 @@ AC_DEFINE_UNQUOTED(HAVE_LD_ALIGNED_SHF_MERGE,
+   [`if test $gcc_cv_ld_aligned_shf_merge = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your linker supports the SHF_MERGE flag with section alignment > 1.])
+ 
+-gcc_GAS_CHECK_FEATURE([stabs directive], gcc_cv_as_stabs_directive,,
+-[.stabs "gcc2_compiled.",60,0,0,0],,
+-[AC_DEFINE(HAVE_AS_STABS_DIRECTIVE, 1,
+-  [Define if your assembler supports .stabs.])])
+-
+ gcc_GAS_CHECK_FEATURE([COMDAT group support (GNU as)],
+  gcc_cv_as_comdat_group,
+  [--fatal-warnings],
+@@ -5100,15 +5095,6 @@ LCF0:
+ 	  ],,
+ 	  [AC_DEFINE(HAVE_AS_REF, 1,
+ 	    [Define if your assembler supports .ref])])
+-
+-	gcc_GAS_CHECK_FEATURE([AIX DWARF location lists section support],
+-	  gcc_cv_as_aix_dwloc,,
+-	  [	.dwsect 0xA0000
+-	Lframe..0:
+-		.vbyte 4,Lframe..0
+-	  ],,
+-	  [AC_DEFINE(HAVE_XCOFF_DWARF_EXTRAS, 1,
+-	    [Define if your assembler supports AIX debug frame section label reference.])])
+ 	;;
+     esac
+     ;;
+@@ -5841,12 +5827,6 @@ foo:
+    fi
+  fi
+ 
+- gcc_GAS_CHECK_FEATURE([--gstabs option],
+-  gcc_cv_as_gstabs_flag,
+-  [--gstabs], [$insn],,
+-  [AC_DEFINE(HAVE_AS_GSTABS_DEBUG_FLAG, 1,
+-[Define if your assembler supports the --gstabs option.])])
+-
+  gcc_GAS_CHECK_FEATURE([--debug-prefix-map option],
+   gcc_cv_as_debug_prefix_map_flag,
+   [--debug-prefix-map /a=/b], [$insn],,
+diff --git a/gcc/dbxout.cc b/gcc/dbxout.cc
+deleted file mode 100644
+index 878d528dc..000000000
+--- a/gcc/dbxout.cc
++++ /dev/null
+@@ -1,3936 +0,0 @@
+-/* Output dbx-format symbol table information from GNU compiler.
+-   Copyright (C) 1987-2022 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
+-.  */
+-
+-
+-/* Output dbx-format symbol table data.
+-   This consists of many symbol table entries, each of them
+-   a .stabs assembler pseudo-op with four operands:
+-   a "name" which is really a description of one symbol and its type,
+-   a "code", which is a symbol defined in stab.h whose name starts with N_,
+-   an unused operand always 0,
+-   and a "value" which is an address or an offset.
+-   The name is enclosed in doublequote characters.
+-
+-   Each function, variable, typedef, and structure tag
+-   has a symbol table entry to define it.
+-   The beginning and end of each level of name scoping within
+-   a function are also marked by special symbol table entries.
+-
+-   The "name" consists of the symbol name, a colon, a kind-of-symbol letter,
+-   and a data type number.  The data type number may be followed by
+-   "=" and a type definition; normally this will happen the first time
+-   the type number is mentioned.  The type definition may refer to
+-   other types by number, and those type numbers may be followed
+-   by "=" and nested definitions.
+-
+-   This can make the "name" quite long.
+-   When a name is more than 80 characters, we split the .stabs pseudo-op
+-   into two .stabs pseudo-ops, both sharing the same "code" and "value".
+-   The first one is marked as continued with a double-backslash at the
+-   end of its "name".
+-
+-   The kind-of-symbol letter distinguished function names from global
+-   variables from file-scope variables from parameters from auto
+-   variables in memory from typedef names from register variables.
+-   See `dbxout_symbol'.
+-
+-   The "code" is mostly redundant with the kind-of-symbol letter
+-   that goes in the "name", but not entirely: for symbols located
+-   in static storage, the "code" says which segment the address is in,
+-   which controls how it is relocated.
+-
+-   The "value" for a symbol in static storage
+-   is the core address of the symbol (actually, the assembler
+-   label for the symbol).  For a symbol located in a stack slot
+-   it is the stack offset; for one in a register, the register number.
+-   For a typedef symbol, it is zero.
+-
+-   If DEBUG_SYMS_TEXT is defined, all debugging symbols must be
+-   output while in the text section.
+-
+-   For more on data type definitions, see `dbxout_type'.  */
+-
+-#include "config.h"
+-#include "system.h"
+-#include "coretypes.h"
+-#include "target.h"
+-#include "function.h"
+-#include "rtl.h"
+-#include "tree.h"
+-#include "memmodel.h"
+-#include "tm_p.h"
+-#include "stringpool.h"
+-#include "insn-config.h"
+-#include "emit-rtl.h"
+-#include "cgraph.h"
+-#include "diagnostic-core.h"
+-#include "fold-const.h"
+-#include "varasm.h"
+-#include "stor-layout.h"
+-#include "reload.h"
+-#include "output.h"
+-#include "dbxout.h"
+-#include "toplev.h"
+-#include "debug.h"
+-#include "common/common-target.h"
+-#include "langhooks.h"
+-#include "expr.h"
+-#include "file-prefix-map.h" /* remap_debug_filename()  */
+-#include "flags.h"
+-
+-#ifdef XCOFF_DEBUGGING_INFO
+-#include "xcoffout.h"
+-#endif
+-
+-#ifndef ASM_STABS_OP
+-# ifdef XCOFF_DEBUGGING_INFO
+-#  define ASM_STABS_OP "\t.stabx\t"
+-# else
+-#  define ASM_STABS_OP "\t.stabs\t"
+-# endif
+-#endif
+-
+-#ifndef ASM_STABN_OP
+-#define ASM_STABN_OP "\t.stabn\t"
+-#endif
+-
+-#ifndef ASM_STABD_OP
+-#define ASM_STABD_OP "\t.stabd\t"
+-#endif
+-
+-#ifndef DBX_TYPE_DECL_STABS_CODE
+-#define DBX_TYPE_DECL_STABS_CODE N_LSYM
+-#endif
+-
+-#ifndef DBX_STATIC_CONST_VAR_CODE
+-#define DBX_STATIC_CONST_VAR_CODE N_FUN
+-#endif
+-
+-#ifndef DBX_REGPARM_STABS_CODE
+-#define DBX_REGPARM_STABS_CODE N_RSYM
+-#endif
+-
+-#ifndef DBX_REGPARM_STABS_LETTER
+-#define DBX_REGPARM_STABS_LETTER 'P'
+-#endif
+-
+-#ifndef NO_DBX_FUNCTION_END
+-#define NO_DBX_FUNCTION_END 0
+-#endif
+-
+-#ifndef NO_DBX_BNSYM_ENSYM
+-#define NO_DBX_BNSYM_ENSYM 0
+-#endif
+-
+-#ifndef NO_DBX_MAIN_SOURCE_DIRECTORY
+-#define NO_DBX_MAIN_SOURCE_DIRECTORY 0
+-#endif
+-
+-#ifndef DBX_BLOCKS_FUNCTION_RELATIVE
+-#define DBX_BLOCKS_FUNCTION_RELATIVE 0
+-#endif
+-
+-#ifndef DBX_LINES_FUNCTION_RELATIVE
+-#define DBX_LINES_FUNCTION_RELATIVE 0
+-#endif
+-
+-#ifndef DBX_CONTIN_LENGTH
+-#define DBX_CONTIN_LENGTH 80
+-#endif
+-
+-#ifndef DBX_CONTIN_CHAR
+-#define DBX_CONTIN_CHAR '\\'
+-#endif
+-
+-enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
+-
+-/* Structure recording information about a C data type.
+-   The status element says whether we have yet output
+-   the definition of the type.  TYPE_XREF says we have
+-   output it as a cross-reference only.
+-   The file_number and type_number elements are used if DBX_USE_BINCL
+-   is defined.  */
+-
+-struct GTY(()) typeinfo {
+-  enum typestatus status;
+-  int file_number;
+-  int type_number;
+-};
+-
+-/* Vector recording information about C data types.
+-   When we first notice a data type (a tree node),
+-   we assign it a number using next_type_number.
+-   That is its index in this vector.  */
+-
+-static GTY ((length ("typevec_len"))) struct typeinfo *typevec;
+-
+-/* Number of elements of space allocated in `typevec'.  */
+-
+-static GTY(()) int typevec_len;
+-
+-/* In dbx output, each type gets a unique number.
+-   This is the number for the next type output.
+-   The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field.  */
+-
+-static GTY(()) int next_type_number;
+-
+-/* The C front end may call dbxout_symbol before dbxout_init runs.
+-   We save all such decls in this list and output them when we get
+-   to dbxout_init.  */
+-
+-static GTY(()) tree preinit_symbols;
+-
+-enum binclstatus {BINCL_NOT_REQUIRED, BINCL_PENDING, BINCL_PROCESSED};
+-
+-/* When using N_BINCL in dbx output, each type number is actually a
+-   pair of the file number and the type number within the file.
+-   This is a stack of input files.  */
+-
+-struct dbx_file
+-{
+-  struct dbx_file *next;
+-  int file_number;
+-  int next_type_number;
+-  enum binclstatus bincl_status;  /* Keep track of lazy bincl.  */
+-  const char *pending_bincl_name; /* Name of bincl.  */
+-  struct dbx_file *prev;          /* Chain to traverse all pending bincls.  */
+-};
+-
+-/* This is the top of the stack.
+-
+-   This is not saved for PCH, because restoring a PCH should not change it.
+-   next_file_number does have to be saved, because the PCH may use some
+-   file numbers; however, just before restoring a PCH, next_file_number
+-   should always be 0 because we should not have needed any file numbers
+-   yet.  */
+-
+-#if (defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)) \
+-    && defined (DBX_USE_BINCL)
+-static struct dbx_file *current_file;
+-#endif
+-
+-/* This is the next file number to use.  */
+-
+-static GTY(()) int next_file_number;
+-
+-/* A counter for dbxout_function_end.  */
+-
+-static GTY(()) int scope_labelno;
+-
+-/* A counter for dbxout_source_line.  */
+-
+-static GTY(()) int dbxout_source_line_counter;
+-
+-/* Number for the next N_SOL filename stabs label.  The number 0 is reserved
+-   for the N_SO filename stabs label.  */
+-
+-static GTY(()) int source_label_number = 1;
+-
+-/* Last source file name mentioned in a NOTE insn.  */
+-
+-static GTY(()) const char *lastfile;
+-
+-/* Last line number mentioned in a NOTE insn.  */
+-
+-static GTY(()) unsigned int lastlineno;
+-
+-/* Used by PCH machinery to detect if 'lastfile' should be reset to
+-   base_input_file.  */
+-static GTY(()) int lastfile_is_base;
+-
+-/* Typical USG systems don't have stab.h, and they also have
+-   no use for DBX-format debugging info.  */
+-
+-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+-
+-#ifdef DBX_USE_BINCL
+-/* If zero then there is no pending BINCL.  */
+-static int pending_bincls = 0;
+-#endif
+-
+-/* The original input file name.  */
+-static const char *base_input_file;
+-
+-#ifdef DEBUG_SYMS_TEXT
+-#define FORCE_TEXT switch_to_section (current_function_section ())
+-#else
+-#define FORCE_TEXT
+-#endif
+-
+-#include "gstab.h"
+-
+-/* 1 if PARM is passed to this function in memory.  */
+-
+-#define PARM_PASSED_IN_MEMORY(PARM) \
+- (MEM_P (DECL_INCOMING_RTL (PARM)))
+-
+-/* A C expression for the integer offset value of an automatic variable
+-   (N_LSYM) having address X (an RTX).  */
+-#ifndef DEBUGGER_AUTO_OFFSET
+-#define DEBUGGER_AUTO_OFFSET(X) \
+-  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+-#endif
+-
+-/* A C expression for the integer offset value of an argument (N_PSYM)
+-   having address X (an RTX).  The nominal offset is OFFSET.
+-   Note that we use OFFSET + 0 here to avoid the self-assign warning
+-   when the macro is called in a context like
+-   number = DEBUGGER_ARG_OFFSET(number, X)  */
+-#ifndef DEBUGGER_ARG_OFFSET
+-#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET + 0)
+-#endif
+-
+-/* This obstack holds the stab string currently being constructed.  We
+-   build it up here, then write it out, so we can split long lines up
+-   properly (see dbxout_finish_complex_stabs).  */
+-static struct obstack stabstr_ob;
+-static size_t stabstr_last_contin_point;
+-
+-#ifdef DBX_USE_BINCL
+-static void emit_bincl_stab             (const char *c);
+-static void emit_pending_bincls         (void);
+-#endif
+-static inline void emit_pending_bincls_if_required (void);
+-
+-static void dbxout_init (const char *);
+-
+-static void dbxout_finish (const char *);
+-static void dbxout_start_source_file (unsigned, const char *);
+-static void dbxout_end_source_file (unsigned);
+-static void dbxout_typedefs (tree);
+-static void dbxout_type_index (tree);
+-static void dbxout_args (tree);
+-static void dbxout_type_fields (tree);
+-static void dbxout_type_method_1 (tree);
+-static void dbxout_type_methods (tree);
+-static void dbxout_range_type (tree, tree, tree);
+-static void dbxout_type (tree, int);
+-static bool print_int_cst_bounds_in_octal_p (tree, tree, tree);
+-static bool is_fortran (void);
+-static void dbxout_type_name (tree);
+-static void dbxout_class_name_qualifiers (tree);
+-static int dbxout_symbol_location (tree, tree, const char *, rtx);
+-static void dbxout_symbol_name (tree, const char *, int);
+-static void dbxout_common_name (tree, const char *, stab_code_type);
+-static const char *dbxout_common_check (tree, int *);
+-static void dbxout_early_global_decl (tree);
+-static void dbxout_late_global_decl (tree);
+-static void dbxout_type_decl (tree, int);
+-static void dbxout_handle_pch (unsigned);
+-static void debug_free_queue (void);
+-
+-/* The debug hooks structure.  */
+-#if defined (DBX_DEBUGGING_INFO)
+-
+-static void dbxout_source_line (unsigned int, unsigned int, const char *,
+-				int, bool);
+-static void dbxout_switch_text_section (void);
+-static void dbxout_begin_prologue (unsigned int, unsigned int, const char *);
+-static void dbxout_source_file (const char *);
+-static void dbxout_function_end (tree);
+-static void dbxout_begin_function (tree);
+-static void dbxout_begin_block (unsigned, unsigned);
+-static void dbxout_end_block (unsigned, unsigned);
+-static void dbxout_function_decl (tree);
+-
+-const struct gcc_debug_hooks dbx_debug_hooks =
+-{
+-  dbxout_init,
+-  dbxout_finish,
+-  debug_nothing_charstar,
+-  debug_nothing_void,
+-  debug_nothing_int_charstar,
+-  debug_nothing_int_charstar,
+-  dbxout_start_source_file,
+-  dbxout_end_source_file,
+-  dbxout_begin_block,
+-  dbxout_end_block,
+-  debug_true_const_tree,	         /* ignore_block */
+-  dbxout_source_line,		         /* source_line */
+-  debug_nothing_int_int_charstar,	 /* set_ignored_loc */
+-  dbxout_begin_prologue,	         /* begin_prologue */
+-  debug_nothing_int_charstar,	         /* end_prologue */
+-  debug_nothing_int_charstar,	         /* begin_epilogue */
+-  debug_nothing_int_charstar,	         /* end_epilogue */
+-#ifdef DBX_FUNCTION_FIRST
+-  dbxout_begin_function,
+-#else
+-  debug_nothing_tree,		         /* begin_function */
+-#endif
+-  debug_nothing_int,		         /* end_function */
+-  debug_nothing_tree,			 /* register_main_translation_unit */
+-  dbxout_function_decl,
+-  dbxout_early_global_decl,		 /* early_global_decl */
+-  dbxout_late_global_decl,		 /* late_global_decl */
+-  dbxout_type_decl,			 /* type_decl */
+-  debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+-  debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+-  debug_nothing_tree_charstar_uhwi,      /* register_external_die */
+-  debug_nothing_tree,		         /* deferred_inline_function */
+-  debug_nothing_tree,		         /* outlining_inline_function */
+-  debug_nothing_rtx_code_label,	         /* label */
+-  dbxout_handle_pch,		         /* handle_pch */
+-  debug_nothing_rtx_insn,	         /* var_location */
+-  debug_nothing_tree,	         	 /* inline_entry */
+-  debug_nothing_tree,			 /* size_function */
+-  dbxout_switch_text_section,            /* switch_text_section */
+-  debug_nothing_tree_tree,		 /* set_name */
+-  0,                                     /* start_end_main_source_file */
+-  TYPE_SYMTAB_IS_ADDRESS                 /* tree_type_symtab_field */
+-};
+-#endif /* DBX_DEBUGGING_INFO  */
+-
+-#if defined (XCOFF_DEBUGGING_INFO)
+-const struct gcc_debug_hooks xcoff_debug_hooks =
+-{
+-  dbxout_init,
+-  dbxout_finish,
+-  debug_nothing_charstar,
+-  debug_nothing_void,
+-  debug_nothing_int_charstar,
+-  debug_nothing_int_charstar,
+-  dbxout_start_source_file,
+-  dbxout_end_source_file,
+-  xcoffout_begin_block,
+-  xcoffout_end_block,
+-  debug_true_const_tree,	         /* ignore_block */
+-  xcoffout_source_line,
+-  debug_nothing_int_int_charstar,	 /* set_ignored_loc */
+-  xcoffout_begin_prologue,	         /* begin_prologue */
+-  debug_nothing_int_charstar,	         /* end_prologue */
+-  debug_nothing_int_charstar,	         /* begin_epilogue */
+-  xcoffout_end_epilogue,
+-  debug_nothing_tree,		         /* begin_function */
+-  xcoffout_end_function,
+-  debug_nothing_tree,			 /* register_main_translation_unit */
+-  debug_nothing_tree,		         /* function_decl */
+-  dbxout_early_global_decl,		 /* early_global_decl */
+-  dbxout_late_global_decl,		 /* late_global_decl */
+-  dbxout_type_decl,			 /* type_decl */
+-  debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+-  debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+-  debug_nothing_tree_charstar_uhwi,      /* register_external_die */
+-  debug_nothing_tree,		         /* deferred_inline_function */
+-  debug_nothing_tree,		         /* outlining_inline_function */
+-  debug_nothing_rtx_code_label,	         /* label */
+-  dbxout_handle_pch,		         /* handle_pch */
+-  debug_nothing_rtx_insn,	         /* var_location */
+-  debug_nothing_tree,	         	 /* inline_entry */
+-  debug_nothing_tree,			 /* size_function */
+-  debug_nothing_void,                    /* switch_text_section */
+-  debug_nothing_tree_tree,	         /* set_name */
+-  0,                                     /* start_end_main_source_file */
+-  TYPE_SYMTAB_IS_ADDRESS                 /* tree_type_symtab_field */
+-};
+-#endif /* XCOFF_DEBUGGING_INFO  */
+-
+-/* Numeric formatting helper macro.  Note that this does not handle
+-   hexadecimal.  */
+-#define NUMBER_FMT_LOOP(P, NUM, BASE)		\
+-  do						\
+-    {						\
+-      int digit = NUM % BASE;			\
+-      NUM /= BASE;				\
+-      *--P = digit + '0';			\
+-    }						\
+-  while (NUM > 0)
+-
+-/* Utility: write a decimal integer NUM to asm_out_file.  */
+-void
+-dbxout_int (int num)
+-{
+-  char buf[64];
+-  char *p = buf + sizeof buf;
+-  unsigned int unum;
+-
+-  if (num == 0)
+-    {
+-      putc ('0', asm_out_file);
+-      return;
+-    }
+-  if (num < 0)
+-    {
+-      putc ('-', asm_out_file);
+-      unum = -(unsigned int) num;
+-    }
+-  else
+-    unum = num;
+-
+-  NUMBER_FMT_LOOP (p, unum, 10);
+-
+-  while (p < buf + sizeof buf)
+-    {
+-      putc (*p, asm_out_file);
+-      p++;
+-    }
+-}
+-
+-
+-/* Primitives for emitting simple stabs directives.  All other stabs
+-   routines should use these functions instead of directly emitting
+-   stabs.  They are exported because machine-dependent code may need
+-   to invoke them, e.g. in a DBX_OUTPUT_* macro whose definition
+-   forwards to code in CPU.c.  */
+-
+-/* The following functions should all be called immediately after one
+-   of the dbxout_begin_stab* functions (below).  They write out
+-   various things as the value of a stab.  */
+-
+-/* Write out a literal zero as the value of a stab.  */
+-void
+-dbxout_stab_value_zero (void)
+-{
+-  fputs ("0\n", asm_out_file);
+-}
+-
+-/* Write out the label LABEL as the value of a stab.  */
+-void
+-dbxout_stab_value_label (const char *label)
+-{
+-  assemble_name (asm_out_file, label);
+-  putc ('\n', asm_out_file);
+-}
+-
+-/* Write out the difference of two labels, LABEL - BASE, as the value
+-   of a stab.  */
+-void
+-dbxout_stab_value_label_diff (const char *label, const char *base)
+-{
+-  assemble_name (asm_out_file, label);
+-  putc ('-', asm_out_file);
+-  assemble_name (asm_out_file, base);
+-  putc ('\n', asm_out_file);
+-}
+-
+-/* Write out an internal label as the value of a stab, and immediately
+-   emit that internal label.  This should be used only when
+-   dbxout_stabd will not work.  STEM is the name stem of the label,
+-   COUNTERP is a pointer to a counter variable which will be used to
+-   guarantee label uniqueness.  */
+-void
+-dbxout_stab_value_internal_label (const char *stem, int *counterp)
+-{
+-  char label[100];
+-  int counter = counterp ? (*counterp)++ : 0;
+-
+-  ASM_GENERATE_INTERNAL_LABEL (label, stem, counter);
+-  dbxout_stab_value_label (label);
+-  targetm.asm_out.internal_label (asm_out_file, stem, counter);
+-}
+-
+-/* Write out the difference between BASE and an internal label as the
+-   value of a stab, and immediately emit that internal label.  STEM and
+-   COUNTERP are as for dbxout_stab_value_internal_label.  */
+-void
+-dbxout_stab_value_internal_label_diff (const char *stem, int *counterp,
+-				       const char *base)
+-{
+-  char label[100];
+-  int counter = counterp ? (*counterp)++ : 0;
+-
+-  ASM_GENERATE_INTERNAL_LABEL (label, stem, counter);
+-  dbxout_stab_value_label_diff (label, base);
+-  targetm.asm_out.internal_label (asm_out_file, stem, counter);
+-}
+-
+-/* The following functions produce specific kinds of stab directives.  */
+-
+-/* Write a .stabd directive with type STYPE and desc SDESC to asm_out_file.  */
+-void
+-dbxout_stabd (int stype, int sdesc)
+-{
+-  fputs (ASM_STABD_OP, asm_out_file);
+-  dbxout_int (stype);
+-  fputs (",0,", asm_out_file);
+-  dbxout_int (sdesc);
+-  putc ('\n', asm_out_file);
+-}
+-
+-/* Write a .stabn directive with type STYPE.  This function stops
+-   short of emitting the value field, which is the responsibility of
+-   the caller (normally it will be either a symbol or the difference
+-   of two symbols).  */
+-
+-void
+-dbxout_begin_stabn (int stype)
+-{
+-  fputs (ASM_STABN_OP, asm_out_file);
+-  dbxout_int (stype);
+-  fputs (",0,0,", asm_out_file);
+-}
+-
+-/* Write a .stabn directive with type N_SLINE and desc LINE.  As above,
+-   the value field is the responsibility of the caller.  */
+-void
+-dbxout_begin_stabn_sline (int lineno)
+-{
+-  fputs (ASM_STABN_OP, asm_out_file);
+-  dbxout_int (N_SLINE);
+-  fputs (",0,", asm_out_file);
+-  dbxout_int (lineno);
+-  putc (',', asm_out_file);
+-}
+-
+-/* Begin a .stabs directive with string "", type STYPE, and desc and
+-   other fields 0.  The value field is the responsibility of the
+-   caller.  This function cannot be used for .stabx directives.  */
+-void
+-dbxout_begin_empty_stabs (int stype)
+-{
+-  fputs (ASM_STABS_OP, asm_out_file);
+-  fputs ("\"\",", asm_out_file);
+-  dbxout_int (stype);
+-  fputs (",0,0,", asm_out_file);
+-}
+-
+-/* Begin a .stabs directive with string STR, type STYPE, and desc 0.
+-   The value field is the responsibility of the caller.  */
+-void
+-dbxout_begin_simple_stabs (const char *str, int stype)
+-{
+-  fputs (ASM_STABS_OP, asm_out_file);
+-  output_quoted_string (asm_out_file, str);
+-  putc (',', asm_out_file);
+-  dbxout_int (stype);
+-  fputs (",0,0,", asm_out_file);
+-}
+-
+-/* As above but use SDESC for the desc field.  */
+-void
+-dbxout_begin_simple_stabs_desc (const char *str, int stype, int sdesc)
+-{
+-  fputs (ASM_STABS_OP, asm_out_file);
+-  output_quoted_string (asm_out_file, str);
+-  putc (',', asm_out_file);
+-  dbxout_int (stype);
+-  fputs (",0,", asm_out_file);
+-  dbxout_int (sdesc);
+-  putc (',', asm_out_file);
+-}
+-
+-/* The next set of functions are entirely concerned with production of
+-   "complex" .stabs directives: that is, .stabs directives whose
+-   strings have to be constructed piecemeal.  dbxout_type,
+-   dbxout_symbol, etc. use these routines heavily.  The string is queued
+-   up in an obstack, then written out by dbxout_finish_complex_stabs, which
+-   is also responsible for splitting it up if it exceeds DBX_CONTIN_LENGTH.
+-   (You might think it would be more efficient to go straight to stdio
+-   when DBX_CONTIN_LENGTH is 0 (i.e. no length limit) but that turns
+-   out not to be the case, and anyway this needs fewer #ifdefs.)  */
+-
+-/* Begin a complex .stabs directive.  If we can, write the initial
+-   ASM_STABS_OP to the asm_out_file.  */
+-
+-static void
+-dbxout_begin_complex_stabs (void)
+-{
+-  emit_pending_bincls_if_required ();
+-  FORCE_TEXT;
+-  fputs (ASM_STABS_OP, asm_out_file);
+-  putc ('"', asm_out_file);
+-  gcc_assert (stabstr_last_contin_point == 0);
+-}
+-
+-/* As above, but do not force text or emit pending bincls.  This is
+-   used by dbxout_symbol_location, which needs to do something else.  */
+-static void
+-dbxout_begin_complex_stabs_noforcetext (void)
+-{
+-  fputs (ASM_STABS_OP, asm_out_file);
+-  putc ('"', asm_out_file);
+-  gcc_assert (stabstr_last_contin_point == 0);
+-}
+-
+-/* Add CHR, a single character, to the string being built.  */
+-#define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr)
+-
+-/* Add STR, a normal C string, to the string being built.  */
+-#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen (str))
+-
+-/* Add the text of ID, an IDENTIFIER_NODE, to the string being built.  */
+-#define stabstr_I(id) obstack_grow (&stabstr_ob, \
+-                                    IDENTIFIER_POINTER (id), \
+-                                    IDENTIFIER_LENGTH (id))
+-
+-/* Add NUM, a signed decimal number, to the string being built.  */
+-static void
+-stabstr_D (HOST_WIDE_INT num)
+-{
+-  char buf[64];
+-  char *p = buf + sizeof buf;
+-  unsigned HOST_WIDE_INT unum;
+-
+-  if (num == 0)
+-    {
+-      stabstr_C ('0');
+-      return;
+-    }
+-  if (num < 0)
+-    {
+-      stabstr_C ('-');
+-      unum = -(unsigned HOST_WIDE_INT) num;
+-    }
+-  else
+-    unum = num;
+-
+-  NUMBER_FMT_LOOP (p, unum, 10);
+-
+-  obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+-}
+-
+-/* Add NUM, an unsigned decimal number, to the string being built.  */
+-static void
+-stabstr_U (unsigned HOST_WIDE_INT num)
+-{
+-  char buf[64];
+-  char *p = buf + sizeof buf;
+-  if (num == 0)
+-    {
+-      stabstr_C ('0');
+-      return;
+-    }
+-  NUMBER_FMT_LOOP (p, num, 10);
+-  obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+-}
+-
+-/* Add CST, an INTEGER_CST tree, to the string being built as an
+-   unsigned octal number.  This routine handles values which are
+-   larger than a single HOST_WIDE_INT.  */
+-static void
+-stabstr_O (tree cst)
+-{
+-  int prec = TYPE_PRECISION (TREE_TYPE (cst));
+-  int res_pres = prec % 3;
+-  int i;
+-  unsigned int digit;
+-
+-  /* Leading zero for base indicator.  */
+-  stabstr_C ('0');
+-
+-  /* If the value is zero, the base indicator will serve as the value
+-     all by itself.  */
+-  if (wi::to_wide (cst) == 0)
+-    return;
+-
+-  /* GDB wants constants with no extra leading "1" bits, so
+-     we need to remove any sign-extension that might be
+-     present.  */
+-  if (res_pres == 1)
+-    {
+-      digit = wi::extract_uhwi (wi::to_wide (cst), prec - 1, 1);
+-      stabstr_C ('0' + digit);
+-    }
+-  else if (res_pres == 2)
+-    {
+-      digit = wi::extract_uhwi (wi::to_wide (cst), prec - 2, 2);
+-      stabstr_C ('0' + digit);
+-    }
+-
+-  prec -= res_pres;
+-  for (i = prec - 3; i >= 0; i = i - 3)
+-    {
+-      digit = wi::extract_uhwi (wi::to_wide (cst), i, 3);
+-      stabstr_C ('0' + digit);
+-    }
+-}
+-
+-/* Called whenever it is safe to break a stabs string into multiple
+-   .stabs directives.  If the current string has exceeded the limit
+-   set by DBX_CONTIN_LENGTH, mark the current position in the buffer
+-   as a continuation point by inserting DBX_CONTIN_CHAR (doubled if
+-   it is a backslash) and a null character.  */
+-static inline void
+-stabstr_continue (void)
+-{
+-  if (DBX_CONTIN_LENGTH > 0
+-      && obstack_object_size (&stabstr_ob) - stabstr_last_contin_point
+-	 > DBX_CONTIN_LENGTH)
+-    {
+-      if (DBX_CONTIN_CHAR == '\\')
+-	obstack_1grow (&stabstr_ob, '\\');
+-      obstack_1grow (&stabstr_ob, DBX_CONTIN_CHAR);
+-      obstack_1grow (&stabstr_ob, '\0');
+-      stabstr_last_contin_point = obstack_object_size (&stabstr_ob);
+-    }
+-}
+-#define CONTIN stabstr_continue ()
+-
+-/* Macro subroutine of dbxout_finish_complex_stabs, which emits
+-   all of the arguments to the .stabs directive after the string.
+-   Overridden by xcoffout.h.  CODE is the stabs code for this symbol;
+-   LINE is the source line to write into the desc field (in extended
+-   mode); SYM is the symbol itself.
+-
+-   ADDR, LABEL, and NUMBER are three different ways to represent the
+-   stabs value field.  At most one of these should be nonzero.
+-
+-     ADDR is used most of the time; it represents the value as an
+-     RTL address constant.
+-
+-     LABEL is used (currently) only for N_CATCH stabs; it represents
+-     the value as a string suitable for assemble_name.
+-
+-     NUMBER is used when the value is an offset from an implicit base
+-     pointer (e.g. for a stack variable), or an index (e.g. for a
+-     register variable).  It represents the value as a decimal integer.  */
+-
+-#ifndef DBX_FINISH_STABS
+-#define DBX_FINISH_STABS(SYM, CODE, LINE, ADDR, LABEL, NUMBER)	\
+-do {								\
+-  int line_ = use_gnu_debug_info_extensions ? LINE : 0;		\
+-								\
+-  dbxout_int (CODE);						\
+-  fputs (",0,", asm_out_file);					\
+-  dbxout_int (line_);						\
+-  putc (',', asm_out_file);					\
+-  if (ADDR)							\
+-    output_addr_const (asm_out_file, ADDR);			\
+-  else if (LABEL)						\
+-    assemble_name (asm_out_file, LABEL);			\
+-  else								\
+-    dbxout_int (NUMBER);					\
+-  putc ('\n', asm_out_file);					\
+-} while (0)
+-#endif
+-
+-/* Finish the emission of a complex .stabs directive.  When DBX_CONTIN_LENGTH
+-   is zero, this has only to emit the close quote and the remainder of
+-   the arguments.  When it is nonzero, the string has been marshalled in
+-   stabstr_ob, and this routine is responsible for breaking it up into
+-   DBX_CONTIN_LENGTH-sized chunks.
+-
+-   SYM is the DECL of the symbol under consideration; it is used only
+-   for its DECL_SOURCE_LINE.  The other arguments are all passed directly
+-   to DBX_FINISH_STABS; see above for details.  */
+-
+-static void
+-dbxout_finish_complex_stabs (tree sym, stab_code_type code,
+-			     rtx addr, const char *label, int number)
+-{
+-  int line ATTRIBUTE_UNUSED;
+-  char *str;
+-  size_t len;
+-
+-  line = sym ? DECL_SOURCE_LINE (sym) : 0;
+-  if (DBX_CONTIN_LENGTH > 0)
+-    {
+-      char *chunk;
+-      size_t chunklen;
+-
+-      /* Nul-terminate the growing string, then get its size and
+-	 address.  */
+-      obstack_1grow (&stabstr_ob, '\0');
+-
+-      len = obstack_object_size (&stabstr_ob);
+-      chunk = str = XOBFINISH (&stabstr_ob, char *);
+-
+-      /* Within the buffer are a sequence of NUL-separated strings,
+-	 each of which is to be written out as a separate stab
+-	 directive.  */
+-      for (;;)
+-	{
+-	  chunklen = strlen (chunk);
+-	  fwrite (chunk, 1, chunklen, asm_out_file);
+-	  fputs ("\",", asm_out_file);
+-
+-	  /* Must add an extra byte to account for the NUL separator.  */
+-	  chunk += chunklen + 1;
+-	  len   -= chunklen + 1;
+-
+-	  /* Only put a line number on the last stab in the sequence.  */
+-	  DBX_FINISH_STABS (sym, code, len == 0 ? line : 0,
+-			    addr, label, number);
+-	  if (len == 0)
+-	    break;
+-
+-	  fputs (ASM_STABS_OP, asm_out_file);
+-	  putc ('"', asm_out_file);
+-	}
+-      stabstr_last_contin_point = 0;
+-    }
+-  else
+-    {
+-      /* No continuations - we can put the whole string out at once.
+-	 It is faster to augment the string with the close quote and
+-	 comma than to do a two-character fputs.  */
+-      obstack_grow (&stabstr_ob, "\",", 2);
+-      len = obstack_object_size (&stabstr_ob);
+-      str = XOBFINISH (&stabstr_ob, char *);
+-
+-      fwrite (str, 1, len, asm_out_file);
+-      DBX_FINISH_STABS (sym, code, line, addr, label, number);
+-    }
+-  obstack_free (&stabstr_ob, str);
+-}
+-
+-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+-
+-/* When -gused is used, emit debug info for only used symbols. But in
+-   addition to the standard intercepted debug_hooks there are some
+-   direct calls into this file, i.e., dbxout_symbol, dbxout_parms, and
+-   dbxout_reg_params.  Those routines may also be called from a higher
+-   level intercepted routine. So to prevent recording data for an inner
+-   call to one of these for an intercept, we maintain an intercept
+-   nesting counter (debug_nesting). We only save the intercepted
+-   arguments if the nesting is 1.  */
+-static int debug_nesting = 0;
+-
+-static tree *symbol_queue;
+-static int symbol_queue_index = 0;
+-static int symbol_queue_size = 0;
+-
+-#define DBXOUT_DECR_NESTING \
+-  if (--debug_nesting == 0 && symbol_queue_index > 0) \
+-    { emit_pending_bincls_if_required (); debug_flush_symbol_queue (); }
+-
+-#define DBXOUT_DECR_NESTING_AND_RETURN(x) \
+-  do {--debug_nesting; return (x);} while (0)
+-
+-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+-
+-#if defined (DBX_DEBUGGING_INFO)
+-
+-static void
+-dbxout_function_end (tree decl ATTRIBUTE_UNUSED)
+-{
+-  char lscope_label_name[100];
+-
+-  /* The Lscope label must be emitted even if we aren't doing anything
+-     else; dbxout_block needs it.  */
+-  switch_to_section (current_function_section ());
+-
+-  /* Convert Lscope into the appropriate format for local labels in case
+-     the system doesn't insert underscores in front of user generated
+-     labels.  */
+-  ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno);
+-  targetm.asm_out.internal_label (asm_out_file, "Lscope", scope_labelno);
+-
+-  /* The N_FUN tag at the end of the function is a GNU extension,
+-     which may be undesirable, and is unnecessary if we do not have
+-     named sections.  */
+-  if (!use_gnu_debug_info_extensions
+-      || NO_DBX_FUNCTION_END
+-      || !targetm_common.have_named_sections)
+-    return;
+-
+-  /* By convention, GCC will mark the end of a function with an N_FUN
+-     symbol and an empty string.  */
+-  if (crtl->has_bb_partition)
+-    {
+-      dbxout_begin_empty_stabs (N_FUN);
+-      if (in_cold_section_p)
+-	dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label,
+-				      crtl->subsections.cold_section_label);
+-      else
+-	dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label,
+-				      crtl->subsections.hot_section_label);
+-    }
+-  else
+-    {
+-      char begin_label[20];
+-      /* Reference current function start using LFBB.  */
+-      ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+-      dbxout_begin_empty_stabs (N_FUN);
+-      dbxout_stab_value_label_diff (lscope_label_name, begin_label);
+-    }
+-
+-  if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols)
+-    dbxout_stabd (N_ENSYM, 0);
+-}
+-#endif /* DBX_DEBUGGING_INFO */
+-
+-/* Get lang description for N_SO stab.  */
+-static unsigned int ATTRIBUTE_UNUSED
+-get_lang_number (void)
+-{
+-  const char *language_string = lang_hooks.name;
+-  if (lang_GNU_C ())
+-    return N_SO_C;
+-  else if (lang_GNU_CXX ())
+-    return N_SO_CC;
+-  else if (strcmp (language_string, "GNU F77") == 0)
+-    return N_SO_FORTRAN;
+-  else if (lang_GNU_Fortran ())
+-    return N_SO_FORTRAN90; /* CHECKME */
+-  else if (strcmp (language_string, "GNU Objective-C") == 0)
+-    return N_SO_OBJC;
+-  else if (strcmp (language_string, "GNU Objective-C++") == 0)
+-    return N_SO_OBJCPLUS;
+-  else
+-    return 0;
+-
+-}
+-
+-static bool
+-is_fortran (void)
+-{
+-   unsigned int lang = get_lang_number ();
+-
+-   return (lang == N_SO_FORTRAN) || (lang == N_SO_FORTRAN90);
+-}
+-
+-/* At the beginning of compilation, start writing the symbol table.
+-   Initialize `typevec' and output the standard data types of C.  */
+-
+-static void
+-dbxout_init (const char *input_file_name)
+-{
+-  char ltext_label_name[100];
+-  bool used_ltext_label_name = false;
+-  tree syms = lang_hooks.decls.getdecls ();
+-  const char *mapped_name;
+-
+-  typevec_len = 100;
+-  typevec = ggc_cleared_vec_alloc (typevec_len);
+-
+-  /* stabstr_ob contains one string, which will be just fine with
+-     1-byte alignment.  */
+-  obstack_specify_allocation (&stabstr_ob, 0, 1, xmalloc, free);
+-
+-  /* Convert Ltext into the appropriate format for local labels in case
+-     the system doesn't insert underscores in front of user generated
+-     labels.  */
+-  ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
+-
+-  /* Put the current working directory in an N_SO symbol.  */
+-  if (use_gnu_debug_info_extensions && !NO_DBX_MAIN_SOURCE_DIRECTORY)
+-    {
+-      static const char *cwd;
+-
+-      if (!cwd)
+-	{
+-	  cwd = get_src_pwd ();
+-	  if (cwd[0] == '\0')
+-	    cwd = "/";
+-	  else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1]))
+-	    cwd = concat (cwd, "/", NULL);
+-	  cwd = remap_debug_filename (cwd);
+-	}
+-#ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
+-      DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd);
+-#else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
+-      dbxout_begin_simple_stabs_desc (cwd, N_SO, get_lang_number ());
+-      dbxout_stab_value_label (ltext_label_name);
+-      used_ltext_label_name = true;
+-#endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
+-    }
+-
+-  mapped_name = remap_debug_filename (input_file_name);
+-#ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
+-  DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, mapped_name);
+-#else
+-  dbxout_begin_simple_stabs_desc (mapped_name, N_SO, get_lang_number ());
+-  dbxout_stab_value_label (ltext_label_name);
+-  used_ltext_label_name = true;
+-#endif
+-
+-  if (used_ltext_label_name)
+-    {
+-      switch_to_section (text_section);
+-      targetm.asm_out.internal_label (asm_out_file, "Ltext", 0);
+-    }
+-
+-  /* Emit an N_OPT stab to indicate that this file was compiled by GCC.
+-     The string used is historical.  */
+-#ifndef NO_DBX_GCC_MARKER
+-  dbxout_begin_simple_stabs ("gcc2_compiled.", N_OPT);
+-  dbxout_stab_value_zero ();
+-#endif
+-
+-  base_input_file = lastfile = input_file_name;
+-
+-  next_type_number = 1;
+-
+-#ifdef DBX_USE_BINCL
+-  current_file = XNEW (struct dbx_file);
+-  current_file->next = NULL;
+-  current_file->file_number = 0;
+-  current_file->next_type_number = 1;
+-  next_file_number = 1;
+-  current_file->prev = NULL;
+-  current_file->bincl_status = BINCL_NOT_REQUIRED;
+-  current_file->pending_bincl_name = NULL;
+-#endif
+-
+-  /* Get all permanent types that have typedef names, and output them
+-     all, except for those already output.  Some language front ends
+-     put these declarations in the top-level scope; some do not;
+-     the latter are responsible for calling debug_hooks->type_decl from
+-     their record_builtin_type function.  */
+-  dbxout_typedefs (syms);
+-
+-  if (preinit_symbols)
+-    {
+-      tree t;
+-      for (t = nreverse (preinit_symbols); t; t = TREE_CHAIN (t))
+-	dbxout_symbol (TREE_VALUE (t), 0);
+-      preinit_symbols = 0;
+-    }
+-}
+-
+-/* Output any typedef names for types described by TYPE_DECLs in SYMS.  */
+-
+-static void
+-dbxout_typedefs (tree syms)
+-{
+-  for (; syms != NULL_TREE; syms = DECL_CHAIN (syms))
+-    {
+-      if (TREE_CODE (syms) == TYPE_DECL)
+-	{
+-	  tree type = TREE_TYPE (syms);
+-	  if (TYPE_NAME (type)
+-	      && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+-	      && COMPLETE_OR_VOID_TYPE_P (type)
+-	      && ! TREE_ASM_WRITTEN (TYPE_NAME (type)))
+-	    dbxout_symbol (TYPE_NAME (type), 0);
+-	}
+-    }
+-}
+-
+-#ifdef DBX_USE_BINCL
+-/* Emit BINCL stab using given name.  */
+-static void
+-emit_bincl_stab (const char *name)
+-{
+-  dbxout_begin_simple_stabs (name, N_BINCL);
+-  dbxout_stab_value_zero ();
+-}
+-
+-/* If there are pending bincls then it is time to emit all of them.  */
+-
+-static inline void
+-emit_pending_bincls_if_required (void)
+-{
+-  if (pending_bincls)
+-    emit_pending_bincls ();
+-}
+-
+-/* Emit all pending bincls.  */
+-
+-static void
+-emit_pending_bincls (void)
+-{
+-  struct dbx_file *f = current_file;
+-
+-  /* Find first pending bincl.  */
+-  while (f->bincl_status == BINCL_PENDING)
+-    f = f->next;
+-
+-  /* Now emit all bincls.  */
+-  f = f->prev;
+-
+-  while (f)
+-    {
+-      if (f->bincl_status == BINCL_PENDING)
+-        {
+-          emit_bincl_stab (f->pending_bincl_name);
+-
+-	  /* Update file number and status.  */
+-          f->file_number = next_file_number++;
+-          f->bincl_status = BINCL_PROCESSED;
+-        }
+-      if (f == current_file)
+-        break;
+-      f = f->prev;
+-    }
+-
+-  /* All pending bincls have been emitted.  */
+-  pending_bincls = 0;
+-}
+-
+-#else
+-
+-static inline void
+-emit_pending_bincls_if_required (void) {}
+-#endif
+-
+-/* Change to reading from a new source file.  Generate a N_BINCL stab.  */
+-
+-static void
+-dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
+-			  const char *filename ATTRIBUTE_UNUSED)
+-{
+-#ifdef DBX_USE_BINCL
+-  struct dbx_file *n = XNEW (struct dbx_file);
+-
+-  n->next = current_file;
+-  n->next_type_number = 1;
+-  /* Do not assign file number now.
+-     Delay it until we actually emit BINCL.  */
+-  n->file_number = 0;
+-  n->prev = NULL;
+-  current_file->prev = n;
+-  n->bincl_status = BINCL_PENDING;
+-  n->pending_bincl_name = remap_debug_filename (filename);
+-  pending_bincls = 1;
+-  current_file = n;
+-#endif
+-}
+-
+-/* Revert to reading a previous source file.  Generate a N_EINCL stab.  */
+-
+-static void
+-dbxout_end_source_file (unsigned int line ATTRIBUTE_UNUSED)
+-{
+-#ifdef DBX_USE_BINCL
+-  /* Emit EINCL stab only if BINCL is not pending.  */
+-  if (current_file->bincl_status == BINCL_PROCESSED)
+-    {
+-      dbxout_begin_stabn (N_EINCL);
+-      dbxout_stab_value_zero ();
+-    }
+-  current_file->bincl_status = BINCL_NOT_REQUIRED;
+-  current_file = current_file->next;
+-#endif
+-}
+-
+-/* Handle a few odd cases that occur when trying to make PCH files work.  */
+-
+-static void
+-dbxout_handle_pch (unsigned at_end)
+-{
+-  if (! at_end)
+-    {
+-      /* When using the PCH, this file will be included, so we need to output
+-	 a BINCL.  */
+-      dbxout_start_source_file (0, lastfile);
+-
+-      /* The base file when using the PCH won't be the same as
+-	 the base file when it's being generated.  */
+-      lastfile = NULL;
+-    }
+-  else
+-    {
+-      /* ... and an EINCL.  */
+-      dbxout_end_source_file (0);
+-
+-      /* Deal with cases where 'lastfile' was never actually changed.  */
+-      lastfile_is_base = lastfile == NULL;
+-    }
+-}
+-
+-#if defined (DBX_DEBUGGING_INFO)
+-
+-static bool dbxout_block (tree, int, tree, int);
+-
+-/* Output debugging info to FILE to switch to sourcefile FILENAME.  */
+-
+-static void
+-dbxout_source_file (const char *filename)
+-{
+-  if (lastfile == 0 && lastfile_is_base)
+-    {
+-      lastfile = base_input_file;
+-      lastfile_is_base = 0;
+-    }
+-
+-  if (filename && (lastfile == 0 || strcmp (filename, lastfile)))
+-    {
+-      /* Don't change section amid function.  */
+-      if (current_function_decl == NULL_TREE)
+-	switch_to_section (text_section);
+-
+-      dbxout_begin_simple_stabs (remap_debug_filename (filename), N_SOL);
+-      dbxout_stab_value_internal_label ("Ltext", &source_label_number);
+-      lastfile = filename;
+-    }
+-}
+-
+-/* Output N_BNSYM, line number symbol entry, and local symbol at
+-   function scope  */
+-
+-static void
+-dbxout_begin_prologue (unsigned int lineno,
+-		       unsigned int column ATTRIBUTE_UNUSED,
+-		       const char *filename)
+-{
+-  if (use_gnu_debug_info_extensions
+-      && !NO_DBX_FUNCTION_END
+-      && !NO_DBX_BNSYM_ENSYM
+-      && !flag_debug_only_used_symbols)
+-    dbxout_stabd (N_BNSYM, 0);
+-
+-  /* pre-increment the scope counter */
+-  scope_labelno++;
+-
+-  dbxout_source_line (lineno, 0, filename, 0, true);
+-  /* Output function begin block at function scope, referenced
+-     by dbxout_block, dbxout_source_line and dbxout_function_end.  */
+-  emit_pending_bincls_if_required ();
+-  targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno);
+-}
+-
+-/* Output a line number symbol entry for source file FILENAME and line
+-   number LINENO.  */
+-
+-static void
+-dbxout_source_line (unsigned int lineno, unsigned int column ATTRIBUTE_UNUSED,
+-		    const char *filename, int discriminator ATTRIBUTE_UNUSED,
+-                    bool is_stmt ATTRIBUTE_UNUSED)
+-{
+-  dbxout_source_file (filename);
+-
+-#ifdef DBX_OUTPUT_SOURCE_LINE
+-  DBX_OUTPUT_SOURCE_LINE (asm_out_file, lineno, dbxout_source_line_counter);
+-#else
+-  if (DBX_LINES_FUNCTION_RELATIVE)
+-    {
+-      char begin_label[20];
+-      dbxout_begin_stabn_sline (lineno);
+-      /* Reference current function start using LFBB.  */
+-      ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+-      dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter,
+-					     begin_label);
+-    }
+-  else
+-    dbxout_stabd (N_SLINE, lineno);
+-#endif
+-  lastlineno = lineno;
+-}
+-
+-/* Unfortunately, at least when emitting relative addresses, STABS
+-   has no way to express multiple partitions.  Represent a function
+-   as two functions in this case.  */
+-
+-static void
+-dbxout_switch_text_section (void)
+-{
+-  /* The N_FUN tag at the end of the function is a GNU extension,
+-     which may be undesirable, and is unnecessary if we do not have
+-     named sections.  */
+-  in_cold_section_p = !in_cold_section_p;
+-  switch_to_section (current_function_section ());
+-  dbxout_block (DECL_INITIAL (current_function_decl), 0,
+-		DECL_ARGUMENTS (current_function_decl), -1);
+-  dbxout_function_end (current_function_decl);
+-  in_cold_section_p = !in_cold_section_p;
+-
+-  switch_to_section (current_function_section ());
+-
+-  tree context = decl_function_context (current_function_decl);
+-  extern tree cold_function_name;
+-
+-  dbxout_begin_complex_stabs ();
+-  stabstr_I (cold_function_name);
+-  stabstr_S (":f");
+-
+-  tree type = TREE_TYPE (current_function_decl);
+-  if (TREE_TYPE (type))
+-    dbxout_type (TREE_TYPE (type), 0);
+-  else
+-    dbxout_type (void_type_node, 0);
+-
+-  if (context != 0)
+-    {
+-      stabstr_C (',');
+-      stabstr_I (cold_function_name);
+-      stabstr_C (',');
+-      stabstr_I (DECL_NAME (context));
+-    }
+-
+-  dbxout_finish_complex_stabs (current_function_decl, N_FUN, 0,
+-			       crtl->subsections.cold_section_label, 0);
+-
+-  /* pre-increment the scope counter */
+-  scope_labelno++;
+-
+-  dbxout_source_line (lastlineno, 0, lastfile, 0, true);
+-  /* Output function begin block at function scope, referenced
+-     by dbxout_block, dbxout_source_line and dbxout_function_end.  */
+-  emit_pending_bincls_if_required ();
+-  targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno);
+-}
+-
+-/* Describe the beginning of an internal block within a function.  */
+-
+-static void
+-dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
+-{
+-  emit_pending_bincls_if_required ();
+-  targetm.asm_out.internal_label (asm_out_file, "LBB", n);
+-}
+-
+-/* Describe the end line-number of an internal block within a function.  */
+-
+-static void
+-dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n)
+-{
+-  emit_pending_bincls_if_required ();
+-  targetm.asm_out.internal_label (asm_out_file, "LBE", n);
+-}
+-
+-/* Output dbx data for a function definition.
+-   This includes a definition of the function name itself (a symbol),
+-   definitions of the parameters (locating them in the parameter list)
+-   and then output the block that makes up the function's body
+-   (including all the auto variables of the function).  */
+-
+-static void
+-dbxout_function_decl (tree decl)
+-{
+-  emit_pending_bincls_if_required ();
+-#ifndef DBX_FUNCTION_FIRST
+-  dbxout_begin_function (decl);
+-#endif
+-  dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl), -1);
+-  dbxout_function_end (decl);
+-}
+-
+-#endif /* DBX_DEBUGGING_INFO  */
+-
+-static void
+-dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+-{
+-  /* NYI for non-dwarf.  */
+-}
+-
+-/* Debug information for a global DECL.  Called from toplev.cc after
+-   compilation proper has finished.  */
+-static void
+-dbxout_late_global_decl (tree decl)
+-{
+-  if (VAR_P (decl) && !DECL_EXTERNAL (decl))
+-    {
+-      int saved_tree_used = TREE_USED (decl);
+-      TREE_USED (decl) = 1;
+-      dbxout_symbol (decl, 0);
+-      TREE_USED (decl) = saved_tree_used;
+-    }
+-}
+-
+-/* This is just a function-type adapter; dbxout_symbol does exactly
+-   what we want but returns an int.  */
+-static void
+-dbxout_type_decl (tree decl, int local)
+-{
+-  dbxout_symbol (decl, local);
+-}
+-
+-/* At the end of compilation, finish writing the symbol table.
+-   The default is to call debug_free_queue but do nothing else.  */
+-
+-static void
+-dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
+-{
+-#ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END
+-  DBX_OUTPUT_MAIN_SOURCE_FILE_END (asm_out_file, filename);
+-#elif defined DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+- {
+-   switch_to_section (text_section);
+-   dbxout_begin_empty_stabs (N_SO);
+-   dbxout_stab_value_internal_label ("Letext", 0);
+- }
+-#endif
+-  debug_free_queue ();
+-}
+-
+-/* Output the index of a type.  */
+-
+-static void
+-dbxout_type_index (tree type)
+-{
+-#ifndef DBX_USE_BINCL
+-  stabstr_D (TYPE_SYMTAB_ADDRESS (type));
+-#else
+-  struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)];
+-  stabstr_C ('(');
+-  stabstr_D (t->file_number);
+-  stabstr_C (',');
+-  stabstr_D (t->type_number);
+-  stabstr_C (')');
+-#endif
+-}
+-
+-
+-/* Generate the symbols for any queued up type symbols we encountered
+-   while generating the type info for some originally used symbol.
+-   This might generate additional entries in the queue.  Only when
+-   the nesting depth goes to 0 is this routine called.  */
+-
+-static void
+-debug_flush_symbol_queue (void)
+-{
+-  int i;
+-
+-  /* Make sure that additionally queued items are not flushed
+-     prematurely.  */
+-
+-  ++debug_nesting;
+-
+-  for (i = 0; i < symbol_queue_index; ++i)
+-    {
+-      /* If we pushed queued symbols then such symbols must be
+-         output no matter what anyone else says.  Specifically,
+-         we need to make sure dbxout_symbol() thinks the symbol was
+-         used and also we need to override TYPE_DECL_SUPPRESS_DEBUG
+-         which may be set for outside reasons.  */
+-      int saved_tree_used = TREE_USED (symbol_queue[i]);
+-      int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]);
+-      TREE_USED (symbol_queue[i]) = 1;
+-      TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0;
+-
+-#ifdef DBX_DEBUGGING_INFO
+-      dbxout_symbol (symbol_queue[i], 0);
+-#endif
+-
+-      TREE_USED (symbol_queue[i]) = saved_tree_used;
+-      TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug;
+-    }
+-
+-  symbol_queue_index = 0;
+-  --debug_nesting;
+-}
+-
+-/* Queue a type symbol needed as part of the definition of a decl
+-   symbol.  These symbols are generated when debug_flush_symbol_queue()
+-   is called.  */
+-
+-static void
+-debug_queue_symbol (tree decl)
+-{
+-  if (symbol_queue_index >= symbol_queue_size)
+-    {
+-      symbol_queue_size += 10;
+-      symbol_queue = XRESIZEVEC (tree, symbol_queue, symbol_queue_size);
+-    }
+-
+-  symbol_queue[symbol_queue_index++] = decl;
+-}
+-
+-/* Free symbol queue.  */
+-static void
+-debug_free_queue (void)
+-{
+-  if (symbol_queue)
+-    {
+-      free (symbol_queue);
+-      symbol_queue = NULL;
+-      symbol_queue_size = 0;
+-    }
+-}
+-
+-/* Used in several places: evaluates to '0' for a private decl,
+-   '1' for a protected decl, '2' for a public decl.  */
+-#define DECL_ACCESSIBILITY_CHAR(DECL) \
+-(TREE_PRIVATE (DECL) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2')
+-
+-/* Subroutine of `dbxout_type'.  Output the type fields of TYPE.
+-   This must be a separate function because anonymous unions require
+-   recursive calls.  */
+-
+-static void
+-dbxout_type_fields (tree type)
+-{
+-  tree tem;
+-
+-  /* Output the name, type, position (in bits), size (in bits) of each
+-     field that we can support.  */
+-  for (tem = TYPE_FIELDS (type); tem; tem = DECL_CHAIN (tem))
+-    {
+-      /* If one of the nodes is an error_mark or its type is then
+-	 return early.  */
+-      if (error_operand_p (tem))
+-	return;
+-
+-      /* Omit here local type decls until we know how to support them.  */
+-      if (TREE_CODE (tem) == TYPE_DECL
+-	  || TREE_CODE (tem) == TEMPLATE_DECL
+-	  /* Member functions emitted after fields.  */
+-	  || TREE_CODE (tem) == FUNCTION_DECL
+-	  /* Omit here the nameless fields that are used to skip bits.  */
+-	  || DECL_IGNORED_P (tem)
+-	  /* Omit fields whose position or size are variable or too large to
+-	     represent.  */
+-	  || (TREE_CODE (tem) == FIELD_DECL
+-	      && (! tree_fits_shwi_p (bit_position (tem))
+-		  || ! DECL_SIZE (tem)
+-		  || ! tree_fits_uhwi_p (DECL_SIZE (tem)))))
+-	continue;
+-
+-      else if (TREE_CODE (tem) != CONST_DECL)
+-	{
+-	  /* Continue the line if necessary,
+-	     but not before the first field.  */
+-	  if (tem != TYPE_FIELDS (type))
+-	    CONTIN;
+-
+-	  if (DECL_NAME (tem))
+-	    stabstr_I (DECL_NAME (tem));
+-	  stabstr_C (':');
+-
+-	  if (use_gnu_debug_info_extensions
+-	      && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem)
+-		  || TREE_CODE (tem) != FIELD_DECL))
+-	    {
+-	      stabstr_C ('/');
+-	      stabstr_C (DECL_ACCESSIBILITY_CHAR (tem));
+-	    }
+-
+-	  dbxout_type ((TREE_CODE (tem) == FIELD_DECL
+-			&& DECL_BIT_FIELD_TYPE (tem))
+-		       ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0);
+-
+-	  if (VAR_P (tem))
+-	    {
+-	      if (TREE_STATIC (tem) && use_gnu_debug_info_extensions)
+-		{
+-		  tree name = DECL_ASSEMBLER_NAME (tem);
+-
+-		  stabstr_C (':');
+-		  stabstr_I (name);
+-		  stabstr_C (';');
+-		}
+-	      else
+-		/* If TEM is non-static, GDB won't understand it.  */
+-		stabstr_S (",0,0;");
+-	    }
+-	  else
+-	    {
+-	      stabstr_C (',');
+-	      stabstr_D (int_bit_position (tem));
+-	      stabstr_C (',');
+-	      stabstr_D (tree_to_uhwi (DECL_SIZE (tem)));
+-	      stabstr_C (';');
+-	    }
+-	}
+-    }
+-}
+-
+-/* Subroutine of `dbxout_type_methods'.  Output debug info about the
+-   method described DECL.  */
+-
+-static void
+-dbxout_type_method_1 (tree decl)
+-{
+-  char c1 = 'A', c2;
+-
+-  if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
+-    c2 = '?';
+-  else /* it's a METHOD_TYPE.  */
+-    {
+-      tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)));
+-      /* A for normal functions.
+-	 B for `const' member functions.
+-	 C for `volatile' member functions.
+-	 D for `const volatile' member functions.  */
+-      if (TYPE_READONLY (TREE_TYPE (firstarg)))
+-	c1 += 1;
+-      if (TYPE_VOLATILE (TREE_TYPE (firstarg)))
+-	c1 += 2;
+-
+-      if (DECL_VINDEX (decl))
+-	c2 = '*';
+-      else
+-	c2 = '.';
+-    }
+-
+-  /* ??? Output the mangled name, which contains an encoding of the
+-     method's type signature.  May not be necessary anymore.  */
+-  stabstr_C (':');
+-  stabstr_I (DECL_ASSEMBLER_NAME (decl));
+-  stabstr_C (';');
+-  stabstr_C (DECL_ACCESSIBILITY_CHAR (decl));
+-  stabstr_C (c1);
+-  stabstr_C (c2);
+-
+-  if (DECL_VINDEX (decl) && tree_fits_shwi_p (DECL_VINDEX (decl)))
+-    {
+-      stabstr_D (tree_to_shwi (DECL_VINDEX (decl)));
+-      stabstr_C (';');
+-      dbxout_type (DECL_CONTEXT (decl), 0);
+-      stabstr_C (';');
+-    }
+-}
+-
+-/* Subroutine of `dbxout_type'.  Output debug info about the member
+-   functions defined in TYPE.  */
+-
+-static void
+-dbxout_type_methods (tree type)
+-{
+-  for (tree fndecl = TYPE_FIELDS (type); fndecl;)
+-    {
+-      int need_prefix = 1;
+-
+-      /* Group together all the methods for the same operation.
+-	 These differ in the types of the arguments.  */
+-      for (tree last = NULL_TREE;
+-	   fndecl && (last == NULL_TREE || DECL_NAME (fndecl) == DECL_NAME (last));
+-	   fndecl = DECL_CHAIN (fndecl))
+-	/* Output the name of the field (after overloading), as
+-	   well as the name of the field before overloading, along
+-	   with its parameter list */
+-	{
+-	  /* Skip non-functions.  */
+-	  if (TREE_CODE (fndecl) != FUNCTION_DECL)
+-	    continue;
+-
+-	  /* Also ignore abstract methods; those are only interesting to
+-	     the DWARF backends.  */
+-	  if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT_P (fndecl))
+-	    continue;
+-
+-	  CONTIN;
+-
+-	  last = fndecl;
+-
+-	  /* Redundantly output the plain name, since that's what gdb
+-	     expects.  */
+-	  if (need_prefix)
+-	    {
+-	      stabstr_I (DECL_NAME (fndecl));
+-	      stabstr_S ("::");
+-	      need_prefix = 0;
+-	    }
+-
+-	  dbxout_type (TREE_TYPE (fndecl), 0);
+-	  dbxout_type_method_1 (fndecl);
+-	}
+-      if (!need_prefix)
+-	stabstr_C (';');
+-    }
+-}
+-
+-/* Emit a "range" type specification, which has the form:
+-   "r;;;".
+-   TYPE is an INTEGER_TYPE, LOW and HIGH are the bounds.  */
+-
+-static void
+-dbxout_range_type (tree type, tree low, tree high)
+-{
+-  stabstr_C ('r');
+-  if (TREE_TYPE (type))
+-    dbxout_type (TREE_TYPE (type), 0);
+-  else if (TREE_CODE (type) != INTEGER_TYPE)
+-    dbxout_type (type, 0);
+-  else
+-    {
+-      /* Traditionally, we made sure 'int' was type 1, and builtin types
+-	 were defined to be sub-ranges of int.  Unfortunately, this
+-	 does not allow us to distinguish true sub-ranges from integer
+-	 types.  So, instead we define integer (non-sub-range) types as
+-	 sub-ranges of themselves.  This matters for Chill.  If this isn't
+-	 a subrange type, then we want to define it in terms of itself.
+-	 However, in C, this may be an anonymous integer type, and we don't
+-	 want to emit debug info referring to it.  Just calling
+-	 dbxout_type_index won't work anyways, because the type hasn't been
+-	 defined yet.  We make this work for both cases by checked to see
+-	 whether this is a defined type, referring to it if it is, and using
+-	 'int' otherwise.  */
+-      if (TYPE_SYMTAB_ADDRESS (type) != 0)
+-	dbxout_type_index (type);
+-      else
+-	dbxout_type_index (integer_type_node);
+-    }
+-
+-  stabstr_C (';');
+-  if (low && tree_fits_shwi_p (low))
+-    {
+-      if (print_int_cst_bounds_in_octal_p (type, low, high))
+-        stabstr_O (low);
+-      else
+-        stabstr_D (tree_to_shwi (low));
+-    }
+-  else
+-    stabstr_C ('0');
+-
+-  stabstr_C (';');
+-  if (high && tree_fits_shwi_p (high))
+-    {
+-      if (print_int_cst_bounds_in_octal_p (type, low, high))
+-        stabstr_O (high);
+-      else
+-        stabstr_D (tree_to_shwi (high));
+-      stabstr_C (';');
+-    }
+-  else
+-    stabstr_S ("-1;");
+-}
+-
+-
+-/* Output a reference to a type.  If the type has not yet been
+-   described in the dbx output, output its definition now.
+-   For a type already defined, just refer to its definition
+-   using the type number.
+-
+-   If FULL is nonzero, and the type has been described only with
+-   a forward-reference, output the definition now.
+-   If FULL is zero in this case, just refer to the forward-reference
+-   using the number previously allocated.  */
+-
+-static void
+-dbxout_type (tree type, int full)
+-{
+-  static int anonymous_type_number = 0;
+-  tree tem, main_variant, low, high;
+-
+-  if (TREE_CODE (type) == INTEGER_TYPE)
+-    {
+-      if (TREE_TYPE (type) == 0)
+-	{
+-	  low = TYPE_MIN_VALUE (type);
+-	  high = TYPE_MAX_VALUE (type);
+-	}
+-
+-      else if (subrange_type_for_debug_p (type, &low, &high))
+-	;
+-
+-      /* If this is a subtype that should not be emitted as a subrange type,
+-	 use the base type.  */
+-      else
+-	{
+-	  type = TREE_TYPE (type);
+-	  low = TYPE_MIN_VALUE (type);
+-	  high = TYPE_MAX_VALUE (type);
+-	}
+-    }
+-
+-  /* If there was an input error and we don't really have a type,
+-     avoid crashing and write something that is at least valid
+-     by assuming `int'.  */
+-  if (type == error_mark_node)
+-    type = integer_type_node;
+-  else
+-    {
+-      if (TYPE_NAME (type)
+-	  && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+-	  && TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
+-	full = 0;
+-    }
+-
+-  /* Try to find the "main variant" with the same name.  */
+-  if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+-      && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+-    main_variant = TREE_TYPE (TYPE_NAME (type));
+-  else
+-    main_variant = TYPE_MAIN_VARIANT (type);
+-
+-  /* If we are not using extensions, stabs does not distinguish const and
+-     volatile, so there is no need to make them separate types.  */
+-  if (!use_gnu_debug_info_extensions)
+-    type = main_variant;
+-
+-  if (TYPE_SYMTAB_ADDRESS (type) == 0)
+-    {
+-      /* Type has no dbx number assigned.  Assign next available number.  */
+-      TYPE_SYMTAB_ADDRESS (type) = next_type_number++;
+-
+-      /* Make sure type vector is long enough to record about this type.  */
+-
+-      if (next_type_number == typevec_len)
+-	{
+-	  typevec = GGC_RESIZEVEC (struct typeinfo, typevec, typevec_len * 2);
+-	  memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]);
+-	  typevec_len *= 2;
+-	}
+-
+-#ifdef DBX_USE_BINCL
+-      emit_pending_bincls_if_required ();
+-      typevec[TYPE_SYMTAB_ADDRESS (type)].file_number
+-	= current_file->file_number;
+-      typevec[TYPE_SYMTAB_ADDRESS (type)].type_number
+-	= current_file->next_type_number++;
+-#endif
+-    }
+-
+-  if (flag_debug_only_used_symbols)
+-    {
+-      if ((TREE_CODE (type) == RECORD_TYPE
+-	   || TREE_CODE (type) == UNION_TYPE
+-	   || TREE_CODE (type) == QUAL_UNION_TYPE
+-	   || TREE_CODE (type) == ENUMERAL_TYPE)
+-	  && TYPE_STUB_DECL (type)
+-	  && DECL_P (TYPE_STUB_DECL (type))
+-	  && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
+-	debug_queue_symbol (TYPE_STUB_DECL (type));
+-      else if (TYPE_NAME (type)
+-	       && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+-	debug_queue_symbol (TYPE_NAME (type));
+-    }
+-
+-  /* Output the number of this type, to refer to it.  */
+-  dbxout_type_index (type);
+-
+-#ifdef DBX_TYPE_DEFINED
+-  if (DBX_TYPE_DEFINED (type))
+-    return;
+-#endif
+-
+-  /* If this type's definition has been output or is now being output,
+-     that is all.  */
+-
+-  switch (typevec[TYPE_SYMTAB_ADDRESS (type)].status)
+-    {
+-    case TYPE_UNSEEN:
+-      break;
+-    case TYPE_XREF:
+-      /* If we have already had a cross reference,
+-	 and either that's all we want or that's the best we could do,
+-	 don't repeat the cross reference.
+-	 Sun dbx crashes if we do.  */
+-      if (! full || !COMPLETE_TYPE_P (type)
+-	  /* No way in DBX fmt to describe a variable size.  */
+-	  || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
+-	return;
+-      break;
+-    case TYPE_DEFINED:
+-      return;
+-    }
+-
+-#ifdef DBX_NO_XREFS
+-  /* For systems where dbx output does not allow the `=xsNAME:' syntax,
+-     leave the type-number completely undefined rather than output
+-     a cross-reference.  If we have already used GNU debug info extensions,
+-     then it is OK to output a cross reference.  This is necessary to get
+-     proper C++ debug output.  */
+-  if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
+-       || TREE_CODE (type) == QUAL_UNION_TYPE
+-       || TREE_CODE (type) == ENUMERAL_TYPE)
+-      && ! use_gnu_debug_info_extensions)
+-    /* We must use the same test here as we use twice below when deciding
+-       whether to emit a cross-reference.  */
+-    if ((TYPE_NAME (type) != 0
+-	 && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+-	       && DECL_IGNORED_P (TYPE_NAME (type)))
+-	 && !full)
+-	|| !COMPLETE_TYPE_P (type)
+-	/* No way in DBX fmt to describe a variable size.  */
+-	|| ! tree_fits_uhwi_p (TYPE_SIZE (type)))
+-      {
+-	typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
+-	return;
+-      }
+-#endif
+-
+-  /* Output a definition now.  */
+-  stabstr_C ('=');
+-
+-  /* Mark it as defined, so that if it is self-referent
+-     we will not get into an infinite recursion of definitions.  */
+-
+-  typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED;
+-
+-  /* If this type is a variant of some other, hand off.  Types with
+-     different names are usefully distinguished.  We only distinguish
+-     cv-qualified types if we're using extensions.  */
+-  if (TYPE_READONLY (type) > TYPE_READONLY (main_variant))
+-    {
+-      stabstr_C ('k');
+-      dbxout_type (build_type_variant (type, 0, TYPE_VOLATILE (type)), 0);
+-      return;
+-    }
+-  else if (TYPE_VOLATILE (type) > TYPE_VOLATILE (main_variant))
+-    {
+-      stabstr_C ('B');
+-      dbxout_type (build_type_variant (type, TYPE_READONLY (type), 0), 0);
+-      return;
+-    }
+-  else if (main_variant != TYPE_MAIN_VARIANT (type))
+-    {
+-      if (flag_debug_only_used_symbols)
+-        {
+-          tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+-
+-          if ((TREE_CODE (orig_type) == RECORD_TYPE
+-               || TREE_CODE (orig_type) == UNION_TYPE
+-               || TREE_CODE (orig_type) == QUAL_UNION_TYPE
+-               || TREE_CODE (orig_type) == ENUMERAL_TYPE)
+-              && TYPE_STUB_DECL (orig_type)
+-              && ! DECL_IGNORED_P (TYPE_STUB_DECL (orig_type)))
+-            debug_queue_symbol (TYPE_STUB_DECL (orig_type));
+-        }
+-      /* 'type' is a typedef; output the type it refers to.  */
+-      dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0);
+-      return;
+-    }
+-  /* else continue.  */
+-
+-  switch (TREE_CODE (type))
+-    {
+-    case VOID_TYPE:
+-    case NULLPTR_TYPE:
+-    case LANG_TYPE:
+-    case OPAQUE_TYPE:
+-      /* For a void type, just define it as itself; i.e., "5=5".
+-	 This makes us consider it defined
+-	 without saying what it is.  The debugger will make it
+-	 a void type when the reference is seen, and nothing will
+-	 ever override that default.  */
+-      dbxout_type_index (type);
+-      break;
+-
+-    case INTEGER_TYPE:
+-      if (type == char_type_node && ! TYPE_UNSIGNED (type))
+-	{
+-	  /* Output the type `char' as a subrange of itself!
+-	     I don't understand this definition, just copied it
+-	     from the output of pcc.
+-	     This used to use `r2' explicitly and we used to
+-	     take care to make sure that `char' was type number 2.  */
+-	  stabstr_C ('r');
+-	  dbxout_type_index (type);
+-	  stabstr_S (";0;127;");
+-	}
+-
+-      /* If this is a subtype of another integer type, always prefer to
+-	 write it as a subtype.  */
+-      else if (TREE_TYPE (type) != 0
+-	       && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
+-	{
+-	  /* If the size is non-standard, say what it is if we can use
+-	     GDB extensions.  */
+-
+-	  if (use_gnu_debug_info_extensions
+-	      && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
+-	    {
+-	      stabstr_S ("@s");
+-	      stabstr_D (TYPE_PRECISION (type));
+-	      stabstr_C (';');
+-	    }
+-
+-	  dbxout_range_type (type, low, high);
+-	}
+-
+-      else
+-	{
+-	  /* If the size is non-standard, say what it is if we can use
+-	     GDB extensions.  */
+-
+-	  if (use_gnu_debug_info_extensions
+-	      && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
+-	    {
+-	      stabstr_S ("@s");
+-	      stabstr_D (TYPE_PRECISION (type));
+-	      stabstr_C (';');
+-	    }
+-
+-	  if (print_int_cst_bounds_in_octal_p (type, low, high))
+-	    {
+-	      stabstr_C ('r');
+-
+-              /* If this type derives from another type, output type index of
+-		 parent type. This is particularly important when parent type
+-		 is an enumerated type, because not generating the parent type
+-		 index would transform the definition of this enumerated type
+-		 into a plain unsigned type.  */
+-              if (TREE_TYPE (type) != 0)
+-                dbxout_type_index (TREE_TYPE (type));
+-              else
+-                dbxout_type_index (type);
+-
+-	      stabstr_C (';');
+-	      stabstr_O (low);
+-	      stabstr_C (';');
+-	      stabstr_O (high);
+-	      stabstr_C (';');
+-	    }
+-
+-	  else
+-	    /* Output other integer types as subranges of `int'.  */
+-	    dbxout_range_type (type, low, high);
+-	}
+-
+-      break;
+-
+-    case REAL_TYPE:
+-    case FIXED_POINT_TYPE:
+-      /* This used to say `r1' and we used to take care
+-	 to make sure that `int' was type number 1.  */
+-      stabstr_C ('r');
+-      dbxout_type_index (integer_type_node);
+-      stabstr_C (';');
+-      stabstr_D (int_size_in_bytes (type));
+-      stabstr_S (";0;");
+-      break;
+-
+-    case BOOLEAN_TYPE:
+-      if (use_gnu_debug_info_extensions)
+-	{
+-	  stabstr_S ("@s");
+-	  stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
+-	  stabstr_S (";-16;");
+-	}
+-      else /* Define as enumeral type (False, True) */
+-	stabstr_S ("eFalse:0,True:1,;");
+-      break;
+-
+-    case COMPLEX_TYPE:
+-      /* Differs from the REAL_TYPE by its new data type number.
+-	 R3 is NF_COMPLEX.  We don't try to use any of the other NF_*
+-	 codes since gdb doesn't care anyway.  */
+-
+-      if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
+-	{
+-	  stabstr_S ("R3;");
+-	  stabstr_D (2 * int_size_in_bytes (TREE_TYPE (type)));
+-	  stabstr_S (";0;");
+-	}
+-      else
+-	{
+-	  /* Output a complex integer type as a structure,
+-	     pending some other way to do it.  */
+-	  stabstr_C ('s');
+-	  stabstr_D (int_size_in_bytes (type));
+-
+-	  stabstr_S ("real:");
+-	  dbxout_type (TREE_TYPE (type), 0);
+-	  stabstr_S (",0,");
+-	  stabstr_D (TYPE_PRECISION (TREE_TYPE (type)));
+-
+-	  stabstr_S (";imag:");
+-	  dbxout_type (TREE_TYPE (type), 0);
+-	  stabstr_C (',');
+-	  stabstr_D (TYPE_PRECISION (TREE_TYPE (type)));
+-	  stabstr_C (',');
+-	  stabstr_D (TYPE_PRECISION (TREE_TYPE (type)));
+-	  stabstr_S (";;");
+-	}
+-      break;
+-
+-    case ARRAY_TYPE:
+-      /* Make arrays of packed bits look like bitstrings for chill.  */
+-      if (TYPE_PACKED (type) && use_gnu_debug_info_extensions)
+-	{
+-	  stabstr_S ("@s");
+-	  stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
+-	  stabstr_S (";@S;S");
+-	  dbxout_type (TYPE_DOMAIN (type), 0);
+-	  break;
+-	}
+-
+-      /* Output "a" followed by a range type definition
+-	 for the index type of the array
+-	 followed by a reference to the target-type.
+-	 ar1;0;N;M for a C array of type M and size N+1.  */
+-      /* Check if a character string type, which in Chill is
+-	 different from an array of characters.  */
+-      if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
+-	{
+-	  stabstr_S ("@S;");
+-	}
+-      tem = TYPE_DOMAIN (type);
+-      if (tem == NULL)
+-	{
+-	  stabstr_S ("ar");
+-	  dbxout_type_index (integer_type_node);
+-	  stabstr_S (";0;-1;");
+-	}
+-      else
+-	{
+-	  stabstr_C ('a');
+-	  dbxout_range_type (tem, TYPE_MIN_VALUE (tem), TYPE_MAX_VALUE (tem));
+-	}
+-
+-      dbxout_type (TREE_TYPE (type), 0);
+-      break;
+-
+-    case VECTOR_TYPE:
+-      /* Make vectors look like an array.  */
+-      if (use_gnu_debug_info_extensions)
+-	stabstr_S ("@V;");
+-
+-      /* Output "a" followed by a range type definition
+-	 for the index type of the array
+-	 followed by a reference to the target-type.
+-	 ar1;0;N;M for a C array of type M and size N+1.  */
+-      stabstr_C ('a');
+-      dbxout_range_type (integer_type_node, size_zero_node,
+-			 size_int (TYPE_VECTOR_SUBPARTS (type) - 1));
+-
+-      dbxout_type (TREE_TYPE (type), 0);
+-      break;
+-
+-    case RECORD_TYPE:
+-    case UNION_TYPE:
+-    case QUAL_UNION_TYPE:
+-      {
+-	tree binfo = TYPE_BINFO (type);
+-
+-	/* Output a structure type.  We must use the same test here as we
+-	   use in the DBX_NO_XREFS case above.  */
+-	if ((TYPE_NAME (type) != 0
+-	     && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+-		   && DECL_IGNORED_P (TYPE_NAME (type)))
+-	     && !full)
+-	    || !COMPLETE_TYPE_P (type)
+-	    /* No way in DBX fmt to describe a variable size.  */
+-	    || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
+-	  {
+-	    /* If the type is just a cross reference, output one
+-	       and mark the type as partially described.
+-	       If it later becomes defined, we will output
+-	       its real definition.
+-	       If the type has a name, don't nest its definition within
+-	       another type's definition; instead, output an xref
+-	       and let the definition come when the name is defined.  */
+-	    stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
+-	    if (TYPE_IDENTIFIER (type))
+-	      {
+-		/* Note that the C frontend creates for anonymous variable
+-		   length records/unions TYPE_NAME with DECL_NAME NULL.  */
+-		dbxout_type_name (type);
+-	      }
+-	    else
+-	      {
+-		stabstr_S ("$$");
+-		stabstr_D (anonymous_type_number++);
+-	      }
+-
+-	    stabstr_C (':');
+-	    typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
+-	    break;
+-	  }
+-
+-	/* Identify record or union, and print its size.  */
+-	stabstr_C ((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u');
+-	stabstr_D (int_size_in_bytes (type));
+-
+-	if (binfo)
+-	  {
+-	    int i;
+-	    tree child;
+-	    vec *accesses = BINFO_BASE_ACCESSES (binfo);
+-
+-	    if (use_gnu_debug_info_extensions)
+-	      {
+-		if (BINFO_N_BASE_BINFOS (binfo))
+-		  {
+-		    stabstr_C ('!');
+-		    stabstr_U (BINFO_N_BASE_BINFOS (binfo));
+-		    stabstr_C (',');
+-		  }
+-	      }
+-	    for (i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++)
+-	      {
+-		tree access = (accesses ? (*accesses)[i] : access_public_node);
+-
+-		if (use_gnu_debug_info_extensions)
+-		  {
+-		    stabstr_C (BINFO_VIRTUAL_P (child) ? '1' : '0');
+-		    stabstr_C (access == access_public_node ? '2' :
+-				   access == access_protected_node
+-				   ? '1' :'0');
+-		    if (BINFO_VIRTUAL_P (child)
+-			&& (lang_GNU_CXX ()
+-			    || strcmp (lang_hooks.name, "GNU Objective-C++") == 0))
+-		      /* For a virtual base, print the (negative)
+-		     	 offset within the vtable where we must look
+-		     	 to find the necessary adjustment.  */
+-		      stabstr_D
+-			(tree_to_shwi (BINFO_VPTR_FIELD (child))
+-			 * BITS_PER_UNIT);
+-		    else
+-		      stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
+-				       * BITS_PER_UNIT);
+-		    stabstr_C (',');
+-		    dbxout_type (BINFO_TYPE (child), 0);
+-		    stabstr_C (';');
+-		  }
+-		else
+-		  {
+-		    /* Print out the base class information with
+-		       fields which have the same names at the types
+-		       they hold.  */
+-		    dbxout_type_name (BINFO_TYPE (child));
+-		    stabstr_C (':');
+-		    dbxout_type (BINFO_TYPE (child), full);
+-		    stabstr_C (',');
+-		    stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
+-				     * BITS_PER_UNIT);
+-		    stabstr_C (',');
+-		    stabstr_D
+-		      (tree_to_shwi (TYPE_SIZE (BINFO_TYPE (child)))
+-		       * BITS_PER_UNIT);
+-		    stabstr_C (';');
+-		  }
+-	      }
+-	  }
+-      }
+-
+-      /* Write out the field declarations.  */
+-      dbxout_type_fields (type);
+-      if (use_gnu_debug_info_extensions)
+-	dbxout_type_methods (type);
+-
+-      stabstr_C (';');
+-
+-      if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE
+-	  /* Avoid the ~ if we don't really need it--it confuses dbx.  */
+-	  && TYPE_VFIELD (type))
+-	{
+-
+-	  /* We need to write out info about what field this class
+-	     uses as its "main" vtable pointer field, because if this
+-	     field is inherited from a base class, GDB cannot necessarily
+-	     figure out which field it's using in time.  */
+-	  stabstr_S ("~%");
+-	  dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0);
+-	  stabstr_C (';');
+-	}
+-      break;
+-
+-    case ENUMERAL_TYPE:
+-      /* We must use the same test here as we use in the DBX_NO_XREFS case
+-	 above.  We simplify it a bit since an enum will never have a variable
+-	 size.  */
+-      if ((TYPE_NAME (type) != 0
+-	   && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+-		 && DECL_IGNORED_P (TYPE_NAME (type)))
+-	   && !full)
+-	  || !COMPLETE_TYPE_P (type))
+-	{
+-	  stabstr_S ("xe");
+-	  dbxout_type_name (type);
+-	  typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
+-	  stabstr_C (':');
+-	  return;
+-	}
+-      if (use_gnu_debug_info_extensions
+-	  && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
+-	{
+-	  stabstr_S ("@s");
+-	  stabstr_D (TYPE_PRECISION (type));
+-	  stabstr_C (';');
+-	}
+-
+-      stabstr_C ('e');
+-      for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
+-	{
+-          tree value = TREE_VALUE (tem);
+-
+-	  stabstr_I (TREE_PURPOSE (tem));
+-	  stabstr_C (':');
+-
+-          if (TREE_CODE (value) == CONST_DECL)
+-            value = DECL_INITIAL (value);
+-
+-	  if (cst_and_fits_in_hwi (value))
+-	    stabstr_D (TREE_INT_CST_LOW (value));
+-	  else
+-	    stabstr_O (value);
+-
+-	  stabstr_C (',');
+-	  if (TREE_CHAIN (tem) != 0)
+-	    CONTIN;
+-	}
+-
+-      stabstr_C (';');
+-      break;
+-
+-    case POINTER_TYPE:
+-      stabstr_C ('*');
+-      dbxout_type (TREE_TYPE (type), 0);
+-      break;
+-
+-    case METHOD_TYPE:
+-      if (use_gnu_debug_info_extensions)
+-	{
+-	  stabstr_C ('#');
+-
+-	  /* Write the argument types out longhand.  */
+-	  dbxout_type (TYPE_METHOD_BASETYPE (type), 0);
+-	  stabstr_C (',');
+-	  dbxout_type (TREE_TYPE (type), 0);
+-	  dbxout_args (TYPE_ARG_TYPES (type));
+-	  stabstr_C (';');
+-	}
+-      else
+-	/* Treat it as a function type.  */
+-	dbxout_type (TREE_TYPE (type), 0);
+-      break;
+-
+-    case OFFSET_TYPE:
+-      if (use_gnu_debug_info_extensions)
+-	{
+-	  stabstr_C ('@');
+-	  dbxout_type (TYPE_OFFSET_BASETYPE (type), 0);
+-	  stabstr_C (',');
+-	  dbxout_type (TREE_TYPE (type), 0);
+-	}
+-      else
+-	/* Should print as an int, because it is really just an offset.  */
+-	dbxout_type (integer_type_node, 0);
+-      break;
+-
+-    case REFERENCE_TYPE:
+-      if (use_gnu_debug_info_extensions)
+-	{
+-	  stabstr_C ('&');
+-	}
+-      else
+-	stabstr_C ('*');
+-      dbxout_type (TREE_TYPE (type), 0);
+-      break;
+-
+-    case FUNCTION_TYPE:
+-      stabstr_C ('f');
+-      dbxout_type (TREE_TYPE (type), 0);
+-      break;
+-
+-    default:
+-      /* A C++ function with deduced return type can have a TEMPLATE_TYPE_PARM
+-	 named 'auto' in its type.
+-	 No debug info for TEMPLATE_TYPE_PARM type supported yet.  */
+-      if (lang_GNU_CXX ())
+-	{
+-	  tree name = TYPE_IDENTIFIER (type);
+-	  if (name == get_identifier ("auto")
+-	      || name == get_identifier ("decltype(auto)"))
+-	    break;
+-	}
+-
+-      gcc_unreachable ();
+-    }
+-}
+-
+-/* Return nonzero if the given type represents an integer whose bounds
+-   should be printed in octal format.  */
+-
+-static bool
+-print_int_cst_bounds_in_octal_p (tree type, tree low, tree high)
+-{
+-  /* If we can use GDB extensions and the size is wider than a long
+-     (the size used by GDB to read them) or we may have trouble writing
+-     the bounds the usual way, write them in octal.  Note the test is for
+-     the *target's* size of "long", not that of the host.  The host test
+-     is just to make sure we can write it out in case the host wide int
+-     is narrower than the target "long".
+-
+-     For unsigned types, we use octal if they are the same size or larger.
+-     This is because we print the bounds as signed decimal, and hence they
+-     can't span same size unsigned types.  */
+-
+-  if (use_gnu_debug_info_extensions
+-      && low && TREE_CODE (low) == INTEGER_CST
+-      && high && TREE_CODE (high) == INTEGER_CST
+-      && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
+-	  || ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+-	      && TYPE_UNSIGNED (type))
+-	  || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
+-	  || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
+-	      && TYPE_UNSIGNED (type))))
+-    return TRUE;
+-  else
+-    return FALSE;
+-}
+-
+-/* Output the name of type TYPE, with no punctuation.
+-   Such names can be set up either by typedef declarations
+-   or by struct, enum and union tags.  */
+-
+-static void
+-dbxout_type_name (tree type)
+-{
+-  tree t = TYPE_NAME (type);
+-
+-  gcc_assert (t);
+-  switch (TREE_CODE (t))
+-    {
+-    case IDENTIFIER_NODE:
+-      break;
+-    case TYPE_DECL:
+-      t = DECL_NAME (t);
+-      break;
+-    default:
+-      gcc_unreachable ();
+-    }
+-
+-  stabstr_I (t);
+-}
+-
+-/* Output leading struct or class names needed for qualifying type
+-   whose scope is limited to a struct or class.  */
+-
+-static void
+-dbxout_class_name_qualifiers (tree decl)
+-{
+-  tree context = decl_type_context (decl);
+-
+-  if (context != NULL_TREE
+-      && TREE_CODE (context) == RECORD_TYPE
+-      && TYPE_NAME (context) != 0
+-      && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
+-          || (DECL_NAME (TYPE_NAME (context)) != 0)))
+-    {
+-      tree name = TYPE_NAME (context);
+-
+-      if (TREE_CODE (name) == TYPE_DECL)
+-	{
+-	  dbxout_class_name_qualifiers (name);
+-	  name = DECL_NAME (name);
+-	}
+-      stabstr_I (name);
+-      stabstr_S ("::");
+-    }
+-}
+-
+-/* This is a specialized subset of expand_expr for use by dbxout_symbol in
+-   evaluating DECL_VALUE_EXPR.  In particular, we stop if we find decls that
+-   haven't been expanded, or if the expression is getting so complex we won't
+-   be able to represent it in stabs anyway.  Returns NULL on failure.  */
+-
+-static rtx
+-dbxout_expand_expr (tree expr)
+-{
+-  switch (TREE_CODE (expr))
+-    {
+-    case VAR_DECL:
+-      /* We can't handle emulated tls variables, because the address is an
+-	 offset to the return value of __emutls_get_address, and there is no
+-	 way to express that in stabs.  Also, there are name mangling issues
+-	 here.  We end up with references to undefined symbols if we don't
+-	 disable debug info for these variables.  */
+-      if (!targetm.have_tls && DECL_THREAD_LOCAL_P (expr))
+-	return NULL;
+-      if (TREE_STATIC (expr)
+-	  && !TREE_ASM_WRITTEN (expr)
+-	  && !DECL_HAS_VALUE_EXPR_P (expr)
+-	  && !TREE_PUBLIC (expr)
+-	  && DECL_RTL_SET_P (expr)
+-	  && MEM_P (DECL_RTL (expr)))
+-	{
+-	  /* If this is a var that might not be actually output,
+-	     return NULL, otherwise stabs might reference an undefined
+-	     symbol.  */
+-	  varpool_node *node = varpool_node::get (expr);
+-	  if (!node || !node->definition)
+-	    return NULL;
+-	}
+-      /* FALLTHRU */
+-
+-    case PARM_DECL:
+-    case RESULT_DECL:
+-      if (DECL_HAS_VALUE_EXPR_P (expr))
+-	return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
+-      /* FALLTHRU */
+-
+-    case CONST_DECL:
+-      return DECL_RTL_IF_SET (expr);
+-
+-    case INTEGER_CST:
+-      return expand_expr (expr, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+-
+-    case COMPONENT_REF:
+-    case ARRAY_REF:
+-    case ARRAY_RANGE_REF:
+-    case BIT_FIELD_REF:
+-      {
+-	machine_mode mode;
+-	poly_int64 bitsize, bitpos;
+-	tree offset, tem;
+-	int unsignedp, reversep, volatilep = 0;
+-	rtx x;
+-
+-	tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode,
+-				   &unsignedp, &reversep, &volatilep);
+-
+-	x = dbxout_expand_expr (tem);
+-	if (x == NULL || !MEM_P (x))
+-	  return NULL;
+-	if (offset != NULL)
+-	  {
+-	    if (!tree_fits_shwi_p (offset))
+-	      return NULL;
+-	    x = adjust_address_nv (x, mode, tree_to_shwi (offset));
+-	  }
+-	if (maybe_ne (bitpos, 0))
+-	  x = adjust_address_nv (x, mode, bits_to_bytes_round_down (bitpos));
+-
+-	return x;
+-      }
+-
+-    default:
+-      return NULL;
+-    }
+-}
+-
+-/* Helper function for output_used_types.  Queue one entry from the
+-   used types hash to be output.  */
+-
+-bool
+-output_used_types_helper (tree const &type, vec *types_p)
+-{
+-  if ((TREE_CODE (type) == RECORD_TYPE
+-       || TREE_CODE (type) == UNION_TYPE
+-       || TREE_CODE (type) == QUAL_UNION_TYPE
+-       || TREE_CODE (type) == ENUMERAL_TYPE)
+-      && TYPE_STUB_DECL (type)
+-      && DECL_P (TYPE_STUB_DECL (type))
+-      && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
+-    types_p->quick_push (TYPE_STUB_DECL (type));
+-  else if (TYPE_NAME (type)
+-	   && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+-    types_p->quick_push (TYPE_NAME (type));
+-
+-  return true;
+-}
+-
+-/* This is a qsort callback which sorts types and declarations into a
+-   predictable order (types, then declarations, sorted by UID
+-   within).  */
+-
+-static int
+-output_types_sort (const void *pa, const void *pb)
+-{
+-  const tree lhs = *((const tree *)pa);
+-  const tree rhs = *((const tree *)pb);
+-
+-  if (TYPE_P (lhs))
+-    {
+-      if (TYPE_P (rhs))
+-	return TYPE_UID (lhs) - TYPE_UID (rhs);
+-      else
+-	return 1;
+-    }
+-  else
+-    {
+-      if (TYPE_P (rhs))
+-	return -1;
+-      else
+-	return DECL_UID (lhs) - DECL_UID (rhs);
+-    }
+-}
+-
+-
+-/* Force all types used by this function to be output in debug
+-   information.  */
+-
+-static void
+-output_used_types (void)
+-{
+-  if (cfun && cfun->used_types_hash)
+-    {
+-      vec types;
+-      int i;
+-      tree type;
+-
+-      types.create (cfun->used_types_hash->elements ());
+-      cfun->used_types_hash->traverse *, output_used_types_helper>
+-       	(&types);
+-
+-      /* Sort by UID to prevent dependence on hash table ordering.  */
+-      types.qsort (output_types_sort);
+-
+-      FOR_EACH_VEC_ELT (types, i, type)
+-	debug_queue_symbol (type);
+-
+-      types.release ();
+-    }
+-}
+-
+-/* Output a .stabs for the symbol defined by DECL,
+-   which must be a ..._DECL node in the normal namespace.
+-   It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
+-   LOCAL is nonzero if the scope is less than the entire file.
+-   Return 1 if a stabs might have been emitted.  */
+-
+-int
+-dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
+-{
+-  tree type = TREE_TYPE (decl);
+-  tree context = NULL_TREE;
+-  int result = 0;
+-  rtx decl_rtl;
+-
+-  /* "Intercept" dbxout_symbol() calls like we do all debug_hooks.  */
+-  ++debug_nesting;
+-
+-  /* Ignore nameless syms, but don't ignore type tags.  */
+-
+-  if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL)
+-      || DECL_IGNORED_P (decl))
+-    DBXOUT_DECR_NESTING_AND_RETURN (0);
+-
+-  /* If we are to generate only the symbols actually used then such
+-     symbol nodes are flagged with TREE_USED.  Ignore any that
+-     aren't flagged as TREE_USED.  */
+-
+-  if (flag_debug_only_used_symbols
+-      && (!TREE_USED (decl)
+-          && (!VAR_P (decl) || !DECL_INITIAL (decl))))
+-    DBXOUT_DECR_NESTING_AND_RETURN (0);
+-
+-  /* If dbxout_init has not yet run, queue this symbol for later.  */
+-  if (!typevec)
+-    {
+-      preinit_symbols = tree_cons (0, decl, preinit_symbols);
+-      DBXOUT_DECR_NESTING_AND_RETURN (0);
+-    }
+-
+-  if (flag_debug_only_used_symbols)
+-    {
+-      tree t;
+-
+-      /* We now have a used symbol.  We need to generate the info for
+-         the symbol's type in addition to the symbol itself.  These
+-         type symbols are queued to be generated after were done with
+-         the symbol itself (otherwise they would fight over the
+-         stabstr obstack).
+-
+-         Note, because the TREE_TYPE(type) might be something like a
+-         pointer to a named type we need to look for the first name
+-         we see following the TREE_TYPE chain.  */
+-
+-      t = type;
+-      while (POINTER_TYPE_P (t))
+-        t = TREE_TYPE (t);
+-
+-      /* RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, and ENUMERAL_TYPE
+-         need special treatment.  The TYPE_STUB_DECL field in these
+-         types generally represents the tag name type we want to
+-         output.  In addition there  could be a typedef type with
+-         a different name.  In that case we also want to output
+-         that.  */
+-
+-      if (TREE_CODE (t) == RECORD_TYPE
+-           || TREE_CODE (t) == UNION_TYPE
+-           || TREE_CODE (t) == QUAL_UNION_TYPE
+-           || TREE_CODE (t) == ENUMERAL_TYPE)
+-        {
+-	    if (TYPE_STUB_DECL (t)
+-		&& TYPE_STUB_DECL (t) != decl
+-		&& DECL_P (TYPE_STUB_DECL (t))
+-		&& ! DECL_IGNORED_P (TYPE_STUB_DECL (t)))
+-	    {
+-	      debug_queue_symbol (TYPE_STUB_DECL (t));
+-	      if (TYPE_NAME (t)
+-		  && TYPE_NAME (t) != TYPE_STUB_DECL (t)
+-		  && TYPE_NAME (t) != decl
+-		  && DECL_P (TYPE_NAME (t)))
+-		debug_queue_symbol (TYPE_NAME (t));
+-	    }
+-	}
+-      else if (TYPE_NAME (t)
+-	       && TYPE_NAME (t) != decl
+-	       && DECL_P (TYPE_NAME (t)))
+-        debug_queue_symbol (TYPE_NAME (t));
+-    }
+-
+-  emit_pending_bincls_if_required ();
+-
+-  switch (TREE_CODE (decl))
+-    {
+-    case CONST_DECL:
+-      /* Enum values are defined by defining the enum type.  */
+-      break;
+-
+-    case FUNCTION_DECL:
+-      decl_rtl = DECL_RTL_IF_SET (decl);
+-      if (!decl_rtl)
+-	DBXOUT_DECR_NESTING_AND_RETURN (0);
+-      if (DECL_EXTERNAL (decl))
+-	break;
+-      /* Don't mention a nested function under its parent.  */
+-      context = decl_function_context (decl);
+-      if (context == current_function_decl)
+-	break;
+-      /* Don't mention an inline instance of a nested function.  */
+-      if (context && DECL_FROM_INLINE (decl))
+-	break;
+-      if (!MEM_P (decl_rtl)
+-	  || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF)
+-	break;
+-
+-      if (flag_debug_only_used_symbols)
+-	output_used_types ();
+-
+-      dbxout_begin_complex_stabs ();
+-      stabstr_I (DECL_ASSEMBLER_NAME (decl));
+-      stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f");
+-      result = 1;
+-
+-      if (TREE_TYPE (type))
+-	dbxout_type (TREE_TYPE (type), 0);
+-      else
+-	dbxout_type (void_type_node, 0);
+-
+-      /* For a nested function, when that function is compiled,
+-	 mention the containing function name
+-	 as well as (since dbx wants it) our own assembler-name.  */
+-      if (context != 0)
+-	{
+-	  stabstr_C (',');
+-	  stabstr_I (DECL_ASSEMBLER_NAME (decl));
+-	  stabstr_C (',');
+-	  stabstr_I (DECL_NAME (context));
+-	}
+-
+-      dbxout_finish_complex_stabs (decl, N_FUN, XEXP (decl_rtl, 0), 0, 0);
+-      break;
+-
+-    case TYPE_DECL:
+-      /* Don't output the same typedef twice.
+-         And don't output what language-specific stuff doesn't want output.  */
+-      if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl))
+-	DBXOUT_DECR_NESTING_AND_RETURN (0);
+-
+-      /* Don't output typedefs for types with magic type numbers (XCOFF).  */
+-#ifdef DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER
+-      {
+-	int fundamental_type_number =
+-	  DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER (decl);
+-
+-	if (fundamental_type_number != 0)
+-	  {
+-	    TREE_ASM_WRITTEN (decl) = 1;
+-	    TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = fundamental_type_number;
+-	    DBXOUT_DECR_NESTING_AND_RETURN (0);
+-	  }
+-      }
+-#endif
+-      FORCE_TEXT;
+-      result = 1;
+-      {
+-	int tag_needed = 1;
+-	int did_output = 0;
+-
+-	if (DECL_NAME (decl))
+-	  {
+-	    /* Nonzero means we must output a tag as well as a typedef.  */
+-	    tag_needed = 0;
+-
+-	    /* Handle the case of a C++ structure or union
+-	       where the TYPE_NAME is a TYPE_DECL
+-	       which gives both a typedef name and a tag.  */
+-	    /* dbx requires the tag first and the typedef second.  */
+-	    if ((TREE_CODE (type) == RECORD_TYPE
+-		 || TREE_CODE (type) == UNION_TYPE
+-		 || TREE_CODE (type) == QUAL_UNION_TYPE)
+-		&& TYPE_NAME (type) == decl
+-		&& !use_gnu_debug_info_extensions
+-		&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
+-		/* Distinguish the implicit typedefs of C++
+-		   from explicit ones that might be found in C.  */
+-		&& DECL_ARTIFICIAL (decl)
+-                /* Do not generate a tag for incomplete records.  */
+-                && COMPLETE_TYPE_P (type)
+-		/* Do not generate a tag for records of variable size,
+-		   since this type cannot be properly described in the
+-		   DBX format, and it confuses some tools such as objdump.  */
+-		&& tree_fits_uhwi_p (TYPE_SIZE (type)))
+-	      {
+-		tree name = TYPE_IDENTIFIER (type);
+-
+-		dbxout_begin_complex_stabs ();
+-		stabstr_I (name);
+-		stabstr_S (":T");
+-		dbxout_type (type, 1);
+-		dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE,
+-					     0, 0, 0);
+-	      }
+-
+-	    dbxout_begin_complex_stabs ();
+-
+-	    /* Output leading class/struct qualifiers.  */
+-	    if (use_gnu_debug_info_extensions)
+-	      dbxout_class_name_qualifiers (decl);
+-
+-	    /* Output typedef name.  */
+-	    stabstr_I (DECL_NAME (decl));
+-	    stabstr_C (':');
+-
+-	    /* Short cut way to output a tag also.  */
+-	    if ((TREE_CODE (type) == RECORD_TYPE
+-		 || TREE_CODE (type) == UNION_TYPE
+-		 || TREE_CODE (type) == QUAL_UNION_TYPE)
+-		&& TYPE_NAME (type) == decl
+-		/* Distinguish the implicit typedefs of C++
+-		   from explicit ones that might be found in C.  */
+-		&& DECL_ARTIFICIAL (decl))
+-	      {
+-		if (use_gnu_debug_info_extensions)
+-		  {
+-		    stabstr_C ('T');
+-		    TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1;
+-		  }
+-	      }
+-
+-	    stabstr_C ('t');
+-	    dbxout_type (type, 1);
+-	    dbxout_finish_complex_stabs (decl, DBX_TYPE_DECL_STABS_CODE,
+-					 0, 0, 0);
+-	    did_output = 1;
+-	  }
+-
+-	/* Don't output a tag if this is an incomplete type.  This prevents
+-	   the sun4 Sun OS 4.x dbx from crashing.  */
+-
+-	if (tag_needed && TYPE_NAME (type) != 0
+-	    && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE
+-		|| (DECL_NAME (TYPE_NAME (type)) != 0))
+-	    && COMPLETE_TYPE_P (type)
+-	    && !TREE_ASM_WRITTEN (TYPE_NAME (type)))
+-	  {
+-	    /* For a TYPE_DECL with no name, but the type has a name,
+-	       output a tag.
+-	       This is what represents `struct foo' with no typedef.  */
+-	    /* In C++, the name of a type is the corresponding typedef.
+-	       In C, it is an IDENTIFIER_NODE.  */
+-	    tree name = TYPE_IDENTIFIER (type);
+-
+-	    dbxout_begin_complex_stabs ();
+-	    stabstr_I (name);
+-	    stabstr_S (":T");
+-	    dbxout_type (type, 1);
+-	    dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, 0, 0, 0);
+-	    did_output = 1;
+-	  }
+-
+-	/* If an enum type has no name, it cannot be referred to, but
+-	   we must output it anyway, to record the enumeration
+-	   constants.  */
+-
+-	if (!did_output && TREE_CODE (type) == ENUMERAL_TYPE)
+-	  {
+-	    dbxout_begin_complex_stabs ();
+-	    /* Some debuggers fail when given NULL names, so give this a
+-	       harmless name of " " (Why not "(anon)"?).  */
+-	    stabstr_S (" :T");
+-	    dbxout_type (type, 1);
+-	    dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, 0, 0, 0);
+-	  }
+-
+-	/* Prevent duplicate output of a typedef.  */
+-	TREE_ASM_WRITTEN (decl) = 1;
+-	break;
+-      }
+-
+-    case PARM_DECL:
+-      if (DECL_HAS_VALUE_EXPR_P (decl))
+-	decl = DECL_VALUE_EXPR (decl);
+-
+-      /* PARM_DECLs go in their own separate chain and are output by
+-	 dbxout_reg_parms and dbxout_parms, except for those that are
+-	 disguised VAR_DECLs like Out parameters in Ada.  */
+-      gcc_assert (VAR_P (decl));
+-
+-      /* fall through */
+-
+-    case RESULT_DECL:
+-    case VAR_DECL:
+-      /* Don't mention a variable that is external.
+-	 Let the file that defines it describe it.  */
+-      if (DECL_EXTERNAL (decl))
+-	break;
+-
+-      /* If the variable is really a constant
+-	 and not written in memory, inform the debugger.
+-
+-	 ??? Why do we skip emitting the type and location in this case?  */
+-      if (TREE_STATIC (decl) && TREE_READONLY (decl)
+-	  && DECL_INITIAL (decl) != 0
+-	  && tree_fits_shwi_p (DECL_INITIAL (decl))
+-	  && ! TREE_ASM_WRITTEN (decl)
+-	  && (DECL_FILE_SCOPE_P (decl)
+-	      || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
+-	      || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+-	  && TREE_PUBLIC (decl) == 0)
+-	{
+-	  /* The sun4 assembler does not grok this.  */
+-
+-	  if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
+-	      || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+-	    {
+-	      HOST_WIDE_INT ival = tree_to_shwi (DECL_INITIAL (decl));
+-
+-	      dbxout_begin_complex_stabs ();
+-	      dbxout_symbol_name (decl, NULL, 'c');
+-	      stabstr_S ("=i");
+-	      stabstr_D (ival);
+-	      dbxout_finish_complex_stabs (0, N_LSYM, 0, 0, 0);
+-	      DBXOUT_DECR_NESTING;
+-	      return 1;
+-	    }
+-	  else
+-	    break;
+-	}
+-      /* else it is something we handle like a normal variable.  */
+-
+-      decl_rtl = dbxout_expand_expr (decl);
+-      if (!decl_rtl)
+-	DBXOUT_DECR_NESTING_AND_RETURN (0);
+-
+-      if (!is_global_var (decl))
+-	decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX);
+-#ifdef LEAF_REG_REMAP
+-      if (crtl->uses_only_leaf_regs)
+-	leaf_renumber_regs_insn (decl_rtl);
+-#endif
+-
+-      result = dbxout_symbol_location (decl, type, 0, decl_rtl);
+-      break;
+-
+-    default:
+-      break;
+-    }
+-  DBXOUT_DECR_NESTING;
+-  return result;
+-}
+-
+-/* Output the stab for DECL, a VAR_DECL, RESULT_DECL or PARM_DECL.
+-   Add SUFFIX to its name, if SUFFIX is not 0.
+-   Describe the variable as residing in HOME
+-   (usually HOME is DECL_RTL (DECL), but not always).
+-   Returns 1 if the stab was really emitted.  */
+-
+-static int
+-dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
+-{
+-  int letter = 0;
+-  stab_code_type code;
+-  rtx addr = 0;
+-  int number = 0;
+-  int regno = -1;
+-
+-  /* Don't mention a variable at all
+-     if it was completely optimized into nothingness.
+-
+-     If the decl was from an inline function, then its rtl
+-     is not identically the rtl that was used in this
+-     particular compilation.  */
+-  if (GET_CODE (home) == SUBREG)
+-    {
+-      rtx value = home;
+-
+-      while (GET_CODE (value) == SUBREG)
+-	value = SUBREG_REG (value);
+-      if (REG_P (value))
+-	{
+-	  if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
+-	    return 0;
+-	}
+-      home = alter_subreg (&home, true);
+-    }
+-  if (REG_P (home))
+-    {
+-      regno = REGNO (home);
+-      if (regno >= FIRST_PSEUDO_REGISTER)
+-	return 0;
+-    }
+-
+-  /* The kind-of-variable letter depends on where
+-     the variable is and on the scope of its name:
+-     G and N_GSYM for static storage and global scope,
+-     S for static storage and file scope,
+-     V for static storage and local scope,
+-     for those two, use N_LCSYM if data is in bss segment,
+-     N_STSYM if in data segment, N_FUN otherwise.
+-     (We used N_FUN originally, then changed to N_STSYM
+-     to please GDB.  However, it seems that confused ld.
+-     Now GDB has been fixed to like N_FUN, says Kingdon.)
+-     no letter at all, and N_LSYM, for auto variable,
+-     r and N_RSYM for register variable.  */
+-
+-  if (MEM_P (home) && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+-    {
+-      if (TREE_PUBLIC (decl))
+-	{
+-	  int offs;
+-	  letter = 'G';
+-	  code = N_GSYM;
+-	  if (dbxout_common_check (decl, &offs) != NULL)
+-	    {
+-	      letter = 'V';
+-	      addr = 0;
+-	      number = offs;
+-	    }
+-	}
+-      else
+-	{
+-	  addr = XEXP (home, 0);
+-
+-	  letter = decl_function_context (decl) ? 'V' : 'S';
+-
+-	  /* Some ports can transform a symbol ref into a label ref,
+-	     because the symbol ref is too far away and has to be
+-	     dumped into a constant pool.  Alternatively, the symbol
+-	     in the constant pool might be referenced by a different
+-	     symbol.  */
+-	  if (GET_CODE (addr) == SYMBOL_REF
+-	      && CONSTANT_POOL_ADDRESS_P (addr))
+-	    {
+-	      bool marked;
+-	      rtx tmp = get_pool_constant_mark (addr, &marked);
+-
+-	      if (GET_CODE (tmp) == SYMBOL_REF)
+-		{
+-		  addr = tmp;
+-		  if (CONSTANT_POOL_ADDRESS_P (addr))
+-		    get_pool_constant_mark (addr, &marked);
+-		  else
+-		    marked = true;
+-		}
+-	      else if (GET_CODE (tmp) == LABEL_REF)
+-		{
+-		  addr = tmp;
+-		  marked = true;
+-		}
+-
+-	      /* If all references to the constant pool were optimized
+-		 out, we just ignore the symbol.  */
+-	      if (!marked)
+-		return 0;
+-	    }
+-
+-	  /* This should be the same condition as in assemble_variable, but
+-	     we don't have access to dont_output_data here.  So, instead,
+-	     we rely on the fact that error_mark_node initializers always
+-	     end up in bss for C++ and never end up in bss for C.  */
+-	  if (DECL_INITIAL (decl) == 0
+-	      || (lang_GNU_CXX ()
+-		  && DECL_INITIAL (decl) == error_mark_node))
+-	    {
+-	      int offs;
+-	      code = N_LCSYM;
+-	      if (dbxout_common_check (decl, &offs) != NULL)
+-	        {
+-		  addr = 0;
+-		  number = offs;
+-		  letter = 'V';
+-		  code = N_GSYM;
+-		}
+-	    }
+-	  else if (DECL_IN_TEXT_SECTION (decl))
+-	    /* This is not quite right, but it's the closest
+-	       of all the codes that Unix defines.  */
+-	    code = DBX_STATIC_CONST_VAR_CODE;
+-	  else
+-	    {
+-	      /* Ultrix `as' seems to need this.  */
+-#ifdef DBX_STATIC_STAB_DATA_SECTION
+-	      switch_to_section (data_section);
+-#endif
+-	      code = N_STSYM;
+-	    }
+-	}
+-    }
+-  else if (regno >= 0)
+-    {
+-      letter = 'r';
+-      code = N_RSYM;
+-      number = DBX_REGISTER_NUMBER (regno);
+-    }
+-  else if (MEM_P (home)
+-	   && (MEM_P (XEXP (home, 0))
+-	       || (REG_P (XEXP (home, 0))
+-		   && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+-		   && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+-#if !HARD_FRAME_POINTER_IS_ARG_POINTER
+-		   && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+-#endif
+-		   )))
+-    /* If the value is indirect by memory or by a register
+-       that isn't the frame pointer
+-       then it means the object is variable-sized and address through
+-       that register or stack slot.  DBX has no way to represent this
+-       so all we can do is output the variable as a pointer.
+-       If it's not a parameter, ignore it.  */
+-    {
+-      if (REG_P (XEXP (home, 0)))
+-	{
+-	  letter = 'r';
+-	  code = N_RSYM;
+-	  if (REGNO (XEXP (home, 0)) >= FIRST_PSEUDO_REGISTER)
+-	    return 0;
+-	  number = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0)));
+-	}
+-      else
+-	{
+-	  code = N_LSYM;
+-	  /* RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
+-	     We want the value of that CONST_INT.  */
+-	  number = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (home, 0), 0));
+-	}
+-
+-      /* Effectively do build_pointer_type, but don't cache this type,
+-	 since it might be temporary whereas the type it points to
+-	 might have been saved for inlining.  */
+-      /* Don't use REFERENCE_TYPE because dbx can't handle that.  */
+-      type = make_node (POINTER_TYPE);
+-      TREE_TYPE (type) = TREE_TYPE (decl);
+-    }
+-  else if (MEM_P (home)
+-	   && REG_P (XEXP (home, 0)))
+-    {
+-      code = N_LSYM;
+-      number = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
+-    }
+-  else if (MEM_P (home)
+-	   && GET_CODE (XEXP (home, 0)) == PLUS
+-	   && CONST_INT_P (XEXP (XEXP (home, 0), 1)))
+-    {
+-      code = N_LSYM;
+-      /* RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
+-	 We want the value of that CONST_INT.  */
+-      number = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
+-    }
+-  else if (MEM_P (home)
+-	   && GET_CODE (XEXP (home, 0)) == CONST)
+-    {
+-      /* Handle an obscure case which can arise when optimizing and
+-	 when there are few available registers.  (This is *always*
+-	 the case for i386/i486 targets).  The RTL looks like
+-	 (MEM (CONST ...)) even though this variable is a local `auto'
+-	 or a local `register' variable.  In effect, what has happened
+-	 is that the reload pass has seen that all assignments and
+-	 references for one such a local variable can be replaced by
+-	 equivalent assignments and references to some static storage
+-	 variable, thereby avoiding the need for a register.  In such
+-	 cases we're forced to lie to debuggers and tell them that
+-	 this variable was itself `static'.  */
+-      int offs;
+-      code = N_LCSYM;
+-      letter = 'V';
+-      if (dbxout_common_check (decl, &offs) == NULL)
+-        addr = XEXP (XEXP (home, 0), 0);
+-      else
+-        {
+-	  addr = 0;
+-	  number = offs;
+-	  code = N_GSYM;
+-	}
+-    }
+-  else if (GET_CODE (home) == CONCAT)
+-    {
+-      tree subtype;
+-
+-      /* If TYPE is not a COMPLEX_TYPE (it might be a RECORD_TYPE,
+-	 for example), then there is no easy way to figure out
+-	 what SUBTYPE should be.  So, we give up.  */
+-      if (TREE_CODE (type) != COMPLEX_TYPE)
+-	return 0;
+-
+-      subtype = TREE_TYPE (type);
+-
+-      /* If the variable's storage is in two parts,
+-	 output each as a separate stab with a modified name.  */
+-      if (WORDS_BIG_ENDIAN)
+-	dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 0));
+-      else
+-	dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 0));
+-
+-      if (WORDS_BIG_ENDIAN)
+-	dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1));
+-      else
+-	dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1));
+-      return 1;
+-    }
+-  else
+-    /* Address might be a MEM, when DECL is a variable-sized object.
+-       Or it might be const0_rtx, meaning previous passes
+-       want us to ignore this variable.  */
+-    return 0;
+-
+-  /* Ok, start a symtab entry and output the variable name.  */
+-  emit_pending_bincls_if_required ();
+-  FORCE_TEXT;
+-
+-#ifdef DBX_STATIC_BLOCK_START
+-  DBX_STATIC_BLOCK_START (asm_out_file, code);
+-#endif
+-
+-  dbxout_begin_complex_stabs_noforcetext ();
+-  dbxout_symbol_name (decl, suffix, letter);
+-  dbxout_type (type, 0);
+-  dbxout_finish_complex_stabs (decl, code, addr, 0, number);
+-
+-#ifdef DBX_STATIC_BLOCK_END
+-  DBX_STATIC_BLOCK_END (asm_out_file, code);
+-#endif
+-  return 1;
+-}
+-
+-/* Output the symbol name of DECL for a stabs, with suffix SUFFIX.
+-   Then output LETTER to indicate the kind of location the symbol has.  */
+-
+-static void
+-dbxout_symbol_name (tree decl, const char *suffix, int letter)
+-{
+-  tree name;
+-
+-  if (DECL_CONTEXT (decl)
+-      && (TYPE_P (DECL_CONTEXT (decl))
+-	  || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
+-    /* One slight hitch: if this is a VAR_DECL which is a class member
+-       or a namespace member, we must put out the mangled name instead of the
+-       DECL_NAME.  Note also that static member (variable) names DO NOT begin
+-       with underscores in .stabs directives.  */
+-    name = DECL_ASSEMBLER_NAME (decl);
+-  else
+-    /* ...but if we're function-local, we don't want to include the junk
+-       added by ASM_FORMAT_PRIVATE_NAME.  */
+-    name = DECL_NAME (decl);
+-
+-  if (name)
+-    stabstr_I (name);
+-  else
+-    stabstr_S ("(anon)");
+-
+-  if (suffix)
+-    stabstr_S (suffix);
+-  stabstr_C (':');
+-  if (letter)
+-    stabstr_C (letter);
+-}
+-
+-
+-/* Output the common block name for DECL in a stabs.
+-
+-   Symbols in global common (.comm) get wrapped with an N_BCOMM/N_ECOMM pair
+-   around each group of symbols in the same .comm area.  The N_GSYM stabs
+-   that are emitted only contain the offset in the common area.  This routine
+-   emits the N_BCOMM and N_ECOMM stabs.  */
+-
+-static void
+-dbxout_common_name (tree decl, const char *name, stab_code_type op)
+-{
+-  dbxout_begin_complex_stabs ();
+-  stabstr_S (name);
+-  dbxout_finish_complex_stabs (decl, op, NULL_RTX, NULL, 0);
+-}
+-
+-/* Check decl to determine whether it is a VAR_DECL destined for storage in a
+-   common area.  If it is, the return value will be a non-null string giving
+-   the name of the common storage block it will go into.  If non-null, the
+-   value is the offset into the common block for that symbol's storage.  */
+-
+-static const char *
+-dbxout_common_check (tree decl, int *value)
+-{
+-  rtx home;
+-  rtx sym_addr;
+-  const char *name = NULL;
+-
+-  /* If the decl isn't a VAR_DECL, or if it isn't static, or if
+-     it does not have a value (the offset into the common area), or if it
+-     is thread local (as opposed to global) then it isn't common, and shouldn't
+-     be handled as such.
+-
+-     ??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs
+-     for thread-local symbols.  Can be handled via same mechanism as used
+-     in dwarf2out.cc.  */
+-  if (!VAR_P (decl)
+-      || !TREE_STATIC (decl)
+-      || !DECL_HAS_VALUE_EXPR_P (decl)
+-      || DECL_THREAD_LOCAL_P (decl)
+-      || !is_fortran ())
+-    return NULL;
+-
+-  home = DECL_RTL (decl);
+-  if (home == NULL_RTX || GET_CODE (home) != MEM)
+-    return NULL;
+-
+-  sym_addr = dbxout_expand_expr (DECL_VALUE_EXPR (decl));
+-  if (sym_addr == NULL_RTX || GET_CODE (sym_addr) != MEM)
+-    return NULL;
+-
+-  sym_addr = XEXP (sym_addr, 0);
+-  if (GET_CODE (sym_addr) == CONST)
+-    sym_addr = XEXP (sym_addr, 0);
+-  if ((GET_CODE (sym_addr) == SYMBOL_REF || GET_CODE (sym_addr) == PLUS)
+-      && DECL_INITIAL (decl) == 0)
+-    {
+-
+-      /* We have a sym that will go into a common area, meaning that it
+-         will get storage reserved with a .comm/.lcomm assembler pseudo-op.
+-
+-         Determine name of common area this symbol will be an offset into,
+-         and offset into that area.  Also retrieve the decl for the area
+-         that the symbol is offset into.  */
+-      tree cdecl = NULL;
+-
+-      switch (GET_CODE (sym_addr))
+-        {
+-        case PLUS:
+-          if (CONST_INT_P (XEXP (sym_addr, 0)))
+-            {
+-              name =
+-                targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 1), 0));
+-              *value = INTVAL (XEXP (sym_addr, 0));
+-              cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1));
+-            }
+-          else
+-            {
+-              name =
+-                targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 0), 0));
+-              *value = INTVAL (XEXP (sym_addr, 1));
+-              cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0));
+-            }
+-          break;
+-
+-        case SYMBOL_REF:
+-          name = targetm.strip_name_encoding (XSTR (sym_addr, 0));
+-          *value = 0;
+-          cdecl = SYMBOL_REF_DECL (sym_addr);
+-          break;
+-
+-        default:
+-          error ("common symbol debug info is not structured as "
+-                 "symbol+offset");
+-        }
+-
+-      /* Check area common symbol is offset into.  If this is not public, then
+-         it is not a symbol in a common block.  It must be a .lcomm symbol, not
+-         a .comm symbol.  */
+-      if (cdecl == NULL || !TREE_PUBLIC (cdecl))
+-        name = NULL;
+-    }
+-  else
+-    name = NULL;
+-
+-  return name;
+-}
+-
+-/* Output definitions of all the decls in a chain. Return nonzero if
+-   anything was output */
+-
+-int
+-dbxout_syms (tree syms)
+-{
+-  int result = 0;
+-  const char *comm_prev = NULL;
+-  tree syms_prev = NULL;
+-
+-  while (syms)
+-    {
+-      int temp, copen, cclos;
+-      const char *comm_new;
+-
+-      /* Check for common symbol, and then progression into a new/different
+-         block of common symbols.  Emit closing/opening common bracket if
+-         necessary.  */
+-      comm_new = dbxout_common_check (syms, &temp);
+-      copen = comm_new != NULL
+-              && (comm_prev == NULL || strcmp (comm_new, comm_prev));
+-      cclos = comm_prev != NULL
+-              && (comm_new == NULL || strcmp (comm_new, comm_prev));
+-      if (cclos)
+-        dbxout_common_name (syms_prev, comm_prev, N_ECOMM);
+-      if (copen)
+-        {
+-          dbxout_common_name (syms, comm_new, N_BCOMM);
+-          syms_prev = syms;
+-        }
+-      comm_prev = comm_new;
+-
+-      result += dbxout_symbol (syms, 1);
+-      syms = DECL_CHAIN (syms);
+-    }
+-
+-  if (comm_prev != NULL)
+-    dbxout_common_name (syms_prev, comm_prev, N_ECOMM);
+-
+-  return result;
+-}
+-
+-/* The following two functions output definitions of function parameters.
+-   Each parameter gets a definition locating it in the parameter list.
+-   Each parameter that is a register variable gets a second definition
+-   locating it in the register.
+-
+-   Printing or argument lists in gdb uses the definitions that
+-   locate in the parameter list.  But reference to the variable in
+-   expressions uses preferentially the definition as a register.  */
+-
+-/* Output definitions, referring to storage in the parmlist,
+-   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */
+-
+-void
+-dbxout_parms (tree parms)
+-{
+-  ++debug_nesting;
+-  emit_pending_bincls_if_required ();
+-  fixed_size_mode rtl_mode, type_mode;
+-
+-  for (; parms; parms = DECL_CHAIN (parms))
+-    if (DECL_NAME (parms)
+-	&& TREE_TYPE (parms) != error_mark_node
+-	&& DECL_RTL_SET_P (parms)
+-	&& DECL_INCOMING_RTL (parms)
+-	/* We can't represent variable-sized types in this format.  */
+-	&& is_a  (TYPE_MODE (TREE_TYPE (parms)), &type_mode)
+-	&& is_a  (GET_MODE (DECL_RTL (parms)), &rtl_mode))
+-      {
+-	tree eff_type;
+-	char letter;
+-	stab_code_type code;
+-	int number;
+-
+-	/* Perform any necessary register eliminations on the parameter's rtl,
+-	   so that the debugging output will be accurate.  */
+-	DECL_INCOMING_RTL (parms)
+-	  = eliminate_regs (DECL_INCOMING_RTL (parms), VOIDmode, NULL_RTX);
+-	SET_DECL_RTL (parms,
+-		      eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX));
+-#ifdef LEAF_REG_REMAP
+-	if (crtl->uses_only_leaf_regs)
+-	  {
+-	    leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms));
+-	    leaf_renumber_regs_insn (DECL_RTL (parms));
+-	  }
+-#endif
+-
+-	if (PARM_PASSED_IN_MEMORY (parms))
+-	  {
+-	    rtx inrtl = XEXP (DECL_INCOMING_RTL (parms), 0);
+-
+-	    /* ??? Here we assume that the parm address is indexed
+-	       off the frame pointer or arg pointer.
+-	       If that is not true, we produce meaningless results,
+-	       but do not crash.  */
+-	    if (GET_CODE (inrtl) == PLUS
+-		&& CONST_INT_P (XEXP (inrtl, 1)))
+-	      number = INTVAL (XEXP (inrtl, 1));
+-	    else
+-	      number = 0;
+-
+-	    code = N_PSYM;
+-	    number = DEBUGGER_ARG_OFFSET (number, inrtl);
+-	    letter = 'p';
+-
+-	    /* It is quite tempting to use TREE_TYPE (parms) instead
+-	       of DECL_ARG_TYPE (parms) for the eff_type, so that gcc
+-	       reports the actual type of the parameter, rather than
+-	       the promoted type.  This certainly makes GDB's life
+-	       easier, at least for some ports.  The change is a bad
+-	       idea however, since GDB expects to be able access the
+-	       type without performing any conversions.  So for
+-	       example, if we were passing a float to an unprototyped
+-	       function, gcc will store a double on the stack, but if
+-	       we emit a stab saying the type is a float, then gdb
+-	       will only read in a single value, and this will produce
+-	       an erroneous value.  */
+-	    eff_type = DECL_ARG_TYPE (parms);
+-	  }
+-	else if (REG_P (DECL_RTL (parms)))
+-	  {
+-	    rtx best_rtl;
+-
+-	    /* Parm passed in registers and lives in registers or nowhere.  */
+-	    code = DBX_REGPARM_STABS_CODE;
+-	    letter = DBX_REGPARM_STABS_LETTER;
+-
+-	    /* For parms passed in registers, it is better to use the
+-	       declared type of the variable, not the type it arrived in.  */
+-	    eff_type = TREE_TYPE (parms);
+-
+-	    /* If parm lives in a register, use that register; pretend
+-	       the parm was passed there.  It would be more consistent
+-	       to describe the register where the parm was passed, but
+-	       in practice that register usually holds something else.
+-	       If the parm lives nowhere, use the register where it
+-	       was passed.  */
+-	    if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
+-	      best_rtl = DECL_RTL (parms);
+-	    else if (GET_CODE (DECL_INCOMING_RTL (parms)) == PARALLEL)
+-	      best_rtl = XEXP (XVECEXP (DECL_INCOMING_RTL (parms), 0, 0), 0);
+-	    else
+-	      best_rtl = DECL_INCOMING_RTL (parms);
+-
+-	    number = DBX_REGISTER_NUMBER (REGNO (best_rtl));
+-	  }
+-	else if (MEM_P (DECL_RTL (parms))
+-		 && REG_P (XEXP (DECL_RTL (parms), 0))
+-		 && REGNO (XEXP (DECL_RTL (parms), 0)) != HARD_FRAME_POINTER_REGNUM
+-		 && REGNO (XEXP (DECL_RTL (parms), 0)) != STACK_POINTER_REGNUM
+-#if !HARD_FRAME_POINTER_IS_ARG_POINTER
+-		 && REGNO (XEXP (DECL_RTL (parms), 0)) != ARG_POINTER_REGNUM
+-#endif
+-		 )
+-	  {
+-	    /* Parm was passed via invisible reference.
+-	       That is, its address was passed in a register.
+-	       Output it as if it lived in that register.
+-	       The debugger will know from the type
+-	       that it was actually passed by invisible reference.  */
+-
+-	    code = DBX_REGPARM_STABS_CODE;
+-
+-	    /* GDB likes this marked with a special letter.  */
+-	    letter = (use_gnu_debug_info_extensions
+-		      ? 'a' : DBX_REGPARM_STABS_LETTER);
+-	    eff_type = TREE_TYPE (parms);
+-
+-	    /* DECL_RTL looks like (MEM (REG...).  Get the register number.
+-	       If it is an unallocated pseudo-reg, then use the register where
+-	       it was passed instead.
+-	       ??? Why is DBX_REGISTER_NUMBER not used here?  */
+-
+-	    if (REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER)
+-	      number = REGNO (XEXP (DECL_RTL (parms), 0));
+-	    else
+-	      number = REGNO (DECL_INCOMING_RTL (parms));
+-	  }
+-	else if (MEM_P (DECL_RTL (parms))
+-		 && MEM_P (XEXP (DECL_RTL (parms), 0)))
+-	  {
+-	    /* Parm was passed via invisible reference, with the reference
+-	       living on the stack.  DECL_RTL looks like
+-	       (MEM (MEM (PLUS (REG ...) (CONST_INT ...)))) or it
+-	       could look like (MEM (MEM (REG))).  */
+-
+-	    code = N_PSYM;
+-	    letter = 'v';
+-	    eff_type = TREE_TYPE (parms);
+-
+-	    if (!REG_P (XEXP (XEXP (DECL_RTL (parms), 0), 0)))
+-	      number = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
+-	    else
+-	      number = 0;
+-
+-	    number = DEBUGGER_ARG_OFFSET (number,
+-					  XEXP (XEXP (DECL_RTL (parms), 0), 0));
+-	  }
+-	else if (MEM_P (DECL_RTL (parms))
+-		 && XEXP (DECL_RTL (parms), 0) != const0_rtx
+-		 /* ??? A constant address for a parm can happen
+-		    when the reg it lives in is equiv to a constant in memory.
+-		    Should make this not happen, after 2.4.  */
+-		 && ! CONSTANT_P (XEXP (DECL_RTL (parms), 0)))
+-	  {
+-	    /* Parm was passed in registers but lives on the stack.  */
+-
+-	    code = N_PSYM;
+-	    letter = 'p';
+-	    eff_type = TREE_TYPE (parms);
+-
+-	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
+-	       in which case we want the value of that CONST_INT,
+-	       or (MEM (REG ...)),
+-	       in which case we use a value of zero.  */
+-	    if (!REG_P (XEXP (DECL_RTL (parms), 0)))
+-	      number = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
+-	    else
+-	      number = 0;
+-
+-	    /* Make a big endian correction if the mode of the type of the
+-	       parameter is not the same as the mode of the rtl.  */
+-	    if (BYTES_BIG_ENDIAN
+-		&& type_mode != rtl_mode
+-		&& GET_MODE_SIZE (type_mode) < UNITS_PER_WORD)
+-	      number += GET_MODE_SIZE (rtl_mode) - GET_MODE_SIZE (type_mode);
+-	  }
+-	else
+-	  /* ??? We don't know how to represent this argument.  */
+-	  continue;
+-
+-	dbxout_begin_complex_stabs ();
+-
+-	if (DECL_NAME (parms))
+-	  {
+-	    stabstr_I (DECL_NAME (parms));
+-	    stabstr_C (':');
+-	  }
+-	else
+-	  stabstr_S ("(anon):");
+-	stabstr_C (letter);
+-	dbxout_type (eff_type, 0);
+-	dbxout_finish_complex_stabs (parms, code, 0, 0, number);
+-      }
+-  DBXOUT_DECR_NESTING;
+-}
+-
+-/* Output definitions for the places where parms live during the function,
+-   when different from where they were passed, when the parms were passed
+-   in memory.
+-
+-   It is not useful to do this for parms passed in registers
+-   that live during the function in different registers, because it is
+-   impossible to look in the passed register for the passed value,
+-   so we use the within-the-function register to begin with.
+-
+-   PARMS is a chain of PARM_DECL nodes.  */
+-
+-void
+-dbxout_reg_parms (tree parms)
+-{
+-  ++debug_nesting;
+-
+-  for (; parms; parms = DECL_CHAIN (parms))
+-    if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms))
+-      {
+-	/* Report parms that live in registers during the function
+-	   but were passed in memory.  */
+-	if (REG_P (DECL_RTL (parms))
+-	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
+-	  dbxout_symbol_location (parms, TREE_TYPE (parms),
+-				  0, DECL_RTL (parms));
+-	else if (GET_CODE (DECL_RTL (parms)) == CONCAT)
+-	  dbxout_symbol_location (parms, TREE_TYPE (parms),
+-				  0, DECL_RTL (parms));
+-	/* Report parms that live in memory but not where they were passed.  */
+-	else if (MEM_P (DECL_RTL (parms))
+-		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
+-	  dbxout_symbol_location (parms, TREE_TYPE (parms),
+-				  0, DECL_RTL (parms));
+-      }
+-  DBXOUT_DECR_NESTING;
+-}
+-
+-/* Given a chain of ..._TYPE nodes (as come in a parameter list),
+-   output definitions of those names, in raw form */
+-
+-static void
+-dbxout_args (tree args)
+-{
+-  while (args)
+-    {
+-      stabstr_C (',');
+-      dbxout_type (TREE_VALUE (args), 0);
+-      args = TREE_CHAIN (args);
+-    }
+-}
+-
+-#if defined (DBX_DEBUGGING_INFO)
+-
+-/* Subroutine of dbxout_block.  Emit an N_LBRAC stab referencing LABEL.
+-   BEGIN_LABEL is the name of the beginning of the function, which may
+-   be required.  */
+-static void
+-dbx_output_lbrac (const char *label,
+-		  const char *begin_label ATTRIBUTE_UNUSED)
+-{
+-  dbxout_begin_stabn (N_LBRAC);
+-  if (DBX_BLOCKS_FUNCTION_RELATIVE)
+-    dbxout_stab_value_label_diff (label, begin_label);
+-  else
+-    dbxout_stab_value_label (label);
+-}
+-
+-/* Subroutine of dbxout_block.  Emit an N_RBRAC stab referencing LABEL.
+-   BEGIN_LABEL is the name of the beginning of the function, which may
+-   be required.  */
+-static void
+-dbx_output_rbrac (const char *label,
+-		  const char *begin_label ATTRIBUTE_UNUSED)
+-{
+-  dbxout_begin_stabn (N_RBRAC);
+-  if (DBX_BLOCKS_FUNCTION_RELATIVE)
+-    dbxout_stab_value_label_diff (label, begin_label);
+-  else
+-    dbxout_stab_value_label (label);
+-}
+-
+-/* Return true if at least one block among BLOCK, its children or siblings
+-   has TREE_USED, TREE_ASM_WRITTEN and BLOCK_IN_COLD_SECTION_P
+-   set.  If there is none, clear TREE_USED bit on such blocks.  */
+-
+-static bool
+-dbx_block_with_cold_children (tree block)
+-{
+-  bool ret = false;
+-  for (; block; block = BLOCK_CHAIN (block))
+-    if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
+-      {
+-	bool children = dbx_block_with_cold_children (BLOCK_SUBBLOCKS (block));
+-	if (BLOCK_IN_COLD_SECTION_P (block) || children)
+-	  ret = true;
+-	else
+-	  TREE_USED (block) = false;
+-      }
+-  return ret;
+-}
+-
+-/* Output everything about a symbol block (a BLOCK node
+-   that represents a scope level),
+-   including recursive output of contained blocks.
+-
+-   BLOCK is the BLOCK node.
+-   DEPTH is its depth within containing symbol blocks.
+-   ARGS is usually zero; but for the outermost block of the
+-   body of a function, it is a chain of PARM_DECLs for the function parameters.
+-   We output definitions of all the register parms
+-   as if they were local variables of that block.
+-
+-   If -g1 was used, we count blocks just the same, but output nothing
+-   except for the outermost block.
+-
+-   Actually, BLOCK may be several blocks chained together.
+-   We handle them all in sequence.
+-
+-   Return true if we emitted any LBRAC/RBRAC.  */
+-
+-static bool
+-dbxout_block (tree block, int depth, tree args, int parent_blocknum)
+-{
+-  bool ret = false;
+-  char begin_label[20];
+-  /* Reference current function start using LFBB.  */
+-  ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+-
+-  /* If called for the second partition, ignore blocks that don't have
+-     any children in the second partition.  */
+-  if (crtl->has_bb_partition && in_cold_section_p && depth == 0)
+-    dbx_block_with_cold_children (block);
+-
+-  for (; block; block = BLOCK_CHAIN (block))
+-    {
+-      /* Ignore blocks never expanded or otherwise marked as real.  */
+-      if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
+-	{
+-	  int did_output;
+-	  int blocknum = BLOCK_NUMBER (block);
+-	  int this_parent = parent_blocknum;
+-
+-	  /* In dbx format, the syms of a block come before the N_LBRAC.
+-	     If nothing is output, we don't need the N_LBRAC, either.  */
+-	  did_output = 0;
+-	  if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
+-	    did_output = dbxout_syms (BLOCK_VARS (block));
+-	  if (args)
+-	    dbxout_reg_parms (args);
+-
+-	  /* Now output an N_LBRAC symbol to represent the beginning of
+-	     the block.  Use the block's tree-walk order to generate
+-	     the assembler symbols LBBn and LBEn
+-	     that final will define around the code in this block.  */
+-	  if (did_output
+-	      && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p)
+-	    {
+-	      char buf[20];
+-	      const char *scope_start;
+-
+-	      ret = true;
+-	      if (depth == 0)
+-		/* The outermost block doesn't get LBB labels; use
+-		   the LFBB local symbol emitted by dbxout_begin_prologue.  */
+-		scope_start = begin_label;
+-	      else
+-		{
+-		  ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum);
+-		  scope_start = buf;
+-		  this_parent = blocknum;
+-		}
+-
+-	      dbx_output_lbrac (scope_start, begin_label);
+-	    }
+-
+-	  /* Output the subblocks.  */
+-	  bool children
+-	    = dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE,
+-			    this_parent);
+-	  ret |= children;
+-
+-	  /* Refer to the marker for the end of the block.  */
+-	  if (did_output
+-	      && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p)
+-	    {
+-	      char buf[100];
+-	      if (depth == 0)
+-		/* The outermost block doesn't get LBE labels;
+-		   use the "scope" label which will be emitted
+-		   by dbxout_function_end.  */
+-		ASM_GENERATE_INTERNAL_LABEL (buf, "Lscope", scope_labelno);
+-	      else
+-		ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum);
+-
+-	      dbx_output_rbrac (buf, begin_label);
+-	    }
+-	  else if (did_output && !children)
+-	    {
+-	      /* If we emitted any vars and didn't output any LBRAC/RBRAC,
+-		 either at this level or any lower level, we need to emit
+-		 an empty LBRAC/RBRAC pair now.  */
+-	      char buf[30];
+-	      const char *scope_start;
+-
+-	      ret = true;
+-	      if (parent_blocknum == -1)
+-		scope_start = begin_label;
+-	      else
+-		{
+-		  ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", parent_blocknum);
+-		  scope_start = buf;
+-		}
+-
+-	      dbx_output_lbrac (scope_start, begin_label);
+-	      dbx_output_rbrac (scope_start, begin_label);
+-	    }
+-	}
+-    }
+-  return ret;
+-}
+-
+-/* Output the information about a function and its arguments and result.
+-   Usually this follows the function's code,
+-   but on some systems, it comes before.  */
+-
+-static void
+-dbxout_begin_function (tree decl)
+-{
+-  int saved_tree_used1;
+-
+-  saved_tree_used1 = TREE_USED (decl);
+-  TREE_USED (decl) = 1;
+-  if (DECL_NAME (DECL_RESULT (decl)) != 0)
+-    {
+-      int saved_tree_used2 = TREE_USED (DECL_RESULT (decl));
+-      TREE_USED (DECL_RESULT (decl)) = 1;
+-      dbxout_symbol (decl, 0);
+-      TREE_USED (DECL_RESULT (decl)) = saved_tree_used2;
+-    }
+-  else
+-    dbxout_symbol (decl, 0);
+-  TREE_USED (decl) = saved_tree_used1;
+-
+-  dbxout_parms (DECL_ARGUMENTS (decl));
+-  if (DECL_NAME (DECL_RESULT (decl)) != 0)
+-    dbxout_symbol (DECL_RESULT (decl), 1);
+-}
+-#endif /* DBX_DEBUGGING_INFO */
+-
+-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+-
+-/* Record an element in the table of global destructors.  SYMBOL is
+-   a SYMBOL_REF of the function to be called; PRIORITY is a number
+-   between 0 and MAX_INIT_PRIORITY.  */
+-
+-void
+-default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED,
+-				  int priority ATTRIBUTE_UNUSED)
+-{
+-#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
+-  /* Tell GNU LD that this is part of the static destructor set.
+-     This will work for any system that uses stabs, most usefully
+-     aout systems.  */
+-  dbxout_begin_simple_stabs ("___DTOR_LIST__", 22 /* N_SETT */);
+-  dbxout_stab_value_label (XSTR (symbol, 0));
+-#else
+-  sorry ("global destructors not supported on this target");
+-#endif
+-}
+-
+-/* Likewise for global constructors.  */
+-
+-void
+-default_stabs_asm_out_constructor (rtx symbol ATTRIBUTE_UNUSED,
+-				   int priority ATTRIBUTE_UNUSED)
+-{
+-#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
+-  /* Tell GNU LD that this is part of the static destructor set.
+-     This will work for any system that uses stabs, most usefully
+-     aout systems.  */
+-  dbxout_begin_simple_stabs ("___CTOR_LIST__", 22 /* N_SETT */);
+-  dbxout_stab_value_label (XSTR (symbol, 0));
+-#else
+-  sorry ("global constructors not supported on this target");
+-#endif
+-}
+-
+-#include "gt-dbxout.h"
+diff --git a/gcc/dbxout.h b/gcc/dbxout.h
+deleted file mode 100644
+index 2c38e76c2..000000000
+--- a/gcc/dbxout.h
++++ /dev/null
+@@ -1,60 +0,0 @@
+-/* dbxout.h - Various declarations for functions found in dbxout.cc
+-   Copyright (C) 1998-2022 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
+-.  */
+-
+-#ifndef GCC_DBXOUT_H
+-#define GCC_DBXOUT_H
+-
+-extern int dbxout_symbol (tree, int);
+-extern void dbxout_parms (tree);
+-extern void dbxout_reg_parms (tree);
+-extern int dbxout_syms (tree);
+-
+-extern void default_stabs_asm_out_destructor (rtx, int);
+-extern void default_stabs_asm_out_constructor (rtx, int);
+-
+-/* dbxout helper functions */
+-#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
+-
+-extern void dbxout_int (int);
+-extern void dbxout_stabd (int, int);
+-extern void dbxout_begin_stabn (int);
+-extern void dbxout_begin_stabn_sline (int);
+-extern void dbxout_begin_empty_stabs (int);
+-extern void dbxout_begin_simple_stabs (const char *, int);
+-extern void dbxout_begin_simple_stabs_desc (const char *, int, int);
+-
+-extern void dbxout_stab_value_zero (void);
+-extern void dbxout_stab_value_label (const char *);
+-extern void dbxout_stab_value_label_diff (const char *, const char *);
+-extern void dbxout_stab_value_internal_label (const char *, int *);
+-extern void dbxout_stab_value_internal_label_diff (const char *, int *,
+-						   const char *);
+-#endif
+-
+-/* Language description for N_SO stabs.  */
+-#define N_SO_AS          1
+-#define N_SO_C           2
+-#define N_SO_ANSI_C      3
+-#define N_SO_CC          4 /* c++*/
+-#define N_SO_FORTRAN     5
+-#define N_SO_FORTRAN90   7
+-#define N_SO_OBJC        50
+-#define N_SO_OBJCPLUS    51
+-
+-#endif /* GCC_DBXOUT_H */
+diff --git a/gcc/debug.h b/gcc/debug.h
+index 17a7e4862..fe85115d5 100644
+--- a/gcc/debug.h
++++ b/gcc/debug.h
+@@ -238,7 +238,6 @@ extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
+ 
+ /* Hooks for various debug formats.  */
+ extern const struct gcc_debug_hooks do_nothing_debug_hooks;
+-extern const struct gcc_debug_hooks dbx_debug_hooks;
+ extern const struct gcc_debug_hooks xcoff_debug_hooks;
+ extern const struct gcc_debug_hooks dwarf2_debug_hooks;
+ extern const struct gcc_debug_hooks dwarf2_lineno_debug_hooks;
+diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
+index 19d073256..a650f60c7 100644
+--- a/gcc/doc/install.texi
++++ b/gcc/doc/install.texi
+@@ -3982,8 +3982,7 @@ on FreeBSD 7 or later) and the use of @code{__cxa_atexit} by default
+ by GCC 4.5 and above.
+ 
+ We support FreeBSD using the ELF file format with DWARF 2 debugging
+-for all CPU architectures.  You may use @option{-gstabs} instead of
+-@option{-g}, if you really want the old debugging format.  There are
++for all CPU architectures.  There are
+ no known issues with mixing object files and libraries with different
+ debugging formats.  Otherwise, this release of GCC should now match
+ more of the configuration used in the stock FreeBSD configuration of
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 4d3eccdb2..7ca60dd64 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -45,7 +45,7 @@ remainder.  @command{g++} accepts mostly the same options as @command{gcc}.
+ @c man end
+ @c man begin SEEALSO
+ gpl(7), gfdl(7), fsf-funding(7),
+-cpp(1), gcov(1), as(1), ld(1), gdb(1), dbx(1)
++cpp(1), gcov(1), as(1), ld(1), gdb(1)
+ and the Info entries for @file{gcc}, @file{cpp}, @file{as},
+ @file{ld}, @file{binutils} and @file{gdb}.
+ @c man end
+@@ -480,7 +480,7 @@ Objective-C and Objective-C++ Dialects}.
+ @gccoptlist{-g  -g@var{level}  -gdwarf  -gdwarf-@var{version} @gol
+ -gbtf -gctf  -gctf@var{level} @gol
+ -ggdb  -grecord-gcc-switches  -gno-record-gcc-switches @gol
+--gstabs  -gstabs+  -gstrict-dwarf  -gno-strict-dwarf @gol
++-gstrict-dwarf  -gno-strict-dwarf @gol
+ -gas-loc-support  -gno-as-loc-support @gol
+ -gas-locview-support  -gno-as-locview-support @gol
+ -gcolumn-info  -gno-column-info  -gdwarf32  -gdwarf64 @gol
+@@ -488,7 +488,7 @@ Objective-C and Objective-C++ Dialects}.
+ -gvariable-location-views  -gno-variable-location-views @gol
+ -ginternal-reset-location-views  -gno-internal-reset-location-views @gol
+ -ginline-points  -gno-inline-points @gol
+--gvms  -gxcoff  -gxcoff+  -gz@r{[}=@var{type}@r{]} @gol
++-gvms -gz@r{[}=@var{type}@r{]} @gol
+ -gsplit-dwarf  -gdescribe-dies  -gno-describe-dies @gol
+ -fdebug-prefix-map=@var{old}=@var{new}  -fdebug-types-section @gol
+ -fno-eliminate-unused-debug-types @gol
+@@ -10276,10 +10276,8 @@ information.
+ On most systems that use stabs format, @option{-g} enables use of extra
+ debugging information that only GDB can use; this extra information
+ makes debugging work better in GDB but probably makes other debuggers
+-crash or
+-refuse to read the program.  If you want to control for certain whether
+-to generate the extra information, use @option{-gstabs+}, @option{-gstabs},
+-@option{-gxcoff+}, @option{-gxcoff}, or @option{-gvms} (see below).
++crash or refuse to read the program.  If you want to control for certain whether
++to generate the extra information, use @option{-gvms} (see below).
+ 
+ @item -ggdb
+ @opindex ggdb
+@@ -10336,34 +10334,6 @@ information, but does not include type information.
+ Level 2 produces type information for entities (functions, data objects etc.)
+ at file-scope or global-scope only.
+ 
+-@item -gstabs
+-@opindex gstabs
+-Produce debugging information in stabs format (if that is supported),
+-without GDB extensions.  This is the format used by DBX on most BSD
+-systems.  On MIPS, Alpha and System V Release 4 systems this option
+-produces stabs debugging output that is not understood by DBX@.
+-On System V Release 4 systems this option requires the GNU assembler.
+-
+-@item -gstabs+
+-@opindex gstabs+
+-Produce debugging information in stabs format (if that is supported),
+-using GNU extensions understood only by the GNU debugger (GDB)@.  The
+-use of these extensions is likely to make other debuggers crash or
+-refuse to read the program.
+-
+-@item -gxcoff
+-@opindex gxcoff
+-Produce debugging information in XCOFF format (if that is supported).
+-This is the format used by the DBX debugger on IBM RS/6000 systems.
+-
+-@item -gxcoff+
+-@opindex gxcoff+
+-Produce debugging information in XCOFF format (if that is supported),
+-using GNU extensions understood only by the GNU debugger (GDB)@.  The
+-use of these extensions is likely to make other debuggers crash or
+-refuse to read the program, and may cause assemblers other than the GNU
+-assembler (GAS) to fail with an error.
+-
+ @item -gvms
+ @opindex gvms
+ Produce debugging information in Alpha/VMS debug format (if that is
+@@ -10371,8 +10341,6 @@ supported).  This is the format used by DEBUG on Alpha/VMS systems.
+ 
+ @item -g@var{level}
+ @itemx -ggdb@var{level}
+-@itemx -gstabs@var{level}
+-@itemx -gxcoff@var{level}
+ @itemx -gvms@var{level}
+ Request debugging information and also use @var{level} to specify how
+ much information.  The default level is 2.
+diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
+index 1e821d4e5..9e8b4f50a 100644
+--- a/gcc/doc/passes.texi
++++ b/gcc/doc/passes.texi
+@@ -1184,7 +1184,7 @@ these files.
+ 
+ This is run after final because it must output the stack slot offsets
+ for pseudo registers that did not get hard registers.  Source files
+-are @file{dbxout.cc} for DBX symbol table format, @file{dwarfout.c} for
++are @file{dwarfout.c} for
+ DWARF symbol table format, files @file{dwarf2out.cc} and @file{dwarf2asm.cc}
+ for DWARF2 symbol table format, and @file{vmsdbgout.cc} for VMS debug
+ symbol table format.
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 2aba523bb..851d31c18 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -9912,9 +9912,6 @@ This describes how to specify debugging information.
+ 
+ @menu
+ * All Debuggers::      Macros that affect all debugging formats uniformly.
+-* DBX Options::        Macros enabling specific options in DBX format.
+-* DBX Hooks::          Hook macros for varying DBX format.
+-* File Names and DBX:: Macros controlling output of file names in DBX format.
+ * DWARF::              Macros for DWARF format.
+ * VMS Debug::          Macros for VMS debug format.
+ * CTF Debug::          Macros for CTF debug format.
+@@ -9965,35 +9962,18 @@ having address @var{x} (an RTL expression).  The nominal offset is
+ A C expression that returns the type of debugging output GCC should
+ produce when the user specifies just @option{-g}.  Define
+ this if you have arranged for GCC to support more than one format of
+-debugging output.  Currently, the allowable values are @code{DBX_DEBUG},
+-@code{DWARF2_DEBUG}, @code{XCOFF_DEBUG}, @code{VMS_DEBUG},
++debugging output.  Currently, the allowable values are
++@code{DWARF2_DEBUG}, @code{VMS_DEBUG},
+ and @code{VMS_AND_DWARF2_DEBUG}.
+ 
+ When the user specifies @option{-ggdb}, GCC normally also uses the
+ value of this macro to select the debugging output format, but with two
+ exceptions.  If @code{DWARF2_DEBUGGING_INFO} is defined, GCC uses the
+-value @code{DWARF2_DEBUG}.  Otherwise, if @code{DBX_DEBUGGING_INFO} is
+-defined, GCC uses @code{DBX_DEBUG}.
++value @code{DWARF2_DEBUG}.
+ 
+ The value of this macro only affects the default debugging output; the
+-user can always get a specific type of output by using @option{-gstabs},
+-@option{-gdwarf-2}, @option{-gxcoff}, or @option{-gvms}.
+-@end defmac
+-
+-@node DBX Options
+-@subsection Specific Options for DBX Output
+-
+-@c prevent bad page break with this line
+-These are specific options for DBX output.
+-
+-@defmac DBX_DEBUGGING_INFO
+-Define this macro if GCC should produce debugging output for DBX
+-in response to the @option{-g} option.
+-@end defmac
+-
+-@defmac XCOFF_DEBUGGING_INFO
+-Define this macro if GCC should produce XCOFF format debugging output
+-in response to the @option{-g} option.  This is a variant of DBX format.
++user can always get a specific type of output by using  @option{-gdwarf-2},
++or @option{-gvms}.
+ @end defmac
+ 
+ @defmac DEFAULT_GDB_EXTENSIONS
+@@ -10004,196 +9984,6 @@ macro, the default is 1: always generate the extended information
+ if there is any occasion to.
+ @end defmac
+ 
+-@defmac DEBUG_SYMS_TEXT
+-Define this macro if all @code{.stabs} commands should be output while
+-in the text section.
+-@end defmac
+-
+-@defmac ASM_STABS_OP
+-A C string constant, including spacing, naming the assembler pseudo op to
+-use instead of @code{"\t.stabs\t"} to define an ordinary debugging symbol.
+-If you don't define this macro, @code{"\t.stabs\t"} is used.  This macro
+-applies only to DBX debugging information format.
+-@end defmac
+-
+-@defmac ASM_STABD_OP
+-A C string constant, including spacing, naming the assembler pseudo op to
+-use instead of @code{"\t.stabd\t"} to define a debugging symbol whose
+-value is the current location.  If you don't define this macro,
+-@code{"\t.stabd\t"} is used.  This macro applies only to DBX debugging
+-information format.
+-@end defmac
+-
+-@defmac ASM_STABN_OP
+-A C string constant, including spacing, naming the assembler pseudo op to
+-use instead of @code{"\t.stabn\t"} to define a debugging symbol with no
+-name.  If you don't define this macro, @code{"\t.stabn\t"} is used.  This
+-macro applies only to DBX debugging information format.
+-@end defmac
+-
+-@defmac DBX_NO_XREFS
+-Define this macro if DBX on your system does not support the construct
+-@samp{xs@var{tagname}}.  On some systems, this construct is used to
+-describe a forward reference to a structure named @var{tagname}.
+-On other systems, this construct is not supported at all.
+-@end defmac
+-
+-@defmac DBX_CONTIN_LENGTH
+-A symbol name in DBX-format debugging information is normally
+-continued (split into two separate @code{.stabs} directives) when it
+-exceeds a certain length (by default, 80 characters).  On some
+-operating systems, DBX requires this splitting; on others, splitting
+-must not be done.  You can inhibit splitting by defining this macro
+-with the value zero.  You can override the default splitting-length by
+-defining this macro as an expression for the length you desire.
+-@end defmac
+-
+-@defmac DBX_CONTIN_CHAR
+-Normally continuation is indicated by adding a @samp{\} character to
+-the end of a @code{.stabs} string when a continuation follows.  To use
+-a different character instead, define this macro as a character
+-constant for the character you want to use.  Do not define this macro
+-if backslash is correct for your system.
+-@end defmac
+-
+-@defmac DBX_STATIC_STAB_DATA_SECTION
+-Define this macro if it is necessary to go to the data section before
+-outputting the @samp{.stabs} pseudo-op for a non-global static
+-variable.
+-@end defmac
+-
+-@defmac DBX_TYPE_DECL_STABS_CODE
+-The value to use in the ``code'' field of the @code{.stabs} directive
+-for a typedef.  The default is @code{N_LSYM}.
+-@end defmac
+-
+-@defmac DBX_STATIC_CONST_VAR_CODE
+-The value to use in the ``code'' field of the @code{.stabs} directive
+-for a static variable located in the text section.  DBX format does not
+-provide any ``right'' way to do this.  The default is @code{N_FUN}.
+-@end defmac
+-
+-@defmac DBX_REGPARM_STABS_CODE
+-The value to use in the ``code'' field of the @code{.stabs} directive
+-for a parameter passed in registers.  DBX format does not provide any
+-``right'' way to do this.  The default is @code{N_RSYM}.
+-@end defmac
+-
+-@defmac DBX_REGPARM_STABS_LETTER
+-The letter to use in DBX symbol data to identify a symbol as a parameter
+-passed in registers.  DBX format does not customarily provide any way to
+-do this.  The default is @code{'P'}.
+-@end defmac
+-
+-@defmac DBX_FUNCTION_FIRST
+-Define this macro if the DBX information for a function and its
+-arguments should precede the assembler code for the function.  Normally,
+-in DBX format, the debugging information entirely follows the assembler
+-code.
+-@end defmac
+-
+-@defmac DBX_BLOCKS_FUNCTION_RELATIVE
+-Define this macro, with value 1, if the value of a symbol describing
+-the scope of a block (@code{N_LBRAC} or @code{N_RBRAC}) should be
+-relative to the start of the enclosing function.  Normally, GCC uses
+-an absolute address.
+-@end defmac
+-
+-@defmac DBX_LINES_FUNCTION_RELATIVE
+-Define this macro, with value 1, if the value of a symbol indicating
+-the current line number (@code{N_SLINE}) should be relative to the
+-start of the enclosing function.  Normally, GCC uses an absolute address.
+-@end defmac
+-
+-@defmac DBX_USE_BINCL
+-Define this macro if GCC should generate @code{N_BINCL} and
+-@code{N_EINCL} stabs for included header files, as on Sun systems.  This
+-macro also directs GCC to output a type number as a pair of a file
+-number and a type number within the file.  Normally, GCC does not
+-generate @code{N_BINCL} or @code{N_EINCL} stabs, and it outputs a single
+-number for a type number.
+-@end defmac
+-
+-@node DBX Hooks
+-@subsection Open-Ended Hooks for DBX Format
+-
+-@c prevent bad page break with this line
+-These are hooks for DBX format.
+-
+-@defmac DBX_OUTPUT_SOURCE_LINE (@var{stream}, @var{line}, @var{counter})
+-A C statement to output DBX debugging information before code for line
+-number @var{line} of the current source file to the stdio stream
+-@var{stream}.  @var{counter} is the number of time the macro was
+-invoked, including the current invocation; it is intended to generate
+-unique labels in the assembly output.
+-
+-This macro should not be defined if the default output is correct, or
+-if it can be made correct by defining @code{DBX_LINES_FUNCTION_RELATIVE}.
+-@end defmac
+-
+-@defmac NO_DBX_FUNCTION_END
+-Some stabs encapsulation formats (in particular ECOFF), cannot handle the
+-@code{.stabs "",N_FUN,,0,0,Lscope-function-1} gdb dbx extension construct.
+-On those machines, define this macro to turn this feature off without
+-disturbing the rest of the gdb extensions.
+-@end defmac
+-
+-@defmac NO_DBX_BNSYM_ENSYM
+-Some assemblers cannot handle the @code{.stabd BNSYM/ENSYM,0,0} gdb dbx
+-extension construct.  On those machines, define this macro to turn this
+-feature off without disturbing the rest of the gdb extensions.
+-@end defmac
+-
+-@node File Names and DBX
+-@subsection File Names in DBX Format
+-
+-@c prevent bad page break with this line
+-This describes file names in DBX format.
+-
+-@defmac DBX_OUTPUT_MAIN_SOURCE_FILENAME (@var{stream}, @var{name})
+-A C statement to output DBX debugging information to the stdio stream
+-@var{stream}, which indicates that file @var{name} is the main source
+-file---the file specified as the input file for compilation.
+-This macro is called only once, at the beginning of compilation.
+-
+-This macro need not be defined if the standard form of output
+-for DBX debugging information is appropriate.
+-
+-It may be necessary to refer to a label equal to the beginning of the
+-text section.  You can use @samp{assemble_name (stream, ltext_label_name)}
+-to do so.  If you do this, you must also set the variable
+-@var{used_ltext_label_name} to @code{true}.
+-@end defmac
+-
+-@defmac NO_DBX_MAIN_SOURCE_DIRECTORY
+-Define this macro, with value 1, if GCC should not emit an indication
+-of the current directory for compilation and current source language at
+-the beginning of the file.
+-@end defmac
+-
+-@defmac NO_DBX_GCC_MARKER
+-Define this macro, with value 1, if GCC should not emit an indication
+-that this object file was compiled by GCC@.  The default is to emit
+-an @code{N_OPT} stab at the beginning of every source file, with
+-@samp{gcc2_compiled.} for the string and value 0.
+-@end defmac
+-
+-@defmac DBX_OUTPUT_MAIN_SOURCE_FILE_END (@var{stream}, @var{name})
+-A C statement to output DBX debugging information at the end of
+-compilation of the main source file @var{name}.  Output should be
+-written to the stdio stream @var{stream}.
+-
+-If you don't define this macro, nothing special is output at the end
+-of compilation, which is correct for most machines.
+-@end defmac
+-
+-@defmac DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-Define this macro @emph{instead of} defining
+-@code{DBX_OUTPUT_MAIN_SOURCE_FILE_END}, if what needs to be output at
+-the end of compilation is an @code{N_SO} stab with an empty string,
+-whose value is the highest absolute text address in the file.
+-@end defmac
+-
+ @need 2000
+ @node DWARF
+ @subsection Macros for DWARF Output
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 817d586ff..ac95cdf7a 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -6603,9 +6603,6 @@ This describes how to specify debugging information.
+ 
+ @menu
+ * All Debuggers::      Macros that affect all debugging formats uniformly.
+-* DBX Options::        Macros enabling specific options in DBX format.
+-* DBX Hooks::          Hook macros for varying DBX format.
+-* File Names and DBX:: Macros controlling output of file names in DBX format.
+ * DWARF::              Macros for DWARF format.
+ * VMS Debug::          Macros for VMS debug format.
+ * CTF Debug::          Macros for CTF debug format.
+@@ -6656,35 +6653,18 @@ having address @var{x} (an RTL expression).  The nominal offset is
+ A C expression that returns the type of debugging output GCC should
+ produce when the user specifies just @option{-g}.  Define
+ this if you have arranged for GCC to support more than one format of
+-debugging output.  Currently, the allowable values are @code{DBX_DEBUG},
+-@code{DWARF2_DEBUG}, @code{XCOFF_DEBUG}, @code{VMS_DEBUG},
++debugging output.  Currently, the allowable values are
++@code{DWARF2_DEBUG}, @code{VMS_DEBUG},
+ and @code{VMS_AND_DWARF2_DEBUG}.
+ 
+ When the user specifies @option{-ggdb}, GCC normally also uses the
+ value of this macro to select the debugging output format, but with two
+ exceptions.  If @code{DWARF2_DEBUGGING_INFO} is defined, GCC uses the
+-value @code{DWARF2_DEBUG}.  Otherwise, if @code{DBX_DEBUGGING_INFO} is
+-defined, GCC uses @code{DBX_DEBUG}.
++value @code{DWARF2_DEBUG}.
+ 
+ The value of this macro only affects the default debugging output; the
+-user can always get a specific type of output by using @option{-gstabs},
+-@option{-gdwarf-2}, @option{-gxcoff}, or @option{-gvms}.
+-@end defmac
+-
+-@node DBX Options
+-@subsection Specific Options for DBX Output
+-
+-@c prevent bad page break with this line
+-These are specific options for DBX output.
+-
+-@defmac DBX_DEBUGGING_INFO
+-Define this macro if GCC should produce debugging output for DBX
+-in response to the @option{-g} option.
+-@end defmac
+-
+-@defmac XCOFF_DEBUGGING_INFO
+-Define this macro if GCC should produce XCOFF format debugging output
+-in response to the @option{-g} option.  This is a variant of DBX format.
++user can always get a specific type of output by using  @option{-gdwarf-2},
++or @option{-gvms}.
+ @end defmac
+ 
+ @defmac DEFAULT_GDB_EXTENSIONS
+@@ -6695,196 +6675,6 @@ macro, the default is 1: always generate the extended information
+ if there is any occasion to.
+ @end defmac
+ 
+-@defmac DEBUG_SYMS_TEXT
+-Define this macro if all @code{.stabs} commands should be output while
+-in the text section.
+-@end defmac
+-
+-@defmac ASM_STABS_OP
+-A C string constant, including spacing, naming the assembler pseudo op to
+-use instead of @code{"\t.stabs\t"} to define an ordinary debugging symbol.
+-If you don't define this macro, @code{"\t.stabs\t"} is used.  This macro
+-applies only to DBX debugging information format.
+-@end defmac
+-
+-@defmac ASM_STABD_OP
+-A C string constant, including spacing, naming the assembler pseudo op to
+-use instead of @code{"\t.stabd\t"} to define a debugging symbol whose
+-value is the current location.  If you don't define this macro,
+-@code{"\t.stabd\t"} is used.  This macro applies only to DBX debugging
+-information format.
+-@end defmac
+-
+-@defmac ASM_STABN_OP
+-A C string constant, including spacing, naming the assembler pseudo op to
+-use instead of @code{"\t.stabn\t"} to define a debugging symbol with no
+-name.  If you don't define this macro, @code{"\t.stabn\t"} is used.  This
+-macro applies only to DBX debugging information format.
+-@end defmac
+-
+-@defmac DBX_NO_XREFS
+-Define this macro if DBX on your system does not support the construct
+-@samp{xs@var{tagname}}.  On some systems, this construct is used to
+-describe a forward reference to a structure named @var{tagname}.
+-On other systems, this construct is not supported at all.
+-@end defmac
+-
+-@defmac DBX_CONTIN_LENGTH
+-A symbol name in DBX-format debugging information is normally
+-continued (split into two separate @code{.stabs} directives) when it
+-exceeds a certain length (by default, 80 characters).  On some
+-operating systems, DBX requires this splitting; on others, splitting
+-must not be done.  You can inhibit splitting by defining this macro
+-with the value zero.  You can override the default splitting-length by
+-defining this macro as an expression for the length you desire.
+-@end defmac
+-
+-@defmac DBX_CONTIN_CHAR
+-Normally continuation is indicated by adding a @samp{\} character to
+-the end of a @code{.stabs} string when a continuation follows.  To use
+-a different character instead, define this macro as a character
+-constant for the character you want to use.  Do not define this macro
+-if backslash is correct for your system.
+-@end defmac
+-
+-@defmac DBX_STATIC_STAB_DATA_SECTION
+-Define this macro if it is necessary to go to the data section before
+-outputting the @samp{.stabs} pseudo-op for a non-global static
+-variable.
+-@end defmac
+-
+-@defmac DBX_TYPE_DECL_STABS_CODE
+-The value to use in the ``code'' field of the @code{.stabs} directive
+-for a typedef.  The default is @code{N_LSYM}.
+-@end defmac
+-
+-@defmac DBX_STATIC_CONST_VAR_CODE
+-The value to use in the ``code'' field of the @code{.stabs} directive
+-for a static variable located in the text section.  DBX format does not
+-provide any ``right'' way to do this.  The default is @code{N_FUN}.
+-@end defmac
+-
+-@defmac DBX_REGPARM_STABS_CODE
+-The value to use in the ``code'' field of the @code{.stabs} directive
+-for a parameter passed in registers.  DBX format does not provide any
+-``right'' way to do this.  The default is @code{N_RSYM}.
+-@end defmac
+-
+-@defmac DBX_REGPARM_STABS_LETTER
+-The letter to use in DBX symbol data to identify a symbol as a parameter
+-passed in registers.  DBX format does not customarily provide any way to
+-do this.  The default is @code{'P'}.
+-@end defmac
+-
+-@defmac DBX_FUNCTION_FIRST
+-Define this macro if the DBX information for a function and its
+-arguments should precede the assembler code for the function.  Normally,
+-in DBX format, the debugging information entirely follows the assembler
+-code.
+-@end defmac
+-
+-@defmac DBX_BLOCKS_FUNCTION_RELATIVE
+-Define this macro, with value 1, if the value of a symbol describing
+-the scope of a block (@code{N_LBRAC} or @code{N_RBRAC}) should be
+-relative to the start of the enclosing function.  Normally, GCC uses
+-an absolute address.
+-@end defmac
+-
+-@defmac DBX_LINES_FUNCTION_RELATIVE
+-Define this macro, with value 1, if the value of a symbol indicating
+-the current line number (@code{N_SLINE}) should be relative to the
+-start of the enclosing function.  Normally, GCC uses an absolute address.
+-@end defmac
+-
+-@defmac DBX_USE_BINCL
+-Define this macro if GCC should generate @code{N_BINCL} and
+-@code{N_EINCL} stabs for included header files, as on Sun systems.  This
+-macro also directs GCC to output a type number as a pair of a file
+-number and a type number within the file.  Normally, GCC does not
+-generate @code{N_BINCL} or @code{N_EINCL} stabs, and it outputs a single
+-number for a type number.
+-@end defmac
+-
+-@node DBX Hooks
+-@subsection Open-Ended Hooks for DBX Format
+-
+-@c prevent bad page break with this line
+-These are hooks for DBX format.
+-
+-@defmac DBX_OUTPUT_SOURCE_LINE (@var{stream}, @var{line}, @var{counter})
+-A C statement to output DBX debugging information before code for line
+-number @var{line} of the current source file to the stdio stream
+-@var{stream}.  @var{counter} is the number of time the macro was
+-invoked, including the current invocation; it is intended to generate
+-unique labels in the assembly output.
+-
+-This macro should not be defined if the default output is correct, or
+-if it can be made correct by defining @code{DBX_LINES_FUNCTION_RELATIVE}.
+-@end defmac
+-
+-@defmac NO_DBX_FUNCTION_END
+-Some stabs encapsulation formats (in particular ECOFF), cannot handle the
+-@code{.stabs "",N_FUN,,0,0,Lscope-function-1} gdb dbx extension construct.
+-On those machines, define this macro to turn this feature off without
+-disturbing the rest of the gdb extensions.
+-@end defmac
+-
+-@defmac NO_DBX_BNSYM_ENSYM
+-Some assemblers cannot handle the @code{.stabd BNSYM/ENSYM,0,0} gdb dbx
+-extension construct.  On those machines, define this macro to turn this
+-feature off without disturbing the rest of the gdb extensions.
+-@end defmac
+-
+-@node File Names and DBX
+-@subsection File Names in DBX Format
+-
+-@c prevent bad page break with this line
+-This describes file names in DBX format.
+-
+-@defmac DBX_OUTPUT_MAIN_SOURCE_FILENAME (@var{stream}, @var{name})
+-A C statement to output DBX debugging information to the stdio stream
+-@var{stream}, which indicates that file @var{name} is the main source
+-file---the file specified as the input file for compilation.
+-This macro is called only once, at the beginning of compilation.
+-
+-This macro need not be defined if the standard form of output
+-for DBX debugging information is appropriate.
+-
+-It may be necessary to refer to a label equal to the beginning of the
+-text section.  You can use @samp{assemble_name (stream, ltext_label_name)}
+-to do so.  If you do this, you must also set the variable
+-@var{used_ltext_label_name} to @code{true}.
+-@end defmac
+-
+-@defmac NO_DBX_MAIN_SOURCE_DIRECTORY
+-Define this macro, with value 1, if GCC should not emit an indication
+-of the current directory for compilation and current source language at
+-the beginning of the file.
+-@end defmac
+-
+-@defmac NO_DBX_GCC_MARKER
+-Define this macro, with value 1, if GCC should not emit an indication
+-that this object file was compiled by GCC@.  The default is to emit
+-an @code{N_OPT} stab at the beginning of every source file, with
+-@samp{gcc2_compiled.} for the string and value 0.
+-@end defmac
+-
+-@defmac DBX_OUTPUT_MAIN_SOURCE_FILE_END (@var{stream}, @var{name})
+-A C statement to output DBX debugging information at the end of
+-compilation of the main source file @var{name}.  Output should be
+-written to the stdio stream @var{stream}.
+-
+-If you don't define this macro, nothing special is output at the end
+-of compilation, which is correct for most machines.
+-@end defmac
+-
+-@defmac DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+-Define this macro @emph{instead of} defining
+-@code{DBX_OUTPUT_MAIN_SOURCE_FILE_END}, if what needs to be output at
+-the end of compilation is an @code{N_SO} stab with an empty string,
+-whose value is the highest absolute text address in the file.
+-@end defmac
+-
+ @need 2000
+ @node DWARF
+ @subsection Macros for DWARF Output
+diff --git a/gcc/dwarf2asm.cc b/gcc/dwarf2asm.cc
+index 274f574f2..7eac83f7b 100644
+--- a/gcc/dwarf2asm.cc
++++ b/gcc/dwarf2asm.cc
+@@ -35,10 +35,6 @@ along with GCC; see the file COPYING3.  If not see
+ #include "emit-rtl.h"
+ #include "fold-const.h"
+ 
+-#ifndef XCOFF_DEBUGGING_INFO
+-#define XCOFF_DEBUGGING_INFO 0
+-#endif
+-
+ 
+ /* Output an unaligned integer with the given value and size.  Prefer not
+    to print a newline, since the caller may want to add a comment.  */
+@@ -384,16 +380,13 @@ dw2_asm_output_nstring (const char *str, size_t orig_len,
+ 
+   if (flag_debug_asm && comment)
+     {
+-      if (XCOFF_DEBUGGING_INFO)
+-	fputs ("\t.byte \"", asm_out_file);
+-      else
+-	fputs ("\t.ascii \"", asm_out_file);
++      fputs ("\t.ascii \"", asm_out_file);
+ 
+       for (i = 0; i < len; i++)
+ 	{
+ 	  int c = str[i];
+ 	  if (c == '\"')
+-	    fputc (XCOFF_DEBUGGING_INFO ? '\"' : '\\', asm_out_file);
++	    fputc ('\\', asm_out_file);
+ 	  else if (c == '\\')
+ 	    fputc ('\\', asm_out_file);
+ 	  if (ISPRINT (c))
+@@ -913,7 +906,7 @@ static GTY(()) hash_map *indirect_pool;
+ static GTY(()) int dw2_const_labelno;
+ 
+ #if defined(HAVE_GAS_HIDDEN)
+-# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO)
++# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
+ #else
+ # define USE_LINKONCE_INDIRECT 0
+ #endif
+diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
+index f0f6f4fd4..380da2589 100644
+--- a/gcc/dwarf2out.cc
++++ b/gcc/dwarf2out.cc
+@@ -105,14 +105,6 @@ static rtx_insn *cached_next_real_insn;
+ static void dwarf2out_decl (tree);
+ static bool is_redundant_typedef (const_tree);
+ 
+-#ifndef XCOFF_DEBUGGING_INFO
+-#define XCOFF_DEBUGGING_INFO 0
+-#endif
+-
+-#ifndef HAVE_XCOFF_DWARF_EXTRAS
+-#define HAVE_XCOFF_DWARF_EXTRAS 0
+-#endif
+-
+ #ifdef VMS_DEBUGGING_INFO
+ int vms_file_stats_name (const char *, long long *, long *, char *, int *);
+ 
+@@ -608,14 +600,11 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second,
+ 				  for_eh + j);
+   ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + j);
+   ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
+-  if (!XCOFF_DEBUGGING_INFO || for_eh)
+-    {
+-      if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
+-	dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
+-			     " indicating 64-bit DWARF extension");
+-      dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
+-			    "FDE Length");
+-    }
++  if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
++    dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
++			 " indicating 64-bit DWARF extension");
++  dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
++			"FDE Length");
+   ASM_OUTPUT_LABEL (asm_out_file, l1);
+ 
+   if (for_eh)
+@@ -812,14 +801,11 @@ output_call_frame_info (int for_eh)
+   /* Output the CIE.  */
+   ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
+   ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
+-  if (!XCOFF_DEBUGGING_INFO || for_eh)
+-    {
+-      if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
+-	dw2_asm_output_data (4, 0xffffffff,
+-	  "Initial length escape value indicating 64-bit DWARF extension");
+-      dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
+-			    "Length of Common Information Entry");
+-    }
++  if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh)
++    dw2_asm_output_data (4, 0xffffffff,
++			 "Initial length escape value indicating 64-bit DWARF extension");
++  dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1,
++			"Length of Common Information Entry");
+   ASM_OUTPUT_LABEL (asm_out_file, l1);
+ 
+   /* Now that the CIE pointer is PC-relative for EH,
+@@ -3679,8 +3665,7 @@ static GTY (()) vec *macinfo_table;
+ /* True if .debug_macinfo or .debug_macros section is going to be
+    emitted.  */
+ #define have_macinfo \
+-  ((!XCOFF_DEBUGGING_INFO || HAVE_XCOFF_DWARF_EXTRAS) \
+-   && debug_info_level >= DINFO_LEVEL_VERBOSE \
++   (debug_info_level >= DINFO_LEVEL_VERBOSE \
+    && !macinfo_table->is_empty ())
+ 
+ /* Vector of dies for which we should generate .debug_ranges info.  */
+@@ -4982,9 +4967,6 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref
+ {
+   dw_attr_node attr;
+ 
+-  if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS)
+-    return;
+-
+   attr.dw_attr = attr_kind;
+   attr.dw_attr_val.val_class = dw_val_class_loc_list;
+   attr.dw_attr_val.val_entry = NULL;
+@@ -5008,9 +4990,6 @@ add_AT_view_list (dw_die_ref die, enum dwarf_attribute attr_kind)
+ {
+   dw_attr_node attr;
+ 
+-  if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS)
+-    return;
+-
+   attr.dw_attr = attr_kind;
+   attr.dw_attr_val.val_class = dw_val_class_view_list;
+   attr.dw_attr_val.val_entry = NULL;
+@@ -11167,15 +11146,12 @@ output_dwarf_version ()
+ static void
+ output_compilation_unit_header (enum dwarf_unit_type ut)
+ {
+-  if (!XCOFF_DEBUGGING_INFO)
+-    {
+-      if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
+-	dw2_asm_output_data (4, 0xffffffff,
+-	  "Initial length escape value indicating 64-bit DWARF extension");
+-      dw2_asm_output_data (dwarf_offset_size,
+-			   next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
+-			   "Length of Compilation Unit Info");
+-    }
++  if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
++    dw2_asm_output_data (4, 0xffffffff,
++      "Initial length escape value indicating 64-bit DWARF extension");
++  dw2_asm_output_data (dwarf_offset_size,
++		       next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
++		       "Length of Compilation Unit Info");
+ 
+   output_dwarf_version ();
+   if (dwarf_version >= 5)
+@@ -11684,14 +11660,11 @@ output_pubnames (vec *names)
+   unsigned long pubnames_length = size_of_pubnames (names);
+   pubname_entry *pub;
+ 
+-  if (!XCOFF_DEBUGGING_INFO)
+-    {
+-      if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
+-	dw2_asm_output_data (4, 0xffffffff,
+-	  "Initial length escape value indicating 64-bit DWARF extension");
+-      dw2_asm_output_data (dwarf_offset_size, pubnames_length,
+-			   "Pub Info Length");
+-    }
++  if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
++    dw2_asm_output_data (4, 0xffffffff,
++			 "Initial length escape value indicating 64-bit DWARF extension");
++  dw2_asm_output_data (dwarf_offset_size, pubnames_length,
++		       "Pub Info Length");
+ 
+   /* Version number for pubnames/pubtypes is independent of dwarf version.  */
+   dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version");
+@@ -11766,14 +11739,11 @@ output_aranges (void)
+   unsigned i;
+   unsigned long aranges_length = size_of_aranges ();
+   
+-  if (!XCOFF_DEBUGGING_INFO)
+-    {
+-      if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
+-	dw2_asm_output_data (4, 0xffffffff,
+-	  "Initial length escape value indicating 64-bit DWARF extension");
+-      dw2_asm_output_data (dwarf_offset_size, aranges_length,
+-			   "Length of Address Ranges Info");
+-    }
++  if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
++    dw2_asm_output_data (4, 0xffffffff,
++			 "Initial length escape value indicating 64-bit DWARF extension");
++  dw2_asm_output_data (dwarf_offset_size, aranges_length,
++		       "Length of Address Ranges Info");
+ 
+   /* Version number for aranges is still 2, even up to DWARF5.  */
+   dw2_asm_output_data (2, 2, "DWARF aranges version");
+@@ -13067,14 +13037,11 @@ output_line_info (bool prologue_only)
+   ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL,
+ 			       output_line_info_generation++);
+ 
+-  if (!XCOFF_DEBUGGING_INFO)
+-    {
+-      if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
+-	dw2_asm_output_data (4, 0xffffffff,
+-	  "Initial length escape value indicating 64-bit DWARF extension");
+-      dw2_asm_output_delta (dwarf_offset_size, l2, l1,
+-			    "Length of Source Line Info");
+-    }
++  if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4)
++    dw2_asm_output_data (4, 0xffffffff,
++			 "Initial length escape value indicating 64-bit DWARF extension");
++  dw2_asm_output_delta (dwarf_offset_size, l2, l1,
++			"Length of Source Line Info");
+ 
+   ASM_OUTPUT_LABEL (asm_out_file, l1);
+ 
+@@ -29144,8 +29111,6 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug)
+   /* AIX Assembler inserts the length, so adjust the reference to match the
+      offset expected by debuggers.  */
+   strcpy (dl_section_ref, debug_line_label);
+-  if (XCOFF_DEBUGGING_INFO)
+-    strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR);
+ 
+   /* For .debug_macro emit the section header.  */
+   if (!dwarf_strict || dwarf_version >= 5)
+@@ -32350,8 +32315,6 @@ dwarf2out_finish (const char *filename)
+   /* AIX Assembler inserts the length, so adjust the reference to match the
+      offset expected by debuggers.  */
+   strcpy (dl_section_ref, debug_line_section_label);
+-  if (XCOFF_DEBUGGING_INFO)
+-    strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR);
+ 
+   if (debug_info_level >= DINFO_LEVEL_TERSE)
+     add_AT_lineptr (main_comp_unit_die, DW_AT_stmt_list,
+@@ -33067,8 +33030,6 @@ dwarf2out_early_finish (const char *filename)
+   /* AIX Assembler inserts the length, so adjust the reference to match the
+      offset expected by debuggers.  */
+   strcpy (dl_section_ref, debug_line_section_label);
+-  if (XCOFF_DEBUGGING_INFO)
+-    strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR);
+ 
+   if (debug_info_level >= DINFO_LEVEL_TERSE)
+     add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list, dl_section_ref);
+diff --git a/gcc/final.cc b/gcc/final.cc
+index af4e529bb..822b2db43 100644
+--- a/gcc/final.cc
++++ b/gcc/final.cc
+@@ -84,16 +84,8 @@ along with GCC; see the file COPYING3.  If not see
+ #include "insn-codes.h"
+ #include "common/common-target.h"
+ 
+-#ifdef XCOFF_DEBUGGING_INFO
+-#include "xcoffout.h"		/* Needed for external data declarations.  */
+-#endif
+-
+ #include "dwarf2out.h"
+ 
+-#ifdef DBX_DEBUGGING_INFO
+-#include "dbxout.h"
+-#endif
+-
+ /* Most ports don't need to define CC_STATUS_INIT.
+    So define a null default for it to save conditionalization later.  */
+ #ifndef CC_STATUS_INIT
+@@ -2326,19 +2318,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+ 	      TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
+ 	      BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
+ 	    }
+-	  if (write_symbols == DBX_DEBUG)
+-	    {
+-	      location_t *locus_ptr
+-		= block_nonartificial_location (NOTE_BLOCK (insn));
+-
+-	      if (locus_ptr != NULL)
+-		{
+-		  override_filename = LOCATION_FILE (*locus_ptr);
+-		  override_linenum = LOCATION_LINE (*locus_ptr);
+-		  override_columnnum = LOCATION_COLUMN (*locus_ptr);
+-		  override_discriminator = compute_discriminator (*locus_ptr);
+-		}
+-	    }
+ 	  break;
+ 
+ 	case NOTE_INSN_BLOCK_END:
+@@ -2361,27 +2340,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
+ 	      gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
+ 			  == in_cold_section_p);
+ 	    }
+-	  if (write_symbols == DBX_DEBUG)
+-	    {
+-	      tree outer_block = BLOCK_SUPERCONTEXT (NOTE_BLOCK (insn));
+-	      location_t *locus_ptr
+-		= block_nonartificial_location (outer_block);
+-
+-	      if (locus_ptr != NULL)
+-		{
+-		  override_filename = LOCATION_FILE (*locus_ptr);
+-		  override_linenum = LOCATION_LINE (*locus_ptr);
+-		  override_columnnum = LOCATION_COLUMN (*locus_ptr);
+-		  override_discriminator = compute_discriminator (*locus_ptr);
+-		}
+-	      else
+-		{
+-		  override_filename = NULL;
+-		  override_linenum = 0;
+-		  override_columnnum = 0;
+-		  override_discriminator = 0;
+-		}
+-	    }
+ 	  break;
+ 
+ 	case NOTE_INSN_DELETED_LABEL:
+@@ -4708,8 +4666,6 @@ rest_of_handle_final (void)
+   if (! quiet_flag)
+     fflush (asm_out_file);
+ 
+-  /* Write DBX symbols if requested.  */
+-
+   /* Note that for those inline functions where we don't initially
+      know for certain that we will be generating an out-of-line copy,
+      the first invocation of this routine (rest_of_compilation) will
+diff --git a/gcc/flag-types.h b/gcc/flag-types.h
+index 64c64eb32..e6121d75e 100644
+--- a/gcc/flag-types.h
++++ b/gcc/flag-types.h
+@@ -24,24 +24,18 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ enum debug_info_type
+ {
+-  DINFO_TYPE_NONE = 0,		  /* No debug info.  */
+-  DINFO_TYPE_DBX = 1,		  /* BSD .stabs for DBX.  */
+-  DINFO_TYPE_DWARF2 = 2,	  /* Dwarf v2 debug info.  */
+-  DINFO_TYPE_XCOFF = 3,		  /* IBM/Xcoff debug info.  */
+-  DINFO_TYPE_VMS = 4,		  /* VMS debug info.  */
+-  DINFO_TYPE_CTF = 5,		  /* CTF debug info.  */
+-  DINFO_TYPE_BTF = 6,		  /* BTF debug info.  */
+-  DINFO_TYPE_BTF_WITH_CORE = 7,	  /* BTF debug info with CO-RE relocations.  */
++  DINFO_TYPE_NONE,		  /* No debug info.  */
++  DINFO_TYPE_DWARF2,		  /* Dwarf v2 debug info.  */
++  DINFO_TYPE_VMS,		  /* VMS debug info.  */
++  DINFO_TYPE_CTF,		  /* CTF debug info.  */
++  DINFO_TYPE_BTF,		  /* BTF debug info.  */
++  DINFO_TYPE_BTF_WITH_CORE,	  /* BTF debug info with CO-RE relocations.  */
+   DINFO_TYPE_MAX = DINFO_TYPE_BTF_WITH_CORE /* Marker only.  */
+ };
+ 
+ #define NO_DEBUG      (0U)
+-/* Write DBX debug info (using dbxout.cc).  */
+-#define DBX_DEBUG     (1U << DINFO_TYPE_DBX)
+ /* Write DWARF2 debug info (using dwarf2out.cc).  */
+ #define DWARF2_DEBUG  (1U << DINFO_TYPE_DWARF2)
+-/* Write IBM/XCOFF debug info (using dbxout.cc).  */
+-#define XCOFF_DEBUG   (1U << DINFO_TYPE_XCOFF)
+ /* Write VMS debug info (using vmsdbgout.cc).  */
+ #define VMS_DEBUG     (1U << DINFO_TYPE_VMS)
+ /* Write CTF debug info (using ctfout.cc).  */
+diff --git a/gcc/function.cc b/gcc/function.cc
+index d84a3240e..49c7ccf4b 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -4628,14 +4628,6 @@ number_blocks (tree fn)
+   int n_blocks;
+   tree *block_vector;
+ 
+-  /* For XCOFF debugging output, we start numbering the blocks
+-     from 1 within each function, rather than keeping a running
+-     count.  */
+-#if defined (XCOFF_DEBUGGING_INFO)
+-  if (write_symbols == XCOFF_DEBUG)
+-    next_block_index = 1;
+-#endif
+-
+   block_vector = get_block_vector (DECL_INITIAL (fn), &n_blocks);
+ 
+   /* The top-level BLOCK isn't numbered at all.  */
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index b0d03430e..32e45adc2 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -927,26 +927,11 @@ proper position among the other output files.  */
+ # else
+ #  define ASM_DEBUG_DWARF_OPTION "--gdwarf2"
+ # endif
+-# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
+-     && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
+-#  define ASM_DEBUG_SPEC						\
+-      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG				\
+-       ? "%{%:debug-level-gt(0):"					\
+-	 "%{gdwarf*:" ASM_DEBUG_DWARF_OPTION "};"			\
+-	 ":%{g*:--gstabs}}" ASM_MAP					\
+-       : "%{%:debug-level-gt(0):"					\
+-	 "%{gstabs*:--gstabs;"						\
+-	 ":%{g*:" ASM_DEBUG_DWARF_OPTION "}}}" ASM_MAP)
+-# else
+-#  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
+-#   define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):--gstabs}}" ASM_MAP
+-#  endif
+ #  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
+ #   define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):" \
+ 	ASM_DEBUG_DWARF_OPTION "}}" ASM_MAP
+ #  endif
+ # endif
+-#endif
+ #ifndef ASM_DEBUG_SPEC
+ # define ASM_DEBUG_SPEC ""
+ #endif
+@@ -960,14 +945,7 @@ proper position among the other output files.  */
+ 	"%:dwarf-version-gt(3):--gdwarf-4 ;"				\
+ 	"%:dwarf-version-gt(2):--gdwarf-3 ;"				\
+ 	":--gdwarf2 }"
+-#  if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO)
+-#  define ASM_DEBUG_OPTION_SPEC						\
+-      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG				\
+-       ? "%{%:debug-level-gt(0):"					\
+-	 "%{gdwarf*:" ASM_DEBUG_OPTION_DWARF_OPT "}}" 			\
+-       : "%{%:debug-level-gt(0):"					\
+-	 "%{!gstabs*:%{g*:" ASM_DEBUG_OPTION_DWARF_OPT "}}}")
+-# elif defined(DWARF2_DEBUGGING_INFO)
++# if defined(DWARF2_DEBUGGING_INFO)
+ #   define ASM_DEBUG_OPTION_SPEC "%{g*:%{%:debug-level-gt(0):" \
+ 	ASM_DEBUG_OPTION_DWARF_OPT "}}"
+ #  endif
+diff --git a/gcc/go/go-lang.cc b/gcc/go/go-lang.cc
+index c8365d259..faaf52341 100644
+--- a/gcc/go/go-lang.cc
++++ b/gcc/go/go-lang.cc
+@@ -507,8 +507,7 @@ go_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
+ }
+ 
+ /* This hook is used to get the current list of declarations as trees.
+-   We don't support that; instead we use the write_globals hook.  This
+-   can't simply crash because it is called by -gstabs.  */
++   We don't support that; instead we use the write_globals hook.  */
+ 
+ static tree
+ go_langhook_getdecls (void)
+diff --git a/gcc/go/gospec.cc b/gcc/go/gospec.cc
+index df92b62d8..1e5140768 100644
+--- a/gcc/go/gospec.cc
++++ b/gcc/go/gospec.cc
+@@ -215,11 +215,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ 	case OPT_gdwarf:
+ 	case OPT_gdwarf_:
+ 	case OPT_ggdb:
+-	case OPT_gstabs:
+-	case OPT_gstabs_:
+ 	case OPT_gvms:
+-	case OPT_gxcoff:
+-	case OPT_gxcoff_:
+ 	  saw_opt_g = true;
+ 	  break;
+ 
+diff --git a/gcc/gstab.h b/gcc/gstab.h
+deleted file mode 100644
+index c597d1200..000000000
+--- a/gcc/gstab.h
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/* Copyright (C) 1997-2022 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
+-.  */
+-
+-#ifndef GCC_GSTAB_H
+-#define GCC_GSTAB_H
+-
+-#define __define_stab(NAME, CODE, STRING) NAME=CODE,
+-
+-enum
+-{
+-#include "stab.def"
+-LAST_UNUSED_STAB_CODE
+-};
+-
+-/* stabs debug codes really are integers with expressive names.  */
+-typedef int stab_code_type;
+-
+-#undef __define_stab
+-
+-#endif /* ! GCC_GSTAB_H */
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 4b4925331..e34e5ee8e 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -53,7 +53,7 @@ const char *const debug_type_names[] =
+ 
+ static uint32_t debug_type_masks[] =
+ {
+-  NO_DEBUG, DBX_DEBUG, DWARF2_DEBUG, XCOFF_DEBUG, VMS_DEBUG,
++  NO_DEBUG, DWARF2_DEBUG, VMS_DEBUG,
+   CTF_DEBUG, BTF_DEBUG
+ };
+ 
+@@ -3186,22 +3186,10 @@ common_handle_option (struct gcc_options *opts,
+       set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc);
+       break;
+ 
+-    case OPT_gstabs:
+-    case OPT_gstabs_:
+-      set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set,
+-		       loc);
+-      break;
+-
+     case OPT_gvms:
+       set_debug_level (VMS_DEBUG, false, arg, opts, opts_set, loc);
+       break;
+ 
+-    case OPT_gxcoff:
+-    case OPT_gxcoff_:
+-      set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg, opts, opts_set,
+-		       loc);
+-      break;
+-
+     case OPT_gz:
+     case OPT_gz_:
+       /* Handled completely via specs.  */
+@@ -3503,8 +3491,6 @@ set_debug_level (uint32_t dinfo, int extended, const char *arg,
+ 		 struct gcc_options *opts, struct gcc_options *opts_set,
+ 		 location_t loc)
+ {
+-  opts->x_use_gnu_debug_info_extensions = extended;
+-
+   if (dinfo == NO_DEBUG)
+     {
+       if (opts->x_write_symbols == NO_DEBUG)
+@@ -3518,8 +3504,6 @@ set_debug_level (uint32_t dinfo, int extended, const char *arg,
+ 		opts->x_write_symbols |= DWARF2_DEBUG;
+ 	      else
+ 		opts->x_write_symbols = DWARF2_DEBUG;
+-#elif defined DBX_DEBUGGING_INFO
+-	      opts->x_write_symbols = DBX_DEBUG;
+ #endif
+ 	    }
+ 
+diff --git a/gcc/stab.def b/gcc/stab.def
+deleted file mode 100644
+index e5af19b2b..000000000
+--- a/gcc/stab.def
++++ /dev/null
+@@ -1,239 +0,0 @@
+-/* Table of DBX symbol codes for the GNU system.
+-   Copyright (C) 1988-2022 Free Software Foundation, Inc.
+-   This file is part of the GNU C Library.
+-
+-   The GNU C Library is free software; you can redistribute it and/or
+-   modify it under the terms of the GNU Library General Public License as
+-   published by the Free Software Foundation; either version 3 of the
+-   License, or (at your option) any later version.
+-
+-   The GNU C Library 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
+-   Library General Public License for more details.
+-
+-   You should have received a copy of the GNU Library General Public
+-   License along with the GNU C Library; see the file COPYING3.  If
+-   not see .  */
+-
+-/* This contains contribution from Cygnus Support.  */
+-
+-/* Global variable.  Only the name is significant.
+-   To find the address, look in the corresponding external symbol.  */
+-__define_stab (N_GSYM, 0x20, "GSYM")
+-
+-/* Function name for BSD Fortran.  Only the name is significant.
+-   To find the address, look in the corresponding external symbol.  */
+-__define_stab (N_FNAME, 0x22, "FNAME")
+-
+-/* Function name or text-segment variable for C.  Value is its address.
+-   Desc is supposedly starting line number, but GCC doesn't set it
+-   and DBX seems not to miss it.  */
+-__define_stab (N_FUN, 0x24, "FUN")
+-
+-/* Data-segment variable with internal linkage.  Value is its address.
+-   "Static Sym".  */
+-__define_stab (N_STSYM, 0x26, "STSYM")
+-
+-/* BSS-segment variable with internal linkage.  Value is its address.  */
+-__define_stab (N_LCSYM, 0x28, "LCSYM")
+-
+-/* Begin function marker.  */
+-__define_stab (N_BNSYM, 0x2e, "BNSYM")
+-
+-/* End function marker.  */
+-__define_stab (N_ENSYM, 0x4e, "ENSYM")
+-
+-/* Name of main routine.  Only the name is significant.
+-   This is not used in C.  */
+-__define_stab (N_MAIN, 0x2a, "MAIN")
+-
+-/* Global symbol in Pascal.
+-   Supposedly the value is its line number; I'm skeptical.  */
+-__define_stab (N_PC, 0x30, "PC")
+-
+-/* Number of symbols:  0, files,,funcs,lines according to Ultrix V4.0.  */
+-__define_stab (N_NSYMS, 0x32, "NSYMS")
+-
+-/* "No DST map for sym: name, ,0,type,ignored"  according to Ultrix V4.0.  */
+-__define_stab (N_NOMAP, 0x34, "NOMAP")
+-
+-/* New stab from Solaris.  I don't know what it means, but it
+-   don't seem to contain useful information.  */
+-__define_stab (N_OBJ, 0x38, "OBJ")
+-
+-/* New stab from Solaris.  I don't know what it means, but it
+-   don't seem to contain useful information.  Possibly related to the
+-   optimization flags used in this module.  */
+-__define_stab (N_OPT, 0x3c, "OPT")
+-
+-/* Register variable.  Value is number of register.  */
+-__define_stab (N_RSYM, 0x40, "RSYM")
+-
+-/* Modula-2 compilation unit.  Can someone say what info it contains?  */
+-__define_stab (N_M2C, 0x42, "M2C")
+-
+-/* Line number in text segment.  Desc is the line number;
+-   value is corresponding address.  */
+-__define_stab (N_SLINE, 0x44, "SLINE")
+-
+-/* Similar, for data segment.  */
+-__define_stab (N_DSLINE, 0x46, "DSLINE")
+-
+-/* Similar, for bss segment.  */
+-__define_stab (N_BSLINE, 0x48, "BSLINE")
+-
+-/* Sun's source-code browser stabs.  ?? Don't know what the fields are.
+-   Supposedly the field is "path to associated .cb file".  THIS VALUE
+-   OVERLAPS WITH N_BSLINE!  */
+-__define_stab (N_BROWS, 0x48, "BROWS")
+-
+-/* GNU Modula-2 definition module dependency.  Value is the modification time
+-   of the definition file.  Other is nonzero if it is imported with the
+-   GNU M2 keyword %INITIALIZE.  Perhaps N_M2C can be used if there
+-   are enough empty fields? */
+-__define_stab(N_DEFD, 0x4a, "DEFD")
+-
+-/* THE FOLLOWING TWO STAB VALUES CONFLICT.  Happily, one is for Modula-2
+-   and one is for C++.   Still,...  */
+-/* GNU C++ exception variable.  Name is variable name.  */
+-__define_stab (N_EHDECL, 0x50, "EHDECL")
+-/* Modula2 info "for imc":  name,,0,0,0  according to Ultrix V4.0.  */
+-__define_stab (N_MOD2, 0x50, "MOD2")
+-
+-/* GNU C++ `catch' clause.  Value is its address.  Desc is nonzero if
+-   this entry is immediately followed by a CAUGHT stab saying what exception
+-   was caught.  Multiple CAUGHT stabs means that multiple exceptions
+-   can be caught here.  If Desc is 0, it means all exceptions are caught
+-   here.  */
+-__define_stab (N_CATCH, 0x54, "CATCH")
+-
+-/* Structure or union element.  Value is offset in the structure.  */
+-__define_stab (N_SSYM, 0x60, "SSYM")
+-
+-/* Name of main source file.
+-   Value is starting text address of the compilation.  */
+-__define_stab (N_SO, 0x64, "SO")
+-
+-/* Automatic variable in the stack.  Value is offset from frame pointer.
+-   Also used for type descriptions.  */
+-__define_stab (N_LSYM, 0x80, "LSYM")
+-
+-/* Beginning of an include file.  Only Sun uses this.
+-   In an object file, only the name is significant.
+-   The Sun linker puts data into some of the other fields.  */
+-__define_stab (N_BINCL, 0x82, "BINCL")
+-
+-/* Name of sub-source file (#include file).
+-   Value is starting text address of the compilation.  */
+-__define_stab (N_SOL, 0x84, "SOL")
+-
+-/* Parameter variable.  Value is offset from argument pointer.
+-   (On most machines the argument pointer is the same as the frame pointer.  */
+-__define_stab (N_PSYM, 0xa0, "PSYM")
+-
+-/* End of an include file.  No name.
+-   This and N_BINCL act as brackets around the file's output.
+-   In an object file, there is no significant data in this entry.
+-   The Sun linker puts data into some of the fields.  */
+-__define_stab (N_EINCL, 0xa2, "EINCL")
+-
+-/* Alternate entry point.  Value is its address.  */
+-__define_stab (N_ENTRY, 0xa4, "ENTRY")
+-
+-/* Beginning of lexical block.
+-   The desc is the nesting level in lexical blocks.
+-   The value is the address of the start of the text for the block.
+-   The variables declared inside the block *precede* the N_LBRAC symbol.  */
+-__define_stab (N_LBRAC, 0xc0, "LBRAC")
+-
+-/* Place holder for deleted include file.  Replaces a N_BINCL and everything
+-   up to the corresponding N_EINCL.  The Sun linker generates these when
+-   it finds multiple identical copies of the symbols from an include file.
+-   This appears only in output from the Sun linker.  */
+-__define_stab (N_EXCL, 0xc2, "EXCL")
+-
+-/* Modula-2 scope information.  Can someone say what info it contains?  */
+-__define_stab (N_SCOPE, 0xc4, "SCOPE")
+-
+-/* End of a lexical block.  Desc matches the N_LBRAC's desc.
+-   The value is the address of the end of the text for the block.  */
+-__define_stab (N_RBRAC, 0xe0, "RBRAC")
+-
+-/* Begin named common block.  Only the name is significant.  */
+-__define_stab (N_BCOMM, 0xe2, "BCOMM")
+-
+-/* End named common block.  Only the name is significant
+-   (and it should match the N_BCOMM).  */
+-__define_stab (N_ECOMM, 0xe4, "ECOMM")
+-
+-/* End common (local name): value is address.
+-   I'm not sure how this is used.  */
+-__define_stab (N_ECOML, 0xe8, "ECOML")
+-
+-/* These STAB's are used on Gould systems for Non-Base register symbols
+-   or something like that.  FIXME.  I have assigned the values at random
+-   since I don't have a Gould here.  Fixups from Gould folk welcome...  */
+-__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
+-__define_stab (N_NBDATA, 0xF2, "NBDATA")
+-__define_stab (N_NBBSS,  0xF4, "NBBSS")
+-__define_stab (N_NBSTS,  0xF6, "NBSTS")
+-__define_stab (N_NBLCS,  0xF8, "NBLCS")
+-
+-/* Second symbol entry containing a length-value for the preceding entry.
+-   The value is the length.  */
+-__define_stab (N_LENG, 0xfe, "LENG")
+-
+-/* The above information, in matrix format.
+-
+-			STAB MATRIX
+-	_________________________________________________
+-	| 00 - 1F are not dbx stab symbols		|
+-	| In most cases, the low bit is the EXTernal bit|
+-
+-	| 00 UNDEF  | 02 ABS	| 04 TEXT   | 06 DATA	|
+-	| 01  |EXT  | 03  |EXT	| 05  |EXT  | 07  |EXT	|
+-
+-	| 08 BSS    | 0A INDR	| 0C FN_SEQ | 0E   	|
+-	| 09  |EXT  | 0B 	| 0D	    | 0F	|
+-
+-	| 10 	    | 12 COMM	| 14 SETA   | 16 SETT	|
+-	| 11	    | 13	| 15 	    | 17	|
+-
+-	| 18 SETD   | 1A SETB	| 1C SETV   | 1E WARNING|
+-	| 19	    | 1B	| 1D 	    | 1F FN	|
+-
+-	|_______________________________________________|
+-	| Debug entries with bit 01 set are unused.	|
+-	| 20 GSYM   | 22 FNAME	| 24 FUN    | 26 STSYM	|
+-	| 28 LCSYM  | 2A MAIN	| 2C	    | 2E BNSYM	|
+-	| 30 PC	    | 32 NSYMS	| 34 NOMAP  | 36	|
+-	| 38 OBJ    | 3A	| 3C OPT    | 3E	|
+-	| 40 RSYM   | 42 M2C	| 44 SLINE  | 46 DSLINE |
+-	| 48 BSLINE*| 4A DEFD	| 4C        | 4E ENSYM	|
+-	| 50 EHDECL*| 52	| 54 CATCH  | 56        |
+-	| 58        | 5A        | 5C        | 5E	|
+-	| 60 SSYM   | 62	| 64 SO	    | 66 	|
+-	| 68 	    | 6A	| 6C	    | 6E	|
+-	| 70	    | 72	| 74	    | 76	|
+-	| 78	    | 7A	| 7C	    | 7E	|
+-	| 80 LSYM   | 82 BINCL	| 84 SOL    | 86	|
+-	| 88	    | 8A	| 8C	    | 8E	|
+-	| 90	    | 92	| 94	    | 96	|
+-	| 98	    | 9A	| 9C	    | 9E	|
+-	| A0 PSYM   | A2 EINCL	| A4 ENTRY  | A6	|
+-	| A8	    | AA	| AC	    | AE	|
+-	| B0	    | B2	| B4	    | B6	|
+-	| B8	    | BA	| BC	    | BE	|
+-	| C0 LBRAC  | C2 EXCL	| C4 SCOPE  | C6	|
+-	| C8	    | CA	| CC	    | CE	|
+-	| D0	    | D2	| D4	    | D6	|
+-	| D8	    | DA	| DC	    | DE	|
+-	| E0 RBRAC  | E2 BCOMM	| E4 ECOMM  | E6	|
+-	| E8 ECOML  | EA	| EC	    | EE	|
+-	| F0	    | F2	| F4	    | F6	|
+-	| F8	    | FA	| FC	    | FE LENG	|
+-	+-----------------------------------------------+
+- * 50 EHDECL is also MOD2.
+- * 48 BSLINE is also BROWS.
+- */
+diff --git a/gcc/system.h b/gcc/system.h
+index e10c34f70..2f56411c0 100644
+--- a/gcc/system.h
++++ b/gcc/system.h
+@@ -1005,8 +1005,7 @@ extern void fancy_abort (const char *, int, const char *)
+ 	ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL HOST_WORDS_BIG_ENDIAN	   \
+ 	OBJC_PROLOGUE ALLOCATE_TRAMPOLINE HANDLE_PRAGMA ROUND_TYPE_SIZE	   \
+ 	ROUND_TYPE_SIZE_UNIT CONST_SECTION_ASM_OP CRT_GET_RFIB_TEXT	   \
+-	DBX_LBRAC_FIRST DBX_OUTPUT_ENUM DBX_OUTPUT_SOURCE_FILENAME	   \
+-	DBX_WORKING_DIRECTORY INSN_CACHE_DEPTH INSN_CACHE_SIZE		   \
++	INSN_CACHE_DEPTH INSN_CACHE_SIZE				   \
+ 	INSN_CACHE_LINE_WIDTH INIT_SECTION_PREAMBLE NEED_ATEXIT ON_EXIT	   \
+ 	EXIT_BODY OBJECT_FORMAT_ROSE MULTIBYTE_CHARS MAP_CHARACTER	   \
+ 	LIBGCC_NEEDS_DOUBLE FINAL_PRESCAN_LABEL DEFAULT_CALLER_SAVES	   \
+@@ -1019,15 +1018,14 @@ extern void fancy_abort (const char *, int, const char *)
+ 	MAX_WCHAR_TYPE_SIZE SHARED_SECTION_ASM_OP INTEGRATE_THRESHOLD      \
+ 	FINAL_REG_PARM_STACK_SPACE MAYBE_REG_PARM_STACK_SPACE		   \
+ 	TRADITIONAL_PIPELINE_INTERFACE DFA_PIPELINE_INTERFACE		   \
+-	DBX_OUTPUT_STANDARD_TYPES BUILTIN_SETJMP_FRAME_VALUE		   \
++	BUILTIN_SETJMP_FRAME_VALUE					   \
+ 	SUNOS4_SHARED_LIBRARIES PROMOTE_FOR_CALL_ONLY			   \
+ 	SPACE_AFTER_L_OPTION NO_RECURSIVE_FUNCTION_CSE			   \
+ 	DEFAULT_MAIN_RETURN TARGET_MEM_FUNCTIONS EXPAND_BUILTIN_VA_ARG	   \
+ 	COLLECT_PARSE_FLAG DWARF2_GENERATE_TEXT_SECTION_LABEL WINNING_GDB  \
+ 	ASM_OUTPUT_FILENAME ASM_OUTPUT_SOURCE_LINE FILE_NAME_JOINER	   \
+-	GDB_INV_REF_REGPARM_STABS_LETTER DBX_MEMPARM_STABS_LETTER	   \
+-	PUT_SDB_SRC_FILE STABS_GCC_MARKER DBX_OUTPUT_FUNCTION_END	   \
+-	DBX_OUTPUT_GCC_MARKER DBX_FINISH_SYMBOL SDB_GENERATE_FAKE	   \
++	GDB_INV_REF_REGPARM_STABS_LETTER				   \
++	PUT_SDB_SRC_FILE STABS_GCC_MARKER SDB_GENERATE_FAKE		   \
+ 	NON_SAVING_SETJMP TARGET_LATE_RTL_PROLOGUE_EPILOGUE		   \
+ 	CASE_DROPS_THROUGH TARGET_BELL TARGET_BS TARGET_CR TARGET_DIGIT0   \
+         TARGET_ESC TARGET_FF TARGET_NEWLINE TARGET_TAB TARGET_VT	   \
+@@ -1052,8 +1050,8 @@ extern void fancy_abort (const char *, int, const char *)
+ 	PREFERRED_OUTPUT_RELOAD_CLASS SYSTEM_INCLUDE_DIR		   \
+ 	STANDARD_INCLUDE_DIR STANDARD_INCLUDE_COMPONENT			   \
+ 	LINK_ELIMINATE_DUPLICATE_LDIRECTORIES MIPS_DEBUGGING_INFO	   \
+-	IDENT_ASM_OP ALL_COP_ADDITIONAL_REGISTER_NAMES DBX_OUTPUT_LBRAC	   \
+-	DBX_OUTPUT_NFUN DBX_OUTPUT_RBRAC RANGE_TEST_NON_SHORT_CIRCUIT	   \
++	IDENT_ASM_OP ALL_COP_ADDITIONAL_REGISTER_NAMES			   \
++	RANGE_TEST_NON_SHORT_CIRCUIT					   \
+ 	REAL_VALUE_TRUNCATE REVERSE_CONDEXEC_PREDICATES_P		   \
+ 	TARGET_ALIGN_ANON_BITFIELDS TARGET_NARROW_VOLATILE_BITFIELDS	   \
+ 	IDENT_ASM_OP UNALIGNED_SHORT_ASM_OP UNALIGNED_INT_ASM_OP	   \
+diff --git a/gcc/target-def.h b/gcc/target-def.h
+index 1c4aa2963..f81f8fe3b 100644
+--- a/gcc/target-def.h
++++ b/gcc/target-def.h
+@@ -62,8 +62,6 @@
+ # else
+ #  ifdef TARGET_ASM_NAMED_SECTION
+ #   define TARGET_ASM_CONSTRUCTOR default_named_section_asm_out_constructor
+-#  else
+-#   define TARGET_ASM_CONSTRUCTOR default_stabs_asm_out_constructor
+ #  endif
+ # endif
+ #endif
+@@ -74,8 +72,6 @@
+ # else
+ #  ifdef TARGET_ASM_NAMED_SECTION
+ #   define TARGET_ASM_DESTRUCTOR default_named_section_asm_out_destructor
+-#  else
+-#   define TARGET_ASM_DESTRUCTOR default_stabs_asm_out_destructor
+ #  endif
+ # endif
+ #endif
+diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C
+deleted file mode 100644
+index 8464aa35a..000000000
+--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C
++++ /dev/null
+@@ -1,12 +0,0 @@
+-// Origin: PR c++/51032
+-// { dg-do compile { target { c++11 && stabs } } }
+-// { dg-options "-gstabs+" }
+-
+-template 
+-struct A {
+-    template using B = U*;
+-    int a;
+-};
+-
+-A a;
+-
+diff --git a/gcc/testsuite/g++.dg/other/PR23205.C b/gcc/testsuite/g++.dg/other/PR23205.C
+deleted file mode 100644
+index 65ba1f6f3..000000000
+--- a/gcc/testsuite/g++.dg/other/PR23205.C
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/* { dg-do compile { target stabs } } */
+-/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types" } */
+-
+-const int foobar = 4;
+-int foo ()
+-{
+-        return foobar + 1;
+-}
+-
+-int main()
+-{
+-        int i;
+-        i = foo();
+-        return i;
+-}
+-
+-/* { dg-final { scan-assembler ".stabs.*foobar:(c=i|S)" } } */
+diff --git a/gcc/testsuite/g++.dg/other/pr23205-2.C b/gcc/testsuite/g++.dg/other/pr23205-2.C
+deleted file mode 100644
+index 7b25c071a..000000000
+--- a/gcc/testsuite/g++.dg/other/pr23205-2.C
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/* { dg-do compile { target stabs } } */
+-/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types -ftoplevel-reorder" } */
+-
+-const int foobar = 4;
+-int foo ()
+-{
+-        return foobar + 1;
+-}
+-
+-int main()
+-{
+-        int i;
+-        i = foo();
+-        return i;
+-}
+-
+-/* { dg-final { scan-assembler ".stabs.*foobar:c=i" } } */
+diff --git a/gcc/testsuite/gcc.dg/20040813-1.c b/gcc/testsuite/gcc.dg/20040813-1.c
+deleted file mode 100644
+index 9cf664dd7..000000000
+--- a/gcc/testsuite/gcc.dg/20040813-1.c
++++ /dev/null
+@@ -1,14 +0,0 @@
+-/* Test lang in N_SO stab.  */
+-/* Contributed by Devang Patel    */
+-
+-/* { dg-do compile { target stabs } } */
+-/* { dg-options "-gstabs" } */
+-
+-int
+-main ()
+-{
+-  return 0;
+-}
+-
+-/* { dg-final { scan-assembler ".stabs.*100,0,2" } } */
+-
+diff --git a/gcc/testsuite/gcc.dg/darwin-20040809-2.c b/gcc/testsuite/gcc.dg/darwin-20040809-2.c
+deleted file mode 100644
+index 98d571276..000000000
+--- a/gcc/testsuite/gcc.dg/darwin-20040809-2.c
++++ /dev/null
+@@ -1,15 +0,0 @@
+-/* Test dead code strip support.  */
+-/* Contributed by Devang Patel    */
+-
+-/* { dg-do compile { target { *-*-darwin* && stabs } } } */
+-/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-symbols" } */
+-
+-int
+-main ()
+-{
+-  return 0;
+-}
+-
+-/* { dg-final { scan-assembler ".stabd.46,0,0" } } */
+-/* { dg-final { scan-assembler ".stabd.78,0,0" } } */
+-
+diff --git a/gcc/testsuite/gcc.dg/debug/pr35154.c b/gcc/testsuite/gcc.dg/debug/pr35154.c
+deleted file mode 100644
+index 08eefaf66..000000000
+--- a/gcc/testsuite/gcc.dg/debug/pr35154.c
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/* Test to make sure that stabs for C symbols that go into .comm have the
+-   proper structure.  These should be lettered G for the struct that gives
+-   the name to the .comm, and should be V or S for .lcomm symbols.  */
+-
+-__attribute__ ((used))
+-static char i_outer;
+-struct {
+-   char f1;
+-   char f2;
+-} opta;
+-struct {
+-   char f1;
+-   char f2;
+-} optb;
+-
+-int
+-main()
+-{
+-   static char i_inner[2] __attribute__ ((used));
+-   i_inner[0] = 'a'; i_inner[1] = 'b';
+-   opta.f1 = 'c';
+-   opta.f2 = 'd';
+-   optb.f1 = 'C';
+-   optb.f2 = 'D';
+-   i_outer = 'e';
+-/* { dg-do compile } */
+-/* { dg-skip-if "No stabs" { mmix-*-* alpha*-*-* hppa*64*-*-* ia64-*-* *-*-vxworks* } } */
+-/* { dg-skip-if "stabs only" { *-*-* } { "*" } { "-gstabs" } } */
+-   return 0;
+-}
+-
+-/* { dg-final { scan-assembler ".stabs.*i_inner:V" } } */
+-/* { dg-final { scan-assembler ".stabs.*i_outer:S" } } */
+-/* { dg-final { scan-assembler ".stabs.*opta:G" } } */
+-/* { dg-final { scan-assembler ".stabs.*optb:G" } } */
+diff --git a/gcc/testsuite/gcc.dg/pr69471-2.c b/gcc/testsuite/gcc.dg/pr69471-2.c
+deleted file mode 100644
+index d5799604b..000000000
+--- a/gcc/testsuite/gcc.dg/pr69471-2.c
++++ /dev/null
+@@ -1,8 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-gstabs2 -gdwarf-4 -gstabs3" } */
+-/* { dg-error "conflicts with prior selectio" "" { target *-*-* } 0 } */
+-
+-void
+-foo (void)
+-{
+-}
+diff --git a/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c b/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c
+deleted file mode 100644
+index 5c7acf18a..000000000
+--- a/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c
++++ /dev/null
+@@ -1,12 +0,0 @@
+-/* Test Attribute Vector associated with vector type stabs.  */
+-/* { dg-do compile { target powerpc*-*-darwin* } } */
+-/* { dg-require-effective-target stabs } */
+-/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types -faltivec" } */
+-
+-int main ()
+-{
+-  vector int vi = { 6,7,8,9 };
+-  return 0;
+-}
+-
+-/* { dg-final { scan-assembler ".stabs.*vi\:\\(0,\[0-9\]+\\)=\@V" } } */
+diff --git a/gcc/testsuite/gcc.target/s390/20041216-1.c b/gcc/testsuite/gcc.target/s390/20041216-1.c
+deleted file mode 100644
+index 492ee6c18..000000000
+--- a/gcc/testsuite/gcc.target/s390/20041216-1.c
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* This test case would get an unresolved symbol during link
+-   because stabs referred to an optimized-away literal pool
+-   entry.  */
+-
+-/* { dg-do run } */
+-/* { dg-options "-O2 -fno-omit-frame-pointer -gstabs" } */
+-
+-int main (void)
+-{
+-  static char buf[4096];
+-  char *p;
+-
+-  do
+-    {
+-      p = buf;
+-      asm volatile ("" : : : "memory", "0", "1", "2", "3", "4", "5", "6",
+-				       "7", "8", "9", "10", "12");
+-    }
+-  while (*p);
+-
+-  return 0;
+-}
+-
+diff --git a/gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f b/gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f
+deleted file mode 100644
+index 5e5c42e9b..000000000
+--- a/gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f
++++ /dev/null
+@@ -1,35 +0,0 @@
+-C     Test program for common block debugging.  G. Helffrich 11 July 2004.
+-C { dg-do compile }
+-C { dg-skip-if "No stabs" { aarch64*-*-* mmix-*-* alpha*-*-* hppa*64*-*-* ia64-*-* *-*-vxworks* } }
+-C { dg-skip-if "No stabs" { *-*-* } { "*" } { "-gstabs" } }
+-      common i,j
+-      common /label/l,m
+-      i = 1
+-      j = 2
+-      k = 3
+-      l = 4
+-      m = 5
+-      call sub
+-      end
+-      subroutine sub
+-      common /label/l,m
+-      logical first
+-      save n
+-      data first /.true./
+-      if (first) then
+-         n = 0
+-	 first = .false.
+-      endif
+-      n = n + 1
+-      l = l + 1
+-      return
+-      end
+-
+-C { dg-final { scan-assembler ".stabs.*\"__BLNK__\",226" } }
+-C { dg-final { scan-assembler ".stabs.*\"i:V.*\",.*,0" } }
+-C { dg-final { scan-assembler ".stabs.*\"j:V.*\",.*,4" } }
+-C { dg-final { scan-assembler ".stabs.*\"__BLNK__\",228" } }
+-C { dg-final { scan-assembler ".stabs.*\"label_\",226" } }
+-C { dg-final { scan-assembler ".stabs.*\"l:V.*\",.*,0" } }
+-C { dg-final { scan-assembler ".stabs.*\"m:V.*\",.*,4" } }
+-C { dg-final { scan-assembler ".stabs.*\"label_\",228" } }
+diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
+index 8c28997dd..5e8acb28b 100644
+--- a/gcc/testsuite/lib/gcc-dg.exp
++++ b/gcc/testsuite/lib/gcc-dg.exp
+@@ -655,7 +655,7 @@ proc gcc-dg-target-supports-debug-format { target_compile trivial type } {
+ proc gcc-dg-debug-runtest { target_compile trivial opt_opts testcases } {
+     if ![info exists DEBUG_TORTURE_OPTIONS] {
+ 	set DEBUG_TORTURE_OPTIONS ""
+-	foreach type {-gctf -gdwarf-2 -gstabs -gstabs+ -gxcoff -gxcoff+} {
++	foreach type {-gctf -gdwarf-2} {
+ 	    if [expr [gcc-dg-target-supports-debug-format \
+ 		      $target_compile $trivial $type]] {
+ 		if { $type == "-gctf" } {
+diff --git a/gcc/testsuite/lib/gfortran-dg.exp b/gcc/testsuite/lib/gfortran-dg.exp
+index 7407be4b8..d4a245e0b 100644
+--- a/gcc/testsuite/lib/gfortran-dg.exp
++++ b/gcc/testsuite/lib/gfortran-dg.exp
+@@ -170,7 +170,7 @@ proc gfortran-dg-debug-runtest { target_compile trivial opt_opts testcases } {
+ 
+     if ![info exists DEBUG_TORTURE_OPTIONS] {
+        set DEBUG_TORTURE_OPTIONS ""
+-       set type_list [list "-gstabs" "-gstabs+" "-gxcoff" "-gxcoff+" "-gdwarf-2" ]
++       set type_list [list "-gdwarf-2" ]
+        foreach type $type_list {
+            set comp_output [$target_compile \
+                    "$srcdir/$subdir/$trivial" "trivial.S" assembly \
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index d404058fd..bd89d4f52 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -1126,15 +1126,6 @@ proc check_effective_target_pthread {} {
+     } "-pthread"]
+ }
+ 
+-# Return 1 if compilation with -gstabs is error-free for trivial
+-# code, 0 otherwise.
+-
+-proc check_effective_target_stabs {} {
+-    return [check_no_compiler_messages stabs object {
+-	void foo (void) { }
+-    } "-gstabs"]
+-}
+-
+ # Return 1 if compilation with -mpe-aligned-commons is error-free
+ # for trivial code, 0 otherwise.
+ 
+diff --git a/gcc/testsuite/objc.dg/stabs-1.m b/gcc/testsuite/objc.dg/stabs-1.m
+deleted file mode 100644
+index b97e4d6a7..000000000
+--- a/gcc/testsuite/objc.dg/stabs-1.m
++++ /dev/null
+@@ -1,19 +0,0 @@
+-/* Check if the final SO STABS record goes into the .text section.  */
+-/* Contributed by Ziemowit Laski  */
+-
+-/* { dg-do compile { target stabs } } */
+-/* { dg-options "-gstabs" } */
+-/* { dg-additional-options "-Wno-objc-root-class" } */
+-
+-@interface MyClass
+-+ newWithArg: arg;
+-@end
+-
+-@implementation MyClass
+-+ newWithArg: arg
+-{
+-}
+-@end
+-
+-/* See PR target/52152 for the xfail.  */
+-/* { dg-final { scan-assembler "(.SUBSPA.*\[\$\]CODE\[\$\]|.text\"?)\n\t.stabs.*100,0,0,(\[\.\$\])?L?L\[\$\]?etext\[0-9\]*\n(\[\.\$\])?L?L\[\$\]?etext" { xfail mips*-*-elf* } } } */
+diff --git a/gcc/toplev.cc b/gcc/toplev.cc
+index 055e0642f..f00a166df 100644
+--- a/gcc/toplev.cc
++++ b/gcc/toplev.cc
+@@ -89,14 +89,6 @@ along with GCC; see the file COPYING3.  If not see
+ #include "ipa-param-manipulation.h"
+ #include "dbgcnt.h"
+ 
+-#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
+-#include "dbxout.h"
+-#endif
+-
+-#ifdef XCOFF_DEBUGGING_INFO
+-#include "xcoffout.h"		/* Needed for external data declarations. */
+-#endif
+-
+ #include "selftest.h"
+ 
+ #ifdef HAVE_isl
+@@ -1415,21 +1407,8 @@ process_options (bool no_backend)
+       && 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)
+-  else if (write_symbols == DBX_DEBUG)
+-    debug_hooks = &dbx_debug_hooks;
+-#endif
+-#if defined(XCOFF_DEBUGGING_INFO)
+-  else if (write_symbols == XCOFF_DEBUG)
+-    debug_hooks = &xcoff_debug_hooks;
+-#endif
+ #ifdef DWARF2_DEBUGGING_INFO
+   else if (dwarf_debuginfo_p ())
+     debug_hooks = &dwarf2_debug_hooks;
+diff --git a/gcc/varasm.cc b/gcc/varasm.cc
+index a4b1cc686..3f69b47a7 100644
+--- a/gcc/varasm.cc
++++ b/gcc/varasm.cc
+@@ -62,10 +62,6 @@ along with GCC; see the file COPYING3.  If not see
+ #include "toplev.h"
+ #include "opts.h"
+ 
+-#ifdef XCOFF_DEBUGGING_INFO
+-#include "xcoffout.h"		/* Needed for external data declarations.  */
+-#endif
+-
+ /* The (assembler) name of the first globally-visible object output.  */
+ extern GTY(()) const char *first_global_object_name;
+ extern GTY(()) const char *weak_global_object_name;
+diff --git a/gcc/xcoffout.cc b/gcc/xcoffout.cc
+deleted file mode 100644
+index bafd35524..000000000
+--- a/gcc/xcoffout.cc
++++ /dev/null
+@@ -1,494 +0,0 @@
+-/* Output xcoff-format symbol table information from GNU compiler.
+-   Copyright (C) 1992-2022 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
+-.  */
+-
+-/* Output xcoff-format symbol table data.  The main functionality is contained
+-   in dbxout.cc.  This file implements the sdbout-like parts of the xcoff
+-   interface.  Many functions are very similar to their counterparts in
+-   the former sdbout.c file.  */
+-
+-#include "config.h"
+-#include "system.h"
+-#include "coretypes.h"
+-#include "target.h"
+-#include "rtl.h"
+-#include "tree.h"
+-#include "diagnostic-core.h"
+-#include "varasm.h"
+-#include "output.h"
+-#include "debug.h"
+-#include "file-prefix-map.h" /* remap_debug_filename()  */
+-
+-#ifdef XCOFF_DEBUGGING_INFO
+-
+-/* This defines the C_* storage classes.  */
+-#include "xcoff.h"
+-#include "xcoffout.h"
+-#include "dbxout.h"
+-#include "gstab.h"
+-
+-/* Line number of beginning of current function, minus one.
+-   Negative means not in a function or not using xcoff.  */
+-
+-static int xcoff_begin_function_line = -1;
+-static int xcoff_inlining = 0;
+-
+-/* Name of the current include file.  */
+-
+-const char *xcoff_current_include_file;
+-
+-/* Name of the current function file.  This is the file the `.bf' is
+-   emitted from.  In case a line is emitted from a different file,
+-   (by including that file of course), then the line number will be
+-   absolute.  */
+-
+-static const char *xcoff_current_function_file;
+-
+-/* Names of bss and data sections.  These should be unique names for each
+-   compilation unit.  */
+-
+-char *xcoff_bss_section_name;
+-char *xcoff_private_data_section_name;
+-char *xcoff_private_rodata_section_name;
+-char *xcoff_tls_data_section_name;
+-char *xcoff_read_only_section_name;
+-
+-/* Last source file name mentioned in a NOTE insn.  */
+-
+-const char *xcoff_lastfile;
+-
+-/* Macro definitions used below.  */
+-
+-#define ABS_OR_RELATIVE_LINENO(LINENO)		\
+-((xcoff_inlining) ? (LINENO) : (LINENO) - xcoff_begin_function_line)
+-
+-/* Output source line numbers via ".line".  */
+-#define ASM_OUTPUT_LINE(FILE,LINENUM)					   \
+-  do									   \
+-    {									   \
+-      /* Make sure we're in a function and prevent output of .line 0, as   \
+-	 line # 0 is meant for symbol addresses in xcoff.  Additionally,   \
+-	 line numbers are 'unsigned short' in 32-bit mode.  */		   \
+-      if (xcoff_begin_function_line >= 0)				   \
+-	{								   \
+-	  int lno = ABS_OR_RELATIVE_LINENO (LINENUM);			   \
+-	  if (lno > 0 && (TARGET_64BIT || lno <= (int)USHRT_MAX))	   \
+-	    fprintf (FILE, "\t.line\t%d\n", lno);			   \
+-	}								   \
+-    }									   \
+-  while (0)
+-
+-#define ASM_OUTPUT_LFB(FILE,LINENUM) \
+-{						\
+-  if (xcoff_begin_function_line == -1)		\
+-    {						\
+-      xcoff_begin_function_line = (LINENUM) - 1;\
+-      fprintf (FILE, "\t.bf\t%d\n", (LINENUM));	\
+-    }						\
+-  xcoff_current_function_file			\
+-    = (xcoff_current_include_file		\
+-       ? xcoff_current_include_file : main_input_filename); \
+-}
+-
+-#define ASM_OUTPUT_LFE(FILE,LINENUM)		\
+-  do						\
+-    {						\
+-      fprintf (FILE, "\t.ef\t%d\n", (LINENUM));	\
+-      xcoff_begin_function_line = -1;		\
+-    }						\
+-  while (0)
+-
+-#define ASM_OUTPUT_LBB(FILE,LINENUM,BLOCKNUM) \
+-  fprintf (FILE, "\t.bb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
+-
+-#define ASM_OUTPUT_LBE(FILE,LINENUM,BLOCKNUM) \
+-  fprintf (FILE, "\t.eb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
+-
+-static void xcoffout_block (tree, int, tree);
+-static void xcoffout_source_file (FILE *, const char *, int);
+-
+-/* Support routines for XCOFF debugging info.  */
+-
+-struct xcoff_type_number
+-{
+-  const char *name;
+-  int number;
+-};
+-static const struct xcoff_type_number xcoff_type_numbers[] = {
+-  { "int", -1 },
+-  { "char", -2 },
+-  { "short int", -3 },
+-  { "long int", -4 },  /* fiddled to -31 if 64 bits */
+-  { "unsigned char", -5 },
+-  { "signed char", -6 },
+-  { "short unsigned int", -7 },
+-  { "unsigned int", -8 },
+-  /* No such type "unsigned".  */
+-  { "long unsigned int", -10 }, /* fiddled to -32 if 64 bits */
+-  { "void", -11 },
+-  { "float", -12 },
+-  { "double", -13 },
+-  { "long double", -14 },
+-  /* Fortran types run from -15 to -29.  */
+-  { "wchar", -30 },  /* XXX Should be "wchar_t" ? */
+-  { "long long int", -31 },
+-  { "long long unsigned int", -32 },
+-  /* Additional Fortran types run from -33 to -37.  */
+-
+-  /* ??? Should also handle built-in C++ and Obj-C types.  There perhaps
+-     aren't any that C doesn't already have.  */
+-};
+-
+-/* Returns an XCOFF fundamental type number for DECL (assumed to be a
+-   TYPE_DECL), or 0 if dbxout.cc should assign a type number normally.  */
+-int
+-xcoff_assign_fundamental_type_number (tree decl)
+-{
+-  const char *name;
+-  size_t i;
+-
+-  /* Do not waste time searching the list for non-intrinsic types.  */
+-  if (DECL_NAME (decl) == 0 || ! DECL_IS_UNDECLARED_BUILTIN (decl))
+-    return 0;
+-
+-  name = IDENTIFIER_POINTER (DECL_NAME (decl));
+-
+-  /* Linear search, blech, but the list is too small to bother
+-     doing anything else.  */
+-  for (i = 0; i < ARRAY_SIZE (xcoff_type_numbers); i++)
+-    if (!strcmp (xcoff_type_numbers[i].name, name))
+-      goto found;
+-  return 0;
+-
+- found:
+-  /* -4 and -10 should be replaced with -31 and -32, respectively,
+-     when used for a 64-bit type.  */
+-  if (int_size_in_bytes (TREE_TYPE (decl)) == 8)
+-    {
+-      if (xcoff_type_numbers[i].number == -4)
+-	return -31;
+-      if (xcoff_type_numbers[i].number == -10)
+-	return -32;
+-    }
+-  return xcoff_type_numbers[i].number;
+-}
+-
+-/* Print an error message for unrecognized stab codes.  */
+-
+-#define UNKNOWN_STAB(STR)	\
+-  internal_error ("no sclass for %s stab (0x%x)", STR, stab)
+-
+-/* Conversion routine from BSD stabs to AIX storage classes.  */
+-
+-int
+-stab_to_sclass (int stab)
+-{
+-  switch (stab)
+-    {
+-    case N_GSYM:
+-      return C_GSYM;
+-
+-    case N_FNAME:
+-      UNKNOWN_STAB ("N_FNAME");
+-
+-    case N_FUN:
+-      return C_FUN;
+-
+-    case N_STSYM:
+-    case N_LCSYM:
+-      return C_STSYM;
+-
+-    case N_MAIN:
+-      UNKNOWN_STAB ("N_MAIN");
+-
+-    case N_RSYM:
+-      return C_RSYM;
+-
+-    case N_SSYM:
+-      UNKNOWN_STAB ("N_SSYM");
+-
+-    case N_RPSYM:
+-      return C_RPSYM;
+-
+-    case N_PSYM:
+-      return C_PSYM;
+-    case N_LSYM:
+-      return C_LSYM;
+-    case N_DECL:
+-      return C_DECL;
+-    case N_ENTRY:
+-      return C_ENTRY;
+-
+-    case N_SO:
+-      UNKNOWN_STAB ("N_SO");
+-
+-    case N_SOL:
+-      UNKNOWN_STAB ("N_SOL");
+-
+-    case N_SLINE:
+-      UNKNOWN_STAB ("N_SLINE");
+-
+-    case N_DSLINE:
+-      UNKNOWN_STAB ("N_DSLINE");
+-
+-    case N_BSLINE:
+-      UNKNOWN_STAB ("N_BSLINE");
+-
+-    case N_BINCL:
+-      UNKNOWN_STAB ("N_BINCL");
+-
+-    case N_EINCL:
+-      UNKNOWN_STAB ("N_EINCL");
+-
+-    case N_EXCL:
+-      UNKNOWN_STAB ("N_EXCL");
+-
+-    case N_LBRAC:
+-      UNKNOWN_STAB ("N_LBRAC");
+-
+-    case N_RBRAC:
+-      UNKNOWN_STAB ("N_RBRAC");
+-
+-    case N_BCOMM:
+-      return C_BCOMM;
+-    case N_ECOMM:
+-      return C_ECOMM;
+-    case N_ECOML:
+-      return C_ECOML;
+-
+-    case N_LENG:
+-      UNKNOWN_STAB ("N_LENG");
+-
+-    case N_PC:
+-      UNKNOWN_STAB ("N_PC");
+-
+-    case N_M2C:
+-      UNKNOWN_STAB ("N_M2C");
+-
+-    case N_SCOPE:
+-      UNKNOWN_STAB ("N_SCOPE");
+-
+-    case N_CATCH:
+-      UNKNOWN_STAB ("N_CATCH");
+-
+-    case N_OPT:
+-      UNKNOWN_STAB ("N_OPT");
+-
+-    default:
+-      UNKNOWN_STAB ("?");
+-    }
+-}
+-
+-/* Output debugging info to FILE to switch to sourcefile FILENAME.
+-   INLINE_P is true if this is from an inlined function.  */
+-
+-static void
+-xcoffout_source_file (FILE *file, const char *filename, int inline_p)
+-{
+-  if (filename
+-      && (xcoff_lastfile == 0 || strcmp (filename, xcoff_lastfile)
+-	  || (inline_p && ! xcoff_inlining)
+-	  || (! inline_p && xcoff_inlining)))
+-    {
+-      if (xcoff_current_include_file)
+-	{
+-	  fprintf (file, "\t.ei\t");
+-	  output_quoted_string (file,
+-	      remap_debug_filename (xcoff_current_include_file));
+-	  fprintf (file, "\n");
+-	  xcoff_current_include_file = NULL;
+-	}
+-      xcoff_inlining = inline_p;
+-      if (strcmp (main_input_filename, filename) || inline_p)
+-	{
+-	  fprintf (file, "\t.bi\t");
+-	  output_quoted_string (file, remap_debug_filename (filename));
+-	  fprintf (file, "\n");
+-	  xcoff_current_include_file = filename;
+-	}
+-      xcoff_lastfile = filename;
+-    }
+-}
+-
+-/* Output a line number symbol entry for location (FILENAME, LINE).  */
+-
+-void
+-xcoffout_source_line (unsigned int line, unsigned int column ATTRIBUTE_UNUSED,
+-		      const char *filename, int discriminator ATTRIBUTE_UNUSED,
+-                      bool is_stmt ATTRIBUTE_UNUSED)
+-{
+-  bool inline_p = (strcmp (xcoff_current_function_file, filename) != 0
+-		   || (int) line < xcoff_begin_function_line);
+-
+-  xcoffout_source_file (asm_out_file, filename, inline_p);
+-
+-  ASM_OUTPUT_LINE (asm_out_file, line);
+-}
+-
+-/* Output the symbols defined in block number DO_BLOCK.
+-
+-   This function works by walking the tree structure of blocks,
+-   counting blocks until it finds the desired block.  */
+-
+-static unsigned int do_block = 0;
+-
+-static void
+-xcoffout_block (tree block, int depth, tree args)
+-{
+-  while (block)
+-    {
+-      /* Ignore blocks never expanded or otherwise marked as real.  */
+-      if (TREE_USED (block))
+-	{
+-	  /* When we reach the specified block, output its symbols.  */
+-	  if (BLOCK_NUMBER (block) == do_block)
+-	    {
+-	      /* Output the syms of the block.  */
+-	      if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
+-		dbxout_syms (BLOCK_VARS (block));
+-	      if (args)
+-		dbxout_reg_parms (args);
+-
+-	      /* We are now done with the block.  Don't go to inner blocks.  */
+-	      return;
+-	    }
+-	  /* If we are past the specified block, stop the scan.  */
+-	  else if (BLOCK_NUMBER (block) >= do_block)
+-	    return;
+-
+-	  /* Output the subblocks.  */
+-	  xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
+-	}
+-      block = BLOCK_CHAIN (block);
+-    }
+-}
+-
+-/* Describe the beginning of an internal block within a function.
+-   Also output descriptions of variables defined in this block.
+-
+-   N is the number of the block, by order of beginning, counting from 1,
+-   and not counting the outermost (function top-level) block.
+-   The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
+-   if the count starts at 0 for the outermost one.  */
+-
+-void
+-xcoffout_begin_block (unsigned int line, unsigned int n)
+-{
+-  tree decl = current_function_decl;
+-
+-  /* The IBM AIX compiler does not emit a .bb for the function level scope,
+-     so we avoid it here also.  */
+-  if (n != 1)
+-    ASM_OUTPUT_LBB (asm_out_file, line, n);
+-
+-  do_block = n;
+-  xcoffout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
+-}
+-
+-/* Describe the end line-number of an internal block within a function.  */
+-
+-void
+-xcoffout_end_block (unsigned int line, unsigned int n)
+-{
+-  if (n != 1)
+-    ASM_OUTPUT_LBE (asm_out_file, line, n);
+-}
+-
+-/* Called at beginning of function (before prologue).
+-   Declare function as needed for debugging.  */
+-
+-void
+-xcoffout_declare_function (FILE *file, tree decl, const char *name)
+-{
+-  size_t len;
+-
+-  if (*name == '*')
+-    name++;
+-  len = strlen (name);
+-  if (name[len - 1] == ']')
+-    {
+-      char *n = XALLOCAVEC (char, len - 3);
+-      memcpy (n, name, len - 4);
+-      n[len - 4] = '\0';
+-      name = n;
+-    }
+-
+-  /* Any pending .bi or .ei must occur before the .function pseudo op.
+-     Otherwise debuggers will think that the function is in the previous
+-     file and/or at the wrong line number.  */
+-  xcoffout_source_file (file, DECL_SOURCE_FILE (decl), 0);
+-  dbxout_symbol (decl, 0);
+-
+-  /* .function NAME, TOP, MAPPING, TYPE, SIZE
+-     16 and 044 are placeholders for backwards compatibility */
+-  fprintf (file, "\t.function .%s,.%s,16,044,FE..%s-.%s\n",
+-	   name, name, name, name);
+-}
+-
+-/* Called at beginning of function body (at start of prologue).
+-   Record the function's starting line number, so we can output
+-   relative line numbers for the other lines.
+-   Record the file name that this function is contained in.  */
+-
+-void
+-xcoffout_begin_prologue (unsigned int line,
+-			 unsigned int column ATTRIBUTE_UNUSED,
+-			 const char *file ATTRIBUTE_UNUSED)
+-{
+-  ASM_OUTPUT_LFB (asm_out_file, line);
+-  dbxout_parms (DECL_ARGUMENTS (current_function_decl));
+-
+-  /* Emit the symbols for the outermost BLOCK's variables.  sdbout.c did this
+-     in sdbout_begin_block, but there is no guarantee that there will be any
+-     inner block 1, so we must do it here.  This gives a result similar to
+-     dbxout, so it does make some sense.  */
+-  do_block = BLOCK_NUMBER (DECL_INITIAL (current_function_decl));
+-  xcoffout_block (DECL_INITIAL (current_function_decl), 0,
+-		  DECL_ARGUMENTS (current_function_decl));
+-
+-  ASM_OUTPUT_LINE (asm_out_file, line);
+-}
+-
+-/* Called at end of function (before epilogue).
+-   Describe end of outermost block.  */
+-
+-void
+-xcoffout_end_function (unsigned int last_linenum)
+-{
+-  ASM_OUTPUT_LFE (asm_out_file, last_linenum);
+-}
+-
+-/* Output xcoff info for the absolute end of a function.
+-   Called after the epilogue is output.  */
+-
+-void
+-xcoffout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
+-		       const char *file ATTRIBUTE_UNUSED)
+-{
+-  /* We need to pass the correct function size to .function, otherwise,
+-     the xas assembler can't figure out the correct size for the function
+-     aux entry.  So, we emit a label after the last instruction which can
+-     be used by the .function pseudo op to calculate the function size.  */
+-
+-  const char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+-  if (*fname == '*')
+-    ++fname;
+-  fprintf (asm_out_file, "FE..");
+-  ASM_OUTPUT_LABEL (asm_out_file, fname);
+-}
+-#endif /* XCOFF_DEBUGGING_INFO */
+diff --git a/gcc/xcoffout.h b/gcc/xcoffout.h
+deleted file mode 100644
+index f28e83ea9..000000000
+--- a/gcc/xcoffout.h
++++ /dev/null
+@@ -1,194 +0,0 @@
+-/* XCOFF definitions.  These are needed in dbxout.cc, final.cc,
+-   and xcoffout.h.
+-   Copyright (C) 1998-2022 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
+-.  */
+-
+-#ifndef GCC_XCOFFOUT_H
+-#define GCC_XCOFFOUT_H
+-
+-/* Tags and typedefs are C_DECL in XCOFF, not C_LSYM.  */
+-
+-#define DBX_TYPE_DECL_STABS_CODE N_DECL
+-
+-/* Use the XCOFF predefined type numbers.  */
+-
+-#define DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER(TYPE) \
+-  xcoff_assign_fundamental_type_number (TYPE)
+-
+-/* Any type with a negative type index has already been output.  */
+-
+-#define DBX_TYPE_DEFINED(TYPE) (TYPE_SYMTAB_ADDRESS (TYPE) < 0)
+-
+-/* Must use N_STSYM for static const variables (those in the text section)
+-   instead of N_FUN.  */
+-
+-#define DBX_STATIC_CONST_VAR_CODE N_STSYM
+-
+-/* For static variables, output code to define the start of a static block.  */
+-
+-#define DBX_STATIC_BLOCK_START(ASMFILE,CODE)				\
+-{									\
+-  if ((CODE) == N_STSYM)						\
+-    fprintf ((ASMFILE), "\t.bs\t%s[RW]\n", xcoff_private_data_section_name);\
+-  else if ((CODE) == N_LCSYM)						\
+-    fprintf ((ASMFILE), "\t.bs\t%s\n", xcoff_bss_section_name);	\
+-}
+-
+-/* For static variables, output code to define the end of a static block.  */
+-
+-#define DBX_STATIC_BLOCK_END(ASMFILE,CODE)				\
+-{									\
+-  if ((CODE) == N_STSYM || (CODE) == N_LCSYM)				\
+-    fputs ("\t.es\n", (ASMFILE));					\
+-}
+-
+-/* We must use N_RPYSM instead of N_RSYM for register parameters.  */
+-
+-#define DBX_REGPARM_STABS_CODE N_RPSYM
+-
+-/* We must use 'R' instead of 'P' for register parameters.  */
+-
+-#define DBX_REGPARM_STABS_LETTER 'R'
+-
+-/* Define our own finish symbol function, since xcoff stabs have their
+-   own different format.  */
+-
+-#define DBX_FINISH_STABS(SYM, CODE, LINE, ADDR, LABEL, NUMBER) do {	\
+-  if (ADDR)								\
+-    {									\
+-      /* If we are writing a function name, we must emit a dot in	\
+-	 order to refer to the function code, not its descriptor.  */	\
+-      if (CODE == N_FUN)						\
+-	putc ('.', asm_out_file);					\
+-									\
+-      /* If we are writing a function name, we must ensure that		\
+-	 there is no storage-class suffix on the name.  */		\
+-      if (CODE == N_FUN && GET_CODE (ADDR) == SYMBOL_REF)		\
+-	{								\
+-	  const char *_p = XSTR (ADDR, 0);				\
+-	  if (*_p == '*')						\
+-	    fputs (_p+1, asm_out_file);					\
+-	  else								\
+-	    for (; *_p != '[' && *_p; _p++)				\
+-	      putc (*_p != '$' ? *_p : '_', asm_out_file);		\
+-	}								\
+-      else								\
+-	output_addr_const (asm_out_file, ADDR);				\
+-    }									\
+-  /* Another special case: N_GSYM always gets the symbol name,		\
+-     whether or not LABEL or NUMBER are set.  */			\
+-  else if (CODE == N_GSYM)						\
+-    assemble_name (asm_out_file, XSTR (XEXP (DECL_RTL (SYM), 0), 0));	\
+-  else if (LABEL)							\
+-    assemble_name (asm_out_file, LABEL);				\
+-  else									\
+-    dbxout_int (NUMBER);						\
+-  putc (',', asm_out_file);						\
+-  dbxout_int (stab_to_sclass (CODE));					\
+-  fputs (",0\n", asm_out_file);						\
+-} while (0)
+-
+-/* These are IBM XCOFF extensions we need to reference in dbxout.cc
+-   and xcoffout.cc.  */
+-
+-/* AIX XCOFF uses this for typedefs.  This can have any value, since it is
+-   only used for translation into a C_DECL storage class.  */
+-#ifndef N_DECL
+-#define N_DECL 0x8c
+-#endif
+-/* AIX XCOFF uses this for parameters passed in registers.  This can have
+-   any value, since it is only used for translation into a C_RPSYM storage
+-   class.  */
+-#ifndef N_RPSYM
+-#define N_RPSYM 0x8e
+-#endif
+-
+-/* Name of the current include file.  */
+-
+-extern const char *xcoff_current_include_file;
+-
+-/* Names of bss and data sections.  These should be unique names for each
+-   compilation unit.  */
+-
+-extern char *xcoff_bss_section_name;
+-extern char *xcoff_private_data_section_name;
+-extern char *xcoff_private_rodata_section_name;
+-extern char *xcoff_tls_data_section_name;
+-extern char *xcoff_read_only_section_name;
+-
+-/* Last source file name mentioned in a NOTE insn.  */
+-
+-extern const char *xcoff_lastfile;
+-
+-/* Don't write out path name for main source file.  */
+-#define NO_DBX_MAIN_SOURCE_DIRECTORY 1
+-
+-/* Write out main source file name using ".file" rather than ".stabs".
+-   We don't actually do this here, because the assembler gets confused if there
+-   is more than one .file directive.  rs6000_xcoff_file_start is already
+-   emitting a .file directory, so we don't output one here also.
+-   Initialize xcoff_lastfile.  */
+-#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(FILE,FILENAME) \
+-  xcoff_lastfile = (FILENAME)
+-
+-/* If we are still in an include file, its end must be marked.  */
+-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME)	\
+-do {							\
+-  if (xcoff_current_include_file)			\
+-    {							\
+-      fputs ("\t.ei\t", (FILE));			\
+-      output_quoted_string ((FILE), xcoff_current_include_file);	\
+-      putc ('\n', (FILE));				\
+-      xcoff_current_include_file = NULL;		\
+-    }							\
+-} while (0)
+-
+-/* Do not emit any marker for XCOFF until assembler allows XFT_CV.  */
+-#define NO_DBX_GCC_MARKER
+-
+-/* XCOFF32 maximum length is 64K; XLC limits to 16K.  */
+-#define DBX_CONTIN_LENGTH 16384
+-
+-/* XLC uses '?' as continuation character.  */
+-#define DBX_CONTIN_CHAR '?'
+-
+-/* Don't try to use the `x' type-cross-reference character in DBX data.
+-   Also has the consequence of putting each struct, union or enum
+-   into a separate .stabs, containing only cross-refs to the others.  */
+-#define DBX_NO_XREFS
+-
+-/* We must put stabs in the text section.  If we don't the assembler
+-   won't handle them correctly; it will sometimes put stabs where gdb
+-   can't find them.  */
+-
+-#define DEBUG_SYMS_TEXT
+-
+-/* Prototype functions in xcoffout.cc.  */
+-
+-extern int stab_to_sclass (int);
+-extern void xcoffout_begin_prologue (unsigned int, unsigned int, const char *);
+-extern void xcoffout_begin_block (unsigned, unsigned);
+-extern void xcoffout_end_epilogue (unsigned int, const char *);
+-extern void xcoffout_end_function (unsigned int);
+-extern void xcoffout_end_block (unsigned, unsigned);
+-extern int xcoff_assign_fundamental_type_number (tree);
+-extern void xcoffout_declare_function (FILE *, tree, const char *);
+-extern void xcoffout_source_line (unsigned int, unsigned int, const char *,
+-				  int, bool);
+-
+-#endif /* GCC_XCOFFOUT_H */
+-- 
+2.33.0
+
diff --git a/0096-Bugfix-Autofdo-use-PMU-sampling-set-num-eauals-den.patch b/0096-Bugfix-Autofdo-use-PMU-sampling-set-num-eauals-den.patch
new file mode 100644
index 0000000..20cf27b
--- /dev/null
+++ b/0096-Bugfix-Autofdo-use-PMU-sampling-set-num-eauals-den.patch
@@ -0,0 +1,45 @@
+From 06e86b362f74ba0706fb5d8377f78d24b658c300 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Sat, 18 May 2024 12:22:23 +0800
+Subject: [PATCH] [Bugfix] Autofdo use PMU sampling set num eauals den
+
+---
+ gcc/final.cc    | 2 +-
+ gcc/tree-cfg.cc | 8 ++++++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/final.cc b/gcc/final.cc
+index f66c9d155..e4bfceabc 100644
+--- a/gcc/final.cc
++++ b/gcc/final.cc
+@@ -4604,7 +4604,7 @@ dump_profile_to_elf_sections ()
+   /* Return if no feedback data.    */
+   if (!flag_profile_use && !flag_auto_profile)
+     {
+-      error ("-fauto-bolt should use with -profile-use or -fauto-profile");
++      error ("-fauto-bolt should use with -fprofile-use or -fauto-profile");
+       return;
+     }
+   
+diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
+index 05fc45147..48b52f785 100644
+--- a/gcc/tree-cfg.cc
++++ b/gcc/tree-cfg.cc
+@@ -9741,6 +9741,14 @@ execute_fixup_cfg (void)
+   /* Same scaling is also done by ipa_merge_profiles.  */
+   profile_count num = node->count;
+   profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
++  /* When autofdo uses PMU as the sampling unit, the number of
++     node can not be obtained directly, sometimes it will be zero,
++     but the execution number for function should at least be 1. We
++     set num be den here to make sure the num will not decrease.  */
++  if (num == profile_count::zero ().afdo () && den.quality () == profile_quality::AFDO)
++    {
++      num = den;
++    }
+   bool scale = num.initialized_p () && !(num == den);
+   auto_bitmap dce_ssa_names;
+ 
+-- 
+2.33.0
+
diff --git a/0097-Improve-non-loop-disambiguation.patch b/0097-Improve-non-loop-disambiguation.patch
new file mode 100644
index 0000000..ae609d2
--- /dev/null
+++ b/0097-Improve-non-loop-disambiguation.patch
@@ -0,0 +1,101 @@
+From 6de2e0d400cbe46da482a672810c37b1832c408c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Thu, 25 Jul 2024 19:45:43 +0800
+Subject: [PATCH] Improve non-loop disambiguation
+
+This optimization is brought from https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=038b077689bb5310386b04d40a2cea234f01e6aa.
+
+When dr_may_alias_p is called without a loop context, it tries
+to use the tree-affine interface to calculate the difference
+between the two addresses and use that difference to check whether
+the gap between the accesses is known at compile time.  However, as the
+example in the PR shows, this doesn't expand SSA_NAMEs and so can easily
+be defeated by things like reassociation.
+
+One fix would have been to use aff_combination_expand to expand the
+SSA_NAMEs, but we'd then need some way of maintaining the associated
+cache.  This patch instead reuses the innermost_loop_behavior fields
+(which exist even when no loop context is provided).
+
+It might still be useful to do the aff_combination_expand thing too,
+if an example turns out to need it.
+---
+ gcc/common.opt                              |  4 ++++
+ gcc/testsuite/gcc.dg/vect/bb-slp-pr106019.c | 16 +++++++++++++++
+ gcc/tree-data-ref.cc                        | 22 +++++++++++++++++++++
+ 3 files changed, 42 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-pr106019.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index b18f0b944..75bf9c9c1 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -3217,6 +3217,10 @@ ftree-loop-vectorize
+ Common Var(flag_tree_loop_vectorize) Optimization EnabledBy(ftree-vectorize)
+ Enable loop vectorization on trees.
+ 
++falias-analysis-expand-ssa
++Common Var(flag_alias_analysis_expand_ssa) Init(0)
++Enable expanded SSA name analysis during alias analysis.
++
+ ftree-slp-vectorize
+ Common Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize)
+ Enable basic block vectorization (SLP) on trees.
+diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr106019.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr106019.c
+new file mode 100644
+index 000000000..5ff8a8a62
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr106019.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-additional-options "-falias-analysis-expand-ssa" } */
++
++void f(double *p, long i)
++{
++    p[i+0] += 1;
++    p[i+1] += 1;
++}
++void g(double *p, long i)
++{
++    double *q = p + i;
++    q[0] += 1;
++    q[1] += 1;
++}
++
++/* { dg-final { scan-tree-dump-not "can't determine dependence" slp2 } } */
+diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
+index e6ae9e847..a05073c51 100644
+--- a/gcc/tree-data-ref.cc
++++ b/gcc/tree-data-ref.cc
+@@ -2993,6 +2993,28 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b,
+      disambiguation.  */
+   if (!loop_nest)
+     {
++      if (flag_alias_analysis_expand_ssa)
++	{
++	  tree tree_size_a = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (a)));
++	  tree tree_size_b = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (b)));
++
++	  if (DR_BASE_ADDRESS (a)
++	     && DR_BASE_ADDRESS (b)
++	     && operand_equal_p (DR_BASE_ADDRESS (a), DR_BASE_ADDRESS (b))
++	     && operand_equal_p (DR_OFFSET (a), DR_OFFSET (b))
++	     && poly_int_tree_p (tree_size_a)
++	     && poly_int_tree_p (tree_size_b)
++	     && !ranges_maybe_overlap_p (wi::to_widest (DR_INIT (a)),
++					 wi::to_widest (tree_size_a),
++					 wi::to_widest (DR_INIT (b)),
++					 wi::to_widest (tree_size_b)))
++	     {
++	       gcc_assert (integer_zerop (DR_STEP (a))
++	     		   && integer_zerop (DR_STEP (b)));
++	       return false;
++	     }
++	}
++
+       aff_tree off1, off2;
+       poly_widest_int size1, size2;
+       get_inner_reference_aff (DR_REF (a), &off1, &size1);
+-- 
+2.33.0
+
diff --git a/0098-CHREC-multiplication-and-undefined-overflow.patch b/0098-CHREC-multiplication-and-undefined-overflow.patch
new file mode 100644
index 0000000..9f9a6b7
--- /dev/null
+++ b/0098-CHREC-multiplication-and-undefined-overflow.patch
@@ -0,0 +1,265 @@
+From c4e4fef145c1e402f0558cc35f6c1ed0a08beffb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Thu, 25 Jul 2024 20:16:52 +0800
+Subject: [PATCH] CHREC multiplication and undefined overflow
+
+This optimization is brought from https://gcc.gnu.org/pipermail/gcc-patches/2024-February/646531.html
+
+When folding a multiply CHRECs are handled like {a, +, b} * c
+is {a*c, +, b*c} but that isn't generally correct when overflow
+invokes undefined behavior.  The following uses unsigned arithmetic
+unless either a is zero or a and b have the same sign.
+
+I've used simple early outs for INTEGER_CSTs and otherwise use
+a range-query since we lack a tree_expr_nonpositive_p and
+get_range_pos_neg isn't a good fit.
+---
+ gcc/common.opt                          |  4 ++
+ gcc/testsuite/gcc.dg/pr68317.c          |  6 +-
+ gcc/testsuite/gcc.dg/torture/pr114074.c | 31 ++++++++++
+ gcc/tree-chrec.cc                       | 81 +++++++++++++++++++++----
+ gcc/tree-chrec.h                        |  2 +-
+ gcc/value-range.cc                      | 12 ++++
+ gcc/value-range.h                       |  2 +
+ 7 files changed, 123 insertions(+), 15 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/torture/pr114074.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index b18f0b944..d3af3ba39 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1771,6 +1771,10 @@ floop-interchange
+ Common Var(flag_loop_interchange) Optimization
+ Enable loop interchange on trees.
+ 
++fchrec-mul-fold-strict-overflow
++Common Var(flag_chrec_mul_fold_strict_overflow) Init(0)
++Enable strict overflow handling during constant folding of multiply CHRECs.
++
+ floop-block
+ Common Alias(floop-nest-optimize)
+ Enable loop nest transforms.  Same as -floop-nest-optimize.
+diff --git a/gcc/testsuite/gcc.dg/pr68317.c b/gcc/testsuite/gcc.dg/pr68317.c
+index bd053a752..671a67d95 100644
+--- a/gcc/testsuite/gcc.dg/pr68317.c
++++ b/gcc/testsuite/gcc.dg/pr68317.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fdisable-tree-ethread" } */
++/* { dg-options "-O2 -fdisable-tree-ethread -fchrec-mul-fold-strict-overflow" } */
+ 
+ /* Note: Threader will collapse loop.  */
+ 
+@@ -12,8 +12,8 @@ foo ()
+ {
+  int32_t index = 0;
+ 
+- for (index; index <= 10; index--) // expected warning here
++ for (index; index <= 10; index--) /* { dg-warning "iteration \[0-9\]+ invokes undefined behavior" } */
+    /* Result of the following multiply will overflow
+       when converted to signed int32_t.  */
+-   bar ((0xcafe + index) * 0xdead);  /* { dg-warning "iteration \[0-9\]+ invokes undefined behavior" } */
++   bar ((0xcafe + index) * 0xdead);
+ }
+diff --git a/gcc/testsuite/gcc.dg/torture/pr114074.c b/gcc/testsuite/gcc.dg/torture/pr114074.c
+new file mode 100644
+index 000000000..9a383d8fc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/torture/pr114074.c
+@@ -0,0 +1,31 @@
++/* { dg-do run } */
++<<<<<<< HEAD
++/* { dg-options "-fchrec-mul-fold-strict-overflow" } */
++=======
++/* { dg-options "-fchrec-mul-fold-strict-overflow"" } */
++>>>>>>> 47092575e7696f5a21cf75284fe3d4feb0c813ab
++int a, b, d;
++
++__attribute__((noipa)) void
++foo (void)
++{
++  ++d;
++}
++
++int
++main ()
++{
++  for (a = 0; a > -3; a -= 2)
++    {
++      int c = a;
++      b = __INT_MAX__ - 3000;
++      a = ~c * b;
++      foo ();
++      if (!a)
++	break;
++      a = c;
++    }
++  if (d != 2)
++    __builtin_abort ();
++  return 0;
++}
+diff --git a/gcc/tree-chrec.cc b/gcc/tree-chrec.cc
+index c44cea754..3323901bc 100644
+--- a/gcc/tree-chrec.cc
++++ b/gcc/tree-chrec.cc
+@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3.  If not see
+ #include "gimple.h"
+ #include "tree-ssa-loop.h"
+ #include "dumpfile.h"
++#include "value-range.h"
++#include "value-query.h"
+ #include "tree-scalar-evolution.h"
+ 
+ /* Extended folder for chrecs.  */
+@@ -404,6 +406,13 @@ chrec_fold_multiply (tree type,
+       || automatically_generated_chrec_p (op1))
+     return chrec_fold_automatically_generated_operands (op0, op1);
+ 
++  if (flag_chrec_mul_fold_strict_overflow)
++    {
++      if (TREE_CODE (op0) != POLYNOMIAL_CHREC
++	  && TREE_CODE (op1) == POLYNOMIAL_CHREC)
++	std::swap (op0, op1);
++    }
++
+   switch (TREE_CODE (op0))
+     {
+     case POLYNOMIAL_CHREC:
+@@ -428,10 +437,53 @@ chrec_fold_multiply (tree type,
+ 	  if (integer_zerop (op1))
+ 	    return build_int_cst (type, 0);
+ 
+-	  return build_polynomial_chrec
+-	    (CHREC_VARIABLE (op0),
+-	     chrec_fold_multiply (type, CHREC_LEFT (op0), op1),
+-	     chrec_fold_multiply (type, CHREC_RIGHT (op0), op1));
++	  if (flag_chrec_mul_fold_strict_overflow)
++	    {
++	      /* When overflow is undefined and CHREC_LEFT/RIGHT do not have the
++		 same sign or CHREC_LEFT is zero then folding the multiply into
++		 the addition does not have the same behavior on overflow.  Use
++		 unsigned arithmetic in that case.  */
++	      value_range rl, rr;
++	      if (!ANY_INTEGRAL_TYPE_P (type)
++		  || TYPE_OVERFLOW_WRAPS (type)
++		  || integer_zerop (CHREC_LEFT (op0))
++		  || (TREE_CODE (CHREC_LEFT (op0)) == INTEGER_CST
++		  && TREE_CODE (CHREC_RIGHT (op0)) == INTEGER_CST
++		  && (tree_int_cst_sgn (CHREC_LEFT (op0))
++		      == tree_int_cst_sgn (CHREC_RIGHT (op0))))
++		  || (get_range_query (cfun)->range_of_expr (rl, CHREC_LEFT (op0))
++		  && !rl.undefined_p ()
++		  && (rl.nonpositive_p () || rl.nonnegative_p ())
++		  && get_range_query (cfun)->range_of_expr (rr,
++							CHREC_RIGHT (op0))
++		  && !rr.undefined_p ()
++		  && ((rl.nonpositive_p () && rr.nonpositive_p ())
++		  || (rl.nonnegative_p () && rr.nonnegative_p ()))))
++		{
++		  tree left = chrec_fold_multiply (type, CHREC_LEFT (op0), op1);
++		  tree right = chrec_fold_multiply (type, CHREC_RIGHT (op0), op1);
++		  return build_polynomial_chrec (CHREC_VARIABLE (op0), left, right);
++		}
++	      else
++		{
++		  tree utype = unsigned_type_for (type);
++		  tree uop1 = chrec_convert_rhs (utype, op1);
++		  tree uleft0 = chrec_convert_rhs (utype, CHREC_LEFT (op0));
++		  tree uright0 = chrec_convert_rhs (utype, CHREC_RIGHT (op0));
++		  tree left = chrec_fold_multiply (utype, uleft0, uop1);
++		  tree right = chrec_fold_multiply (utype, uright0, uop1);
++		  tree tem = build_polynomial_chrec (CHREC_VARIABLE (op0),
++							left, right);
++		  return chrec_convert_rhs (type, tem);
++		}
++	     }
++	   else
++	     {
++	       return build_polynomial_chrec
++		  (CHREC_VARIABLE (op0),
++		   chrec_fold_multiply (type, CHREC_LEFT (op0), op1),
++		   chrec_fold_multiply (type, CHREC_RIGHT (op0), op1));
++	     }
+ 	}
+ 
+     CASE_CONVERT:
+@@ -449,13 +501,20 @@ chrec_fold_multiply (tree type,
+       switch (TREE_CODE (op1))
+ 	{
+ 	case POLYNOMIAL_CHREC:
+-	  gcc_checking_assert
+-	    (!chrec_contains_symbols_defined_in_loop (op1,
+-						      CHREC_VARIABLE (op1)));
+-	  return build_polynomial_chrec
+-	    (CHREC_VARIABLE (op1),
+-	     chrec_fold_multiply (type, CHREC_LEFT (op1), op0),
+-	     chrec_fold_multiply (type, CHREC_RIGHT (op1), op0));
++	  if (flag_chrec_mul_fold_strict_overflow)
++	    {
++	      gcc_unreachable ();
++	    }
++	  else
++	   {
++	     gcc_checking_assert
++		(!chrec_contains_symbols_defined_in_loop (op1,
++				CHREC_VARIABLE (op1)));
++	     return build_polynomial_chrec
++		(CHREC_VARIABLE (op1),
++		 chrec_fold_multiply (type, CHREC_LEFT (op1), op0),
++		 chrec_fold_multiply (type, CHREC_RIGHT (op1), op0));
++	    }
+ 
+ 	CASE_CONVERT:
+ 	  if (tree_contains_chrecs (op1, NULL))
+diff --git a/gcc/tree-chrec.h b/gcc/tree-chrec.h
+index fcf41710d..cdc97d5d9 100644
+--- a/gcc/tree-chrec.h
++++ b/gcc/tree-chrec.h
+@@ -63,7 +63,7 @@ extern tree chrec_fold_plus (tree, tree, tree);
+ extern tree chrec_fold_minus (tree, tree, tree);
+ extern tree chrec_fold_multiply (tree, tree, tree);
+ extern tree chrec_convert (tree, tree, gimple *, bool = true, tree = NULL);
+-extern tree chrec_convert_rhs (tree, tree, gimple *);
++extern tree chrec_convert_rhs (tree, tree, gimple * = NULL);
+ extern tree chrec_convert_aggressive (tree, tree, bool *);
+ 
+ /* Operations.  */
+diff --git a/gcc/value-range.cc b/gcc/value-range.cc
+index 000bbcf89..a1dc10a24 100644
+--- a/gcc/value-range.cc
++++ b/gcc/value-range.cc
+@@ -656,6 +656,18 @@ irange::contains_p (tree cst) const
+ 
+   return false;
+ }
++bool
++irange::nonnegative_p () const
++{
++  return wi::ge_p (lower_bound (), 0, TYPE_SIGN (type ()));
++}
++
++bool
++irange::nonpositive_p () const
++{
++  return wi::le_p (upper_bound (), 0, TYPE_SIGN (type ()));
++}
++
+ 
+ 
+ /* Normalize addresses into constants.  */
+diff --git a/gcc/value-range.h b/gcc/value-range.h
+index d4cba22d5..2dc0907de 100644
+--- a/gcc/value-range.h
++++ b/gcc/value-range.h
+@@ -69,6 +69,8 @@ public:
+   bool varying_p () const;
+   bool singleton_p (tree *result = NULL) const;
+   bool contains_p (tree) const;
++  bool nonnegative_p () const;
++  bool nonpositive_p () const;
+ 
+   // In-place operators.
+   void union_ (const irange &);
+-- 
+2.33.0
+
diff --git a/0099-Enable-Transposed-SLP.patch b/0099-Enable-Transposed-SLP.patch
new file mode 100644
index 0000000..b4e8b24
--- /dev/null
+++ b/0099-Enable-Transposed-SLP.patch
@@ -0,0 +1,5624 @@
+From 0dd3b8532f35486bd5db2c71342c8dfed4c0893a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Thu, 25 Jul 2024 17:25:23 +0800
+Subject: [PATCH] Enable Transposed SLP.
+
+---
+ gcc/common.opt                          |    4 +
+ gcc/testsuite/gcc.dg/vect/transpose-1.c |   53 +
+ gcc/testsuite/gcc.dg/vect/transpose-2.c |   50 +
+ gcc/testsuite/gcc.dg/vect/transpose-3.c |   54 +
+ gcc/testsuite/gcc.dg/vect/transpose-4.c |   53 +
+ gcc/testsuite/gcc.dg/vect/transpose-5.c |   74 ++
+ gcc/testsuite/gcc.dg/vect/transpose-6.c |   67 +
+ gcc/testsuite/gcc.dg/vect/transpose-7.c |   53 +
+ gcc/testsuite/gcc.dg/vect/transpose-8.c |   53 +
+ gcc/testsuite/gcc.dg/vect/vect.exp      |    7 +
+ gcc/tree-loop-distribution.cc           | 1464 ++++++++++++++++++++-
+ gcc/tree-vect-data-refs.cc              |  237 ++++
+ gcc/tree-vect-loop.cc                   |   42 +-
+ gcc/tree-vect-patterns.cc               |    4 +-
+ gcc/tree-vect-slp.cc                    | 1553 ++++++++++++++++++++---
+ gcc/tree-vect-stmts.cc                  |  973 +++++++++++++-
+ gcc/tree-vectorizer.h                   |   96 +-
+ 17 files changed, 4648 insertions(+), 189 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-4.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-5.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-6.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-7.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/transpose-8.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index b18f0b944..5958c4e0b 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -3221,6 +3221,10 @@ ftree-slp-vectorize
+ Common Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize)
+ Enable basic block vectorization (SLP) on trees.
+ 
++ftree-slp-transpose-vectorize
++Common Var(flag_tree_slp_transpose_vectorize) Optimization Init(0)
++Enable basic block vectorization (SLP) for transposed stores and loads on trees.
++
+ fvect-cost-model=
+ Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Optimization
+ -fvect-cost-model=[unlimited|dynamic|cheap|very-cheap]	Specifies the cost model for vectorization.
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-1.c b/gcc/testsuite/gcc.dg/vect/transpose-1.c
+new file mode 100644
+index 000000000..8237a8b9e
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-1.c
+@@ -0,0 +1,53 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 4
++#define M 256
++
++int foo (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2)
++{
++  int i = 0;
++  int sum = 0;
++  unsigned c0[N], c1[N], c2[N], c3[N], c4[N], c5[N], c6[N], c7[N];
++  for (i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++      c2[i] = pix1[2] - pix2[2];
++      c3[i] = pix1[3] - pix2[3];
++      c4[i] = pix1[4] - pix2[4];
++      c5[i] = pix1[5] - pix2[5];
++      c6[i] = pix1[6] - pix2[6];
++      c7[i] = pix1[7] - pix2[7];
++    }
++  for (int i = 0; i < N; i++)
++    {
++      sum += c0[i] + c1[i] + c2[i] + c3[i] + c4[i] + c5[i] + c6[i] + c7[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned char input1[M];
++  unsigned char input2[M];
++  int i1 = 16;
++  int i2 = 8;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 2;
++	input2[i] = i;
++    }
++  int sum = foo (input1, i1, input2, i2);
++  if (sum != 1264)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-2.c b/gcc/testsuite/gcc.dg/vect/transpose-2.c
+new file mode 100644
+index 000000000..fdf4dbd96
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-2.c
+@@ -0,0 +1,50 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-additional-options "-fno-tree-loop-vectorize -fno-tree-dse" } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 8
++#define M 256
++
++int foo (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2)
++{
++  int i = 0;
++  int sum = 0;
++  unsigned short c0[N], c1[N], c2[N], c3[N], c4[N], c5[N], c6[N], c7[N];
++  for (i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++      c2[i] = pix1[2] - pix2[2];
++      c3[i] = pix1[3] - pix2[3];
++    }
++  for (int i = 0; i < N; i++)
++    {
++      sum += c0[i] + c1[i] + c2[i] + c3[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned char input1[M];
++  unsigned char input2[M];
++  int i1 = 5;
++  int i2 = 4;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 4;
++	input2[i] = i * 2;
++    }
++  int sum = foo (input1, i1, input2, i2);
++  if (sum != 1440)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-3.c b/gcc/testsuite/gcc.dg/vect/transpose-3.c
+new file mode 100644
+index 000000000..e492e3717
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-3.c
+@@ -0,0 +1,54 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-additional-options "-fno-tree-loop-vectorize -fno-tree-dse -fno-tree-fre" } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 4
++#define M 256
++
++int foo (unsigned short *pix1, int i_pix1, unsigned short *pix2, int i_pix2)
++{
++  int i = 0;
++  int sum = 0;
++  unsigned c0[N], c1[N], c2[N], c3[N], c4[N], c5[N], c6[N], c7[N];
++  for (i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++      c2[i] = pix1[2] - pix2[2];
++      c3[i] = pix1[3] - pix2[3];
++      c4[i] = pix1[4] - pix2[4];
++      c5[i] = pix1[5] - pix2[5];
++      c6[i] = pix1[6] - pix2[6];
++      c7[i] = pix1[7] - pix2[7];
++    }
++  for (int i = 0; i < N; i++)
++     {
++      sum += c0[i] + c1[i] + c2[i] + c3[i] + c4[i] + c5[i] + c6[i] + c7[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned short input1[M];
++  unsigned short input2[M];
++  int i1 = 8;
++  int i2 = 4;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 4;
++	input2[i] = i;
++    }
++  int sum = foo (input1, i1, input2, i2);
++  if (sum != 1680)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-4.c b/gcc/testsuite/gcc.dg/vect/transpose-4.c
+new file mode 100644
+index 000000000..0b4adea9b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-4.c
+@@ -0,0 +1,53 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 4
++#define M 256
++
++int foo (unsigned *pix1, int i_pix1, unsigned *pix2, int i_pix2)
++{
++  int i = 0;
++  int sum = 0;
++  unsigned c0[N], c1[N], c2[N], c3[N], c4[N], c5[N], c6[N], c7[N];
++  for (i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++      c2[i] = pix1[2] - pix2[2];
++      c3[i] = pix1[3] - pix2[3];
++      c4[i] = pix1[4] - pix2[4];
++      c5[i] = pix1[5] - pix2[5];
++      c6[i] = pix1[6] - pix2[6];
++      c7[i] = pix1[7] - pix2[7];
++    }
++  for (int i = 0; i < N; i++)
++     {
++      sum += c0[i] + c1[i] + c2[i] + c3[i] + c4[i] + c5[i] + c6[i] + c7[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned input1[M];
++  unsigned input2[M];
++  int i1 = 12;
++  int i2 = 6;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 7;
++	input2[i] = i * 3;
++    }
++  int sum = foo (input1, i1, input2, i2);
++  if (sum != 3616)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-5.c b/gcc/testsuite/gcc.dg/vect/transpose-5.c
+new file mode 100644
+index 000000000..040dedf1b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-5.c
+@@ -0,0 +1,74 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-additional-options "-fno-tree-dse -fno-tree-fre" } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 4
++#define M 256
++#define eps 1e-8
++
++double foo (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2)
++{
++  unsigned a0[N];
++  unsigned a1[N];
++  unsigned a2[N];
++  unsigned a3[N];
++
++  int b0[N];
++  int b1[N];
++  int b2[N];
++  int b3[N];
++
++  for (int i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      a0[i] = (pix1[0] - pix2[0]) + ((pix1[4] + pix2[4]) << 16);
++      a1[i] = (pix1[1] - pix2[1]) + ((pix1[5] + pix2[5]) << 16);
++      a2[i] = (pix1[2] - pix2[2]) + ((pix1[6] + pix2[6]) << 16);
++      a3[i] = (pix1[3] - pix2[3]) + ((pix1[7] + pix2[7]) << 16);
++    }
++
++  for (int i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      b0[i] = (pix1[0] - pix2[0]) + (pix1[4] + pix2[4]);
++      b1[i] = (pix1[1] - pix2[1]) + (pix1[5] + pix2[5]);
++      b2[i] = (pix1[2] - pix2[2]) + (pix1[6] + pix2[6]);
++      b3[i] = (pix1[3] - pix2[3]) + (pix1[7] + pix2[7]);
++    }
++
++  double sum = 0;
++  for (int i = 0; i < N; i++)
++    {
++      sum += a0[i] + a1[i] + a2[i] + a3[i] + b0[i] + b1[i] + b2[i] + b3[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned char input1[M];
++  unsigned char input2[M];
++  int i1 = 8;
++  int i2 = 3;
++  unsigned char m = 2;
++  unsigned short n = 12;
++  float t = 3.0;
++  double k = 4.2;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 6;
++	input2[i] = i * 3;
++    }
++  double sum = foo (input1, i1, input2, i2);
++  if (fabs (sum - 78648144) > eps)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
++/* { dg-final { scan-tree-dump-times "vectorizable_store for slp transpose" 2 "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-6.c b/gcc/testsuite/gcc.dg/vect/transpose-6.c
+new file mode 100644
+index 000000000..3e134ac02
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-6.c
+@@ -0,0 +1,67 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-require-effective-target vect_int } */
++/* { dg-require-effective-target vect_float } */
++#include 
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 4
++#define M 256
++#define eps 1e-8
++
++float foo (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2)
++{
++  unsigned a0[N];
++  unsigned a1[N];
++  unsigned a2[N];
++  unsigned a3[N];
++
++  float c0[N];
++  float c1[N];
++  float c2[N];
++  float c3[N];
++
++  for (int i = 0; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      a0[i] = (pix1[0] - pix2[0]) + ((pix1[4] - pix2[4]) << 16);
++      a1[i] = (pix1[1] - pix2[1]) + ((pix1[5] - pix2[5]) << 16);
++      a2[i] = (pix1[2] - pix2[2]) + ((pix1[6] - pix2[6]) << 16);
++      a3[i] = (pix1[3] - pix2[3]) + ((pix1[7] - pix2[7]) << 16);
++
++      c0[i] = (pix1[0] * pix2[0]) + (pix1[4] * pix2[4]);
++      c1[i] = (pix1[1] * pix2[1]) + (pix1[5] * pix2[5]);
++      c2[i] = (pix1[2] * pix2[2]) + (pix1[6] * pix2[6]);
++      c3[i] = (pix1[3] * pix2[3]) + (pix1[7] * pix2[7]);
++    }
++
++  float sum = 0;
++  for (int i = 0; i < N; i++)
++    {
++      sum += a0[i] + a1[i] + a2[i] + a3[i] + c0[i] + c1[i] + c2[i] + c3[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned char input1[M];
++  unsigned char input2[M];
++  int i1 = 18;
++  int i2 = 6;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 4;
++	input2[i] = i * 2;
++    }
++  float sum = foo (input1, i1, input2, i2);
++  if (fabs (sum - 106041168) > eps) 
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
++/* { dg-final { scan-tree-dump-times "vectorizable_store for slp transpose" 2 "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-7.c b/gcc/testsuite/gcc.dg/vect/transpose-7.c
+new file mode 100644
+index 000000000..8ba1b1b6d
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-7.c
+@@ -0,0 +1,53 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-additional-options "-fno-tree-loop-vectorize -fno-tree-dse" } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 16
++#define M 256
++
++int foo (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2)
++{
++  int i = 0;
++  int sum = 0;
++  unsigned char c0[N], c1[N];
++  for (int i = 0; i < N/2; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++    }
++  for (int i = N/2; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++   }
++  for (int i = 0; i < N; i++)
++    {
++      sum += c0[i] + c1[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned char input1[M];
++  unsigned char input2[M];
++  int i1 = 6;
++  int i2 = 4;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 5;
++	input2[i] = i * 2;
++    }
++  int sum = foo (input1, i1, input2, i2);
++  if (sum != 3280)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/transpose-8.c b/gcc/testsuite/gcc.dg/vect/transpose-8.c
+new file mode 100644
+index 000000000..a154f012a
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/transpose-8.c
+@@ -0,0 +1,53 @@
++/* { dg-do compile { target { aarch64*-*-linux* } } } */
++/* { dg-additional-options "-fno-tree-loop-vectorize" } */
++/* { dg-require-effective-target vect_int } */
++#include 
++#include 
++#include "tree-vect.h"
++
++#define N 32
++#define M 256
++
++int foo (unsigned char *pix1, int i_pix1, unsigned char *pix2, int i_pix2)
++{
++  int i = 0;
++  int sum = 0;
++  unsigned char c0[N], c1[N];
++  for (int i = 0; i < N/2; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++    }
++  for (int i = N/2; i < N; i++, pix1 += i_pix1, pix2 += i_pix2)
++    {
++      c0[i] = pix1[0] - pix2[0];
++      c1[i] = pix1[1] - pix2[1];
++   }
++  for (int i = 0; i < N; i++)
++    {
++      sum += c0[i] + c1[i];
++    }
++  return sum;
++}
++
++int main (int argc, const char* argv[])
++{
++  unsigned char input1[M];
++  unsigned char input2[M];
++  int i1 = 6;
++  int i2 = 4;
++  check_vect ();
++  for (int i = 0; i < M; i++)
++    {
++	input1[i] = i * 5;
++	input2[i] = i * 2;
++    }
++  int sum = foo (input1, i1, input2, i2);
++  if (sum != 7584)
++    {
++      abort ();
++    }
++  return 0;
++}
++
++/* { dg-final { scan-tree-dump "vectorized using transposed version" "slp1" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
+index dcaef1e0a..ae5212411 100644
+--- a/gcc/testsuite/gcc.dg/vect/vect.exp
++++ b/gcc/testsuite/gcc.dg/vect/vect.exp
+@@ -117,6 +117,13 @@ et-dg-runtest dg-runtest [lsort \
+ 	[glob -nocomplain $srcdir/$subdir/no-vfa-*.\[cS\]]] \
+ 	"" $DEFAULT_VECTCFLAGS
+ 
++# -ftree-slp-transpose-vectorize SLP tests
++set VECT_SLP_CFLAGS $SAVED_VECT_SLP_CFLAGS
++lappend VECT_SLP_CFLAGS "-ftree-slp-transpose-vectorize"
++et-dg-runtest dg-runtest [lsort \
++	[glob -nocomplain $srcdir/$subdir/transpose-*.\[cS\]]] \
++	"" "-ftree-slp-transpose-vectorize -fdump-tree-slp-details -O3"
++
+ # -ffast-math tests
+ set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
+ lappend DEFAULT_VECTCFLAGS "-ffast-math"
+diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
+index 606eb05e6..8d118e987 100644
+--- a/gcc/tree-loop-distribution.cc
++++ b/gcc/tree-loop-distribution.cc
+@@ -36,6 +36,47 @@ along with GCC; see the file COPYING3.  If not see
+    |   D(I) = A(I-1)*E
+    |ENDDO
+ 
++   If an unvectorizable loop has grouped loads, and calculations from grouped
++   loads are isomorphic, build temp arrays using stmts where isomorphic
++   calculations end.  Afer distribution, the partition built from temp
++   arrays can be vectorized in pass SLP after loop unrolling.  For example,
++
++   |DO I = 1, N
++   |    A = FOO (ARG_1);
++   |    B = FOO (ARG_2);
++   |    C = BAR_0 (A);
++   |    D = BAR_1 (B);
++   |ENDDO
++
++   is transformed to
++
++   |DO I = 1, N
++   |    J = FOO (ARG_1);
++   |    K = FOO (ARG_2);
++   |    X[I] = J;
++   |    Y[I] = K;
++   |    A = X[I];
++   |    B = Y[I];
++   |    C = BAR_0 (A);
++   |    D = BAR_1 (B);
++   |ENDDO
++
++   and is then distributed to
++
++   |DO I = 1, N
++   |    J = FOO (ARG_1);
++   |    K = FOO (ARG_2);
++   |    X[I] = J;
++   |    Y[I] = K;
++   |ENDDO
++
++   |DO I = 1, N
++   |    A = X[I];
++   |    B = Y[I];
++   |    C = BAR_0 (A);
++   |    D = BAR_1 (B);
++   |ENDDO
++
+    Loop distribution is the dual of loop fusion.  It separates statements
+    of a loop (or loop nest) into multiple loops (or loop nests) with the
+    same loop header.  The major goal is to separate statements which may
+@@ -44,7 +85,9 @@ along with GCC; see the file COPYING3.  If not see
+ 
+      1) Seed partitions with specific type statements.  For now we support
+ 	two types seed statements: statement defining variable used outside
+-	of loop; statement storing to memory.
++	of loop; statement storing to memory.  Moreover, for unvectorizable
++	loops, we try to find isomorphic stmts from grouped load and build
++	temp arrays as new seed statements.
+      2) Build reduced dependence graph (RDG) for loop to be distributed.
+ 	The vertices (RDG:V) model all statements in the loop and the edges
+ 	(RDG:E) model flow and control dependencies between statements.
+@@ -90,6 +133,8 @@ along with GCC; see the file COPYING3.  If not see
+ 	data reuse.  */
+ 
+ #include "config.h"
++#define INCLUDE_MAP
++#define INCLUDE_ALGORITHM
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -115,6 +160,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-vectorizer.h"
+ #include "tree-eh.h"
+ #include "gimple-fold.h"
++#include "optabs-tree.h"
+ #include "tree-affine.h"
+ #include "intl.h"
+ #include "rtl.h"
+@@ -188,6 +234,52 @@ struct rdg_vertex
+ #define RDG_MEM_WRITE_STMT(RDG, I) RDGV_HAS_MEM_WRITE (&(RDG->vertices[I]))
+ #define RDG_MEM_READS_STMT(RDG, I) RDGV_HAS_MEM_READS (&(RDG->vertices[I]))
+ 
++/* Results of isomorphic group analysis.  */
++#define UNINITIALIZED	(0)
++#define ISOMORPHIC	(1)
++#define HETEROGENEOUS	(1 << 1)
++#define UNCERTAIN	(1 << 2)
++
++/* Information of a stmt while analyzing isomorphic use in group.  */
++
++typedef struct _group_info
++{
++  gimple *stmt;
++
++  /* True if stmt can be a cut point.  */
++  bool cut_point;
++
++  /* For use_stmt with two rhses, one of which is the lhs of stmt.
++     If the other is unknown to be isomorphic, mark it uncertain.  */
++  bool uncertain;
++
++  /* Searching of isomorphic stmt reaches heterogeneous groups or reaches
++     MEM stmts.  */
++  bool done;
++
++  _group_info ()
++    {
++      stmt = NULL;
++      cut_point = false;
++      uncertain = false;
++      done = false;
++    }
++} *group_info;
++
++/* PAIR of cut points and corresponding profit.  */
++typedef std::pair *, int> stmts_profit;
++
++/* MAP of vector factor VF and corresponding stmts_profit PAIR.  */
++typedef std::map vf_stmts_profit_map;
++
++/* PAIR of group_num and iteration_num.  We consider rhses from the same
++   group and interation are isomorphic.  */
++typedef std::pair group_iteration;
++
++/* An isomorphic stmt is detetmined by lhs of use_stmt, group_num and
++   the iteration_num when we insert this stmt to this map.  */
++typedef std::map isomer_stmt_lhs;
++
+ /* Data dependence type.  */
+ 
+ enum rdg_dep_type
+@@ -600,13 +692,14 @@ class loop_distribution
+   /* Returns true when PARTITION1 and PARTITION2 access the same memory
+      object in RDG.  */
+   bool share_memory_accesses (struct graph *rdg,
+-			      partition *partition1, partition *partition2);
++			      partition *partition1, partition *partition2,
++			      hash_set *excluded_arrays);
+ 
+   /* For each seed statement in STARTING_STMTS, this function builds
+      partition for it by adding depended statements according to RDG.
+      All partitions are recorded in PARTITIONS.  */
+   void rdg_build_partitions (struct graph *rdg,
+-			     vec starting_stmts,
++			     vec *starting_stmts,
+ 			     vec *partitions);
+ 
+   /* Compute partition dependence created by the data references in DRS1
+@@ -643,15 +736,50 @@ class loop_distribution
+ 
+   /* Fuse PARTITIONS of LOOP if necessary before finalizing distribution.
+      ALIAS_DDRS contains ddrs which need runtime alias check.  */
+-  void finalize_partitions (class loop *loop, vec
+-			    *partitions, vec *alias_ddrs);
++  void finalize_partitions (class loop *loop,
++			    vec *partitions,
++			    vec *alias_ddrs, bitmap producers);
++
++  /* Analyze loop form and if it's vectorizable to decide if we need to
++     insert temp arrays to distribute it.  */
++  bool may_insert_temp_arrays (loop_p loop, struct graph *&rdg,
++			       control_dependences *cd);
++
++  /* Reset gimple_uid of GIMPLE_DEBUG and GIMPLE_LABEL to -1.  */
++  void reset_gimple_uid (loop_p loop);
++
++  bool check_loop_vectorizable (loop_p loop);
++
++  inline void rebuild_rdg (loop_p loop, struct graph *&rdg,
++			   control_dependences *cd);
++
++  /* If loop is not distributed, remove inserted temp arrays.  */
++  void remove_insertion (loop_p loop, struct graph *flow_only_rdg,
++			 bitmap producers, struct partition *partition);
++
++  /* Insert temp arrays if isomorphic computation exists.  Temp arrays will be
++     regarded as SEED_STMTS for building partitions in succeeding processes.  */
++  bool insert_temp_arrays (loop_p loop, vec seed_stmts,
++			   hash_set *tmp_array_vars, bitmap producers);
++
++  void build_producers (loop_p loop, bitmap producers,
++			vec &transformed);
++
++  void do_insertion (loop_p loop, struct graph *flow_only_rdg, tree iv,
++		     bitmap cut_points, hash_set  *tmp_array_vars,
++		     bitmap producers);
++
++  /* Fuse PARTITIONS built from inserted temp arrays into one partition,
++     fuse the rest into another.  */
++  void merge_remaining_partitions (vec *partitions,
++				   bitmap producers);
+ 
+   /* Distributes the code from LOOP in such a way that producer statements
+      are placed before consumer statements.  Tries to separate only the
+      statements from STMTS into separate loops.  Returns the number of
+      distributed loops.  Set NB_CALLS to number of generated builtin calls.
+      Set *DESTROY_P to whether LOOP needs to be destroyed.  */
+-  int distribute_loop (class loop *loop, const vec &stmts,
++  int distribute_loop (class loop *loop, vec &stmts,
+ 		       control_dependences *cd, int *nb_calls, bool *destroy_p,
+ 		       bool only_patterns_p);
+ 
+@@ -1893,7 +2021,8 @@ loop_distribution::classify_partition (loop_p loop,
+ 
+ bool
+ loop_distribution::share_memory_accesses (struct graph *rdg,
+-		       partition *partition1, partition *partition2)
++		       partition *partition1, partition *partition2,
++		       hash_set  *excluded_arrays)
+ {
+   unsigned i, j;
+   bitmap_iterator bi, bj;
+@@ -1927,7 +2056,10 @@ loop_distribution::share_memory_accesses (struct graph *rdg,
+ 	  if (operand_equal_p (DR_BASE_ADDRESS (dr1), DR_BASE_ADDRESS (dr2), 0)
+ 	      && operand_equal_p (DR_OFFSET (dr1), DR_OFFSET (dr2), 0)
+ 	      && operand_equal_p (DR_INIT (dr1), DR_INIT (dr2), 0)
+-	      && operand_equal_p (DR_STEP (dr1), DR_STEP (dr2), 0))
++	      && operand_equal_p (DR_STEP (dr1), DR_STEP (dr2), 0)
++	      /* An exception, if PARTITION1 and PARTITION2 contain the
++		 temp array we inserted, do not merge them.  */
++	      && !excluded_arrays->contains (DR_REF (dr1)))
+ 	    return true;
+ 	}
+     }
+@@ -1941,14 +2073,14 @@ loop_distribution::share_memory_accesses (struct graph *rdg,
+ 
+ void
+ loop_distribution::rdg_build_partitions (struct graph *rdg,
+-					 vec starting_stmts,
++					 vec *starting_stmts,
+ 					 vec *partitions)
+ {
+   auto_bitmap processed;
+   int i;
+   gimple *stmt;
+ 
+-  FOR_EACH_VEC_ELT (starting_stmts, i, stmt)
++  FOR_EACH_VEC_ELT (*starting_stmts, i, stmt)
+     {
+       int v = rdg_vertex_for_stmt (rdg, stmt);
+ 
+@@ -2912,13 +3044,47 @@ fuse_memset_builtins (vec *partitions)
+     }
+ }
+ 
++void
++loop_distribution::merge_remaining_partitions
++			(vec *partitions,
++			 bitmap producers)
++{
++  struct partition *partition = NULL;
++  struct partition *p1 = NULL, *p2 = NULL;
++  for (unsigned i = 0; partitions->iterate (i, &partition); i++)
++    {
++      if (bitmap_intersect_p (producers, partition->stmts))
++	{
++	  if (p1 == NULL)
++	    {
++	      p1 = partition;
++	      continue;
++	    }
++	  partition_merge_into (NULL, p1, partition, FUSE_FINALIZE);
++	}
++      else
++	{
++	  if (p2 == NULL)
++	    {
++	      p2 = partition;
++	      continue;
++	    }
++	  partition_merge_into (NULL, p2, partition, FUSE_FINALIZE);
++	}
++      partitions->unordered_remove (i);
++      partition_free (partition);
++      i--;
++    }
++}
++
+ void
+ loop_distribution::finalize_partitions (class loop *loop,
+ 					vec *partitions,
+-					vec *alias_ddrs)
++					vec *alias_ddrs,
++					bitmap producers)
+ {
+   unsigned i;
+-  struct partition *partition, *a;
++  struct partition *partition;
+ 
+   if (partitions->length () == 1
+       || alias_ddrs->length () > 0)
+@@ -2950,13 +3116,7 @@ loop_distribution::finalize_partitions (class loop *loop,
+       || (loop->inner == NULL
+ 	  && i >= NUM_PARTITION_THRESHOLD && num_normal > num_builtin))
+     {
+-      a = (*partitions)[0];
+-      for (i = 1; partitions->iterate (i, &partition); ++i)
+-	{
+-	  partition_merge_into (NULL, a, partition, FUSE_FINALIZE);
+-	  partition_free (partition);
+-	}
+-      partitions->truncate (1);
++      merge_remaining_partitions (partitions, producers);
+     }
+ 
+   /* Fuse memset builtins if possible.  */
+@@ -2964,6 +3124,1216 @@ loop_distribution::finalize_partitions (class loop *loop,
+     fuse_memset_builtins (partitions);
+ }
+ 
++/* Gimple uids of GIMPLE_DEBUG and GIMPLE_LABEL were changed during function
++   vect_analyze_loop, reset them to -1.  */
++
++void
++loop_distribution::reset_gimple_uid (loop_p loop)
++{
++  basic_block *bbs = get_loop_body_in_custom_order (loop, this,
++						    bb_top_order_cmp_r);
++  for (int i = 0; i < int (loop->num_nodes); i++)
++    {
++      basic_block bb = bbs[i];
++      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
++	   gsi_next (&gsi))
++	{
++	  gimple *stmt = gsi_stmt (gsi);
++	  if (is_gimple_debug (stmt) || gimple_code (stmt) == GIMPLE_LABEL)
++	    gimple_set_uid (stmt, -1);
++	}
++    }
++  free (bbs);
++}
++
++bool
++loop_distribution::check_loop_vectorizable (loop_p loop)
++{
++  vec_info_shared shared;
++  vect_analyze_loop (loop, &shared, true);
++  loop_vec_info vinfo = loop_vec_info_for_loop (loop);
++  reset_gimple_uid (loop);
++  if (vinfo == NULL)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file,
++		 "Loop %d no temp array insertion: bad data access pattern,"
++		 " unable to generate loop_vinfo.\n", loop->num);
++      return false;
++    }
++  if (vinfo->vectorizable)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Loop %d no temp array insertion: original loop"
++			    " can be vectorized without distribution.\n",
++			    loop->num);
++      delete vinfo;
++      loop->aux = NULL;
++      return false;
++    }
++  if (vinfo->grouped_loads.length () == 0)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Loop %d no temp array insertion: original loop"
++			    " has no grouped loads.\n" , loop->num);
++      delete vinfo;
++      loop->aux = NULL;
++      return false;
++    }
++  return true;
++}
++
++inline void
++loop_distribution::rebuild_rdg (loop_p loop, struct graph *&rdg,
++				control_dependences *cd)
++{
++  free_rdg (rdg);
++  rdg = build_rdg (loop, cd);
++  gcc_checking_assert (rdg != NULL);
++}
++
++bool
++loop_distribution::may_insert_temp_arrays (loop_p loop, struct graph *&rdg,
++					   control_dependences *cd)
++{
++  if (!(flag_tree_slp_transpose_vectorize && flag_tree_loop_vectorize))
++    return false;
++
++  /* Only loops with two basic blocks HEADER and LATCH are supported.  HEADER
++     is the main body of a LOOP and LATCH is the basic block that controls the
++     LOOP execution.  Size of temp array is determined by loop execution time,
++     so it must be a const.  */
++  tree loop_extent = number_of_latch_executions (loop);
++  if (loop->inner != NULL || loop->num_nodes > 2
++      || TREE_CODE (loop_extent) != INTEGER_CST)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Loop %d: no temp array insertion: bad loop"
++			    " form.\n", loop->num);
++      return false;
++    }
++
++  if (loop->dont_vectorize)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Loop %d: no temp array insertion: this loop"
++			    " should never be vectorized.\n",
++			    loop->num);
++      return false;
++    }
++
++  /* Do not distribute a LOOP that is able to be vectorized without
++     distribution.  */
++  if (!check_loop_vectorizable (loop))
++    {
++      rebuild_rdg (loop, rdg, cd);
++      return false;
++    }
++
++  rebuild_rdg (loop, rdg, cd);
++  return true;
++}
++
++/* Return max grouped loads' length if all groupes length satisfy len = 2 ^ n.
++   Otherwise, return 0.  */
++
++static unsigned
++get_max_vf (loop_vec_info vinfo)
++{
++  unsigned size = 0;
++  unsigned max = 0;
++  stmt_vec_info stmt_info;
++  unsigned i = 0;
++  FOR_EACH_VEC_ELT (vinfo->grouped_loads, i, stmt_info)
++    {
++      size = stmt_info->size;
++      if (!pow2p_hwi (size))
++	return 0;
++      max = size > max ? size : max;
++    }
++  return max;
++}
++
++/* Convert grouped_loads from linked list to vector with length vf.  Init
++   group_info of each stmt in the same group and put then into a vector.  And
++   these vectors consist WORKLISTS.  We will re-analyze a group if it is
++   uncertain, so we regard WORKLISTS as a circular queue.  */
++
++static unsigned
++build_queue (loop_vec_info vinfo, unsigned vf,
++	     vec *> &worklists)
++{
++  stmt_vec_info stmt_info;
++  unsigned i = 0;
++  group_info ginfo = NULL;
++  vec *worklist = NULL;
++  FOR_EACH_VEC_ELT (vinfo->grouped_loads, i, stmt_info)
++    {
++      unsigned group_size = stmt_info->size;
++      stmt_vec_info c_stmt_info = stmt_info;
++      bool succ = true;
++      while (group_size >= vf)
++	{
++	  vec_alloc (worklist, vf);
++	  for (unsigned j = 0; j < vf; ++j)
++	    {
++	      if (c_stmt_info == NULL)
++		{
++		  succ = false;
++		  break;
++		}
++	      ginfo = new _group_info ();
++	      ginfo->stmt = c_stmt_info->stmt;
++	      worklist->safe_push (ginfo);
++	      c_stmt_info = c_stmt_info->next_element;
++	    }
++	  if (!succ)
++	    {
++	      unsigned k = 0;
++	      ginfo = NULL;
++	      FOR_EACH_VEC_ELT (*worklist, k, ginfo)
++		delete ginfo;
++	      vec_free (worklist);
++	      break;
++	    }
++	  worklists.safe_push (worklist);
++	  group_size -= vf;
++	}
++    }
++  return worklists.length ();
++}
++
++static bool
++check_same_oprand_type (tree op1, tree op2)
++{
++  tree type1 = TREE_TYPE (op1);
++  tree type2 = TREE_TYPE (op2);
++  if (TREE_CODE (type1) != INTEGER_TYPE && TREE_CODE (type1) != REAL_TYPE)
++    return false;
++
++  return (TREE_CODE (type1) == TREE_CODE (type2)
++	  && TYPE_UNSIGNED (type1) == TYPE_UNSIGNED (type2)
++	  && TYPE_PRECISION (type1) == TYPE_PRECISION (type2));
++}
++
++static bool
++bit_field_p (gimple *stmt)
++{
++  unsigned i = 0;
++  auto_vec datarefs_vec;
++  data_reference_p dr;
++  if (!find_data_references_in_stmt (NULL, stmt, &datarefs_vec))
++    return true;
++
++  FOR_EACH_VEC_ELT (datarefs_vec, i, dr)
++    {
++      if (TREE_CODE (DR_REF (dr)) == COMPONENT_REF
++	  && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1)))
++	return true;
++    }
++  return false;
++}
++
++static inline bool
++shift_operation (enum tree_code op)
++{
++  return op == LSHIFT_EXPR || op == RSHIFT_EXPR || op == LROTATE_EXPR
++	 || op == RROTATE_EXPR;
++}
++
++/* Return relationship between USE_STMT and the first use_stmt of the group.
++   RHS1 is the lhs of stmt recorded in group_info.  If another rhs of use_stmt
++   is not a constant, return UNCERTAIN and re-check it later.  */
++
++static unsigned
++check_isomorphic (gimple *use_stmt, gimple *first,
++		  tree rhs1, vec &hetero_lhs)
++{
++  /* Check same operation.  */
++  enum tree_code rhs_code_first = gimple_assign_rhs_code (first);
++  enum tree_code rhs_code_current = gimple_assign_rhs_code (use_stmt);
++  if (rhs_code_first != rhs_code_current)
++    return HETEROGENEOUS;
++
++  /* For shift operations, oprands should be equal.  */
++  if (shift_operation (rhs_code_current))
++    {
++      tree shift_op_first = gimple_assign_rhs2 (first);
++      tree shift_op_current = gimple_assign_rhs2 (use_stmt);
++      if (!operand_equal_p (shift_op_first, shift_op_current, 0)
++	  || !TREE_CONSTANT (shift_op_first))
++	return HETEROGENEOUS;
++
++      return ISOMORPHIC;
++    }
++  /* Type convertion expr or assignment.  */
++  if (gimple_num_ops (first) == 2)
++    return (rhs_code_first == NOP_EXPR || rhs_code_first == CONVERT_EXPR
++	      || rhs_code_first == SSA_NAME) ? ISOMORPHIC : HETEROGENEOUS;
++
++  /* We find USE_STMT from lhs of a stmt, denote it as rhs1 of USE_STMT and
++     the other one as rhs2.  Check if define-stmt of current rhs2 is isomorphic
++     with define-stmt of rhs2 in the first USE_STMT at this group.  */
++  tree rhs2_first = gimple_assign_rhs1 (use_stmt) == rhs1
++		    ? gimple_assign_rhs2 (first) : gimple_assign_rhs1 (first);
++  tree rhs2_curr = gimple_assign_rhs1 (use_stmt) == rhs1
++	      ? gimple_assign_rhs2 (use_stmt) : gimple_assign_rhs1 (use_stmt);
++
++  if (check_same_oprand_type (rhs2_first, rhs2_curr))
++    {
++      if (TREE_CONSTANT (rhs2_curr))
++	return ISOMORPHIC;
++      else if (hetero_lhs.contains (rhs2_curr))
++	return HETEROGENEOUS;
++
++      /* Provisionally set the stmt as uncertain and analyze the whole group
++	 in function CHECK_UNCERTAIN later if all use_stmts are uncertain.  */
++      return UNCERTAIN;
++    }
++  return HETEROGENEOUS;
++}
++
++static bool
++unsupported_operations (gimple *stmt)
++{
++  enum tree_code code = gimple_assign_rhs_code (stmt);
++  return code == COND_EXPR;
++}
++
++/* Check if the single use_stmt of STMT is isomorphic with the first one's
++   use_stmt in current group.  */
++
++static unsigned
++check_use_stmt (group_info elmt, gimple *&first,
++		vec &tmp_stmts, vec &hetero_lhs)
++{
++  if (gimple_code (elmt->stmt) != GIMPLE_ASSIGN)
++    return HETEROGENEOUS;
++  use_operand_p dummy;
++  tree lhs = gimple_assign_lhs (elmt->stmt);
++  gimple *use_stmt = NULL;
++  single_imm_use (lhs, &dummy, &use_stmt);
++  /* STMTs with three rhs are not supported, e.g., GIMPLE_COND.  */
++  if (use_stmt == NULL || gimple_code (use_stmt) != GIMPLE_ASSIGN
++      || unsupported_operations (use_stmt) || bit_field_p (use_stmt))
++    return HETEROGENEOUS;
++  tmp_stmts.safe_push (use_stmt);
++  if (first == NULL)
++    {
++      first = use_stmt;
++      return UNINITIALIZED;
++    }
++  /* Check if current use_stmt and the first menber's use_stmt in the group
++     are of the same type.  */
++  tree first_lhs = gimple_assign_lhs (first);
++  tree curr_lhs = gimple_assign_lhs (use_stmt);
++  if (!check_same_oprand_type (first_lhs, curr_lhs))
++    return HETEROGENEOUS;
++  return check_isomorphic (use_stmt, first, lhs, hetero_lhs);
++}
++
++/* Replace stmt field in group with stmts in TMP_STMTS, and insert their
++   lhs_info to ISOMER_LHS.  */
++
++static void
++update_isomer_lhs (vec *group, unsigned group_num,
++		   unsigned iteration, isomer_stmt_lhs &isomer_lhs,
++		   vec &tmp_stmts, int &profit,
++		   vec &merged_groups)
++{
++  group_info elmt = NULL;
++  /* Do not insert temp array if isomorphic stmts from grouped load have
++     only casting operations.  Once isomorphic calculation has 3 oprands,
++     such as plus operation, this group can be regarded as cut point.  */
++  bool operated = (gimple_num_ops (tmp_stmts[0]) == 3);
++  /* Do not insert temp arrays if search of iosomophic stmts reaches
++     MEM stmts.  */
++  bool has_vdef = gimple_vdef (tmp_stmts[0]) != NULL;
++  bool merge = false;
++  for (unsigned i = 0; i < group->length (); i++)
++    {
++      elmt = (*group)[i];
++      elmt->stmt = has_vdef ? NULL : tmp_stmts[i];
++      elmt->cut_point = has_vdef ? false : (elmt->cut_point || operated);
++      elmt->uncertain = false;
++      elmt->done = has_vdef;
++      tree lhs = gimple_assign_lhs (tmp_stmts[i]);
++      if (isomer_lhs.find (lhs) != isomer_lhs.end ())
++	{
++	  merge = true;
++	  continue;
++	}
++      isomer_lhs[lhs] = std::make_pair (group_num, iteration);
++    }
++  if (merge)
++    {
++      merged_groups.safe_push (group_num);
++      profit = 0;
++      return;
++    }
++  enum vect_cost_for_stmt kind = scalar_stmt;
++  int scalar_cost = builtin_vectorization_cost (kind, NULL_TREE, 0);
++  profit = (tmp_stmts.length () - 1) * scalar_cost;
++}
++
++/* Try to find rhs2 in ISOMER_LHS, if all rhs2 were found and their group_num
++   and iteration are same, GROUP is isomorphic.  */
++
++static unsigned
++check_isomorphic_rhs (vec *group, vec &tmp_stmts,
++		      isomer_stmt_lhs &isomer_lhs)
++{
++  group_info elmt = NULL;
++  gimple *stmt = NULL;
++  unsigned j = 0;
++  unsigned group_num = -1u;
++  unsigned iteration = -1u;
++  tree rhs1 = NULL;
++  tree rhs2 = NULL;
++  unsigned status = UNINITIALIZED;
++  FOR_EACH_VEC_ELT (*group, j, elmt)
++    {
++      rhs1 = gimple_assign_lhs (elmt->stmt);
++      stmt = tmp_stmts[j];
++      rhs2 = (rhs1 == gimple_assign_rhs1 (stmt))
++	     ? gimple_assign_rhs2 (stmt) : gimple_assign_rhs1 (stmt);
++      isomer_stmt_lhs::iterator iter = isomer_lhs.find (rhs2);
++      if (iter != isomer_lhs.end ())
++	{
++	  if (group_num == -1u)
++	    {
++	      group_num = iter->second.first;
++	      iteration = iter->second.second;
++	      status |= ISOMORPHIC;
++	      continue;
++	    }
++	  if (iter->second.first == group_num
++	      && iter->second.second == iteration)
++	    {
++	      status |= ISOMORPHIC;
++	      continue;
++	    }
++	  return HETEROGENEOUS;
++	}
++      else
++	status |= UNCERTAIN;
++    }
++  return status;
++}
++
++/* Update group_info for uncertain groups.  */
++
++static void
++update_uncertain_stmts (vec *group, unsigned group_num,
++			 unsigned iteration, vec &tmp_stmts)
++{
++  unsigned j = 0;
++  group_info elmt = NULL;
++  FOR_EACH_VEC_ELT (*group, j, elmt)
++    {
++      elmt->uncertain = true;
++      elmt->done = false;
++    }
++}
++
++/* Push stmts in TMP_STMTS into HETERO_LHS.  */
++
++static void
++set_hetero (vec *group, vec &hetero_lhs,
++	    vec &tmp_stmts)
++{
++  group_info elmt = NULL;
++  unsigned i = 0;
++  for (i = 0; i < group->length (); i++)
++    {
++      elmt = (*group)[i];
++      elmt->uncertain = false;
++      elmt->done = true;
++    }
++  gimple *stmt = NULL;
++  FOR_EACH_VEC_ELT (tmp_stmts, i, stmt)
++    if (stmt != NULL)
++      hetero_lhs.safe_push (gimple_assign_lhs (stmt));
++}
++
++/* Given an uncertain group, TMP_STMTS are use_stmts of stmts in GROUP.
++   Rhs1 is the lhs of stmt in GROUP, rhs2 is the other rhs of USE_STMT.
++
++   Try to find rhs2 in ISOMER_LHS, if all found rhs2 have same group_num
++   and iteration, this uncertain group is isomorphic.
++
++   If no rhs matched, this GROUP remains uncertain and update group_info.
++
++   Otherwise, this GROUP is heterogeneous and return true to end analysis
++   for this group.  */
++
++static bool
++check_uncertain (vec *group, unsigned group_num,
++		 unsigned iteration, int &profit,
++		 vec &tmp_stmts, isomer_stmt_lhs &isomer_lhs,
++		 vec &hetero_lhs, vec &merged_groups)
++{
++  unsigned status = check_isomorphic_rhs (group, tmp_stmts, isomer_lhs);
++  bool done = false;
++  switch (status)
++    {
++      case UNCERTAIN:
++	update_uncertain_stmts (group, group_num, iteration, tmp_stmts);
++	break;
++      case ISOMORPHIC:
++	update_isomer_lhs (group, group_num, iteration, isomer_lhs,
++			   tmp_stmts, profit, merged_groups);
++	break;
++      default:
++	set_hetero (group, hetero_lhs, tmp_stmts);
++	done = true;
++    }
++  return done;
++}
++
++/* Return false if analysis of this group is not finished, e.g., isomorphic or
++   uncertain.  Calculate the profit if vectorized.  */
++
++static bool
++check_group (vec *group, unsigned group_num, unsigned iteration,
++	     int &profit, vec &merged_groups,
++	     isomer_stmt_lhs &isomer_lhs, vec &hetero_lhs)
++{
++  unsigned j = 0;
++  group_info elmt = NULL;
++  gimple *first = NULL;
++  unsigned res = 0;
++  /* Record single use stmts in TMP_STMTS and decide whether replace stmts in
++     ginfo in succeeding processes.  */
++  auto_vec tmp_stmts;
++  FOR_EACH_VEC_ELT (*group, j, elmt)
++    {
++      if (merged_groups.contains (group_num))
++	return true;
++      res |= check_use_stmt (elmt, first, tmp_stmts, hetero_lhs);
++    }
++
++  /* Update each group member according to RES.  */
++  switch (res)
++    {
++      case ISOMORPHIC:
++	update_isomer_lhs (group, group_num, iteration, isomer_lhs,
++			   tmp_stmts, profit, merged_groups);
++	return false;
++      case UNCERTAIN:
++	return check_uncertain (group, group_num, iteration, profit,
++				tmp_stmts, isomer_lhs, hetero_lhs,
++				merged_groups);
++      default:
++	set_hetero (group, hetero_lhs, tmp_stmts);
++	return true;
++    }
++}
++
++/* Return true if all analysises are done except uncertain groups.  */
++
++static bool
++end_of_search (vec *> &circular_queue,
++	       vec &merged_groups)
++{
++  unsigned i = 0;
++  vec *group = NULL;
++  group_info elmt = NULL;
++  FOR_EACH_VEC_ELT (circular_queue, i, group)
++    {
++      if (merged_groups.contains (i))
++	continue;
++      elmt = (*group)[0];
++      /* If there is any isomorphic use_stmts, continue analysis of isomorphic
++	 use_stmts.  */
++      if (!elmt->done && !elmt->uncertain)
++	return false;
++    }
++  return true;
++}
++
++/* Push valid stmts to STMTS as cutpoints.  */
++
++static bool
++check_any_cutpoints (vec *> &circular_queue,
++		     vec *&stmts, vec &merged_groups)
++{
++  unsigned front = 0;
++  vec *group = NULL;
++  group_info elmt = NULL;
++  unsigned max = circular_queue.length () * circular_queue[0]->length ();
++  vec_alloc (stmts, max);
++  while (front < circular_queue.length ())
++    {
++      unsigned i = 0;
++      if (merged_groups.contains (front))
++	{
++	  front++;
++	  continue;
++	}
++      group = circular_queue[front++];
++      FOR_EACH_VEC_ELT (*group, i, elmt)
++	if (elmt->stmt != NULL && elmt->done && elmt->cut_point)
++	  stmts->safe_push (elmt->stmt);
++    }
++  return stmts->length () != 0;
++}
++
++/* Grouped loads are isomorphic.  Make pair for group number and iteration,
++   map load stmt to this pair.  We set iteration 0 here.  */
++
++static void
++init_isomer_lhs (vec *> &groups, isomer_stmt_lhs &isomer_lhs)
++{
++  vec *group = NULL;
++  group_info elmt = NULL;
++  unsigned i = 0;
++  FOR_EACH_VEC_ELT (groups, i, group)
++    {
++      unsigned j = 0;
++      FOR_EACH_VEC_ELT (*group, j, elmt)
++	isomer_lhs[gimple_assign_lhs (elmt->stmt)] = std::make_pair (i, 0);
++    }
++}
++
++/* It's not a strict analysis of load/store profit.  Assume scalar and vector
++   load/store are of the same cost.  The result PROFIT equals profit form
++   vectorizing of scalar loads/stores minus cost of a vectorized load/store.  */
++
++static int
++load_store_profit (unsigned scalar_mem_ops, unsigned vf, unsigned new_mem_ops)
++{
++  int profit = 0;
++  enum vect_cost_for_stmt kind = scalar_load;
++  int scalar_cost = builtin_vectorization_cost (kind, NULL_TREE, 0);
++  profit += (scalar_mem_ops - (scalar_mem_ops / vf)) * scalar_cost;
++  profit -= new_mem_ops / vf * scalar_cost;
++  kind = scalar_store;
++  scalar_cost = builtin_vectorization_cost (kind, NULL_TREE, 0);
++  profit -= new_mem_ops / vf * scalar_cost;
++  return profit;
++}
++
++/* Breadth first search the graph consisting of define-use chain starting from
++   the circular queue initialized by function BUILD_QUEUE.  Find single use of
++   each stmt in group and check if they are isomorphic.  Isomorphic is defined
++   as same rhs type, same operator, and isomorphic calculation of each rhs
++   starting from load.  If another rhs is uncertain to be isomorphic, put it
++   at the end of circular queue and re-analyze it during the next iteration.
++   If a group shares the same use_stmt with another group, skip one of them in
++   succeedor prcoesses as merged.  Iterate the circular queue until all
++   remianing groups heterogeneous or reaches MEN stmts.  If all other groups
++   have finishes the analysis, and the remaining groups are uncertain,
++   return false to avoid endless loop.  */
++
++bool
++bfs_find_isomer_stmts (vec *> &circular_queue,
++		       stmts_profit &profit_pair, unsigned vf,
++		       bool &reach_vdef)
++{
++  isomer_stmt_lhs isomer_lhs;
++  auto_vec hetero_lhs;
++  auto_vec merged_groups;
++  vec *group = NULL;
++  /* True if analysis finishes.  */
++  bool done = false;
++  int profit_sum = 0;
++  vec *stmts = NULL;
++  init_isomer_lhs (circular_queue, isomer_lhs);
++  for (unsigned i = 1; !done; ++i)
++    {
++      unsigned front = 0;
++      /* Re-initialize DONE to TRUE while a new iteration begins.  */
++      done = true;
++      while (front < circular_queue.length ())
++	{
++	  int profit = 0;
++	  group = circular_queue[front];
++	  done &= check_group (group, front, i, profit, merged_groups,
++			       isomer_lhs, hetero_lhs);
++	  profit_sum += profit;
++	  if (profit != 0 && (*group)[0]->stmt == NULL)
++	    {
++	      reach_vdef = true;
++	      return false;
++	    }
++	  ++front;
++	}
++      /* Uncertain result, return.  */
++      if (!done && end_of_search (circular_queue, merged_groups))
++	return false;
++    }
++  if (check_any_cutpoints (circular_queue, stmts, merged_groups))
++    {
++      profit_pair.first = stmts;
++      unsigned loads = circular_queue.length () * circular_queue[0]->length ();
++      profit_pair.second = profit_sum + load_store_profit (loads, vf,
++							   stmts->length ());
++      if (profit_pair.second > 0)
++	return true;
++    }
++  return false;
++}
++
++/* Free memory allocated by ginfo.  */
++
++static void
++free_ginfos (vec *> &worklists)
++{
++  vec *worklist;
++  unsigned i = 0;
++  while (i < worklists.length ())
++    {
++      worklist = worklists[i++];
++      group_info ginfo;
++      unsigned j = 0;
++      FOR_EACH_VEC_ELT (*worklist, j, ginfo)
++	delete ginfo;
++      vec_free (worklist);
++    }
++}
++
++static void
++release_tmp_stmts (vf_stmts_profit_map &candi_stmts)
++{
++  vf_stmts_profit_map::iterator iter;
++  for (iter = candi_stmts.begin (); iter != candi_stmts.end (); ++iter)
++    iter->second.first->release ();
++}
++
++/* Choose the group of stmt with maximun profit.  */
++
++static bool
++decide_stmts_by_profit (vf_stmts_profit_map &candi_stmts, vec &stmts)
++{
++  vf_stmts_profit_map::iterator iter;
++  int profit = 0;
++  int max = 0;
++  vec *tmp = NULL;
++  for (iter = candi_stmts.begin (); iter != candi_stmts.end (); ++iter)
++    {
++      profit = iter->second.second;
++      if (profit > max)
++	{
++	  tmp = iter->second.first;
++	  max = profit;
++	}
++    }
++  if (max == 0)
++    {
++      release_tmp_stmts (candi_stmts);
++      return false;
++    }
++  unsigned i = 0;
++  gimple *stmt = NULL;
++  FOR_EACH_VEC_ELT (*tmp, i, stmt)
++    stmts.safe_push (stmt);
++  release_tmp_stmts (candi_stmts);
++  return stmts.length () != 0;
++}
++
++/* Find isomorphic stmts from grouped loads with vector factor VF.
++
++   Given source code as follows and ignore casting.
++
++   a0 = (a[0] + b[0]) + ((a[4] - b[4]) << 16);
++   a1 = (a[1] + b[1]) + ((a[5] - b[5]) << 16);
++   a2 = (a[2] + b[2]) + ((a[6] - b[6]) << 16);
++   a3 = (a[3] + b[3]) + ((a[7] - b[7]) << 16);
++
++   We get grouped loads in VINFO as
++
++   GROUP_1		GROUP_2
++   _1 = *a		_11 = *b
++   _2 = *(a + 1)	_12 = *(b + 1)
++   _3 = *(a + 2)	_13 = *(b + 2)
++   _4 = *(a + 3)	_14 = *(b + 3)
++   _5 = *(a + 4)	_15 = *(b + 4)
++   _6 = *(a + 5)	_16 = *(b + 5)
++   _7 = *(a + 6)	_17 = *(b + 6)
++   _8 = *(a + 7)	_18 = *(b + 7)
++
++   First we try VF = 8, we get two worklists
++
++   WORKLIST_1		WORKLIST_2
++   _1 = *a		_11 = *b
++   _2 = *(a + 1)	_12 = *(b + 1)
++   _3 = *(a + 2)	_13 = *(b + 2)
++   _4 = *(a + 3)	_14 = *(b + 3)
++   _5 = *(a + 4)	_15 = *(b + 4)
++   _6 = *(a + 5)	_16 = *(b + 5)
++   _7 = *(a + 6)	_17 = *(b + 6)
++   _8 = *(a + 7)	_18 = *(b + 7)
++
++   We find _111 = _1 + _11 and _115 = _5 - _15 are not isomorphic,
++   so we try VF = VF / 2.
++
++   GROUP_1		GROUP_2
++   _1 = *a		_5 = *(a + 4)
++   _2 = *(a + 1)	_6 = *(a + 5)
++   _3 = *(a + 2)	_7 = *(a + 6)
++   _4 = *(a + 3)	_8 = *(a + 7)
++
++   GROUP_3		GROUP_4
++   _11 = *b		_15 = *(b + 4)
++   _12 = *(b + 1)	_16 = *(b + 5)
++   _13 = *(b + 2)	_17 = *(b + 6)
++   _14 = *(b + 3)	_18 = *(b + 7)
++
++   We first analyze group_1, and find all operations are isomorphic, then
++   replace stmts in group_1 with their use_stmts.  Group_2 as well.
++
++   GROUP_1		GROUP_2
++   _111 = _1 + _11	_115 = _5 - _15
++   _112 = _2 + _12	_116 = _6 - _16
++   _113 = _3 + _13	_117 = _7 - _17
++   _114 = _4 + _14	_118 = _8 - _18
++
++   When analyzing group_3 and group_4, we find their use_stmts are the same
++   as group_1 and group_2.  So group_3 is regarded as being merged to group_1
++   and group_4 being merged to group_2.  In future procedures, we will skip
++   group_3 and group_4.
++
++   We repeat such processing until opreations are not isomorphic or searching
++   reaches MEM stmts.  In our given case, searching end up at a0, a1, a2 and
++   a3.  */
++
++static bool
++find_isomorphic_stmts (loop_vec_info vinfo, vec &stmts)
++{
++  unsigned vf = get_max_vf (vinfo);
++  if (vf == 0)
++    return false;
++  auto_vec *> circular_queue;
++  /* Map of vector factor and corresponding vectorizing profit.  */
++  stmts_profit profit_map;
++  /* Map of cut_points and vector factor.  */
++  vf_stmts_profit_map candi_stmts;
++  bool reach_vdef = false;
++  while (vf > 2)
++    {
++      if (build_queue (vinfo, vf, circular_queue) == 0)
++	return false;
++      if (!bfs_find_isomer_stmts (circular_queue, profit_map, vf, reach_vdef))
++	{
++	  if (reach_vdef)
++	    {
++	      release_tmp_stmts (candi_stmts);
++	      free_ginfos (circular_queue);
++	      circular_queue.release ();
++	      return false;
++	    }
++	  vf /= 2;
++	  free_ginfos (circular_queue);
++	  circular_queue.release ();
++	  continue;
++	}
++      candi_stmts[vf] = profit_map;
++      free_ginfos (circular_queue);
++      vf /= 2;
++      circular_queue.release ();
++    }
++  return decide_stmts_by_profit (candi_stmts, stmts);
++}
++
++/* Get iv from SEED_STMTS and make sure each seed_stmt has only one iv as index
++   and all indices are the same.  */
++
++static tree
++find_index (vec seed_stmts)
++{
++  if (seed_stmts.length () == 0)
++    return NULL;
++  bool found_index = false;
++  tree index = NULL;
++  unsigned ui = 0;
++  for (ui = 0; ui < seed_stmts.length (); ui++)
++    {
++      if (!gimple_vdef (seed_stmts[ui]))
++	return NULL;
++      tree lhs = gimple_assign_lhs (seed_stmts[ui]);
++      unsigned num_index = 0;
++      while (TREE_CODE (lhs) == ARRAY_REF)
++	{
++	  if (TREE_CODE (TREE_OPERAND (lhs, 1)) == SSA_NAME)
++	    {
++	      num_index++;
++	      if (num_index > 1)
++		return NULL;
++	      if (index == NULL)
++		{
++		  index = TREE_OPERAND (lhs, 1);
++		  found_index = true;
++		}
++	      else if (index != TREE_OPERAND (lhs, 1))
++		return NULL;
++	    }
++	  lhs = TREE_OPERAND (lhs, 0);
++	}
++      if (!found_index)
++	return NULL;
++    }
++  return index;
++}
++
++/* Check if expression of phi is an increament of a const.  */
++
++static void
++check_phi_inc (struct vertex *v_phi, struct graph *rdg, bool &found_inc)
++{
++  struct graph_edge *e_phi;
++  for (e_phi = v_phi->succ; e_phi; e_phi = e_phi->succ_next)
++    {
++      struct vertex *v_inc = &(rdg->vertices[e_phi->dest]);
++      if (!is_gimple_assign (RDGV_STMT (v_inc))
++	  || gimple_expr_code (RDGV_STMT (v_inc)) != PLUS_EXPR)
++	continue;
++      tree rhs1 = gimple_assign_rhs1 (RDGV_STMT (v_inc));
++      tree rhs2 = gimple_assign_rhs2 (RDGV_STMT (v_inc));
++      if (!(integer_onep (rhs1) || integer_onep (rhs2)))
++	continue;
++      struct graph_edge *e_inc;
++      /* find cycle with only two vertices inc and phi: inc <--> phi.  */
++      bool found_cycle = false;
++      for (e_inc = v_inc->succ; e_inc; e_inc = e_inc->succ_next)
++	{
++	  if (e_inc->dest == e_phi->src)
++	    {
++	      found_cycle = true;
++	      break;
++	    }
++	}
++      if (!found_cycle)
++	continue;
++      found_inc = true;
++    }
++}
++
++/* Check if phi satisfies form like PHI <0, i>.  */
++
++static inline bool
++iv_check_phi_stmt (gimple *phi_stmt)
++{
++  return gimple_phi_num_args (phi_stmt) == 2
++	 && (integer_zerop (gimple_phi_arg_def (phi_stmt, 0))
++	     || integer_zerop (gimple_phi_arg_def (phi_stmt, 1)));
++}
++
++/* Make sure the iteration varible is a phi.  */
++
++static tree
++get_iv_from_seed (struct graph *flow_only_rdg, vec seed_stmts)
++{
++  tree index = find_index (seed_stmts);
++  if (index == NULL)
++    return NULL;
++  for (int i = 0; i < flow_only_rdg->n_vertices; i++)
++    {
++      struct vertex *v = &(flow_only_rdg->vertices[i]);
++      if (RDGV_STMT (v) != seed_stmts[0])
++	continue;
++      struct graph_edge *e;
++      bool found_phi = false;
++      for (e = v->pred; e; e = e->pred_next)
++	{
++	  struct vertex *v_phi = &(flow_only_rdg->vertices[e->src]);
++	  gimple *phi_stmt = RDGV_STMT (v_phi);
++	  if (gimple_code (phi_stmt) != GIMPLE_PHI
++	      || gimple_phi_result (phi_stmt) != index)
++	    continue;
++	  if (!iv_check_phi_stmt (phi_stmt))
++	    return NULL;
++	  /* find inc expr in succ of phi.  */
++	  bool found_inc = false;
++	  check_phi_inc (v_phi, flow_only_rdg, found_inc);
++	  if (!found_inc)
++	    return NULL;
++	  found_phi = true;
++	  break;
++	}
++      if (!found_phi)
++	return NULL;
++      break;
++    }
++  return index;
++}
++
++/* Do not distribute loop if vertexes in ROOT_MAP have antidependence with in
++   FLOW_ONLY_RDG.  */
++
++static bool
++check_no_dependency (struct graph *flow_only_rdg, bitmap root_map)
++{
++  bitmap_iterator bi;
++  unsigned ui;
++  auto_vec visited_nodes;
++  auto_bitmap visited_map;
++  EXECUTE_IF_SET_IN_BITMAP (root_map, 0, ui, bi)
++    visited_nodes.safe_push (ui);
++  for (ui = 0; ui < visited_nodes.length (); ui++)
++    {
++      struct vertex *v = &(flow_only_rdg->vertices[visited_nodes[ui]]);
++      struct graph_edge *e;
++      for (e = v->succ; e; e = e->succ_next)
++	{
++	  if (bitmap_bit_p (root_map, e->dest))
++	    return false;
++	  if (bitmap_bit_p (visited_map, e->dest))
++	    continue;
++	  visited_nodes.safe_push (e->dest);
++	  bitmap_set_bit (visited_map, e->dest);
++	}
++    }
++  return true;
++}
++
++/* Find isomorphic stmts from GROUPED_LOADS in VINFO and make sure
++   there is no dependency among those STMT we found.  */
++
++static unsigned
++get_cut_points (struct graph *flow_only_rdg, bitmap cut_points,
++		loop_vec_info vinfo)
++{
++  unsigned n_stmts = 0;
++
++  /* STMTS that may be CUT_POINTS.  */
++  auto_vec stmts;
++  if (!find_isomorphic_stmts (vinfo, stmts))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "No temp array insertion: no isomorphic stmts"
++			    " were found.\n");
++      return 0;
++    }
++
++  for (int i = 0; i < flow_only_rdg->n_vertices; i++)
++    {
++      if (stmts.contains (RDG_STMT (flow_only_rdg, i)))
++	bitmap_set_bit (cut_points, i);
++    }
++  n_stmts = bitmap_count_bits (cut_points);
++
++  bool succ = check_no_dependency (flow_only_rdg, cut_points);
++  if (!succ)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "No temp array inserted: data dependency"
++			    " among isomorphic stmts.\n");
++      return 0;
++    }
++  return n_stmts;
++}
++
++static void
++build_temp_array (struct vertex *v, gimple_stmt_iterator &gsi,
++		  poly_uint64 array_extent, tree iv,
++		  hash_set *tmp_array_vars, vec *transformed)
++{
++  gimple *stmt = RDGV_STMT (v);
++  tree lhs = gimple_assign_lhs (stmt);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "original stmt:\t");
++      print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
++    }
++  tree var_ssa = duplicate_ssa_name (lhs, stmt);
++  gimple_assign_set_lhs (stmt, var_ssa);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "changed to:\t");
++      print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_MEMSYMS);
++    }
++  gimple_set_uid (gsi_stmt (gsi), -1);
++  tree vect_elt_type = TREE_TYPE (lhs);
++  tree array_type = build_array_type_nelts (vect_elt_type, array_extent);
++  tree array = create_tmp_var (array_type);
++  tree array_ssa = build4 (ARRAY_REF, vect_elt_type, array, iv, NULL, NULL);
++  tmp_array_vars->add (array_ssa);
++  gimple *store = gimple_build_assign (array_ssa, var_ssa);
++  tree new_vdef = make_ssa_name (gimple_vop (cfun), store);
++  gsi_insert_after (&gsi, store, GSI_NEW_STMT);
++  gimple_set_vdef (store, new_vdef);
++  transformed->safe_push (store);
++  gimple_set_uid (gsi_stmt (gsi), -1);
++  tree array_ssa2 = build4 (ARRAY_REF, vect_elt_type, array, iv, NULL, NULL);
++  tmp_array_vars->add (array_ssa2);
++  gimple *load = gimple_build_assign (lhs, array_ssa2);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "insert stmt:\t");
++      print_gimple_stmt (dump_file, store, 0, TDF_VOPS|TDF_MEMSYMS);
++      fprintf (dump_file, " and stmt:\t");
++      print_gimple_stmt (dump_file, load, 0, TDF_VOPS|TDF_MEMSYMS);
++    }
++  gimple_set_vuse (load, new_vdef);
++  gsi_insert_after (&gsi, load, GSI_NEW_STMT);
++  gimple_set_uid (gsi_stmt (gsi), -1);
++}
++
++/* Set bitmap PRODUCERS based on vec TRANSFORMED.  */
++
++void
++loop_distribution::build_producers (loop_p loop, bitmap producers,
++				    vec &transformed)
++{
++  auto_vec stmts;
++  stmts_from_loop (loop, &stmts);
++  int i = 0;
++  gimple *stmt = NULL;
++
++  FOR_EACH_VEC_ELT (stmts, i, stmt)
++    gimple_set_uid (stmt, i);
++  i = 0;
++  FOR_EACH_VEC_ELT (transformed, i, stmt)
++    bitmap_set_bit (producers, stmt->uid);
++}
++
++/* Transform stmt
++
++   A = FOO (ARG_1);
++
++   to
++
++   STMT_1: A1 = FOO (ARG_1);
++   STMT_2: X[I] = A1;
++   STMT_3: A = X[I];
++
++   Producer is STMT_2 who defines the temp array and consumer is
++   STMT_3 who uses the temp array.  */
++
++void
++loop_distribution::do_insertion (loop_p loop, struct graph *flow_only_rdg,
++				 tree iv, bitmap cut_points,
++				 hash_set *tmp_array_vars,
++				 bitmap producers)
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "=== do insertion ===\n");
++
++  auto_vec transformed;
++
++  /* Execution times of loop.  */
++  poly_uint64 array_extent
++    = tree_to_poly_uint64 (number_of_latch_executions (loop)) + 1;
++
++  basic_block *bbs = get_loop_body_in_custom_order (loop, this,
++						    bb_top_order_cmp_r);
++
++  for (int i = 0; i < int (loop->num_nodes); i++)
++    {
++      basic_block bb = bbs[i];
++
++      /* Find all cut points in bb and transform them.  */
++      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
++	   gsi_next (&gsi))
++	{
++	  unsigned j = gimple_uid (gsi_stmt (gsi));
++	  if (bitmap_bit_p (cut_points, j))
++	    {
++	      struct vertex *v = &(flow_only_rdg->vertices[j]);
++	      build_temp_array (v, gsi, array_extent, iv, tmp_array_vars,
++				&transformed);
++	    }
++	}
++    }
++  build_producers (loop, producers, transformed);
++  update_ssa (TODO_update_ssa);
++  free (bbs);
++}
++
++/* After temp array insertion, given stmts
++   STMT_1: M = FOO (ARG_1);
++   STMT_2: X[I] = M;
++   STMT_3: A = X[I];
++   STMT_2 is the producer, STMT_1 is its prev and STMT_3 is its next.
++   Replace M with A, and remove STMT_2 and STMT_3.  */
++
++static void
++reset_gimple_assign (struct graph *flow_only_rdg, struct partition *partition,
++		     gimple_stmt_iterator &gsi, int j)
++{
++  struct vertex *v = &(flow_only_rdg->vertices[j]);
++  gimple *stmt = RDGV_STMT (v);
++  gimple *prev = stmt->prev;
++  gimple *next = stmt->next;
++  tree n_lhs = gimple_assign_lhs (next);
++  gimple_assign_set_lhs (prev, n_lhs);
++  unlink_stmt_vdef (stmt);
++  if (partition)
++    bitmap_clear_bit (partition->stmts, gimple_uid (gsi_stmt (gsi)));
++  gsi_remove (&gsi, true);
++  release_defs (stmt);
++  if (partition)
++    bitmap_clear_bit (partition->stmts, gimple_uid (gsi_stmt (gsi)));
++  gsi_remove (&gsi, true);
++}
++
++void
++loop_distribution::remove_insertion (loop_p loop, struct graph *flow_only_rdg,
++		  bitmap producers, struct partition *partition)
++{
++  basic_block *bbs = get_loop_body_in_custom_order (loop, this,
++						    bb_top_order_cmp_r);
++  for (int i = 0; i < int (loop->num_nodes); i++)
++    {
++      basic_block bb = bbs[i];
++      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
++	   gsi_next (&gsi))
++	{
++	  unsigned j = gimple_uid (gsi_stmt (gsi));
++	  if (bitmap_bit_p (producers, j))
++	    reset_gimple_assign (flow_only_rdg, partition, gsi, j);
++	}
++    }
++  update_ssa (TODO_update_ssa);
++  free (bbs);
++}
++
++/* Insert temp arrays if isomorphic computation exists.  Temp arrays will be
++   regarded as SEED_STMTS for building partitions in succeeding processes.  */
++
++bool
++loop_distribution::insert_temp_arrays (loop_p loop, vec seed_stmts,
++			hash_set *tmp_array_vars, bitmap producers)
++{
++  struct graph *flow_only_rdg = build_rdg (loop, NULL);
++  gcc_checking_assert (flow_only_rdg != NULL);
++  tree iv = get_iv_from_seed (flow_only_rdg, seed_stmts);
++  if (iv == NULL)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Loop %d no temp array insertion: failed to get"
++			    " iteration variable.\n", loop->num);
++      free_rdg (flow_only_rdg);
++      return false;
++  }
++  auto_bitmap cut_points;
++  loop_vec_info vinfo = loop_vec_info_for_loop (loop);
++  unsigned n_cut_points = get_cut_points (flow_only_rdg, cut_points, vinfo);
++  delete vinfo;
++  loop->aux = NULL;
++  if (n_cut_points == 0)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++	fprintf (dump_file, "Loop %d no temp array insertion: no cut points"
++			    " found.\n", loop->num);
++      free_rdg (flow_only_rdg);
++      return false;
++    }
++  do_insertion (loop, flow_only_rdg, iv, cut_points, tmp_array_vars, producers);
++  if (dump_enabled_p ())
++    {
++      dump_user_location_t loc = find_loop_location (loop);
++      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "Insertion done:"
++		       " %d temp arrays inserted in Loop %d.\n",
++		       n_cut_points, loop->num);
++    }
++  free_rdg (flow_only_rdg);
++  return true;
++}
++
++static bool find_seed_stmts_for_distribution (class loop *, vec *);
++
+ /* Distributes the code from LOOP in such a way that producer statements
+    are placed before consumer statements.  Tries to separate only the
+    statements from STMTS into separate loops.  Returns the number of
+@@ -2972,7 +4342,7 @@ loop_distribution::finalize_partitions (class loop *loop,
+ 
+ int
+ loop_distribution::distribute_loop (class loop *loop,
+-		 const vec &stmts,
++		 vec &stmts,
+ 		 control_dependences *cd, int *nb_calls, bool *destroy_p,
+ 		 bool only_patterns_p)
+ {
+@@ -3021,6 +4391,33 @@ loop_distribution::distribute_loop (class loop *loop,
+       return 0;
+     }
+ 
++  /* Try to distribute LOOP if LOOP is simple enough and unable to vectorize.
++     If LOOP has grouped loads, recursively find isomorphic stmts and insert
++     temp arrays, rebuild RDG and call find_seed_stmts_for_distribution
++     to replace STMTS.  */
++
++  hash_set tmp_array_vars;
++
++  /* STMTs that define those inserted TMP_ARRAYs.  */
++  auto_bitmap producers;
++
++  /* New SEED_STMTS after insertion.  */
++  auto_vec work_list;
++  bool insert_success = false;
++  if (may_insert_temp_arrays (loop, rdg, cd))
++    {
++      if (insert_temp_arrays (loop, stmts, &tmp_array_vars, producers))
++	{
++	  if (find_seed_stmts_for_distribution (loop, &work_list))
++	    {
++	      insert_success = true;
++	    }
++	  else
++	    remove_insertion (loop, rdg, producers, NULL);
++	  rebuild_rdg (loop, rdg, cd);
++	}
++     }
++
+   data_reference_p dref;
+   for (i = 0; datarefs_vec.iterate (i, &dref); ++i)
+     dref->aux = (void *) (uintptr_t) i;
+@@ -3029,7 +4426,10 @@ loop_distribution::distribute_loop (class loop *loop,
+     dump_rdg (dump_file, rdg);
+ 
+   auto_vec partitions;
+-  rdg_build_partitions (rdg, stmts, &partitions);
++  if (work_list.length() > stmts.length())
++	rdg_build_partitions (rdg, &work_list, &partitions);
++  else
++	rdg_build_partitions (rdg, &stmts, &partitions);
+ 
+   auto_vec alias_ddrs;
+ 
+@@ -3101,7 +4501,7 @@ loop_distribution::distribute_loop (class loop *loop,
+       for (int j = i + 1;
+ 	   partitions.iterate (j, &partition); ++j)
+ 	{
+-	  if (share_memory_accesses (rdg, into, partition))
++	  if (share_memory_accesses (rdg, into, partition, &tmp_array_vars))
+ 	    {
+ 	      partition_merge_into (rdg, into, partition, FUSE_SHARE_REF);
+ 	      partitions.unordered_remove (j);
+@@ -3151,7 +4551,7 @@ loop_distribution::distribute_loop (class loop *loop,
+ 	}
+     }
+ 
+-  finalize_partitions (loop, &partitions, &alias_ddrs);
++  finalize_partitions (loop, &partitions, &alias_ddrs, producers);
+ 
+   /* If there is a reduction in all partitions make sure the last one
+      is not classified for builtin code generation.  */
+@@ -3169,6 +4569,24 @@ loop_distribution::distribute_loop (class loop *loop,
+     }
+ 
+   nbp = partitions.length ();
++
++  /* If we have inserted TMP_ARRAYs but there is only one partition left in
++     the succeeding processes, remove those inserted TMP_ARRAYs back to the
++     original version.  */
++
++  if (nbp == 1 && insert_success)
++    {
++      struct partition *partition = NULL;
++      partitions.iterate (0, &partition);
++      remove_insertion (loop, rdg, producers, partition);
++      if (dump_enabled_p ())
++	{
++	  dump_user_location_t loc = find_loop_location (loop);
++	  dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "Insertion removed:"
++			   " unable to distribute loop %d.\n", loop->num);
++	}
++    }
++
+   if (nbp == 0
+       || (nbp == 1 && !partition_builtin_p (partitions[0]))
+       || (nbp > 1 && partition_contains_all_rw (rdg, partitions)))
+diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
+index 04e68f621..aae7f62f3 100644
+--- a/gcc/tree-vect-data-refs.cc
++++ b/gcc/tree-vect-data-refs.cc
+@@ -2791,6 +2791,9 @@ vect_analyze_group_access_1 (vec_info *vinfo, dr_vec_info *dr_info)
+       DR_GROUP_GAP (stmt_info) = groupsize - last_accessed_element;
+ 
+       DR_GROUP_SIZE (stmt_info) = groupsize;
++
++      DR_GROUP_SLP_TRANSPOSE (stmt_info) = false;
++
+       if (dump_enabled_p ())
+ 	{
+ 	  dump_printf_loc (MSG_NOTE, vect_location,
+@@ -2820,6 +2823,20 @@ vect_analyze_group_access_1 (vec_info *vinfo, dr_vec_info *dr_info)
+ 			     DR_GROUP_GAP (stmt_info));
+ 	}
+ 
++      /* SLP: create an SLP data structure for every interleaving group of
++	 loads for further analysis in vect_analyse_slp.  */
++      if (DR_IS_READ (dr) && !slp_impossible)
++	{
++	  if (loop_vinfo)
++	    {
++	      LOOP_VINFO_GROUPED_LOADS (loop_vinfo).safe_push (stmt_info);
++	    }
++	  if (bb_vinfo)
++	    {
++	      BB_VINFO_GROUPED_LOADS (bb_vinfo).safe_push (stmt_info);
++	    }
++	}
++
+       /* SLP: create an SLP data structure for every interleaving group of
+ 	 stores for further analysis in vect_analyse_slp.  */
+       if (DR_IS_WRITE (dr) && !slp_impossible)
+@@ -5636,6 +5653,226 @@ vect_permute_store_chain (vec_info *vinfo, vec &dr_chain,
+     }
+ }
+ 
++/* Encoding the PERM_MASK_FIRST.  */
++
++static void
++vect_indices_encoding_first (tree vectype, unsigned int array_num,
++			     tree &perm_mask_high_first,
++			     tree &perm_mask_low_first)
++{
++  unsigned int nelt = TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
++  vec_perm_builder sel (nelt, nelt, 1);
++  sel.quick_grow (nelt);
++  unsigned int group_num = nelt / array_num;
++  unsigned int index = 0;
++  unsigned int array = 0;
++  unsigned int group = 0;
++
++  /* The encoding has 1 pattern in the fisrt stage.  */
++  for (array = 0; array < array_num / 2; array++)
++    {
++      for (group = 0; group < group_num * 2; group++)
++	{
++	  sel[index++] = array + array_num * group;
++	}
++    }
++  vec_perm_indices indices (sel, 2, nelt);
++  perm_mask_high_first = vect_gen_perm_mask_checked (vectype, indices);
++
++  index = 0;
++  for (array = array_num / 2; array < array_num; array++)
++    {
++      for (group = 0; group < group_num * 2; group++)
++	{
++	  sel[index++] = array + array_num * group;
++	}
++    }
++  indices.new_vector (sel, 2, nelt);
++  perm_mask_low_first = vect_gen_perm_mask_checked (vectype, indices);
++}
++
++/* Encoding the PERM_MASK.  */
++
++static void
++vect_indices_encoding (tree vectype, unsigned int array_num,
++		       tree &perm_mask_high, tree &perm_mask_low)
++{
++  unsigned int nelt = TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
++  vec_perm_builder sel (nelt, nelt, 1);
++  sel.quick_grow (nelt);
++  unsigned int group_num = nelt / array_num;
++  unsigned int index = 0;
++  unsigned int array = 0;
++  unsigned int group = 0;
++
++  /* The encoding has 2 patterns in the folllowing stages.  */
++  for (array = 0; array < array_num / 2; array++)
++    {
++      for (group = 0; group < group_num; group++)
++	{
++	  sel[index++] = group + group_num * array;
++	}
++      for (group = 0; group < group_num; group++)
++	{
++	  sel[index++] = nelt + group + group_num * array;
++	}
++    }
++  vec_perm_indices indices (sel, 2, nelt);
++  perm_mask_high = vect_gen_perm_mask_checked (vectype, indices);
++
++  index = 0;
++  for (array = array_num / 2; array < array_num; array++)
++    {
++      for (group = 0; group < group_num; group++)
++	{
++	  sel[index++] = group + group_num * array;
++	}
++      for (group = 0; group < group_num; group++)
++	{
++	  sel[index++] = nelt + group + group_num * array;
++	}
++    }
++  indices.new_vector (sel, 2, nelt);
++  perm_mask_low = vect_gen_perm_mask_checked (vectype, indices);
++}
++
++/* Function vect_transpose_store_chain.
++
++   Given a chain of interleaved stores in DR_CHAIN of LENGTH and ARRAY_NUM that
++   must be a power of 2.  Generate interleave_high/low stmts to reorder
++   the data correctly for the stores.  Return the final references for stores
++   in RESULT_CHAIN.  This function is similar to vect_permute_store_chain (),
++   we interleave the contents of the vectors in their order.
++
++   E.g., LENGTH is 4, the scalar type is short (i.e., VF is 8) and ARRAY_NUM
++   is 4.  That is, the input is 4 vectors each containing 8 elements.
++   And 2 (VF / ARRAY_NUM) of 8 elements come from the same array.  we interleave
++   the contents of the four vectors in their order.  We assign a number to each
++   element, the input sequence is:
++
++   1st vec:   0  1  2  3  4  5  6  7
++   2nd vec:   8  9 10 11 12 13 14 15
++   3rd vec:  16 17 18 19 20 21 22 23
++   4th vec:  24 25 26 27 28 29 30 31
++
++   The output sequence should be:
++
++   1st vec:   0  4  8 12 16 20 24 28
++   2nd vec:   1  5  9 13 17 21 25 29
++   3rd vec:   2  6 10 14 18 22 26 30
++   4th vec:   3  7 11 15 19 23 27 31
++
++   In our example,
++   We get 2 (VF / ARRAY_NUM) elements together in every vector.
++
++   I1:   0  4  1  5  2  6  3  7
++   I2:   8 12  9 13 10 14 11 15
++   I3:  16 20 17 21 18 22 19 23
++   I4:  24 28 25 29 26 30 27 31
++
++   Then, we use interleave_high/low instructions to create such output.
++   Every 2 (VF / ARRAY_NUM) elements are regarded as a whole.  The permutation
++   is done in log LENGTH stages.
++
++   I1: interleave_high (1st vec, 3rd vec)
++   I2: interleave_low (1st vec, 3rd vec)
++   I3: interleave_high (2nd vec, 4th vec)
++   I4: interleave_low (2nd vec, 4th vec)
++
++   The first stage of the sequence should be:
++
++   I1:   0  4 16 20  1  5 17 21
++   I2:   2  6 18 22  3  7 19 23
++   I3:   8 12 24 28  9 13 25 29
++   I4:  10 14 26 30 11 15 27 31
++
++   The following stage sequence should be, i.e. the final result is:
++
++   I1:   0  4  8 12 16 20 24 28
++   I2:   1  5  9 13 17 21 25 29
++   I3:   2  6 10 14 18 22 26 30
++   I4:   3  7 11 15 19 23 27 31.  */
++
++void
++vect_transpose_store_chain (vec_info *vinfo, vec dr_chain,
++			    unsigned int length, unsigned int array_num,
++			    stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
++			    vec *result_chain)
++{
++  gimple *perm_stmt = NULL;
++  tree vectype = STMT_VINFO_VECTYPE (stmt_info);
++  tree perm_mask_low_first = NULL;
++  tree perm_mask_high_first = NULL;
++  tree perm_mask_low = NULL;
++  tree perm_mask_high = NULL;
++  unsigned int log_length = exact_log2 (length);
++
++  /* Only power of 2 is supported.  */
++  gcc_assert (pow2p_hwi (length));
++
++  /* The encoding has 2 types, one for the grouped pattern in the fisrt stage,
++     another for the interleaved patterns in the following stages.  */
++  gcc_assert (array_num != 0);
++
++  /* Create grouped stmt (in the first stage):
++	group = nelt / array_num;
++	high_first = VEC_PERM_EXPR 
++	low_first = VEC_PERM_EXPR   */
++  vect_indices_encoding_first (vectype, array_num, perm_mask_high_first,
++			       perm_mask_low_first);
++
++  /* Create interleaving stmt (in the following stages):
++	high = VEC_PERM_EXPR 
++	low = VEC_PERM_EXPR   */
++  vect_indices_encoding (vectype, array_num, perm_mask_high, perm_mask_low);
++
++  for (unsigned int perm_time = 0; perm_time < log_length; perm_time++)
++    {
++      for (unsigned int index = 0; index < length / 2; index++)
++	{
++	  tree vect1 = dr_chain[index];
++	  tree vect2 = dr_chain[index + length / 2];
++
++	  tree high = make_temp_ssa_name (vectype, NULL, "vect_inter_high");
++	  perm_stmt = gimple_build_assign (high, VEC_PERM_EXPR, vect1, vect2,
++					   perm_time == 0 ? perm_mask_high_first
++							  : perm_mask_high);
++	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
++	  (*result_chain)[2 * index] = high;
++
++	  tree low = make_temp_ssa_name (vectype, NULL, "vect_inter_low");
++	  perm_stmt = gimple_build_assign (low, VEC_PERM_EXPR, vect1, vect2,
++					   perm_time == 0 ? perm_mask_low_first
++							  : perm_mask_low);
++	  vect_finish_stmt_generation (vinfo, stmt_info, perm_stmt, gsi);
++	  (*result_chain)[2 * index+1] = low;
++	}
++      memcpy (dr_chain.address (), result_chain->address (),
++	      length * sizeof (tree));
++    }
++}
++
+ /* Function vect_setup_realignment
+ 
+    This function is called when vectorizing an unaligned load using
+diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
+index 3435f9378..f296e9415 100644
+--- a/gcc/tree-vect-loop.cc
++++ b/gcc/tree-vect-loop.cc
+@@ -2856,7 +2856,7 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared,
+ 		     loop_vec_info main_loop_vinfo,
+ 		     const vector_modes &vector_modes, unsigned &mode_i,
+ 		     machine_mode &autodetected_vector_mode,
+-		     bool &fatal)
++		     bool &fatal, bool result_only_p)
+ {
+   loop_vec_info loop_vinfo
+     = vect_create_loop_vinfo (loop, shared, loop_form_info, main_loop_vinfo);
+@@ -2865,6 +2865,8 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared,
+   loop_vinfo->vector_mode = vector_mode;
+   unsigned int suggested_unroll_factor = 1;
+ 
++  /* Loop_vinfo for loop-distribution pass.  */
++  opt_loop_vec_info fail_loop_vinfo = opt_loop_vec_info::success (NULL);
+   /* Run the main analysis.  */
+   opt_result res = vect_analyze_loop_2 (loop_vinfo, fatal,
+ 					&suggested_unroll_factor);
+@@ -2933,7 +2935,21 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared,
+ 
+   if (!res)
+     {
+-      delete loop_vinfo;
++
++	/* If current analysis shows LOOP is unable to vectorize, loop_vinfo
++	will be deleted.  If LOOP is under ldist analysis, backup it before
++	it is deleted and return it if all modes are analyzed and still
++	fail to vectorize.  */
++      if (result_only_p && (mode_i == vector_modes.length ()
++	    || autodetected_vector_mode == VOIDmode))
++	{
++	    fail_loop_vinfo = opt_loop_vec_info::success (loop_vinfo);
++	    loop->aux = (loop_vec_info) fail_loop_vinfo;
++	}
++      else
++	{
++	    delete loop_vinfo;
++	}
+       if (fatal)
+ 	gcc_checking_assert (main_loop_vinfo == NULL);
+       return opt_loop_vec_info::propagate_failure (res);
+@@ -2946,9 +2962,11 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared,
+ 
+    Apply a set of analyses on LOOP, and create a loop_vec_info struct
+    for it.  The different analyses will record information in the
+-   loop_vec_info struct.  */
++   loop_vec_info struct.  When RESULT_ONLY_P is true, quit analysis
++   if loop is vectorizable, otherwise, do not delete vinfo. */
+ opt_loop_vec_info
+-vect_analyze_loop (class loop *loop, vec_info_shared *shared)
++vect_analyze_loop (class loop *loop, vec_info_shared *shared,
++		   bool result_only_p)
+ {
+   DUMP_VECT_SCOPE ("analyze_loop_nest");
+ 
+@@ -2996,6 +3014,12 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+ 			     && !unlimited_cost_model (loop));
+   machine_mode autodetected_vector_mode = VOIDmode;
+   opt_loop_vec_info first_loop_vinfo = opt_loop_vec_info::success (NULL);
++  /* Loop_vinfo for loop-distribution pass.  */
++  opt_loop_vec_info fail_loop_vinfo = opt_loop_vec_info::success (NULL);
++  if (result_only_p)
++  {
++     vect_slp_init ();
++  }
+   unsigned int mode_i = 0;
+   unsigned HOST_WIDE_INT simdlen = loop->simdlen;
+ 
+@@ -3019,10 +3043,16 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+       opt_loop_vec_info loop_vinfo
+ 	= vect_analyze_loop_1 (loop, shared, &loop_form_info,
+ 			       NULL, vector_modes, mode_i,
+-			       autodetected_vector_mode, fatal);
++			       autodetected_vector_mode, fatal, result_only_p);
+       if (fatal)
+ 	break;
+ 
++      if (result_only_p && (mode_i == vector_modes.length ()
++	  || autodetected_vector_mode == VOIDmode))
++	{
++		return loop_vinfo;
++	}
++
+       if (loop_vinfo)
+ 	{
+ 	  /*  Analyzis has been successful so update the VF value.  The
+@@ -3132,7 +3162,7 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared)
+ 	= vect_analyze_loop_1 (loop, shared, &loop_form_info,
+ 			       first_loop_vinfo,
+ 			       vector_modes, mode_i,
+-			       autodetected_vector_mode, fatal);
++			       autodetected_vector_mode, fatal, result_only_p);
+       if (fatal)
+ 	break;
+ 
+diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
+index e1bcab0f7..c0c15773d 100644
+--- a/gcc/tree-vect-patterns.cc
++++ b/gcc/tree-vect-patterns.cc
+@@ -5632,8 +5632,8 @@ static vect_recog_func vect_vect_recog_func_ptrs[] = {
+      internal functions.  */
+   { vect_recog_gather_scatter_pattern, "gather_scatter" },
+   { vect_recog_mask_conversion_pattern, "mask_conversion" },
+-  { vect_recog_widen_plus_pattern, "widen_plus" },
+-  { vect_recog_widen_minus_pattern, "widen_minus" },
++  // { vect_recog_widen_plus_pattern, "widen_plus" },
++  // { vect_recog_widen_minus_pattern, "widen_minus" },
+ };
+ 
+ const unsigned int NUM_PATTERNS = ARRAY_SIZE (vect_vect_recog_func_ptrs);
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index af477c31a..6cbf8085f 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -49,6 +49,8 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-eh.h"
+ #include "tree-cfg.h"
+ #include "alloc-pool.h"
++#include "print-tree.h"
++#include "gimple-pretty-print.h"
+ 
+ static bool vectorizable_slp_permutation (vec_info *, gimple_stmt_iterator *,
+ 					  slp_tree, stmt_vector_for_cost *);
+@@ -994,6 +996,21 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
+ 	}
+ 
+       gcc_assert (vectype);
++      if (!STMT_VINFO_VECTYPE (stmt_info))
++	STMT_VINFO_VECTYPE (stmt_info) = vectype;
++      if (dump_file)
++	{
++	  fprintf (dump_file, "vect_build_slp_tree_1: %p\n", stmt_info);
++	  print_gimple_stmt (dump_file, stmt, 0);
++	  fprintf (dump_file, "vect_build_slp_tree_1: vectype=");
++	  if (vectype)
++	    print_generic_expr (dump_file, vectype);
++	  fprintf (dump_file, "\n");
++	  fprintf (dump_file, "internal vectype=");
++	  if (STMT_VINFO_VECTYPE (stmt_info))
++	    print_generic_expr (dump_file, STMT_VINFO_VECTYPE (stmt_info));
++	  fprintf (dump_file, "\n");
++	}
+ 
+       gcall *call_stmt = dyn_cast  (stmt);
+       if (call_stmt)
+@@ -1575,10 +1592,10 @@ vect_build_slp_tree (vec_info *vinfo,
+ 	dump_printf_loc (MSG_NOTE, vect_location,
+ 			 "SLP discovery for node %p succeeded\n", res);
+       gcc_assert (res_ == res);
+-      res->max_nunits = this_max_nunits;
++      res_->max_nunits = this_max_nunits;
+       vect_update_max_nunits (max_nunits, this_max_nunits);
+       /* Keep a reference for the bst_map use.  */
+-      SLP_TREE_REF_COUNT (res)++;
++      SLP_TREE_REF_COUNT (res_)++;
+     }
+   return res_;
+ }
+@@ -3190,8 +3207,10 @@ vect_build_slp_instance (vec_info *vinfo,
+ 
+       /* For basic block SLP, try to break the group up into multiples of
+ 	 a vector size.  */
++      bb_vec_info bb_vinfo = dyn_cast  (vinfo);
+       if (is_a  (vinfo)
+-	  && (i > 1 && i < group_size))
++	  && (i > 1 && i < group_size)
++	  && !bb_vinfo->transposed)
+ 	{
+ 	  tree scalar_type
+ 	    = TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
+@@ -3301,84 +3320,1034 @@ vect_analyze_slp_instance (vec_info *vinfo,
+       scalar_stmts.create (DR_GROUP_SIZE (stmt_info));
+       while (next_info)
+ 	{
+-	  scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
+-	  next_info = DR_GROUP_NEXT_ELEMENT (next_info);
++	  scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
++	  next_info = DR_GROUP_NEXT_ELEMENT (next_info);
++	}
++    }
++  else if (kind == slp_inst_kind_reduc_chain)
++    {
++      /* Collect the reduction stmts and store them in scalar_stmts.  */
++      scalar_stmts.create (REDUC_GROUP_SIZE (stmt_info));
++      while (next_info)
++	{
++	  scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
++	  next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
++	}
++      /* Mark the first element of the reduction chain as reduction to properly
++	 transform the node.  In the reduction analysis phase only the last
++	 element of the chain is marked as reduction.  */
++      STMT_VINFO_DEF_TYPE (stmt_info)
++	= STMT_VINFO_DEF_TYPE (scalar_stmts.last ());
++      STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))
++	= STMT_VINFO_REDUC_DEF (vect_orig_stmt (scalar_stmts.last ()));
++    }
++  else if (kind == slp_inst_kind_ctor)
++    {
++      tree rhs = gimple_assign_rhs1 (stmt_info->stmt);
++      tree val;
++      scalar_stmts.create (CONSTRUCTOR_NELTS (rhs));
++      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
++	{
++	  stmt_vec_info def_info = vinfo->lookup_def (val);
++	  def_info = vect_stmt_to_vectorize (def_info);
++	  scalar_stmts.quick_push (def_info);
++	}
++      if (dump_enabled_p ())
++	dump_printf_loc (MSG_NOTE, vect_location,
++			 "Analyzing vectorizable constructor: %G\n",
++			 stmt_info->stmt);
++    }
++  else if (kind == slp_inst_kind_reduc_group)
++    {
++      /* Collect reduction statements.  */
++      const vec &reductions
++	= as_a  (vinfo)->reductions;
++      scalar_stmts.create (reductions.length ());
++      for (i = 0; reductions.iterate (i, &next_info); i++)
++	if ((STMT_VINFO_RELEVANT_P (next_info)
++	     || STMT_VINFO_LIVE_P (next_info))
++	    /* ???  Make sure we didn't skip a conversion around a reduction
++	       path.  In that case we'd have to reverse engineer that conversion
++	       stmt following the chain using reduc_idx and from the PHI
++	       using reduc_def.  */
++	    && STMT_VINFO_DEF_TYPE (next_info) == vect_reduction_def)
++	  scalar_stmts.quick_push (next_info);
++      /* If less than two were relevant/live there's nothing to SLP.  */
++      if (scalar_stmts.length () < 2)
++	return false;
++    }
++  else
++    gcc_unreachable ();
++
++  vec roots = vNULL;
++  if (kind == slp_inst_kind_ctor)
++    {
++      roots.create (1);
++      roots.quick_push (stmt_info);
++    }
++  /* Build the tree for the SLP instance.  */
++  bool res = vect_build_slp_instance (vinfo, kind, scalar_stmts,
++				      roots,
++				      max_tree_size, limit, bst_map,
++				      kind == slp_inst_kind_store
++				      ? stmt_info : NULL);
++  if (!res)
++    roots.release ();
++
++  /* ???  If this is slp_inst_kind_store and the above succeeded here's
++     where we should do store group splitting.  */
++
++  return res;
++}
++
++static inline bool
++is_const_assign (stmt_vec_info store_elem)
++{
++  if (store_elem == NULL)
++    {
++      gcc_unreachable ();
++    }
++  gimple *stmt = store_elem->stmt;
++  gimple_rhs_class rhs_class = gimple_assign_rhs_class (stmt);
++  return rhs_class == GIMPLE_SINGLE_RHS
++	 && TREE_CONSTANT (gimple_assign_rhs1 (store_elem->stmt));
++}
++
++/* Push inits to INNERMOST_INITS and check const assign.  */
++
++static bool
++record_innermost (vec &innermost_inits,
++		  vec &innermost_offsets,
++		  stmt_vec_info stmt_vinfo)
++{
++  if (!stmt_vinfo)
++    {
++      return false;
++    }
++  stmt_vec_info next_info = stmt_vinfo;
++  while (next_info)
++    {
++      /* No need to vectorize constant assign in a transposed version.  */
++      if (is_const_assign (next_info))
++	{
++	  if (dump_enabled_p ())
++	    {
++	      dump_printf_loc (MSG_NOTE, vect_location,
++			      "no need to vectorize, store is const assign: %G",
++			      next_info->stmt);
++	    }
++	  return false;
++	}
++      innermost_inits.safe_push (STMT_VINFO_DR_INIT (next_info));
++      innermost_offsets.safe_push (STMT_VINFO_DR_OFFSET (next_info));
++      next_info = DR_GROUP_NEXT_ELEMENT (next_info);
++    }
++  return true;
++}
++
++/* Compare inits to INNERMOST_INITS, return FALSE if inits do not match
++   the first grouped_store.  And check const assign meanwhile.  */
++
++static bool
++compare_innermost (const vec &innermost_inits,
++		   const vec &innermost_offsets,
++		   stmt_vec_info stmt_vinfo)
++{
++  if (!stmt_vinfo || innermost_inits.length () != stmt_vinfo->size)
++    {
++      return false;
++    }
++  stmt_vec_info next_info = stmt_vinfo;
++  unsigned int i = 0;
++  while (next_info)
++    {
++      if (is_const_assign (next_info))
++	{
++	  if (dump_enabled_p ())
++	    {
++	      dump_printf_loc (MSG_NOTE, vect_location,
++			       "no need to vectorize, store is const "
++			       "assign: %G", next_info->stmt);
++	    }
++	  return false;
++	}
++      if (innermost_inits[i] != STMT_VINFO_DR_INIT (next_info)
++	  || innermost_offsets[i] != STMT_VINFO_DR_OFFSET (next_info))
++	{
++	  return false;
++	}
++      next_info = DR_GROUP_NEXT_ELEMENT (next_info);
++      i++;
++    }
++  return true;
++}
++
++static bool
++check_same_bb (stmt_vec_info grp1, stmt_vec_info grp2)
++{
++  if (grp1->stmt->bb->index == grp2->stmt->bb->index)
++    {
++       return true;
++    }
++  return false;
++}
++
++/* Check if grouped stores are of same type.
++   input: t1/t2 = TREE_TYPE (gimple_assign_lhs (first_element->stmt))
++   output: 0 if same, 1 or -1 else.  */
++
++static int
++tree_type_cmp (const tree t1, const tree t2)
++{
++  gcc_checking_assert (t1 != NULL && t2 != NULL);
++  if (t1 != t2)
++    {
++      if (TREE_CODE (t1) != TREE_CODE (t2))
++	{
++	  return TREE_CODE (t1) > TREE_CODE (t2) ? 1 : -1;
++	}
++      if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
++	{
++	  return TYPE_UNSIGNED (t1) > TYPE_UNSIGNED (t2) ? 1 : -1;
++	}
++      if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2))
++	{
++	  return TYPE_PRECISION (t1) > TYPE_PRECISION (t2) ? 1 : -1;
++	}
++    }
++  return 0;
++}
++
++/* Check it if 2 grouped stores are of same type that
++   we can analyze them in a transpose group.  */
++static int
++check_same_store_type (stmt_vec_info grp1, stmt_vec_info grp2)
++{
++  if (grp1 == grp2)
++    {
++      return 0;
++    }
++  if (grp1->size != grp2->size)
++    {
++      return grp1->size > grp2->size ? 1 : -1;
++    }
++  tree lhs1 = gimple_assign_lhs (grp1->stmt);
++  tree lhs2 = gimple_assign_lhs (grp2->stmt);
++  if (TREE_CODE (lhs1) != TREE_CODE (lhs2))
++    {
++      return TREE_CODE (lhs1) > TREE_CODE (lhs2) ? 1 : -1;
++    }
++  tree grp_type1 = TREE_TYPE (gimple_assign_lhs (grp1->stmt));
++  tree grp_type2 = TREE_TYPE (gimple_assign_lhs (grp2->stmt));
++  int cmp = tree_type_cmp (grp_type1, grp_type2);
++  return cmp;
++}
++
++/* Sort grouped stores according to group_size and store_type.
++   output: 0 if same, 1 if grp1 > grp2, -1 otherwise.  */
++
++static int
++grouped_store_cmp (const void *grp1_, const void *grp2_)
++{
++  stmt_vec_info grp1 = *(stmt_vec_info *)const_cast(grp1_);
++  stmt_vec_info grp2 = *(stmt_vec_info *)const_cast(grp2_);
++  return check_same_store_type (grp1, grp2);
++}
++
++/* Transposing is based on permutation in registers.  Permutation requires
++   vector length being power of 2 and satisfying the vector mode.  */
++
++static inline bool
++check_filling_reg (stmt_vec_info current_element)
++{
++  if (current_element->size == 0)
++    {
++      return false;
++    }
++  /* If the gimple STMT was already vectorized in vect pass, it's unable to
++     conduct transpose analysis, skip it.  */
++  bool lhs_vectorized
++	= TREE_CODE (TREE_TYPE (gimple_get_lhs (current_element->stmt)))
++	  == VECTOR_TYPE;
++  bool rhs_vectorized
++	= TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (current_element->stmt)))
++	  == VECTOR_TYPE;
++  if (lhs_vectorized || rhs_vectorized)
++    {
++      return false;
++    }
++  unsigned int store_precision
++    = TYPE_PRECISION (TREE_TYPE (gimple_get_lhs (current_element->stmt)));
++  auto_vector_modes vector_modes;
++  targetm.vectorize.autovectorize_vector_modes (&vector_modes, false);
++  unsigned min_mode_size = -1u;
++  for (unsigned i = 0; i < vector_modes.length (); i++)
++    {
++      unsigned mode_bit_size = (GET_MODE_BITSIZE (vector_modes[i])).coeffs[0];
++      min_mode_size = mode_bit_size < min_mode_size
++			? mode_bit_size : min_mode_size;
++    }
++  return store_precision != 0
++	 && pow2p_hwi (current_element->size)
++	 && (current_element->size * store_precision % min_mode_size == 0);
++}
++
++/* Check if previous groups are suitable to transpose, if not, set their
++   group number to -1, reduce grp_num and clear current_groups.
++   Otherwise, just clear current_groups.  */
++
++static void
++check_and_clear_groups (vec ¤t_groups,
++			unsigned int &grp_num)
++{
++  stmt_vec_info first_element;
++  if (current_groups.length () == 1
++      || (current_groups.length () != 0
++	  && !pow2p_hwi (current_groups.length ())))
++    {
++      while (current_groups.length () != 0)
++	{
++	  first_element = current_groups.pop ();
++	  first_element->group_number = -1;
++	}
++      grp_num--;
++    }
++  else
++    {
++      while (current_groups.length ())
++	{
++	  current_groups.pop ();
++	}
++    }
++}
++
++
++/* Make sure that transpose slp vectorization is conducted only if grouped
++   stores are one dimension array ref.  */
++
++static bool
++is_store_one_dim_array (gimple *stmt)
++{
++  tree op = gimple_get_lhs (stmt);
++  if (TREE_CODE (op) != ARRAY_REF)
++    return false;
++  return TREE_OPERAND_LENGTH (op) > 0
++	 && TREE_OPERAND_LENGTH (TREE_OPERAND (op, 0)) == 0;
++}
++
++/* Set grouped_stores with similar MEM_REF to the same group and mark their
++   grp_num.  Groups with same grp_num consist the minimum unit to analyze
++   transpose.  Return num of such units.  */
++
++static unsigned
++vect_prepare_transpose (bb_vec_info bb_vinfo)
++{
++  stmt_vec_info current_element = NULL;
++  stmt_vec_info first_element = NULL;
++  unsigned int i = 0;
++  unsigned int grp_num = 0;
++  /* Use arrays to record MEM_REF data in different GROUPED_STORES.  */
++  auto_vec innermost_inits;
++  auto_vec innermost_offsets;
++
++  /* A set of stmt_vec_info with same store type.  Analyze them if their size
++     is suitable to transpose.  */
++  auto_vec current_groups;
++
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_stores, i, current_element)
++    {
++      /* Compare current grouped_store to the first one if first_element exists,
++	 push current_element to current_groups if they are similar on innermost
++	 behavior of MEM_REF.  */
++      if (first_element != NULL
++	  && !check_same_store_type (first_element, current_element)
++	  && compare_innermost (innermost_inits, innermost_offsets,
++				current_element)
++	  && check_same_bb (first_element, current_element))
++	{
++	  current_groups.safe_push (current_element);
++	  current_element->group_number = grp_num;
++	  /* If current_element is the last element in grouped_stores, continue
++	     will exit the loop and leave the last group unanalyzed.  */
++	  if (i == bb_vinfo->grouped_stores.length () - 1)
++	    {
++	      check_and_clear_groups (current_groups, grp_num);
++	    }
++	  continue;
++	}
++      check_and_clear_groups (current_groups, grp_num);
++      innermost_inits.release ();
++      innermost_offsets.release ();
++      /* Beginning of a new group to analyze whether they are able to consist
++	 a unit to conduct transpose analysis.  */
++      first_element = NULL;
++      if (is_store_one_dim_array (current_element->stmt)
++	  && check_filling_reg (current_element)
++	  && record_innermost (innermost_inits, innermost_offsets,
++			       current_element))
++	{
++	  first_element = current_element;
++	  current_groups.safe_push (current_element);
++	  current_element->group_number = ++grp_num;
++	  if (i == bb_vinfo->grouped_stores.length () - 1)
++	    {
++	      check_and_clear_groups (current_groups, grp_num);
++	    }
++	  continue;
++	}
++      current_element->group_number = -1;
++    }
++  return grp_num;
++}
++
++/* Return a flag to transpose grouped stores before building slp tree.
++   Add bool may_transpose in class vec_info.  */
++
++static bool
++vect_may_transpose (bb_vec_info bb_vinfo)
++{
++  if (targetm.vectorize.vec_perm_const == NULL)
++    {
++      return false;
++    }
++
++  if (bb_vinfo->grouped_stores.length () < 2)
++    {
++      return false;
++    }
++
++  DUMP_VECT_SCOPE ("analyze if grouped stores may transpose to slp");
++  /* Sort grouped_stores according to size and type for function
++     vect_prepare_transpose ().  */
++  bb_vinfo->grouped_stores.qsort (grouped_store_cmp);
++
++  int groups = vect_prepare_transpose (bb_vinfo);
++  BB_VINFO_TRANS_GROUPS (bb_vinfo) = groups;
++  if (dump_enabled_p ())
++      dump_printf_loc (MSG_NOTE, vect_location,
++		       "%d groups to analyze transposed slp.\n", groups);
++  return groups != 0;
++}
++
++/* Get the base address of STMT_INFO.  */
++
++static tree
++get_op_base_address (stmt_vec_info stmt_info)
++{
++  struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
++  tree op = DR_BASE_ADDRESS (dr);
++  while (TREE_OPERAND_LENGTH (op) > 0)
++    {
++      op = TREE_OPERAND (op, 0);
++    }
++  return op;
++}
++
++/* Compare the UID of the two stmt_info STMTINFO_A and STMTINFO_B.
++   Sorting them in ascending order.  */
++
++static int
++dr_group_cmp (const void *stmtinfo_a_, const void *stmtinfo_b_)
++{
++  stmt_vec_info stmtinfo_a
++	= *(stmt_vec_info *) const_cast (stmtinfo_a_);
++  stmt_vec_info stmtinfo_b
++	= *(stmt_vec_info *) const_cast (stmtinfo_b_);
++
++  /* Stabilize sort.  */
++  if (stmtinfo_a == stmtinfo_b)
++    {
++      return 0;
++    }
++  return gimple_uid (stmtinfo_a->stmt) < gimple_uid (stmtinfo_b->stmt) ? -1 : 1;
++}
++
++/* Find the first elements of the grouped loads which are required to merge.  */
++
++static void
++vect_slp_grouped_load_find (bb_vec_info bb_vinfo, vec &visited,
++			    vec &res)
++{
++  unsigned int i = 0;
++  stmt_vec_info merge_first_element = NULL;
++  stmt_vec_info first_element = NULL;
++  tree opa = NULL;
++  unsigned int grp_size_a = 0;
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_loads, i, first_element)
++    {
++      if (visited[i])
++	{
++	  continue;
++	}
++      if (!STMT_VINFO_GROUPED_ACCESS (first_element)
++	  || !pow2p_hwi (DR_GROUP_SIZE (first_element)))
++	{
++	  /* Non-conforming grouped load should be grouped separately.  */
++	  if (merge_first_element == NULL)
++	    {
++	      visited[i] = true;
++	      res.safe_push (first_element);
++	      return;
++	    }
++	}
++      if (merge_first_element == NULL)
++	{
++	  merge_first_element = first_element;
++	  opa = get_op_base_address (first_element);
++	  grp_size_a = DR_GROUP_SIZE (first_element);
++	  res.safe_push (first_element);
++	  visited[i] = true;
++	  continue;
++	}
++
++      /* If the two first elements are of the same base address and group size,
++	 these two grouped loads need to be merged.  */
++      tree opb = get_op_base_address (first_element);
++      unsigned int grp_size_b = DR_GROUP_SIZE (first_element);
++      if (opa == opb && grp_size_a == grp_size_b)
++	{
++	  res.safe_push (first_element);
++	  visited[i] = true;
++	}
++    }
++}
++
++/* Merge the grouped loads that are found from
++   vect_slp_grouped_load_find ().  */
++
++static stmt_vec_info
++vect_slp_grouped_load_merge (vec &res)
++{
++  stmt_vec_info stmt_info = res[0];
++  if (res.length () == 1)
++    {
++      return stmt_info;
++    }
++  unsigned int i = 0;
++  unsigned int size = DR_GROUP_SIZE (res[0]);
++  unsigned int new_group_size = size * res.length ();
++  stmt_vec_info first_element = NULL;
++  stmt_vec_info merge_first_element = NULL;
++  stmt_vec_info last_element = NULL;
++  FOR_EACH_VEC_ELT (res, i, first_element)
++    {
++      if (merge_first_element == NULL)
++	{
++	  merge_first_element = first_element;
++	  last_element = merge_first_element;
++	  size = DR_GROUP_SIZE (merge_first_element);
++	}
++
++      if (last_element != first_element
++	  && !DR_GROUP_NEXT_ELEMENT (last_element))
++	{
++	  DR_GROUP_NEXT_ELEMENT (last_element) = first_element;
++	  /* Store the gap from the previous member of the group.  If there is
++	     no gap in the access, DR_GROUP_GAP is always 1.  */
++	  DR_GROUP_GAP_TRANS (first_element) = DR_GROUP_GAP (first_element);
++	  DR_GROUP_GAP (first_element) = 1;
++	}
++      for (stmt_info = first_element; stmt_info;
++	   stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info))
++	{
++	  DR_GROUP_FIRST_ELEMENT (stmt_info) = merge_first_element;
++	  DR_GROUP_SIZE_TRANS (stmt_info) = DR_GROUP_SIZE (stmt_info);
++	  DR_GROUP_SIZE (stmt_info) = new_group_size;
++	  last_element = stmt_info;
++	}
++    }
++  DR_GROUP_SIZE (merge_first_element) = new_group_size;
++  DR_GROUP_SLP_TRANSPOSE (merge_first_element) = true;
++  DR_GROUP_NEXT_ELEMENT (last_element) = NULL;
++  return merge_first_element;
++}
++
++/* Merge the grouped loads which have the same base address and group size.
++   For example, for grouped loads (opa_1, opa_2, opb_1, opb_2):
++     opa_1: a0->a1->a2->a3
++     opa_2: a8->a9->a10->a11
++     opb_1: b0->b1
++     opb_2: b16->b17
++   we can probably get two merged grouped loads:
++     opa: a0->a1->a2->a3->a8->a9->a10->a11
++     opb: b0->b1->b16->b17.  */
++
++static bool
++vect_merge_slp_grouped_loads (bb_vec_info bb_vinfo)
++{
++  if (bb_vinfo->grouped_loads.length () <= 0)
++    {
++      if (dump_enabled_p ())
++	{
++	  dump_printf_loc (MSG_NOTE, vect_location,
++			   "The number of grouped loads is 0.\n");
++	}
++      return false;
++    }
++  bb_vinfo->grouped_loads.qsort (dr_group_cmp);
++  auto_vec visited (bb_vinfo->grouped_loads.length ());
++  auto_vec grouped_loads_merge;
++  for (unsigned int i = 0; i < bb_vinfo->grouped_loads.length (); i++)
++    {
++      visited.safe_push (false);
++    }
++  while (1)
++    {
++      /* Find grouped loads which are required to merge.  */
++      auto_vec res;
++      vect_slp_grouped_load_find (bb_vinfo, visited, res);
++      if (res.is_empty ())
++	{
++	  break;
++	}
++      /* Merge the required grouped loads into one group.  */
++      grouped_loads_merge.safe_push (vect_slp_grouped_load_merge (res));
++    }
++  if (grouped_loads_merge.length () == bb_vinfo->grouped_loads.length ())
++    {
++      if (dump_enabled_p ())
++	{
++	  dump_printf_loc (MSG_NOTE, vect_location,
++			   "No grouped loads need to be merged.\n");
++	}
++      return false;
++    }
++  if (dump_enabled_p ())
++    {
++      dump_printf_loc (MSG_NOTE, vect_location,
++		       "Merging grouped loads successfully.\n");
++    }
++  BB_VINFO_GROUPED_LOADS (bb_vinfo).release ();
++  for (unsigned int i = 0; i < grouped_loads_merge.length (); i++)
++    {
++      BB_VINFO_GROUPED_LOADS (bb_vinfo).safe_push (grouped_loads_merge[i]);
++    }
++  return true;
++}
++
++/* Find the first elements of the grouped stores
++   which are required to transpose and merge.  */
++
++static void
++vect_slp_grouped_store_find (bb_vec_info bb_vinfo, vec &visited,
++			     vec &res)
++{
++  stmt_vec_info first_element = NULL;
++  stmt_vec_info merge_first_element = NULL;
++  unsigned int k = 0;
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_stores, k, first_element)
++    {
++      if (visited[k])
++	{
++	  continue;
++	}
++      /* Non-conforming grouped store should be grouped separately.  */
++      if (!STMT_VINFO_GROUPED_ACCESS (first_element)
++	  || first_element->group_number == -1)
++	{
++	  if (merge_first_element == NULL)
++	    {
++	      visited[k] = true;
++	      res.safe_push (first_element);
++	      return;
++	    }
++	}
++      if (first_element->group_number != -1
++	  && merge_first_element == NULL)
++	{
++	  merge_first_element = first_element;
++	}
++      if (merge_first_element->group_number == first_element->group_number)
++	{
++	  visited[k] = true;
++	  res.safe_push (first_element);
++	}
++    }
++}
++
++/* Transpose and merge the grouped stores that are found from
++   vect_slp_grouped_store_find ().  */
++
++static stmt_vec_info
++vect_slp_grouped_store_transform (vec &res)
++{
++  stmt_vec_info stmt_info = res[0];
++  if (res.length () == 1)
++    {
++      return stmt_info;
++    }
++  stmt_vec_info rearrange_first_element = stmt_info;
++  stmt_vec_info last_element = rearrange_first_element;
++
++  unsigned int size = DR_GROUP_SIZE (rearrange_first_element);
++  unsigned int new_group_size = size * res.length ();
++  for (unsigned int i = 1; i < res.length (); i++)
++    {
++      /* Store the gap from the previous member of the group.  If there is no
++	 gap in the access, DR_GROUP_GAP is always 1.  */
++      DR_GROUP_GAP_TRANS (res[i]) = DR_GROUP_GAP (res[i]);
++      DR_GROUP_GAP (res[i]) = 1;
++    }
++  while (!res.is_empty ())
++    {
++      stmt_info = res[0];
++      res.ordered_remove (0);
++      if (DR_GROUP_NEXT_ELEMENT (stmt_info))
++	{
++	  res.safe_push (DR_GROUP_NEXT_ELEMENT (stmt_info));
++	}
++      DR_GROUP_FIRST_ELEMENT (stmt_info) = rearrange_first_element;
++      DR_GROUP_NEXT_ELEMENT (last_element) = stmt_info;
++      DR_GROUP_SIZE_TRANS (stmt_info) = DR_GROUP_SIZE (stmt_info);
++      DR_GROUP_SIZE (stmt_info) = new_group_size;
++      last_element = stmt_info;
++    }
++
++  DR_GROUP_SIZE (rearrange_first_element) = new_group_size;
++  DR_GROUP_SLP_TRANSPOSE (rearrange_first_element) = true;
++  DR_GROUP_NEXT_ELEMENT (last_element) = NULL;
++  return rearrange_first_element;
++}
++
++/* Save the STMT_INFO in the grouped stores to BB_VINFO_SCALAR_STORES for
++   transposing back grouped stores.  */
++
++static void
++get_scalar_stores (bb_vec_info bb_vinfo)
++{
++  unsigned int k = 0;
++  stmt_vec_info first_element = NULL;
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_stores, k, first_element)
++    {
++      /* Filter the grouped store which is unnecessary for transposing.  */
++      if (!STMT_VINFO_GROUPED_ACCESS (first_element)
++	  || first_element->group_number == -1)
++	{
++	  continue;
++	}
++      vec tmp_scalar_store;
++      tmp_scalar_store.create (DR_GROUP_SIZE (first_element));
++      for (stmt_vec_info stmt_info = first_element; stmt_info;
++	   stmt_info = DR_GROUP_NEXT_ELEMENT (stmt_info))
++	{
++	  tmp_scalar_store.safe_push (stmt_info);
++	}
++      BB_VINFO_SCALAR_STORES (bb_vinfo).safe_push (tmp_scalar_store);
++    }
++}
++
++/* Transpose and merge the grouped stores which have the same group number.
++   For example, for grouped stores (opa_0, opa_1, opa_2, opa_3):
++     opa_0: a00->a01->a02->a03
++     opa_1: a10->a11->a12->a13
++     opa_2: a20->a21->a22->a23
++     opa_2: a30->a31->a32->a33
++   we can probably get the merged grouped store:
++     opa: a00->a10->a20->a30
++	->a01->a11->a21->a31
++	->a02->a12->a22->a32
++	->a03->a13->a23->a33.  */
++
++static bool
++vect_transform_slp_grouped_stores (bb_vec_info bb_vinfo)
++{
++  if (bb_vinfo->grouped_stores.length () <= 0)
++    {
++      if (dump_enabled_p ())
++	{
++	  dump_printf_loc (MSG_NOTE, vect_location,
++			   "The number of grouped stores is 0.\n");
++	}
++      return false;
++    }
++
++  bb_vinfo->grouped_stores.qsort (dr_group_cmp);
++  auto_vec grouped_stores_merge;
++  auto_vec visited (bb_vinfo->grouped_stores.length ());
++  unsigned int i = 0;
++  for (i = 0; i < bb_vinfo->grouped_stores.length (); i++)
++    {
++      visited.safe_push (false);
++    }
++
++  /* Get scalar stores for the following transposition recovery.  */
++  get_scalar_stores (bb_vinfo);
++
++  while (1)
++    {
++      /* Find grouped stores which are required to transpose and merge.  */
++      auto_vec res;
++      vect_slp_grouped_store_find (bb_vinfo, visited, res);
++      if (res.is_empty ())
++	{
++	  break;
++	}
++      /* Transpose and merge the required grouped stores into one group.  */
++      grouped_stores_merge.safe_push (vect_slp_grouped_store_transform (res));
++    }
++
++  BB_VINFO_GROUPED_STORES (bb_vinfo).release ();
++  for (i = 0; i < grouped_stores_merge.length (); i++)
++    {
++      BB_VINFO_GROUPED_STORES (bb_vinfo).safe_push (grouped_stores_merge[i]);
++    }
++
++  if (dump_enabled_p ())
++    {
++      dump_printf_loc (MSG_NOTE, vect_location,
++		       "Transposing grouped stores successfully.\n");
++    }
++  return true;
++}
++
++/* A helpful function of vect_transform_back_slp_grouped_stores ().  */
++
++static auto_vec
++vect_transform_back_slp_grouped_store (bb_vec_info bb_vinfo,
++				       stmt_vec_info first_stmt_info)
++{
++  auto_vec grouped_stores_split;
++  for (unsigned int i = 0; i < bb_vinfo->scalar_stores.length (); i++)
++    {
++      vec scalar_tmp = bb_vinfo->scalar_stores[i];
++      if (scalar_tmp.length () > 1
++	  && scalar_tmp[0]->group_number != first_stmt_info->group_number)
++	{
++	  continue;
++	}
++      stmt_vec_info cur_stmt_info = NULL;
++      stmt_vec_info cur_first_stmt_info = NULL;
++      stmt_vec_info last_stmt_info = NULL;
++      unsigned int k = 0;
++      FOR_EACH_VEC_ELT (scalar_tmp, k, cur_stmt_info)
++	{
++	  if (k == 0)
++	    {
++	      cur_first_stmt_info = cur_stmt_info;
++	      last_stmt_info = cur_stmt_info;
++	    }
++	  DR_GROUP_FIRST_ELEMENT (cur_stmt_info) = cur_first_stmt_info;
++	  DR_GROUP_NEXT_ELEMENT (last_stmt_info) = cur_stmt_info;
++	  last_stmt_info = cur_stmt_info;
++	}
++      DR_GROUP_SIZE (cur_first_stmt_info) = k;
++      DR_GROUP_NEXT_ELEMENT (last_stmt_info) = NULL;
++      if (first_stmt_info != cur_first_stmt_info)
++	{
++	  DR_GROUP_GAP (cur_first_stmt_info)
++		= DR_GROUP_GAP_TRANS (cur_first_stmt_info);
++	  DR_GROUP_SLP_TRANSPOSE (cur_first_stmt_info) = false;
++	  DR_GROUP_NUMBER (cur_first_stmt_info) = -1;
++	}
++      grouped_stores_split.safe_push (cur_first_stmt_info);
++    }
++  return grouped_stores_split;
++}
++
++/* Transform the grouped store back.  */
++
++void
++vect_transform_back_slp_grouped_stores (bb_vec_info bb_vinfo,
++					stmt_vec_info first_stmt_info)
++{
++  if (first_stmt_info->group_number == -1)
++    {
++      return;
++    }
++  /* Transform back.  */
++  auto_vec grouped_stores_split
++	= vect_transform_back_slp_grouped_store (bb_vinfo, first_stmt_info);
++
++  /* Add the remaining grouped stores to grouped_stores_split.  */
++  stmt_vec_info first_element = NULL;
++  unsigned int i = 0;
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_stores, i, first_element)
++    {
++      if (first_element->group_number != first_stmt_info->group_number)
++	{
++	  grouped_stores_split.safe_push (first_element);
++	}
++    }
++  DR_GROUP_SLP_TRANSPOSE (first_stmt_info) = false;
++  DR_GROUP_NUMBER (first_stmt_info) = -1;
++  BB_VINFO_GROUPED_STORES (bb_vinfo).release ();
++  for (i = 0; i < grouped_stores_split.length (); i++)
++    {
++      BB_VINFO_GROUPED_STORES (bb_vinfo).safe_push (grouped_stores_split[i]);
++    }
++}
++
++/* Function check_for_slp_vectype
++
++   Restriction for grouped stores by checking their vectype.
++   If the vectype of the grouped store is changed, it need transform back.
++   If all grouped stores need to be transformed back, return FALSE.  */
++
++static bool
++check_for_slp_vectype (bb_vec_info bb_vinfo)
++{
++  if (dump_file)
++    fprintf (dump_file, "check_for_slp_vectype: enter\n");
++  stmt_vec_info first_element = NULL;
++  unsigned int i = 0;
++  int count = 0;
++  auto_vec grouped_stores_check;
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_stores, i, first_element)
++    {
++      grouped_stores_check.safe_push (first_element);
++    }
++  FOR_EACH_VEC_ELT (grouped_stores_check, i, first_element)
++    {
++      if (STMT_VINFO_GROUPED_ACCESS (first_element)
++	  && first_element->group_number != -1)
++	{
++	  unsigned int group_size_b
++			= DR_GROUP_SIZE_TRANS (first_element);
++	  tree vectype = STMT_VINFO_VECTYPE (first_element);
++	  gimple *stmt = STMT_VINFO_STMT (first_element);
++	  tree lhs = gimple_get_lhs (stmt);
++	  tree type = TREE_TYPE (lhs);
++#if 0
++	  if (!vectype && !type)
++	    {
++	      if (dump_file)
++		fprintf (dump_file, "check_for_slp_vectype: no vectype/stmt type\n");
++	      continue;
++	    }
++
++	  if (!vectype)
++	    vectype = type;
++#endif
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "check_for_slp_vectype: %p\n", first_element);
++	      print_gimple_stmt (dump_file, stmt, 0);
++	      fprintf (dump_file, "check_for_slp_vectype: vectype=");
++	      if (vectype)
++		print_generic_expr (dump_file, vectype);
++	      fprintf (dump_file, "\n");
++	    }
++#if 0
++	  if (!vectype || !VECTOR_TYPE_P (vectype))
++	    continue;
++#endif
++	  poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
++	  if (nunits.to_constant () > group_size_b)
++	    {
++	      count++;
++	      /* If the vectype is changed, this grouped store need
++		 to be transformed back.  */
++	      vect_transform_back_slp_grouped_stores (bb_vinfo, first_element);
++	      if (dump_enabled_p ())
++		{
++		  dump_printf_loc (MSG_NOTE, vect_location,
++				   "No supported: only supported for"
++				   " group_size geq than nunits.\n");
++		}
++	    }
++	}
++    }
++  if (count == BB_VINFO_TRANS_GROUPS (bb_vinfo))
++    {
++      return false;
++    }
++  if (dump_file)
++    fprintf (dump_file, "check_for_slp_vectype: True\n");
++  return true;
++}
++
++/* Function check_for_dr_alignment
++
++   Check the alignment of the slp instance loads.
++   Return FALSE if a load cannot be vectorized.  */
++
++static bool
++check_for_dr_alignment (bb_vec_info bb_vinfo, slp_instance instance)
++{
++  slp_tree node = NULL;
++  unsigned int i = 0;
++  FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), i, node)
++    {
++      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 (dump_file)
++	{
++	  fprintf (dump_file, "check_for_dr_alignment: %p\n", first_stmt_info);
++
++	  gimple *stmt = STMT_VINFO_STMT (first_stmt_info);
++	  tree lhs = gimple_get_lhs (stmt);
++	  tree type = TREE_TYPE (lhs);
++	  print_gimple_stmt (dump_file, stmt, 0);
++	}
++
++      tree vectype = STMT_VINFO_VECTYPE (first_stmt_info);
++      int malign = dr_misalignment (first_dr_info, vectype);
++      enum dr_alignment_support supportable_dr_alignment
++	= vect_supportable_dr_alignment (bb_vinfo, first_dr_info,
++					 vectype, malign);
++      if (supportable_dr_alignment == dr_explicit_realign_optimized
++	  || supportable_dr_alignment == dr_explicit_realign)
++	{
++	  return false;
+ 	}
+     }
+-  else if (kind == slp_inst_kind_reduc_chain)
++  return true;
++}
++
++/* Initialize slp_transpose flag before transposing.  */
++
++static void
++init_stmt_info_slp_transpose (bb_vec_info bb_vinfo)
++{
++  stmt_vec_info first_element = NULL;
++  unsigned int k = 0;
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_stores, k, first_element)
+     {
+-      /* Collect the reduction stmts and store them in scalar_stmts.  */
+-      scalar_stmts.create (REDUC_GROUP_SIZE (stmt_info));
+-      while (next_info)
++      if (STMT_VINFO_GROUPED_ACCESS (first_element))
+ 	{
+-	  scalar_stmts.quick_push (vect_stmt_to_vectorize (next_info));
+-	  next_info = REDUC_GROUP_NEXT_ELEMENT (next_info);
++	  DR_GROUP_SLP_TRANSPOSE (first_element) = false;
+ 	}
+-      /* Mark the first element of the reduction chain as reduction to properly
+-	 transform the node.  In the reduction analysis phase only the last
+-	 element of the chain is marked as reduction.  */
+-      STMT_VINFO_DEF_TYPE (stmt_info)
+-	= STMT_VINFO_DEF_TYPE (scalar_stmts.last ());
+-      STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))
+-	= STMT_VINFO_REDUC_DEF (vect_orig_stmt (scalar_stmts.last ()));
+     }
+-  else if (kind == slp_inst_kind_ctor)
++  FOR_EACH_VEC_ELT (bb_vinfo->grouped_loads, k, first_element)
+     {
+-      tree rhs = gimple_assign_rhs1 (stmt_info->stmt);
+-      tree val;
+-      scalar_stmts.create (CONSTRUCTOR_NELTS (rhs));
+-      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
++      if (STMT_VINFO_GROUPED_ACCESS (first_element))
+ 	{
+-	  stmt_vec_info def_info = vinfo->lookup_def (val);
+-	  def_info = vect_stmt_to_vectorize (def_info);
+-	  scalar_stmts.quick_push (def_info);
++	  DR_GROUP_SLP_TRANSPOSE (first_element) = false;
+ 	}
+-      if (dump_enabled_p ())
+-	dump_printf_loc (MSG_NOTE, vect_location,
+-			 "Analyzing vectorizable constructor: %G\n",
+-			 stmt_info->stmt);
+     }
+-  else if (kind == slp_inst_kind_reduc_group)
++}
++
++/* Analyze and transpose the stmts before building the SLP tree.  */
++
++static bool
++vect_analyze_transpose (bb_vec_info bb_vinfo)
++{
++  DUMP_VECT_SCOPE ("vect_analyze_transpose");
++
++  if (!vect_may_transpose (bb_vinfo))
+     {
+-      /* Collect reduction statements.  */
+-      const vec &reductions
+-	= as_a  (vinfo)->reductions;
+-      scalar_stmts.create (reductions.length ());
+-      for (i = 0; reductions.iterate (i, &next_info); i++)
+-	if ((STMT_VINFO_RELEVANT_P (next_info)
+-	     || STMT_VINFO_LIVE_P (next_info))
+-	    /* ???  Make sure we didn't skip a conversion around a reduction
+-	       path.  In that case we'd have to reverse engineer that conversion
+-	       stmt following the chain using reduc_idx and from the PHI
+-	       using reduc_def.  */
+-	    && STMT_VINFO_DEF_TYPE (next_info) == vect_reduction_def)
+-	  scalar_stmts.quick_push (next_info);
+-      /* If less than two were relevant/live there's nothing to SLP.  */
+-      if (scalar_stmts.length () < 2)
+-	return false;
++      return false;
+     }
+-  else
+-    gcc_unreachable ();
+ 
+-  vec roots = vNULL;
+-  if (kind == slp_inst_kind_ctor)
++  /* For basic block SLP, try to merge the grouped stores and loads
++     into one group.  */
++  init_stmt_info_slp_transpose (bb_vinfo);
++  if (vect_transform_slp_grouped_stores (bb_vinfo)
++      && vect_merge_slp_grouped_loads (bb_vinfo))
+     {
+-      roots.create (1);
+-      roots.quick_push (stmt_info);
++      if (dump_enabled_p ())
++	{
++	  dump_printf_loc (MSG_NOTE, vect_location,
++			   "Analysis succeeded with SLP transposed.\n");
++	}
++      return true;
+     }
+-  /* Build the tree for the SLP instance.  */
+-  bool res = vect_build_slp_instance (vinfo, kind, scalar_stmts,
+-				      roots,
+-				      max_tree_size, limit, bst_map,
+-				      kind == slp_inst_kind_store
+-				      ? stmt_info : NULL);
+-  if (!res)
+-    roots.release ();
+-
+-  /* ???  If this is slp_inst_kind_store and the above succeeded here's
+-     where we should do store group splitting.  */
+-
+-  return res;
++  if (dump_enabled_p ())
++    {
++      dump_printf_loc (MSG_NOTE, vect_location,
++		       "Analysis failed with SLP transposed.\n");
++    }
++  return false;
+ }
+ 
+ /* Check if there are stmts in the loop can be vectorized using SLP.  Build SLP
+@@ -4963,7 +5932,7 @@ vect_slp_analyze_operations (vec_info *vinfo)
+ 	  /* Check we can vectorize the reduction.  */
+ 	  || (SLP_INSTANCE_KIND (instance) == slp_inst_kind_bb_reduc
+ 	      && !vectorizable_bb_reduc_epilogue (instance, &cost_vec)))
+-        {
++	{
+ 	  slp_tree node = SLP_INSTANCE_TREE (instance);
+ 	  stmt_vec_info stmt_info;
+ 	  if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ())
+@@ -4975,7 +5944,7 @@ vect_slp_analyze_operations (vec_info *vinfo)
+ 			     "removing SLP instance operations starting from: %G",
+ 			     stmt_info->stmt);
+ 	  vect_free_slp_instance (instance);
+-          vinfo->slp_instances.ordered_remove (i);
++	  vinfo->slp_instances.ordered_remove (i);
+ 	  cost_vec.release ();
+ 	  while (!visited_vec.is_empty ())
+ 	    visited.remove (visited_vec.pop ());
+@@ -5204,7 +6173,7 @@ vect_bb_slp_scalar_cost (vec_info *vinfo,
+       gimple *orig_stmt = orig_stmt_info->stmt;
+ 
+       /* If there is a non-vectorized use of the defs then the scalar
+-         stmt is kept live in which case we do not account it or any
++	 stmt is kept live in which case we do not account it or any
+ 	 required defs in the SLP children in the scalar cost.  This
+ 	 way we make the vectorization more costly when compared to
+ 	 the scalar cost.  */
+@@ -5481,7 +6450,11 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo,
+ 
+       vec_outside_cost = vec_prologue_cost + vec_epilogue_cost;
+ 
+-      if (dump_enabled_p ())
++      BB_VINFO_VEC_INSIDE_COST (bb_vinfo) = vec_inside_cost;
++      BB_VINFO_VEC_OUTSIDE_COST (bb_vinfo) = vec_outside_cost;
++      BB_VINFO_SCALAR_COST (bb_vinfo) = scalar_cost;
++
++      if (!unlimited_cost_model (NULL) && dump_enabled_p ())
+ 	{
+ 	  dump_printf_loc (MSG_NOTE, vect_location,
+ 			   "Cost model analysis for part in loop %d:\n", sl);
+@@ -5819,7 +6792,7 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+   if (!vect_analyze_data_refs (bb_vinfo, &min_vf, NULL))
+     {
+       if (dump_enabled_p ())
+-        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ 			 "not vectorized: unhandled data-ref in basic "
+ 			 "block.\n");
+       return false;
+@@ -5854,6 +6827,22 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+ 
+   vect_pattern_recog (bb_vinfo);
+ 
++  /* Transpose grouped stores and loads for better vectorizable version.  */
++  if (bb_vinfo->transposed)
++    {
++      if (!vect_analyze_transpose (bb_vinfo))
++	{
++	  if (dump_enabled_p ())
++	    {
++	       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++				"not vectorized: unhandled slp transposed in "
++				"basic block.\n");
++	    }
++	  return false;
++	}
++    }
++  bb_vinfo->before_slp = true;
++
+   /* Update store groups from pattern processing.  */
+   vect_fixup_store_groups_with_patterns (bb_vinfo);
+ 
+@@ -5872,6 +6861,20 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+       return false;
+     }
+ 
++  /* Check if the vectype is suitable for SLP transposed.  */
++  if (bb_vinfo->transposed && !check_for_slp_vectype (bb_vinfo))
++    {
++      if (dump_enabled_p ())
++	{
++	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++			   "Failed to SLP transposed in the basic block.\n");
++	  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++			   "not vectorized: vectype is not suitable for "
++			   "SLP transposed in basic block.\n");
++	}
++      return false;
++    }
++
+   /* Optimize permutations.  */
+   vect_optimize_slp (bb_vinfo);
+ 
+@@ -5914,6 +6917,27 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+   if (! BB_VINFO_SLP_INSTANCES (bb_vinfo).length ())
+     return false;
+ 
++  /* Check if the alignment is suitable for SLP transposed.  */
++  if (bb_vinfo->transposed)
++    {
++      for (i = 0; BB_VINFO_SLP_INSTANCES (bb_vinfo).iterate (i, &instance); i++)
++	{
++	  if (!check_for_dr_alignment (bb_vinfo, instance))
++	    {
++	      if (dump_enabled_p ())
++		{
++		  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++				   "Failed to SLP transposed in the basic "
++				   "block.\n");
++		  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++				   "not vectorized: alignment is not suitable "
++				   "for SLP transposed in basic block.\n");
++		}
++	      return false;
++	    }
++	}
++    }
++
+   if (!vect_slp_analyze_operations (bb_vinfo))
+     {
+       if (dump_enabled_p ())
+@@ -5923,7 +6947,88 @@ vect_slp_analyze_bb_1 (bb_vec_info bb_vinfo, int n_stmts, bool &fatal,
+     }
+ 
+   vect_bb_partition_graph (bb_vinfo);
++  return true;
++}
++
++static bool
++may_new_transpose_bbvinfo (bb_vec_info bb_vinfo_ori, bool res_ori,
++			   loop_p orig_loop)
++{
++  /* If the flag is false or the slp analysis is broken before
++     vect_analyze_slp, we don't try to analyze the transposed SLP version.  */
++  if (!flag_tree_slp_transpose_vectorize
++      || !BB_VINFO_BEFORE_SLP (bb_vinfo_ori))
++    {
++      return false;
++    }
++
++  /* If the original bb_vinfo can't be vectorized, try to new a bb_vinfo
++     of the transposed version.  */
++  if (!res_ori)
++    {
++      return true;
++    }
++
++  /* Caculate the cost of the original bb_vinfo.  */
++  if (unlimited_cost_model (NULL))
++    {
++      vec &instances = BB_VINFO_SLP_INSTANCES (bb_vinfo_ori);
++      vect_bb_vectorization_profitable_p (bb_vinfo_ori, instances, orig_loop);
++    }
++  /* If the vec cost and scalar cost are not much difference (here we set the
++     threshold to 4), we try to new a bb_vinfo of the transposed version.  */
++  if (BB_VINFO_SCALAR_COST (bb_vinfo_ori)
++      < 4 * (BB_VINFO_VEC_INSIDE_COST (bb_vinfo_ori)
++	     + BB_VINFO_VEC_OUTSIDE_COST (bb_vinfo_ori)))
++    {
++      return true;
++    }
++  return false;
++}
+ 
++static bool
++may_choose_transpose_bbvinfo (bb_vec_info bb_vinfo_trans, bool res_trans,
++			      bb_vec_info bb_vinfo_ori, bool res_ori,
++			      loop_p orig_loop)
++{
++  /* The original bb_vinfo is chosen if the transposed bb_vinfo
++     can't be vectorized.  */
++  if (!res_trans)
++    {
++      return false;
++    }
++  /* Caculate the cost of the transposed bb_vinfo.  */
++  if (unlimited_cost_model (NULL))
++    {
++      vec &instances = BB_VINFO_SLP_INSTANCES (bb_vinfo_trans);
++      vect_bb_vectorization_profitable_p (bb_vinfo_trans, instances,
++					  orig_loop);
++    }
++  int diff_bb_cost = -1;
++  int diff_bb_cost_trans = -1;
++  if (res_ori)
++    {
++      diff_bb_cost = BB_VINFO_SCALAR_COST (bb_vinfo_ori)
++		     - BB_VINFO_VEC_INSIDE_COST (bb_vinfo_ori)
++		     - BB_VINFO_VEC_OUTSIDE_COST (bb_vinfo_ori);
++    }
++  if (res_trans)
++    {
++      diff_bb_cost_trans = BB_VINFO_SCALAR_COST (bb_vinfo_trans)
++			   - BB_VINFO_VEC_INSIDE_COST (bb_vinfo_trans)
++			   - BB_VINFO_VEC_OUTSIDE_COST (bb_vinfo_trans);
++    }
++  /* The original bb_vinfo is chosen when one of the following conditions
++     is satisfied as follows:
++	1) The cost of original version is better transposed version.
++	2) The vec cost is similar to scalar cost in the transposed version.  */
++  if ((res_ori && res_trans && diff_bb_cost >= diff_bb_cost_trans)
++      || (res_trans && BB_VINFO_SCALAR_COST (bb_vinfo_trans)
++		       <= (BB_VINFO_VEC_INSIDE_COST (bb_vinfo_trans)
++			  + BB_VINFO_VEC_OUTSIDE_COST (bb_vinfo_trans))))
++    {
++      return false;
++    }
+   return true;
+ }
+ 
+@@ -5937,6 +7042,7 @@ vect_slp_region (vec bbs, vec datarefs,
+ 		 loop_p orig_loop)
+ {
+   bb_vec_info bb_vinfo;
++  bb_vec_info bb_vinfo_trans = NULL;
+   auto_vector_modes vector_modes;
+ 
+   /* Autodetect first vector size we try.  */
+@@ -5951,6 +7057,10 @@ vect_slp_region (vec bbs, vec datarefs,
+     {
+       bool vectorized = false;
+       bool fatal = false;
++      bool res_bb_vinfo_ori = false;
++      bool res_bb_vinfo_trans = false;
++
++      /* New a bb_vinfo of the original version.  */
+       bb_vinfo = new _bb_vec_info (bbs, &shared);
+ 
+       bool first_time_p = shared.datarefs.is_empty ();
+@@ -5960,8 +7070,113 @@ vect_slp_region (vec bbs, vec datarefs,
+       else
+ 	bb_vinfo->shared->check_datarefs ();
+       bb_vinfo->vector_mode = next_vector_mode;
++      bb_vinfo->transposed = false;
++      bb_vinfo->before_slp = false;
++
++      res_bb_vinfo_ori = vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal,
++						dataref_groups);
++      auto_vec profitable_subgraphs;
++      auto_vec profitable_subgraphs_trans;
++      for (slp_instance instance : BB_VINFO_SLP_INSTANCES (bb_vinfo))
++	{
++	  if (instance->subgraph_entries.is_empty ())
++	    continue;
++
++	    vect_location = instance->location ();
++	    if (!unlimited_cost_model (NULL)
++		&& !vect_bb_vectorization_profitable_p
++		      (bb_vinfo, instance->subgraph_entries, orig_loop))
++	      {
++		if (dump_enabled_p ())
++		  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++				   "not vectorized: vectorization is not "
++				   "profitable.\n");
++		  continue;
++	      }
++	    if (res_bb_vinfo_ori)
++	      {
++		if (!dbg_cnt (vect_slp))
++		  continue;
++		profitable_subgraphs.safe_push (instance);
++	      }
++	}
++
++      /* Analyze and new a transposed bb_vinfo.  */
++      if (may_new_transpose_bbvinfo (bb_vinfo, res_bb_vinfo_ori, orig_loop))
++	{
++	  bool fatal_trans = false;
++	  bb_vinfo_trans
++	    = new _bb_vec_info (bbs, &shared);
++	  bool first_time_p = shared.datarefs.is_empty ();
++	  BB_VINFO_DATAREFS (bb_vinfo_trans) = datarefs;
++	  if (first_time_p)
++	    {
++	      bb_vinfo_trans->shared->save_datarefs ();
++	    }
++	  else
++	    {
++	      bb_vinfo_trans->shared->check_datarefs ();
++	    }
++	  bb_vinfo_trans->vector_mode = next_vector_mode;
++	  bb_vinfo_trans->transposed = true;
++	  bb_vinfo_trans->before_slp = false;
++
++	  res_bb_vinfo_trans
++	    = vect_slp_analyze_bb_1 (bb_vinfo_trans, n_stmts, fatal_trans,
++				     dataref_groups);
++	  if (res_bb_vinfo_trans)
++	    {
++	      for (slp_instance instance : BB_VINFO_SLP_INSTANCES (bb_vinfo_trans))
++		{
++		  if (instance->subgraph_entries.is_empty ())
++		    continue;
++
++		  vect_location = instance->location ();
++		  if (!unlimited_cost_model (NULL)
++		      && !vect_bb_vectorization_profitable_p
++			(bb_vinfo_trans, instance->subgraph_entries, orig_loop))
++		    {
++		      if (dump_enabled_p ())
++			  dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
++					   "not vectorized: transpose vectorization is not "
++					   "profitable.\n");
++		      res_bb_vinfo_trans = false;
++		      continue;
++		     }
++		  if (res_bb_vinfo_trans)
++		    {
++		      if (!dbg_cnt (vect_slp))
++			continue;
++		      profitable_subgraphs_trans.safe_push (instance);
++		    }
++		}
++	    }
++	  if (may_choose_transpose_bbvinfo (bb_vinfo_trans,
++					    res_bb_vinfo_trans,
++					    bb_vinfo, res_bb_vinfo_ori,
++					    orig_loop))
++	    {
++	      bb_vinfo = bb_vinfo_trans;
++	      fatal = fatal_trans;
++	      if (dump_enabled_p ())
++		{
++		  dump_printf_loc (MSG_NOTE, vect_location,
++				   "Basic block part vectorized "
++				   "using transposed version.\n");
++		}
++	    }
++	  else
++	    {
++	      if (dump_enabled_p ())
++		{
++		  dump_printf_loc (MSG_NOTE, vect_location,
++				   "Basic block part vectorized "
++				   "\n");
++		}
++	    }
++	}
+ 
+-      if (vect_slp_analyze_bb_1 (bb_vinfo, n_stmts, fatal, dataref_groups))
++      if (res_bb_vinfo_ori || res_bb_vinfo_trans)
+ 	{
+ 	  if (dump_enabled_p ())
+ 	    {
+@@ -5972,90 +7187,129 @@ vect_slp_region (vec bbs, vec datarefs,
+ 	    }
+ 
+ 	  bb_vinfo->shared->check_datarefs ();
+-
+-	  auto_vec profitable_subgraphs;
+-	  for (slp_instance instance : BB_VINFO_SLP_INSTANCES (bb_vinfo))
++	  if (!res_bb_vinfo_trans)
+ 	    {
+-	      if (instance->subgraph_entries.is_empty ())
+-		continue;
+-
+-	      vect_location = instance->location ();
+-	      if (!unlimited_cost_model (NULL)
+-		  && !vect_bb_vectorization_profitable_p
+-			(bb_vinfo, instance->subgraph_entries, orig_loop))
++	      /* When we're vectorizing an if-converted loop body make sure
++		 we vectorized all if-converted code.  */
++	      if (!profitable_subgraphs.is_empty ()
++		  && orig_loop)
+ 		{
+-		  if (dump_enabled_p ())
+-		    dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+-				     "not vectorized: vectorization is not "
+-				     "profitable.\n");
+-		  continue;
++		  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_UNLIMITED)
++			continue;
++
++		      if (gassign *ass = dyn_cast  (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);
++			 }
++		    }
+ 		}
+ 
+-	      if (!dbg_cnt (vect_slp))
+-		continue;
++	      /* 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;
+ 
+-	      profitable_subgraphs.safe_push (instance);
+-	    }
++		  vect_schedule_slp (bb_vinfo, instance->subgraph_entries);
+ 
+-	  /* When we're vectorizing an if-converted loop body make sure
+-	     we vectorized all if-converted code.  */
+-	  if (!profitable_subgraphs.is_empty ()
+-	      && orig_loop)
++		  unsigned HOST_WIDE_INT bytes;
++		  if (dump_enabled_p ())
++		    {
++		      if (GET_MODE_SIZE
++			   (bb_vinfo->vector_mode).is_constant (&bytes))
++			 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
++					  "basic block part vectorized using %wu "
++					  "byte vectors\n", bytes);
++		      else
++			 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
++					  "basic block part vectorized using "
++					  "variable length vectors\n");
++		    }
++		}
++	    }
++	  else
+ 	    {
+-	      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))
++	      if (!profitable_subgraphs_trans.is_empty ()
++		  && orig_loop)
+ 		{
+-		  /* 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)))
++		  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))
+ 		    {
+-		      gimple_set_visited (gsi_stmt (gsi), false);
+-		      continue;
++		      /* 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_UNLIMITED)
++			 continue;
++
++		       if (gassign *ass = dyn_cast  (gsi_stmt (gsi)))
++			if (gimple_assign_rhs_code (ass) == COND_EXPR)
++			 {
++			   if (!profitable_subgraphs_trans.is_empty ()
++			       && dump_enabled_p ())
++			     dump_printf_loc (MSG_NOTE, vect_location,
++					      "not profitable because of "
++					      "unprofitable if-converted scalar "
++					      "code\n");
++			   profitable_subgraphs_trans.truncate (0);
++			 }
+ 		    }
+-		  if (flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED)
+-		    continue;
+-
+-		  if (gassign *ass = dyn_cast  (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;
++	      /* Finally schedule the profitable subgraphs.  */
++	      for (slp_instance instance : profitable_subgraphs_trans)
++		{
++		  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, instance->subgraph_entries);
++		  vect_schedule_slp (bb_vinfo, instance->subgraph_entries);
+ 
+-	      unsigned HOST_WIDE_INT bytes;
+-	      if (dump_enabled_p ())
+-		{
+-		  if (GET_MODE_SIZE
+-			(bb_vinfo->vector_mode).is_constant (&bytes))
+-		    dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
+-				     "basic block part vectorized using %wu "
+-				     "byte vectors\n", bytes);
+-		  else
+-		    dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
+-				     "basic block part vectorized using "
+-				     "variable length vectors\n");
++		  unsigned HOST_WIDE_INT bytes;
++		  if (dump_enabled_p ())
++		    {
++		      if (GET_MODE_SIZE
++			   (bb_vinfo->vector_mode).is_constant (&bytes))
++			 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
++					  "basic block part vectorized using %wu "
++					  "byte vectors\n", bytes);
++		      else
++			 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, vect_location,
++					  "basic block part vectorized using "
++					  "variable length vectors\n");
++		    }
+ 		}
+ 	    }
++
+ 	}
+       else
+ 	{
+@@ -6081,6 +7335,10 @@ vect_slp_region (vec bbs, vec datarefs,
+ 	  }
+ 
+       delete bb_vinfo;
++      if (bb_vinfo_trans)
++	{
++	  bb_vinfo_trans = NULL;
++	}
+ 
+       if (mode_i < vector_modes.length ()
+ 	  && VECTOR_MODE_P (autodetected_vector_mode)
+@@ -7244,10 +8502,17 @@ vect_schedule_slp_node (vec_info *vinfo,
+ 	 ready early, vectorized stores go before the last scalar
+ 	 stmt which is where all uses are ready.  */
+       stmt_vec_info last_stmt_info = NULL;
+-      if (DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
+-	last_stmt_info = vect_find_first_scalar_stmt_in_slp (node);
+-      else /* DR_IS_WRITE */
+-	last_stmt_info = vect_find_last_scalar_stmt_in_slp (node);
++
++      if (DR_GROUP_FIRST_ELEMENT (stmt_info)
++	  && DR_GROUP_SLP_TRANSPOSE (DR_GROUP_FIRST_ELEMENT (stmt_info)))
++	 last_stmt_info = vect_find_last_scalar_stmt_in_slp (node);
++      else
++	{
++	   if (DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
++		last_stmt_info = vect_find_first_scalar_stmt_in_slp (node);
++	   else /* DR_IS_WRITE */
++		last_stmt_info = vect_find_last_scalar_stmt_in_slp (node);
++	}
+       si = gsi_for_stmt (last_stmt_info->stmt);
+     }
+   else if ((STMT_VINFO_TYPE (stmt_info) == cycle_phi_info_type
+diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
+index 349200411..3099f6743 100644
+--- a/gcc/tree-vect-stmts.cc
++++ b/gcc/tree-vect-stmts.cc
+@@ -1369,10 +1369,10 @@ vect_get_load_cost (vec_info *, stmt_vec_info stmt_info, int ncopies,
+ 
+ static void
+ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
+-		    gimple_stmt_iterator *gsi)
++		    gimple_stmt_iterator *gsi, bool transpose=false)
+ {
+   if (gsi)
+-    vect_finish_stmt_generation (vinfo, stmt_vinfo, new_stmt, gsi);
++    vect_finish_stmt_generation (vinfo, stmt_vinfo, new_stmt, gsi, transpose);
+   else
+     vinfo->insert_on_entry (stmt_vinfo, new_stmt);
+ 
+@@ -1393,7 +1393,7 @@ vect_init_vector_1 (vec_info *vinfo, stmt_vec_info stmt_vinfo, gimple *new_stmt,
+ 
+ tree
+ vect_init_vector (vec_info *vinfo, stmt_vec_info stmt_info, tree val, tree type,
+-		  gimple_stmt_iterator *gsi)
++		  gimple_stmt_iterator *gsi, bool transpose)
+ {
+   gimple *init_stmt;
+   tree new_temp;
+@@ -1418,7 +1418,7 @@ vect_init_vector (vec_info *vinfo, stmt_vec_info stmt_info, tree val, tree type,
+ 		  new_temp = make_ssa_name (TREE_TYPE (type));
+ 		  init_stmt = gimple_build_assign (new_temp, COND_EXPR,
+ 						   val, true_val, false_val);
+-		  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi);
++		  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi, transpose);
+ 		  val = new_temp;
+ 		}
+ 	    }
+@@ -1437,7 +1437,7 @@ vect_init_vector (vec_info *vinfo, stmt_vec_info stmt_info, tree val, tree type,
+ 		{
+ 		  init_stmt = gsi_stmt (gsi2);
+ 		  gsi_remove (&gsi2, false);
+-		  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi);
++		  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi, transpose);
+ 		}
+ 	    }
+ 	}
+@@ -1446,7 +1446,7 @@ vect_init_vector (vec_info *vinfo, stmt_vec_info stmt_info, tree val, tree type,
+ 
+   new_temp = vect_get_new_ssa_name (type, vect_simple_var, "cst_");
+   init_stmt = gimple_build_assign (new_temp, val);
+-  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi);
++  vect_init_vector_1 (vinfo, stmt_info, init_stmt, gsi, transpose);
+   return new_temp;
+ }
+ 
+@@ -1572,9 +1572,11 @@ vect_get_vec_defs (vec_info *vinfo, stmt_vec_info stmt_info, slp_tree slp_node,
+    statement and create and return a stmt_vec_info for it.  */
+ 
+ static void
+-vect_finish_stmt_generation_1 (vec_info *,
+-			       stmt_vec_info stmt_info, gimple *vec_stmt)
++vect_finish_stmt_generation_1 (vec_info *vinfo,
++			       stmt_vec_info stmt_info, gimple *vec_stmt, bool transpose=false)
+ {
++  if (transpose)
++    stmt_vec_info vec_stmt_info = vinfo->add_pattern_stmt (vec_stmt, NULL);
+   if (dump_enabled_p ())
+     dump_printf_loc (MSG_NOTE, vect_location, "add new stmt: %G", vec_stmt);
+ 
+@@ -1616,7 +1618,7 @@ vect_finish_replace_stmt (vec_info *vinfo,
+ void
+ vect_finish_stmt_generation (vec_info *vinfo,
+ 			     stmt_vec_info stmt_info, gimple *vec_stmt,
+-			     gimple_stmt_iterator *gsi)
++			     gimple_stmt_iterator *gsi, bool transpose)
+ {
+   gcc_assert (!stmt_info || gimple_code (stmt_info->stmt) != GIMPLE_LABEL);
+ 
+@@ -1648,7 +1650,7 @@ vect_finish_stmt_generation (vec_info *vinfo,
+ 	}
+     }
+   gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
+-  vect_finish_stmt_generation_1 (vinfo, stmt_info, vec_stmt);
++  vect_finish_stmt_generation_1 (vinfo, stmt_info, vec_stmt, transpose);
+ }
+ 
+ /* We want to vectorize a call to combined function CFN with function
+@@ -2159,6 +2161,173 @@ vector_vector_composition_type (tree vtype, poly_uint64 nelts, tree *ptype)
+   return NULL_TREE;
+ }
+ 
++/* Check succeedor BB, BB without load is regarded as empty BB.  Ignore empty
++   BB in DFS.  */
++
++static unsigned
++mem_refs_in_bb (basic_block bb, vec &stmts)
++{
++  unsigned num = 0;
++  for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
++       !gsi_end_p (gsi); gsi_next (&gsi))
++    {
++      gimple *stmt = gsi_stmt (gsi);
++      if (is_gimple_debug (stmt))
++	continue;
++      if (is_gimple_assign (stmt) && gimple_has_mem_ops (stmt)
++	  && !gimple_has_volatile_ops (stmt))
++	{
++	  if (gimple_assign_rhs_code (stmt) == MEM_REF
++	      || gimple_assign_rhs_code (stmt) == ARRAY_REF)
++	    {
++	      stmts.safe_push (stmt);
++	      num++;
++	    }
++	  else if (TREE_CODE (gimple_get_lhs (stmt)) == MEM_REF
++		   || TREE_CODE (gimple_get_lhs (stmt)) == ARRAY_REF)
++	    num++;
++	}
++    }
++  return num;
++}
++
++static bool
++check_same_base (vec *datarefs, data_reference_p dr)
++{
++  for (unsigned ui = 0; ui < datarefs->length (); ui++)
++    {
++      tree op1 = TREE_OPERAND (DR_BASE_OBJECT (dr), 0);
++      tree op2 = TREE_OPERAND (DR_BASE_OBJECT ((*datarefs)[ui]), 0);
++      if (TREE_CODE (op1) != TREE_CODE (op2))
++	continue;
++      if (TREE_CODE (op1) == ADDR_EXPR)
++	{
++	  op1 = TREE_OPERAND (op1, 0);
++	  op2 = TREE_OPERAND (op2, 0);
++	}
++      enum tree_code code = TREE_CODE (op1);
++      switch (code)
++	{
++	case VAR_DECL:
++	  if (DECL_NAME (op1) == DECL_NAME (op2)
++	      && DR_IS_READ ((*datarefs)[ui]))
++	    return true;
++	  break;
++	case SSA_NAME:
++	  if (SSA_NAME_VERSION (op1) == SSA_NAME_VERSION (op2)
++	      && DR_IS_READ ((*datarefs)[ui]))
++	    return true;
++	  break;
++	default:
++	  break;
++	}
++    }
++  return false;
++}
++
++/* Iterate all load STMTS, if staisfying same base vectorized stmt, then return,
++   Otherwise, set false to SUCCESS.  */
++
++static void
++check_vec_use (loop_vec_info loop_vinfo, vec &stmts,
++	       stmt_vec_info stmt_info, bool &success)
++{
++  if (stmt_info == NULL)
++    {
++      success = false;
++      return;
++    }
++  if (DR_IS_READ (stmt_info->dr_aux.dr))
++    {
++      success = false;
++      return;
++    }
++  unsigned ui = 0;
++  gimple *candidate = NULL;
++  FOR_EACH_VEC_ELT (stmts, ui, candidate)
++    {
++      if (TREE_CODE (TREE_TYPE (gimple_get_lhs (candidate))) != VECTOR_TYPE)
++	continue;
++
++      if (candidate->bb != candidate->bb->loop_father->header)
++	{
++	  success = false;
++	  return;
++	}
++      auto_vec datarefs;
++      tree res = find_data_references_in_bb (candidate->bb->loop_father,
++					     candidate->bb, &datarefs);
++      if (res == chrec_dont_know)
++	{
++	  success = false;
++	  return;
++	}
++      if (check_same_base (&datarefs, stmt_info->dr_aux.dr))
++	return;
++    }
++  success = false;
++}
++
++/* Deep first search from present BB.  If succeedor has load STMTS,
++   stop further searching.  */
++
++static void
++dfs_check_bb (loop_vec_info loop_vinfo, basic_block bb, stmt_vec_info stmt_info,
++	      bool &success, vec &visited_bbs)
++{
++  if (bb == cfun->cfg->x_exit_block_ptr)
++    {
++      success = false;
++      return;
++    }
++  if (!success || visited_bbs.contains (bb) || bb == loop_vinfo->loop->latch)
++    return;
++
++  visited_bbs.safe_push (bb);
++  auto_vec stmts;
++  unsigned num = mem_refs_in_bb (bb, stmts);
++  /* Empty BB.  */
++  if (num == 0)
++    {
++      edge e;
++      edge_iterator ei;
++      FOR_EACH_EDGE (e, ei, bb->succs)
++	{
++	  dfs_check_bb (loop_vinfo, e->dest, stmt_info, success, visited_bbs);
++	  if (!success)
++	    return;
++	}
++      return;
++    }
++  /* Non-empty BB.  */
++  check_vec_use (loop_vinfo, stmts, stmt_info, success);
++}
++
++/* For grouped store, if all succeedors of present BB have vectorized load
++   from same base of store.  If so, set memory_access_type using
++   VMAT_CONTIGUOUS_PERMUTE instead of VMAT_LOAD_STORE_LANES.  */
++
++static bool
++conti_perm (stmt_vec_info stmt_vinfo, loop_vec_info loop_vinfo)
++{
++  gimple *stmt = stmt_vinfo->stmt;
++  if (gimple_code (stmt) != GIMPLE_ASSIGN)
++    return false;
++
++  if (DR_IS_READ (stmt_vinfo->dr_aux.dr))
++    return false;
++
++  basic_block bb = stmt->bb;
++  bool success = true;
++  auto_vec visited_bbs;
++  visited_bbs.safe_push (bb);
++  edge e;
++  edge_iterator ei;
++  FOR_EACH_EDGE (e, ei, bb->succs)
++    dfs_check_bb (loop_vinfo, e->dest, stmt_vinfo, success, visited_bbs);
++  return success;
++}
++
+ /* A subroutine of get_load_store_type, with a subset of the same
+    arguments.  Handle the case where STMT_INFO is part of a grouped load
+    or store.
+@@ -2373,6 +2542,20 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
+ 	      *memory_access_type = VMAT_CONTIGUOUS_PERMUTE;
+ 	      overrun_p = would_overrun_p;
+ 	    }
++
++	  if (*memory_access_type == VMAT_LOAD_STORE_LANES
++	      && TREE_CODE (loop_vinfo->num_iters) == INTEGER_CST
++	      && maybe_eq (tree_to_shwi (loop_vinfo->num_iters),
++			   loop_vinfo->vectorization_factor)
++	      && conti_perm (stmt_info, loop_vinfo)
++	      && (vls_type == VLS_LOAD
++		  ? vect_grouped_load_supported (vectype, single_element_p,
++						 group_size)
++		  : vect_grouped_store_supported (vectype, group_size)))
++	    {
++	      *memory_access_type = VMAT_CONTIGUOUS_PERMUTE;
++	      overrun_p = would_overrun_p;
++	    }
+ 	}
+ 
+       /* As a last resort, trying using a gather load or scatter store.
+@@ -7456,6 +7639,154 @@ vectorizable_scan_store (vec_info *vinfo,
+   return true;
+ }
+ 
++/* Function vect_permute_store_chains
++
++   Call function vect_permute_store_chain ().
++   Given a chain of interleaved stores in DR_CHAIN, generate
++   interleave_high/low stmts to reorder the data correctly.
++   Return the final references for stores in RESULT_CHAIN.  */
++
++static void
++vect_permute_store_chains (vec_info *vinfo, vec dr_chain,
++			   unsigned int num_each, stmt_vec_info stmt_info,
++			   gimple_stmt_iterator *gsi, vec *result_chain,
++			   unsigned int group)
++{
++  unsigned int k = 0;
++  unsigned int t = 0;
++
++  /* Divide vectors into GROUP parts.  And permute every NUM_EACH vectors
++     together.  */
++  for (k = 0; k < group; k++)
++    {
++      auto_vec dr_chain_transposed (num_each);
++      auto_vec result_chain_transposed (num_each);
++      for (t = k; t < dr_chain.length (); t = t + group)
++	{
++	  dr_chain_transposed.quick_push (dr_chain[t]);
++	}
++      vect_permute_store_chain (vinfo, dr_chain_transposed, num_each,
++				stmt_info, gsi, &result_chain_transposed);
++      for (t = 0; t < num_each; t++)
++	{
++	  result_chain->quick_push (result_chain_transposed[t]);
++	}
++    }
++}
++
++/* Function transpose_oprnd_store
++
++    Calculate the transposed results from VEC_OPRNDS (VEC_STMT)
++    for vectorizable_store.  */
++
++static void
++transpose_oprnd_store (vec_info *vinfo, vecvec_oprnds,
++		       vec *result_chain, unsigned int vec_num,
++		       unsigned int const_nunits, unsigned int array_num,
++		       stmt_vec_info first_stmt_info,
++		       gimple_stmt_iterator *gsi)
++{
++  unsigned int group_for_transform = 0;
++  unsigned int num_each = 0;
++
++  /* Transpose back for vec_oprnds.  */
++  /* vec = {vec1, vec2, ...}  */
++  if (array_num < const_nunits
++      && const_nunits % array_num == 0)
++    {
++      vect_transpose_store_chain (vinfo, vec_oprnds,
++				  vec_num, array_num,
++				  first_stmt_info,
++				  gsi, result_chain);
++    }
++   /* vec1 = {vec_part1}, vec2 = {vec_part2}, ...  */
++  else if (array_num >= const_nunits
++	   && array_num % const_nunits == 0)
++    {
++      group_for_transform = array_num / const_nunits;
++      num_each = vec_oprnds.length () / group_for_transform;
++      vect_permute_store_chains (vinfo, vec_oprnds,
++				 num_each, first_stmt_info,
++				 gsi, result_chain,
++				 group_for_transform);
++    }
++  else
++    {
++      gcc_unreachable ();
++    }
++}
++
++static dr_vec_info *
++get_dr_info (stmt_vec_info stmt_info)
++{
++  dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
++  if (dr_info->misalignment == DR_MISALIGNMENT_UNINITIALIZED)
++    {
++      SET_DR_MISALIGNMENT (dr_info, DR_MISALIGNMENT_UNKNOWN);
++    }
++  return dr_info;
++}
++
++static unsigned
++dr_align_vect_store (vec_info *vinfo, dr_vec_info *cur_first_dr_info,
++		     tree vectype, unsigned HOST_WIDE_INT &align)
++{
++  unsigned misalign = 0;
++  align = known_alignment (DR_TARGET_ALIGNMENT (cur_first_dr_info));
++  if (aligned_access_p (cur_first_dr_info, vectype))
++    {
++      return misalign;
++    }
++  else if (cur_first_dr_info->misalignment == -1)
++    {
++      align = dr_alignment (vect_dr_behavior (vinfo, cur_first_dr_info));
++    }
++  else
++    {
++      misalign = cur_first_dr_info->misalignment;
++    }
++  return misalign;
++}
++
++static void
++add_new_stmt_vect_store (vec_info *vinfo, tree vectype, tree dataref_ptr,
++			 tree dataref_offset, tree ref_type,
++			 dr_vec_info *cur_first_dr_info, tree vec_oprnd,
++			 gimple_stmt_iterator *gsi, stmt_vec_info stmt_info)
++{
++  /* Data align.  */
++  unsigned HOST_WIDE_INT align;
++  unsigned misalign = dr_align_vect_store (vinfo, cur_first_dr_info,
++					   vectype, align);
++
++  if (dataref_offset == NULL_TREE && TREE_CODE (dataref_ptr) == SSA_NAME)
++    {
++      set_ptr_info_alignment (get_ptr_info (dataref_ptr), align, misalign);
++    }
++
++  /* Get data_ref.  */
++  tree offset = dataref_offset ? dataref_offset : build_int_cst (ref_type, 0);
++  tree data_ref = fold_build2 (MEM_REF, vectype, dataref_ptr, offset);
++  if (aligned_access_p (cur_first_dr_info, vectype))
++    {
++      ;
++    }
++  else if (cur_first_dr_info->misalignment == -1)
++    {
++      TREE_TYPE (data_ref) = build_aligned_type (TREE_TYPE (data_ref),
++						 align * BITS_PER_UNIT);
++    }
++  else
++    {
++      tree elem_type = TREE_TYPE (vectype);
++      TREE_TYPE (data_ref) = build_aligned_type (TREE_TYPE (data_ref),
++						 TYPE_ALIGN (elem_type));
++    }
++  /* Add new stmt.  */
++  vect_copy_ref_info (data_ref, DR_REF (cur_first_dr_info->dr));
++  gassign *new_stmt = gimple_build_assign (data_ref, vec_oprnd);
++  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi, true);
++}
+ 
+ /* Function vectorizable_store.
+ 
+@@ -8333,6 +8664,16 @@ vectorizable_store (vec_info *vinfo,
+ 					   &vec_offsets);
+ 	      vec_offset = vec_offsets[0];
+ 	    }
++	  /* If the stmt_info need to be transposed recovery, dataref_ptr
++	     will be caculated later.  */
++	  else if (memory_access_type == VMAT_CONTIGUOUS
++		   && is_a  (vinfo)
++		   && STMT_VINFO_GROUPED_ACCESS (stmt_info)
++		   && DR_GROUP_SLP_TRANSPOSE (
++			DR_GROUP_FIRST_ELEMENT (stmt_info)))
++	    {
++	      dataref_ptr = NULL_TREE;
++	    }
+ 	  else
+ 	    dataref_ptr
+ 	      = vect_create_data_ref_ptr (vinfo, first_stmt_info, aggr_type,
+@@ -8423,6 +8764,75 @@ vectorizable_store (vec_info *vinfo,
+ 	}
+       else
+ 	{
++	  /* group_size: the size of group after transposing and merging.
++	     group_size_b: the size of group before transposing and merging,
++			 and only group_size_b >= const_nunits is supported.
++	     array_num: the number of arrays.
++	     const_nunits: TYPE_VECTOR_SUBPARTS (vectype).
++	     ncontinues: group_size_b / const_nunits, it means the number of
++			 times an array is stored in memory.  */
++	  if (slp && is_a  (vinfo)
++	      && STMT_VINFO_GROUPED_ACCESS (stmt_info)
++	      && DR_GROUP_SLP_TRANSPOSE (DR_GROUP_FIRST_ELEMENT (stmt_info)))
++	    {
++	      if (dump_enabled_p ())
++		{
++		  dump_printf_loc (MSG_NOTE, vect_location,
++				   "vectorizable_store for slp transpose.\n");
++		}
++	      /* Transpose back for grouped stores.  */
++	      vect_transform_back_slp_grouped_stores (bb_vinfo,
++						      first_stmt_info);
++
++	      result_chain.create (vec_oprnds.length ());
++	      unsigned int const_nunits = nunits.to_constant ();
++	      unsigned int group_size_b = DR_GROUP_SIZE_TRANS (first_stmt_info);
++	      unsigned int array_num = group_size / group_size_b;
++	      transpose_oprnd_store (vinfo, vec_oprnds, &result_chain, vec_num,
++				     const_nunits, array_num,
++				     first_stmt_info, gsi);
++
++	      /* For every store group, not for every vec, because transposing
++		 and merging have changed the data reference access.  */
++	      gcc_assert (group_size_b >= const_nunits);
++	      unsigned int ncontinues = group_size_b / const_nunits;
++
++	      unsigned int k = 0;
++	      for (i = 0; i < array_num; i++)
++		{
++		  stmt_vec_info first_stmt_b;
++		  BB_VINFO_GROUPED_STORES (vinfo).iterate (i, &first_stmt_b);
++		  bool simd_lane_access_p
++			= STMT_VINFO_SIMD_LANE_ACCESS_P (first_stmt_b) != 0;
++		  tree ref_type = get_group_alias_ptr_type (first_stmt_b);
++		  dataref_ptr = vect_create_data_ref_ptr (
++				 vinfo, first_stmt_b, aggr_type,
++				 simd_lane_access_p ? loop : NULL,
++				 offset, &dummy, gsi, &ptr_incr,
++				 simd_lane_access_p, bump);
++		  dr_vec_info *cur_first_dr_info = get_dr_info (first_stmt_b);
++		  for (unsigned int t = 0; t < ncontinues; t++)
++		    {
++		      vec_oprnd = result_chain[k];
++		      k++;
++		      if (t > 0)
++			{
++			  /* Bump the vector pointer.  */
++			  dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr,
++							 ptr_incr, gsi,
++							 first_stmt_b, bump);
++			}
++		      add_new_stmt_vect_store (vinfo, vectype, dataref_ptr,
++					       dataref_offset, ref_type,
++					       cur_first_dr_info, vec_oprnd,
++					       gsi, first_stmt_b);
++		    }
++		}
++	      oprnds.release ();
++	      result_chain.release ();
++	      vec_oprnds.release ();
++	      return true;
++	    }
+ 	  new_stmt = NULL;
+ 	  if (grouped_store)
+ 	    {
+@@ -8719,6 +9129,451 @@ hoist_defs_of_uses (stmt_vec_info stmt_info, class loop *loop)
+   return true;
+ }
+ 
++static tree
++calculate_new_type (tree vectype, unsigned int const_nunits,
++		    unsigned int group_size_b, unsigned int &nloads,
++		    unsigned int &ncontinues, tree &lvectype)
++{
++  tree ltype = TREE_TYPE (vectype);
++  /* nloads is the number of ARRAYs in a vector.
++     vectemp = {a[], b[], ...}  */
++  if (group_size_b < const_nunits)
++    {
++      tree ptype;
++      tree vtype
++	= vector_vector_composition_type (vectype,
++					  const_nunits / group_size_b,
++					  &ptype);
++      if (vtype != NULL_TREE)
++	{
++	  nloads = const_nunits / group_size_b;
++	  lvectype = vtype;
++	  ltype = ptype;
++	  ncontinues = 1;
++	}
++    }
++  /* ncontinues is the number of vectors from an ARRAY.
++     vectemp1 = {a[0], a[1], ...}
++     ...
++     vectempm = {a[k], a[k+1], ...}  */
++  else
++    {
++      nloads = 1;
++      ltype = vectype;
++      ncontinues = group_size_b / const_nunits;
++    }
++  ltype = build_aligned_type (ltype, TYPE_ALIGN (TREE_TYPE (vectype)));
++  return ltype;
++}
++
++static void
++generate_old_load_permutations (slp_tree slp_node, unsigned int group_size,
++				vec &old_load_permutation)
++{
++  /* Generate the old load permutations from the slp_node.  */
++  unsigned i = 0;
++  unsigned k = 0;
++
++  /* If SLP_NODE has load_permutation, we copy it to old_load_permutation.
++     Otherwise, we generate a permutation sequentially.  */
++  if (SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
++    {
++      FOR_EACH_VEC_ELT (SLP_TREE_LOAD_PERMUTATION (slp_node), i, k)
++	{
++	  old_load_permutation.safe_push (k);
++	}
++    }
++  else
++    {
++      for (unsigned i = 0; i < group_size; i++)
++	{
++	  old_load_permutation.safe_push (i);
++	}
++    }
++}
++
++static void
++generate_new_load_permutation_mapping (unsigned slp_node_length,
++				       vec &group_idx,
++				       const vec &load_permutation,
++				       unsigned int group_size_b,
++				       unsigned &new_group_size,
++				       vec &group_from)
++{
++  /* group_num_vec: only stores the group_loads IDs which are caculated from
++     load_permutation.  */
++  auto_vec group_num_vec;
++
++  /* Caculate which group_loads are the stmts in SLP_NODE from.  */
++  unsigned i = 0;
++  unsigned k = 0;
++  FOR_EACH_VEC_ELT (load_permutation, i, k)
++    {
++      unsigned int t0 = k / group_size_b;
++      if (!group_num_vec.contains (t0))
++	{
++	  group_num_vec.safe_push (t0);
++	}
++      group_from.safe_push (t0);
++    }
++  group_num_vec.qsort (cmp_for_group_num);
++  /* n_groups: the number of group_loads.  */
++  unsigned int n_groups = group_num_vec.length ();
++  new_group_size = n_groups * group_size_b;
++  for (i = 0; i < n_groups; i++)
++    {
++      group_idx.safe_push (group_num_vec[i] * group_size_b);
++    }
++  /* A new mapping from group_ind_vec to group_from.
++      For example:
++	Origin: group_from = {1,1,3,3,5,5,7,7};
++	After mapping: group_from = {0,0,1,1,2,2,2,2};  */
++  auto_vec group_ind_vec (n_groups);
++  for (k = 0; k < n_groups; k++)
++    {
++      group_ind_vec.safe_push (k);
++    }
++  for (i = 0; i < slp_node_length; i++)
++    {
++      for (k = 0; k < n_groups; k++)
++	{
++	  if (group_from[i] == group_num_vec[k])
++	    {
++	      group_from[i] = group_ind_vec[k];
++	      break;
++	    }
++	}
++    }
++}
++
++static void
++generate_new_load_permutation (vec &new_load_permutation,
++			       const vec &old_load_permutation,
++			       slp_tree slp_node, bool &this_load_permuted,
++			       const vec &group_from,
++			       unsigned int group_size_b)
++{
++  unsigned slp_node_length = SLP_TREE_SCALAR_STMTS (slp_node).length ();
++  /* Generate the new load permutation from the new mapping.  */
++  new_load_permutation.create (slp_node_length);
++  unsigned i = 0;
++  unsigned k = 0;
++  FOR_EACH_VEC_ELT (old_load_permutation, i, k)
++    {
++      /* t1 is the new permutation of k in the old permutation.
++	 t1 = base_address + offset:
++	 base_address = group_from[i] * group_size_b;
++	 offset = k % group_size_b.  */
++      unsigned int t1
++	= group_from[i] * group_size_b + k % group_size_b;
++      new_load_permutation.safe_push (t1);
++      if (t1 != k)
++	{
++	  this_load_permuted = true;
++	}
++    }
++}
++
++static bool
++is_slp_perm (bool slp_perm, bool this_load_permuted, poly_uint64 nunits,
++	     unsigned int group_size, stmt_vec_info first_stmt_info)
++{
++  /* Calculate the unrolling factor based on the smallest type.  */
++  poly_uint64 unrolling_factor
++    = exact_div (common_multiple (nunits, group_size), group_size);
++  /* The load requires permutation when unrolling exposes
++     a gap either because the group is larger than the SLP
++     group-size or because there is a gap between the groups.  */
++  if (!slp_perm && !this_load_permuted
++      && (known_eq (unrolling_factor, 1U)
++	  || (group_size == DR_GROUP_SIZE (first_stmt_info)
++	      && DR_GROUP_GAP (first_stmt_info) == 0)))
++    {
++      return false;
++    }
++  else
++    {
++      return true;
++    }
++}
++
++static void
++generate_load_permutation (slp_tree slp_node, unsigned &new_group_size,
++			   unsigned int group_size, unsigned int group_size_b,
++			   bool &this_load_permuted, vec &group_idx,
++			   vec &new_load_permutation)
++{
++  /* Generate the old load permutations from SLP_NODE.  */
++  vec old_load_permutation;
++  old_load_permutation.create (group_size);
++  generate_old_load_permutations (slp_node, group_size, old_load_permutation);
++
++  /* Caculate which group_loads are the stmts in SLP_NODE from.  */
++  unsigned slp_node_length = SLP_TREE_SCALAR_STMTS (slp_node).length ();
++  /* group_from: stores the group_loads ID for every stmt in SLP_NODE.  */
++  vec group_from;
++  group_from.create (slp_node_length);
++  generate_new_load_permutation_mapping (slp_node_length, group_idx,
++					 old_load_permutation,
++					 group_size_b, new_group_size,
++					 group_from);
++
++  /* Generate the new load permutation from the new mapping and caculate
++     this_load_permuted flag.  If this_load_permuted is true, we need execute
++     slp permutation by using new load permutation.  */
++  generate_new_load_permutation (new_load_permutation, old_load_permutation,
++				 slp_node, this_load_permuted, group_from,
++				 group_size_b);
++  old_load_permutation.release ();
++  group_from.release ();
++}
++
++static unsigned int
++dr_align_vect_load (vec_info *vinfo, dr_vec_info *cur_first_dr_info,
++		    tree vectype, unsigned HOST_WIDE_INT &align,
++		    enum dr_alignment_support alignment_support_scheme)
++{
++  unsigned int misalign = 0;
++
++  align = known_alignment (DR_TARGET_ALIGNMENT (cur_first_dr_info));
++  if (alignment_support_scheme == dr_aligned)
++    {
++      gcc_assert (aligned_access_p (cur_first_dr_info, vectype));
++    }
++  else if (cur_first_dr_info->misalignment == -1)
++    {
++      align = dr_alignment (vect_dr_behavior (vinfo, cur_first_dr_info));
++    }
++  else
++    {
++      misalign = cur_first_dr_info->misalignment;
++    }
++  return misalign;
++}
++
++static stmt_vec_info
++add_new_stmt_vect_load (vec_info *vinfo, tree vectype, tree dataref_ptr,
++			tree dataref_offset, tree ref_type, tree ltype,
++			gassign *(&new_stmt), dr_vec_info *cur_first_dr_info,
++			gimple_stmt_iterator *gsi, stmt_vec_info stmt_info)
++{
++  /* Data align.  */
++  int malign = dr_misalignment (cur_first_dr_info, vectype);
++  enum dr_alignment_support alignment_support_scheme
++	= vect_supportable_dr_alignment (vinfo, cur_first_dr_info,
++					 vectype, malign);
++  unsigned HOST_WIDE_INT align;
++  unsigned int misalign = dr_align_vect_load (vinfo, cur_first_dr_info,
++					      vectype, align,
++					      alignment_support_scheme);
++  if (dataref_offset == NULL_TREE && TREE_CODE (dataref_ptr) == SSA_NAME)
++    {
++      set_ptr_info_alignment (get_ptr_info (dataref_ptr), align, misalign);
++    }
++
++  /* Get data_ref.  */
++  tree offset = dataref_offset ? dataref_offset : build_int_cst (ref_type, 0);
++  tree data_ref = fold_build2 (MEM_REF, ltype, dataref_ptr, offset);
++  if (alignment_support_scheme == dr_aligned)
++    {
++      ;
++    }
++  else if (cur_first_dr_info->misalignment == -1)
++    {
++      TREE_TYPE (data_ref)
++	= build_aligned_type (TREE_TYPE (data_ref), align * BITS_PER_UNIT);
++    }
++  else
++    {
++      tree elem_type = TREE_TYPE (vectype);
++      TREE_TYPE (data_ref)
++	= build_aligned_type (TREE_TYPE (data_ref), TYPE_ALIGN (elem_type));
++    }
++
++  /* Add new stmt.  */
++  vect_copy_ref_info (data_ref, DR_REF (cur_first_dr_info->dr));
++  new_stmt = gimple_build_assign (make_ssa_name (ltype), data_ref);
++  vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi, true);
++  stmt_vec_info vec_stmt_info = vinfo->lookup_stmt (new_stmt);
++  return vec_stmt_info;
++}
++
++static void
++push_new_stmt_to_dr_chain (bool slp_perm, stmt_vec_info new_stmt_info,
++			   vec dr_chain, slp_tree slp_node)
++{
++  if (slp_perm)
++    dr_chain.quick_push (gimple_assign_lhs (new_stmt_info->stmt));
++  else
++    SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info->stmt);
++}
++
++static stmt_vec_info
++get_first_stmt_info_before_transpose (stmt_vec_info first_stmt_info,
++				      unsigned int group_el,
++				      unsigned int group_size)
++{
++  stmt_vec_info last_stmt_info = first_stmt_info;
++  unsigned int count = 0;
++  gcc_assert (group_el < group_size);
++  while (count < group_el)
++    {
++      last_stmt_info = DR_GROUP_NEXT_ELEMENT (last_stmt_info);
++      count++;
++    }
++  return last_stmt_info;
++}
++
++static stmt_vec_info
++add_new_stmt_for_nloads_greater_than_one (vec_info *vinfo, tree lvectype,
++					  tree vectype,
++					  vec *v,
++					  stmt_vec_info stmt_info,
++					  gimple_stmt_iterator *gsi)
++{
++  tree vec_inv = build_constructor (lvectype, v);
++  tree new_temp = vect_init_vector (vinfo, stmt_info, vec_inv, lvectype, gsi, true);
++  stmt_vec_info new_stmt_info = vinfo->lookup_def (new_temp);
++  if (lvectype != vectype)
++    {
++      gassign *new_stmt = gimple_build_assign (make_ssa_name (vectype),
++					       VIEW_CONVERT_EXPR,
++					       build1 (VIEW_CONVERT_EXPR,
++						       vectype, new_temp));
++      vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi, true);
++      new_stmt_info = vinfo->lookup_stmt (new_stmt);
++    }
++  return new_stmt_info;
++}
++
++/* Function new_vect_stmt_for_nloads.
++
++   New a VEC_STMT when nloads Arrays are merged into a vector.
++
++   ncopies is the number of vectors that need to be loaded from memmory.
++   nloads is the number of ARRAYs in a vector.
++   vectemp = {a[], b[], ...}  */
++
++static void
++new_vect_stmt_for_nloads (vec_info *vinfo, unsigned int ncopies,
++			  unsigned int nloads, const vec &group_idx,
++			  stmt_vec_info stmt_info, offset_info *offset_info,
++			  vectype_info *vectype_info,
++			  vect_memory_access_type memory_access_type,
++			  bool slp_perm, vec dr_chain, slp_tree slp_node,
++			  gimple_stmt_iterator *gsi)
++{
++  vec *v = NULL;
++  stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
++  unsigned int group_size = DR_GROUP_SIZE (first_stmt_info);
++  stmt_vec_info first_stmt_info_b = NULL;
++  stmt_vec_info new_stmt_info = NULL;
++  tree dataref_ptr = NULL_TREE;
++  tree dummy;
++  gimple *ptr_incr = NULL;
++  unsigned int n = 0;
++  for (unsigned int i = 0; i < ncopies; i++)
++    {
++      vec_alloc (v, nloads);
++      for (unsigned int t = 0; t < nloads; t++)
++	{
++	  first_stmt_info_b = get_first_stmt_info_before_transpose (
++				first_stmt_info, group_idx[n++], group_size);
++	  dr_vec_info* cur_first_dr_info = get_dr_info (first_stmt_info_b);
++	  tree bump = vect_get_data_ptr_increment (vinfo, cur_first_dr_info,
++						   vectype_info->ltype,
++						   memory_access_type);
++	  bool simd_lane_access_p
++		= STMT_VINFO_SIMD_LANE_ACCESS_P (first_stmt_info_b) != 0;
++
++	  /* Create dataref_ptr which is point to init_address.  */
++	  dataref_ptr = vect_create_data_ref_ptr (
++			 vinfo, first_stmt_info_b, vectype_info->ltype, NULL,
++			 offset_info->offset, &dummy, gsi, &ptr_incr,
++			 simd_lane_access_p, bump);
++
++	  gassign *new_stmt = NULL;
++	  new_stmt_info = add_new_stmt_vect_load (vinfo, vectype_info->vectype, dataref_ptr,
++				  offset_info->dataref_offset,
++				  vectype_info->ref_type,  vectype_info->ltype,
++				  new_stmt, cur_first_dr_info, gsi,
++				  first_stmt_info_b);
++
++	  CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, gimple_assign_lhs (new_stmt));
++	}
++	new_stmt_info = add_new_stmt_for_nloads_greater_than_one (
++				 vinfo, vectype_info->lvectype,
++				 vectype_info->vectype, v,
++				 first_stmt_info_b, gsi);
++	push_new_stmt_to_dr_chain (slp_perm, new_stmt_info,
++				   dr_chain, slp_node);
++    }
++}
++
++/* Function new_vect_stmt_for_ncontinues.
++
++   New a VEC_STMTs when an Array is divided into several vectors.
++
++   n_groups is the number of ARRAYs.
++   ncontinues is the number of vectors from an ARRAY.
++   vectemp1 = {a[0], a[1], ...}
++   ...
++   vectempm = {a[k], a[k+1], ...}  */
++
++static void
++new_vect_stmt_for_ncontinues (vec_info *vinfo, unsigned int ncontinues,
++			      const vec &group_idx,
++			      stmt_vec_info stmt_info,
++			      offset_info* offset_info,
++			      vectype_info* vectype_info,
++			      vect_memory_access_type memory_access_type,
++			      bool slp_perm, vec &dr_chain,
++			      slp_tree slp_node,
++			      gimple_stmt_iterator *gsi)
++{
++  stmt_vec_info first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
++  unsigned int group_size = DR_GROUP_SIZE (first_stmt_info);
++  stmt_vec_info new_stmt_info = NULL;
++  tree dataref_ptr = NULL_TREE;
++  tree dummy;
++  gimple *ptr_incr = NULL;
++  unsigned int n_groups = group_idx.length ();
++  for (unsigned int i = 0; i < n_groups; i++)
++    {
++      stmt_vec_info first_stmt_info_b = get_first_stmt_info_before_transpose (
++				first_stmt_info, group_idx[i], group_size);
++      dr_vec_info* cur_first_dr_info = get_dr_info (first_stmt_info_b);
++      tree bump = vect_get_data_ptr_increment (vinfo, cur_first_dr_info,
++			vectype_info->ltype, memory_access_type);
++      bool simd_lane_access_p
++		= STMT_VINFO_SIMD_LANE_ACCESS_P (first_stmt_info_b) != 0;
++      for (unsigned int k = 0; k < ncontinues; k++)
++	{
++	  /* Create dataref_ptr which is point to init_address.  */
++	  if (k == 0)
++	    {
++	      dataref_ptr = vect_create_data_ref_ptr (
++			 vinfo, first_stmt_info_b, vectype_info->ltype, NULL,
++			 offset_info->offset, &dummy, gsi, &ptr_incr,
++			 simd_lane_access_p, bump);
++	    }
++	  else
++	    {
++	      dataref_ptr = bump_vector_ptr (vinfo, dataref_ptr, ptr_incr,
++					     gsi, first_stmt_info_b, bump);
++	    }
++	  gassign *new_stmt = NULL;
++	  new_stmt_info = add_new_stmt_vect_load (vinfo, vectype_info->vectype, dataref_ptr,
++				  offset_info->dataref_offset,
++				  vectype_info->ref_type, vectype_info->ltype,
++				  new_stmt, cur_first_dr_info, gsi,
++				  first_stmt_info_b);
++	  push_new_stmt_to_dr_chain (slp_perm, new_stmt_info,
++	  		dr_chain, slp_node);
++	}
++    }
++}
++
+ /* vectorizable_load.
+ 
+    Check if STMT_INFO reads a non scalar data-ref (array/pointer/structure)
+@@ -9338,6 +10193,8 @@ vectorizable_load (vec_info *vinfo,
+       if (bb_vinfo)
+ 	first_stmt_info_for_drptr
+ 	  = vect_find_first_scalar_stmt_in_slp (slp_node);
++  // first_stmt_info_for_drptr = SLP_TREE_SCALAR_STMTS (slp_node)[0];
++
+ 
+       /* Check if the chain of loads is already vectorized.  */
+       if (STMT_VINFO_VEC_STMTS (first_stmt_info).exists ()
+@@ -9601,6 +10458,9 @@ vectorizable_load (vec_info *vinfo,
+     }
+   tree vec_mask = NULL_TREE;
+   poly_uint64 group_elt = 0;
++  unsigned new_group_size = 0;
++  vec new_load_permutation;
++
+   for (j = 0; j < ncopies; j++)
+     {
+       /* 1. Create the vector or array pointer update chain.  */
+@@ -9621,6 +10481,15 @@ vectorizable_load (vec_info *vinfo,
+ 	      dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr_info->dr));
+ 	      dataref_offset = build_int_cst (ref_type, 0);
+ 	    }
++	  /* If the stmt_info need to be transposed recovery, dataref_ptr
++	     will be caculated later.  */
++	  else if (slp && is_a  (vinfo)
++		   && STMT_VINFO_GROUPED_ACCESS (stmt_info)
++		   && DR_GROUP_SLP_TRANSPOSE (
++			DR_GROUP_FIRST_ELEMENT (stmt_info)))
++	    {
++	      dataref_ptr = NULL_TREE;
++	    }
+ 	  else if (diff_first_stmt_info)
+ 	    {
+ 	      dataref_ptr
+@@ -9731,6 +10600,63 @@ vectorizable_load (vec_info *vinfo,
+ 	  /* Record that VEC_ARRAY is now dead.  */
+ 	  vect_clobber_variable (vinfo, stmt_info, gsi, vec_array);
+ 	}
++      else if (slp && is_a  (vinfo)
++	       && STMT_VINFO_GROUPED_ACCESS (stmt_info)
++	       && DR_GROUP_SLP_TRANSPOSE (DR_GROUP_FIRST_ELEMENT (stmt_info)))
++	{
++	  if (dump_enabled_p ())
++	    {
++	      dump_printf_loc (MSG_NOTE, vect_location,
++			       "vectorizable_load for slp transpose.\n");
++	    }
++	  /* group_size: the size of group after merging.
++	     group_size_b: the size of group before merging.
++	     const_nunits: TYPE_VECTOR_SUBPARTS (vectype), it is the number of
++		elements in a vector.
++	     nloads: const_nunits / group_size_b or 1, it means the number
++		of ARRAYs in a vector.
++	     ncontinues: group_size_b / const_nunits or 1, it means the number
++		of vectors from an ARRAY.  */
++	  unsigned int group_size_b = DR_GROUP_SIZE_TRANS (first_stmt_info);
++	  unsigned int const_nunits = nunits.to_constant ();
++	  unsigned int nloads = const_nunits;
++	  unsigned int ncontinues = group_size_b;
++	  tree lvectype = vectype;
++	  tree ltype = calculate_new_type (vectype, const_nunits,
++					   group_size_b, nloads,
++					   ncontinues, lvectype);
++	  bool this_load_permuted = false;
++	  auto_vec group_idx;
++	  generate_load_permutation (slp_node, new_group_size, group_size,
++				     group_size_b, this_load_permuted,
++				     group_idx, new_load_permutation);
++	  slp_perm = is_slp_perm (slp_perm, this_load_permuted, nunits,
++				  group_size, first_stmt_info);
++
++	  /* ncopies: the number of vectors that need to be loaded from
++		 memmory.  */
++	  unsigned int ncopies = new_group_size / const_nunits;
++	  offset_info offset_info = {offset, NULL_TREE, dataref_offset};
++	  vectype_info vectype_info = {vectype, ltype, lvectype, ref_type};
++	  if (slp_perm)
++	    {
++	       dr_chain.create (ncopies);
++	    }
++	  if (nloads > 1 && ncontinues == 1)
++	    {
++	      new_vect_stmt_for_nloads (vinfo, ncopies, nloads, group_idx,
++					stmt_info, &offset_info, &vectype_info,
++					memory_access_type, slp_perm, dr_chain,
++					slp_node, gsi);
++	    }
++	  else
++	    {
++	      new_vect_stmt_for_ncontinues (vinfo, ncontinues, group_idx,
++					    stmt_info, &offset_info,
++					    &vectype_info, memory_access_type,
++					    slp_perm, dr_chain, slp_node, gsi);
++	    }
++	}
+       else
+ 	{
+ 	  for (i = 0; i < vec_num; i++)
+@@ -10177,7 +11103,32 @@ vectorizable_load (vec_info *vinfo,
+       if (slp && !slp_perm)
+ 	continue;
+ 
+-      if (slp_perm)
++      /* Using the new load permutation to generate vector permute statements
++	 from a list of loads in DR_CHAIN.  */
++      if (slp && slp_perm && is_a  (vinfo)
++	  && STMT_VINFO_GROUPED_ACCESS (stmt_info)
++	  && DR_GROUP_SLP_TRANSPOSE (DR_GROUP_FIRST_ELEMENT (stmt_info)))
++	{
++	  unsigned n_perms;
++	  stmt_vec_info stmt_info_ = SLP_TREE_SCALAR_STMTS (slp_node)[0];
++	  unsigned int old_size = DR_GROUP_SIZE (stmt_info);
++	  DR_GROUP_SIZE (stmt_info_) = new_group_size;
++	  vec old_load_permutation
++			  = SLP_TREE_LOAD_PERMUTATION (slp_node);
++	  SLP_TREE_LOAD_PERMUTATION (slp_node) = new_load_permutation;
++	  bool perm_load_success = vect_transform_slp_perm_load (
++				     vinfo, slp_node, dr_chain, gsi, vf,
++				     false, &n_perms);
++	  DR_GROUP_SIZE (stmt_info_) = old_size;
++	  SLP_TREE_LOAD_PERMUTATION (slp_node) = old_load_permutation;
++	  new_load_permutation.release ();
++	  if (!perm_load_success)
++	    {
++	      dr_chain.release ();
++	      return false;
++	    }
++	}
++      else if (slp_perm)
+         {
+ 	  unsigned n_perms;
+ 	  /* For SLP we know we've seen all possible uses of dr_chain so
+diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
+index 642eb0aeb..e13bc6c99 100644
+--- a/gcc/tree-vectorizer.h
++++ b/gcc/tree-vectorizer.h
+@@ -412,6 +412,21 @@ public:
+   vec ddrs;
+ };
+ 
++/* Information about offset in vectorizable_load.  */
++struct offset_info {
++  tree offset;
++  tree byte_offset;
++  tree dataref_offset;
++};
++
++/* Information about vectype in vectorizable_load.  */
++struct vectype_info {
++  tree vectype;
++  tree ltype;
++  tree lvectype;
++  tree ref_type;
++};
++
+ /* Vectorizer state common between loop and basic-block vectorization.  */
+ class vec_info {
+ public:
+@@ -455,6 +470,14 @@ public:
+      stmt in the chain.  */
+   auto_vec grouped_stores;
+ 
++  /* All interleaving chains of loads, represented by the first
++     stmt in the chain.  */
++  auto_vec grouped_loads;
++
++  /* All interleaving chains of stores (before transposed), represented by all
++     stmt in the chain.  */
++  auto_vec > scalar_stores;
++
+   /* The set of vector modes used in the vectorized region.  */
+   mode_set used_vector_modes;
+ 
+@@ -899,6 +922,8 @@ public:
+ #define LOOP_VINFO_CHECK_NONZERO(L)        (L)->check_nonzero
+ #define LOOP_VINFO_LOWER_BOUNDS(L)         (L)->lower_bounds
+ #define LOOP_VINFO_GROUPED_STORES(L)       (L)->grouped_stores
++#define LOOP_VINFO_GROUPED_LOADS(L)	    (L)->grouped_loads
++#define LOOP_VINFO_SCALAR_STORES(L)	    (L)->scalar_stores
+ #define LOOP_VINFO_SLP_INSTANCES(L)        (L)->slp_instances
+ #define LOOP_VINFO_SLP_UNROLLING_FACTOR(L) (L)->slp_unrolling_factor
+ #define LOOP_VINFO_REDUCTIONS(L)           (L)->reductions
+@@ -982,6 +1007,25 @@ public:
+   vec bbs;
+ 
+   vec roots;
++
++  /* True, if bb_vinfo can goto vect_analyze_slp.  */
++  bool before_slp;
++
++  /* True, if bb_vinfo is a transposed version.  */
++  bool transposed;
++
++  /* The number of transposed groups.  */
++  int transposed_group;
++
++  /* The cost of the scalar iterations.  */
++  int scalar_cost;
++
++  /* The cost of the vector prologue and epilogue, including peeled
++     iterations and set-up code.  */
++  int vec_outside_cost;
++
++  /* The cost of the vector loop body.  */
++  int vec_inside_cost;
+ } *bb_vec_info;
+ 
+ #define BB_VINFO_BB(B)               (B)->bb
+@@ -989,6 +1033,14 @@ public:
+ #define BB_VINFO_SLP_INSTANCES(B)    (B)->slp_instances
+ #define BB_VINFO_DATAREFS(B)         (B)->shared->datarefs
+ #define BB_VINFO_DDRS(B)             (B)->shared->ddrs
++#define BB_VINFO_GROUPED_LOADS(B)    (B)->grouped_loads
++#define BB_VINFO_SCALAR_STORES(B)    (B)->scalar_stores
++#define BB_VINFO_VEC_OUTSIDE_COST(B) (B)->vec_outside_cost
++#define BB_VINFO_VEC_INSIDE_COST(B)  (B)->vec_inside_cost
++#define BB_VINFO_SCALAR_COST(B)      (B)->scalar_cost
++#define BB_VINFO_SLP_TRANSPOSED(B)   (B)->transposed
++#define BB_VINFO_BEFORE_SLP(B)       (B)->before_slp
++#define BB_VINFO_TRANS_GROUPS(B)     (B)->transposed_group
+ 
+ /*-----------------------------------------------------------------*/
+ /* Info on vectorized defs.                                        */
+@@ -1219,6 +1271,17 @@ public:
+   stmt_vec_info next_element;
+   /* The size of the group.  */
+   unsigned int size;
++
++  /* The size of the group before transposed.  */
++  unsigned int size_before_transpose;
++
++  /* If true, the stmt_info is slp transposed.  */
++  bool slp_transpose;
++
++  /* Mark the group store number for rebuild interleaving chain
++     during transpose phase.  Value -1 represents unable to transpose.  */
++  int group_number;
++
+   /* For stores, number of stores from this group seen. We vectorize the last
+      one.  */
+   unsigned int store_count;
+@@ -1226,6 +1289,9 @@ public:
+      is 1.  */
+   unsigned int gap;
+ 
++  /* The gap before transposed.  */
++  unsigned int gap_before_transpose;
++
+   /* The minimum negative dependence distance this stmt participates in
+      or zero if none.  */
+   unsigned int min_neg_dist;
+@@ -1427,6 +1493,12 @@ struct gather_scatter_info {
+ #define STMT_VINFO_SLP_VECT_ONLY(S)     (S)->slp_vect_only_p
+ #define STMT_VINFO_SLP_VECT_ONLY_PATTERN(S) (S)->slp_vect_pattern_only_p
+ 
++#define DR_GROUP_SLP_TRANSPOSE(S) \
++  (gcc_checking_assert ((S)->dr_aux.dr), (S)->slp_transpose)
++#define DR_GROUP_SIZE_TRANS(S) \
++  (gcc_checking_assert ((S)->dr_aux.dr), (S)->size_before_transpose)
++#define DR_GROUP_NUMBER(S) \
++  (gcc_checking_assert ((S)->dr_aux.dr), (S)->group_number)
+ #define DR_GROUP_FIRST_ELEMENT(S) \
+   (gcc_checking_assert ((S)->dr_aux.dr), (S)->first_element)
+ #define DR_GROUP_NEXT_ELEMENT(S) \
+@@ -1437,6 +1509,8 @@ struct gather_scatter_info {
+   (gcc_checking_assert ((S)->dr_aux.dr), (S)->store_count)
+ #define DR_GROUP_GAP(S) \
+   (gcc_checking_assert ((S)->dr_aux.dr), (S)->gap)
++#define DR_GROUP_GAP_TRANS(S) \
++  (gcc_checking_assert ((S)->dr_aux.dr), (S)->gap_before_transpose)
+ 
+ #define REDUC_GROUP_FIRST_ELEMENT(S) \
+   (gcc_checking_assert (!(S)->dr_aux.dr), (S)->first_element)
+@@ -2033,6 +2107,17 @@ vect_get_scalar_dr_size (dr_vec_info *dr_info)
+   return tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_info->dr))));
+ }
+ 
++/* Compare two unsigned int A and B.
++   Sorting them in ascending order.  */
++
++static inline int
++cmp_for_group_num (const void *a_, const void *b_)
++{
++  unsigned int a = *(unsigned int *)const_cast(a_);
++  unsigned int b = *(unsigned int *)const_cast(b_);
++  return a < b ? -1 : 1;
++}
++
+ /* Return true if LOOP_VINFO requires a runtime check for whether the
+    vector loop is profitable.  */
+ 
+@@ -2152,7 +2237,7 @@ record_stmt_cost (stmt_vector_for_cost *body_cost_vec, int count,
+ 
+ extern void vect_finish_replace_stmt (vec_info *, stmt_vec_info, gimple *);
+ extern void vect_finish_stmt_generation (vec_info *, stmt_vec_info, gimple *,
+-					 gimple_stmt_iterator *);
++					 gimple_stmt_iterator *,bool transpose=false);
+ extern opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info, bool *);
+ extern tree vect_get_store_rhs (stmt_vec_info);
+ void vect_get_vec_defs_for_operand (vec_info *vinfo, stmt_vec_info, unsigned,
+@@ -2168,7 +2253,7 @@ void vect_get_vec_defs (vec_info *, stmt_vec_info, slp_tree, unsigned,
+ 			tree = NULL, vec * = NULL, tree = NULL,
+ 			tree = NULL, vec * = NULL, tree = NULL);
+ extern tree vect_init_vector (vec_info *, stmt_vec_info, tree, tree,
+-                              gimple_stmt_iterator *);
++			      gimple_stmt_iterator *, bool transpose=false);
+ extern tree vect_get_slp_vect_def (slp_tree, unsigned);
+ extern bool vect_transform_stmt (vec_info *, stmt_vec_info,
+ 				 gimple_stmt_iterator *,
+@@ -2235,6 +2320,9 @@ extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT, bool);
+ extern void vect_permute_store_chain (vec_info *, vec &,
+ 				      unsigned int, stmt_vec_info,
+ 				      gimple_stmt_iterator *, vec *);
++extern void vect_transpose_store_chain (vec_info *, vec, unsigned int,
++					unsigned int, stmt_vec_info,
++					gimple_stmt_iterator *, vec *);
+ extern tree vect_setup_realignment (vec_info *,
+ 				    stmt_vec_info, gimple_stmt_iterator *,
+ 				    tree *, enum dr_alignment_support, tree,
+@@ -2262,7 +2350,8 @@ extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree,
+ 				  enum tree_code);
+ extern bool needs_fold_left_reduction_p (tree, code_helper);
+ /* Drive for loop analysis stage.  */
+-extern opt_loop_vec_info vect_analyze_loop (class loop *, vec_info_shared *);
++extern opt_loop_vec_info vect_analyze_loop (class loop *, vec_info_shared *,
++					    bool result_only_p = false);
+ extern tree vect_build_loop_niters (loop_vec_info, bool * = NULL);
+ extern void vect_gen_vector_loop_niters (loop_vec_info, tree, tree *,
+ 					 tree *, bool);
+@@ -2331,6 +2420,7 @@ extern bool vect_transform_slp_perm_load (vec_info *, slp_tree, const vec
+ 					  gimple_stmt_iterator *, poly_uint64,
+ 					  bool, unsigned *,
+ 					  unsigned * = nullptr, bool = false);
++extern void vect_transform_back_slp_grouped_stores (bb_vec_info, stmt_vec_info);
+ extern bool vect_slp_analyze_operations (vec_info *);
+ extern void vect_schedule_slp (vec_info *, const vec &);
+ extern opt_result vect_analyze_slp (vec_info *, unsigned);
+-- 
+2.33.0
+
diff --git a/0100-Add-hip09-machine-discribtion.patch b/0100-Add-hip09-machine-discribtion.patch
new file mode 100644
index 0000000..c2221d9
--- /dev/null
+++ b/0100-Add-hip09-machine-discribtion.patch
@@ -0,0 +1,882 @@
+From d9131757175667d35e74d9ee84689039990af768 Mon Sep 17 00:00:00 2001
+From: xingyushuai 
+Date: Fri, 3 Mar 2023 09:31:04 +0800
+Subject: [PATCH 001/157] Add hip09 machine discribtion
+
+Here is the patch introducing hip09 machine model
+for the scheduler.
+---
+ gcc/config/aarch64/aarch64-cores.def     |   1 +
+ gcc/config/aarch64/aarch64-cost-tables.h | 104 +++++
+ gcc/config/aarch64/aarch64-tune.md       |   2 +-
+ gcc/config/aarch64/aarch64.cc            | 109 +++++
+ gcc/config/aarch64/aarch64.md            |   1 +
+ gcc/config/aarch64/hip09.md              | 558 +++++++++++++++++++++++
+ 6 files changed, 774 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/config/aarch64/hip09.md
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 70b11eb80..a854bdb24 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -130,6 +130,7 @@ AARCH64_CORE("a64fx", a64fx, a64fx, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F
+ 
+ /* HiSilicon ('H') cores. */
+ AARCH64_CORE("tsv110",  tsv110, tsv110, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
++AARCH64_CORE("hip09", hip09, hip09, 8_5A, AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_I8MM | AARCH64_FL_F32MM | AARCH64_FL_F64MM | AARCH64_FL_PROFILE | AARCH64_FL_PREDRES, hip09, 0x48, 0xd02, 0x0)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+diff --git a/gcc/config/aarch64/aarch64-cost-tables.h b/gcc/config/aarch64/aarch64-cost-tables.h
+index 48522606f..fc5a3cbe4 100644
+--- a/gcc/config/aarch64/aarch64-cost-tables.h
++++ b/gcc/config/aarch64/aarch64-cost-tables.h
+@@ -668,6 +668,110 @@ const struct cpu_cost_table a64fx_extra_costs =
+   }
+ };
+ 
++const struct cpu_cost_table hip09_extra_costs =
++{
++  /* ALU */
++  {
++    0,                 /* arith.  */
++    0,                 /* logical.  */
++    0,                 /* shift.  */
++    0,                 /* shift_reg.  */
++    COSTS_N_INSNS (1), /* arith_shift.  */
++    COSTS_N_INSNS (1), /* arith_shift_reg.  */
++    COSTS_N_INSNS (1), /* log_shift.  */
++    COSTS_N_INSNS (1), /* log_shift_reg.  */
++    0,                 /* extend.  */
++    COSTS_N_INSNS (1), /* extend_arith.  */
++    0,                 /* bfi.  */
++    0,                 /* bfx.  */
++    0,                 /* clz.  */
++    0,                 /* rev.  */
++    0,                 /* non_exec.  */
++    true               /* non_exec_costs_exec.  */
++  },
++
++  {
++    /* MULT SImode */
++    {
++      COSTS_N_INSNS (2),       /* simple.  */
++      COSTS_N_INSNS (2),       /* flag_setting.  */
++      COSTS_N_INSNS (2),       /* extend.  */
++      COSTS_N_INSNS (2),       /* add.  */
++      COSTS_N_INSNS (2),       /* extend_add.  */
++      COSTS_N_INSNS (11)       /* idiv.  */
++    },
++        /* MULT DImode */
++    {
++      COSTS_N_INSNS (3),       /* simple.  */
++      0,                       /* flag_setting (N/A).  */
++      COSTS_N_INSNS (3),       /* extend.  */
++      COSTS_N_INSNS (3),       /* add.  */
++      COSTS_N_INSNS (3),       /* extend_add.  */
++      COSTS_N_INSNS (19)       /* idiv.  */
++    }
++  },
++  /* LD/ST */
++  {
++    COSTS_N_INSNS (3),         /* load.  */
++    COSTS_N_INSNS (4),         /* load_sign_extend.  */
++    COSTS_N_INSNS (3),         /* ldrd.  */
++    COSTS_N_INSNS (3),         /* ldm_1st.  */
++    1,                         /* ldm_regs_per_insn_1st.  */
++    2,                         /* ldm_regs_per_insn_subsequent.  */
++    COSTS_N_INSNS (4),         /* loadf.  */
++    COSTS_N_INSNS (4),         /* loadd.  */
++    COSTS_N_INSNS (4),         /* load_unaligned.  */
++    0,                         /* store.  */
++    0,                         /* strd.  */
++    0,                         /* stm_1st.  */
++    1,                         /* stm_regs_per_insn_1st.  */
++    2,                         /* stm_regs_per_insn_subsequent.  */
++    0,                         /* storef.  */
++    0,                         /* stored.  */
++    COSTS_N_INSNS (1),         /* store_unaligned.  */
++    COSTS_N_INSNS (4),         /* loadv.  */
++    COSTS_N_INSNS (4)          /* storev.  */
++  },
++  {
++    /* FP SFmode */
++    {
++      COSTS_N_INSNS (10),      /* div.  */
++      COSTS_N_INSNS (4),       /* mult.  */
++      COSTS_N_INSNS (4),       /* mult_addsub.  */
++      COSTS_N_INSNS (4),       /* fma.  */
++      COSTS_N_INSNS (4),       /* addsub.  */
++      COSTS_N_INSNS (1),       /* fpconst.  */
++      COSTS_N_INSNS (1),       /* neg.  */
++      COSTS_N_INSNS (1),       /* compare.  */
++      COSTS_N_INSNS (2),       /* widen.  */
++      COSTS_N_INSNS (2),       /* narrow.  */
++      COSTS_N_INSNS (2),       /* toint.  */
++      COSTS_N_INSNS (1),       /* fromint.  */
++      COSTS_N_INSNS (2)        /* roundint.  */
++    },
++    /* FP DFmode */
++    {
++      COSTS_N_INSNS (17),      /* div.  */
++      COSTS_N_INSNS (4),       /* mult.  */
++      COSTS_N_INSNS (6),       /* mult_addsub.  */
++      COSTS_N_INSNS (6),       /* fma.  */
++      COSTS_N_INSNS (3),       /* addsub.  */
++      COSTS_N_INSNS (1),       /* fpconst.  */
++      COSTS_N_INSNS (1),       /* neg.  */
++      COSTS_N_INSNS (1),       /* compare.  */
++      COSTS_N_INSNS (2),       /* widen.  */
++      COSTS_N_INSNS (2),       /* narrow.  */
++      COSTS_N_INSNS (2),       /* toint.  */
++      COSTS_N_INSNS (1),       /* fromint.  */
++      COSTS_N_INSNS (2)        /* roundint.  */
++    }
++  },
++  /* Vector */
++  {
++    COSTS_N_INSNS (1)  /* alu.  */
++  }
++};
++
+ const struct cpu_cost_table ampere1_extra_costs =
+ {
+   /* ALU */
+diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
+index 9dc9adc70..238bb6e31 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,ampere1,ampere1a,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,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2,neoversen2,demeter,neoversev2"
++	"cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,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,hip09,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2,neoversen2,demeter,neoversev2"
+ 	(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 5537a537c..e9b3980c4 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -465,6 +465,22 @@ static const struct cpu_addrcost_table tsv110_addrcost_table =
+   0, /* imm_offset  */
+ };
+ 
++static const struct cpu_addrcost_table hip09_addrcost_table =
++{
++    {
++        1, /* hi  */
++        0, /* si  */
++        0, /* di  */
++        1, /* ti  */
++    },
++  0, /* pre_modify  */
++  0, /* post_modify  */
++  0, /* register_offset  */
++  1, /* register_sextend  */
++  1, /* register_zextend  */
++  0, /* imm_offset  */
++};
++
+ static const struct cpu_addrcost_table qdf24xx_addrcost_table =
+ {
+     {
+@@ -660,6 +676,16 @@ static const struct cpu_regmove_cost a64fx_regmove_cost =
+   2 /* FP2FP  */
+ };
+ 
++static const struct cpu_regmove_cost hip09_regmove_cost =
++{
++  1, /* GP2GP  */
++  /* Avoid the use of slow int<->fp moves for spilling by setting
++     their cost higher than memmov_cost.  */
++  2, /* GP2FP  */
++  3, /* FP2GP  */
++  2  /* FP2FP  */
++};
++
+ static const struct cpu_regmove_cost neoversen2_regmove_cost =
+ {
+   1, /* GP2GP  */
+@@ -947,6 +973,43 @@ static const struct cpu_vector_cost tsv110_vector_cost =
+   nullptr /* issue_info  */
+ };
+ 
++static const advsimd_vec_cost hip09_advsimd_vector_cost =
++{
++  2, /* int_stmt_cost  */
++  2, /* fp_stmt_cost  */
++  0, /* ld2_st2_permute_cost  */
++  0, /* ld3_st3_permute_cost  */
++  0, /* ld4_st4_permute_cost  */
++  2, /* permute_cost  */
++  3, /* reduc_i8_cost  */
++  3, /* reduc_i16_cost  */
++  3, /* reduc_i32_cost  */
++  3, /* reduc_i64_cost  */
++  3, /* reduc_f16_cost  */
++  3, /* reduc_f32_cost  */
++  3, /* reduc_f64_cost  */
++  3, /* store_elt_extra_cost  */
++  3, /* vec_to_scalar_cost  */
++  2, /* scalar_to_vec_cost  */
++  5, /* align_load_cost  */
++  5, /* unalign_load_cost  */
++  1, /* unalign_store_cost  */
++  1  /* store_cost  */
++};
++
++static const struct cpu_vector_cost hip09_vector_cost =
++{
++  1, /* scalar_int_stmt_cost  */
++  1, /* scalar_fp_stmt_cost  */
++  5, /* scalar_load_cost  */
++  1, /* scalar_store_cost  */
++  1, /* cond_taken_branch_cost  */
++  1, /* cond_not_taken_branch_cost  */
++  &hip09_advsimd_vector_cost, /* advsimd  */
++  nullptr, /* sve  */
++  nullptr /* issue_info  */
++};
++
+ static const advsimd_vec_cost cortexa57_advsimd_vector_cost =
+ {
+   2, /* int_stmt_cost  */
+@@ -1293,6 +1356,18 @@ static const cpu_prefetch_tune tsv110_prefetch_tune =
+   -1                    /* default_opt_level  */
+ };
+ 
++
++static const cpu_prefetch_tune hip09_prefetch_tune =
++{
++  0,                    /* num_slots  */
++  64,                   /* l1_cache_size  */
++  64,                   /* l1_cache_line_size  */
++  512,                  /* l2_cache_size  */
++  true,                 /* prefetch_dynamic_strides */
++  -1,                   /* minimum_stride */
++  -1                    /* default_opt_level  */
++};
++
+ static const cpu_prefetch_tune xgene1_prefetch_tune =
+ {
+   8,			/* num_slots  */
+@@ -1658,6 +1733,40 @@ static const struct tune_params tsv110_tunings =
+   &tsv110_prefetch_tune
+ };
+ 
++static const struct tune_params hip09_tunings =
++{
++  &hip09_extra_costs,
++  &hip09_addrcost_table,
++  &hip09_regmove_cost,
++  &hip09_vector_cost,
++  &generic_branch_cost,
++  &generic_approx_modes,
++  SVE_256, /* sve_width  */
++  { 4, /* load_int.  */
++    4, /* store_int.  */
++    4, /* load_fp.  */
++    4, /* store_fp.  */
++    4, /* load_pred.  */
++    4 /* store_pred.  */
++  }, /* memmov_cost.  */
++  4,    /* issue_rate  */
++  (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_ALU_BRANCH
++   | AARCH64_FUSE_ALU_CBZ), /* fusible_ops  */
++  "16", /* function_align.  */
++  "4",  /* jump_align.  */
++  "8",  /* loop_align.  */
++  2,    /* int_reassoc_width.  */
++  4,    /* fp_reassoc_width.  */
++  1,    /* vec_reassoc_width.  */
++  2,    /* min_div_recip_mul_sf.  */
++  2,    /* min_div_recip_mul_df.  */
++  0,    /* max_case_values.  */
++  tune_params::AUTOPREFETCHER_WEAK,     /* autoprefetcher_model.  */
++  (AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS
++   | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT),     /* tune_flags.  */
++  &hip09_prefetch_tune
++};
++
+ static const struct tune_params xgene1_tunings =
+ {
+   &xgene1_extra_costs,
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index d24c8afcf..cf699e4c7 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -477,6 +477,7 @@
+ (include "thunderx2t99.md")
+ (include "tsv110.md")
+ (include "thunderx3t110.md")
++(include "hip09.md")
+ 
+ ;; -------------------------------------------------------------------
+ ;; Jumps and other miscellaneous insns
+diff --git a/gcc/config/aarch64/hip09.md b/gcc/config/aarch64/hip09.md
+new file mode 100644
+index 000000000..25428de9a
+--- /dev/null
++++ b/gcc/config/aarch64/hip09.md
+@@ -0,0 +1,558 @@
++;; hip09 pipeline description
++;; Copyright (C) 2023 Free Software Foundation, Inc.
++;;
++;;Contributed by Yushuai Xing
++;;
++;; 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
++;; .
++
++(define_automaton "hip09")
++(define_automaton "hip09_ldst")
++(define_automaton "hip09_fsu")
++
++(define_attr "hip09_type"
++  "hip09_neon_abs, hip09_neon_fp_arith, hip09_neon_mul, hip09_neon_mla,
++   hip09_neon_dot, hip09_neon_fp_div, hip09_neon_fp_sqrt,
++   hip09_neon_ins, hip09_neon_load1, hip09_neon_load1_lanes,
++   hip09_neon_load2and4, hip09_neon_load3_3reg,
++   hip09_neon_load4_4reg, hip09_neon_store1and2,
++   hip09_neon_store1_1reg, hip09_neon_store1_2reg,
++   hip09_neon_store1_3reg, hip09_neon_store1_4reg,
++   hip09_neon_store3and4_lane, hip09_neon_store3_3reg,
++   hip09_neon_store4_4reg, unknown"
++  (cond [
++         (eq_attr "type" "neon_abs,neon_abs_q,neon_add,neon_add_q,\
++                  neon_neg,neon_neg_q,neon_sub,neon_sub_q,neon_add_widen,\
++                  neon_sub_widen,neon_qadd,neon_qadd_q,\
++                  neon_add_long,neon_sub_long,\
++                  neon_qabs,neon_qabs_q,neon_qneg,\
++                  neon_qneg_q,neon_qsub,neon_qsub_q,neon_compare,\
++                  neon_compare_q,neon_compare_zero,\
++                  neon_compare_zero_q,neon_logic,neon_logic_q,\
++                  neon_minmax,neon_minmax_q,neon_tst,\
++                  neon_tst_q,neon_bsl,neon_bsl_q,\
++                  neon_cls,neon_cls_q,neon_ext,\
++                  neon_ext_q,neon_rev,neon_rev_q,\
++                  neon_tbl1,neon_tbl1_q,neon_fp_abs_s,\
++                  neon_fp_abs_s_q,neon_fp_abs_d,\
++                  neon_fp_neg_s,neon_fp_neg_s_q,\
++                  neon_fp_neg_d,neon_fp_neg_d_q,\
++                  neon_shift_imm_narrow_q,neon_move,neon_move_q")
++           (const_string "hip09_neon_abs")
++         (eq_attr "type" "neon_abd,neon_abd_q,\
++                  neon_arith_acc,neon_arith_acc_q,\
++                  neon_add_halve,neon_add_halve_q,\
++                  neon_sub_halve,neon_sub_halve_q,\
++                  neon_add_halve_narrow_q,\
++                  neon_sub_halve_narrow_q,neon_reduc_add,\
++                  neon_reduc_add_q,\
++                  neon_sat_mul_b,neon_sat_mul_b_q,\
++                  neon_sat_mul_b_long,neon_mul_b,neon_mul_b_q,\
++                  neon_mul_b_long,neon_mla_b,neon_mla_b_q,\
++                  neon_mla_b_long,neon_sat_mla_b_long,\
++                  neon_sat_shift_imm,\
++                  neon_sat_shift_imm_q,neon_shift_imm_long,\
++                  neon_shift_imm,neon_shift_imm_q,neon_cnt,\
++                  neon_cnt_q,neon_fp_recpe_s,neon_fp_recpe_s_q,\
++                  neon_fp_recpe_d,neon_fp_recpe_d_q,\
++                  neon_fp_rsqrte_s,neon_fp_rsqrte_s_q,\
++                  neon_fp_rsqrte_d,neon_fp_rsqrte_d_q,\
++                  neon_fp_recpx_s,neon_fp_recpx_s_q,\
++                  neon_fp_recpx_d,neon_fp_recpx_d_q,\
++                  neon_tbl2,neon_tbl2_q,neon_to_gp,\
++                  neon_to_gp_q,neon_fp_abd_s,neon_fp_abd_s_q,\
++                  neon_fp_abd_d,neon_fp_abd_d_q,\
++                  neon_fp_addsub_s,neon_fp_addsub_s_q,\
++                  neon_fp_addsub_d,neon_fp_addsub_d_q,\
++                  neon_fp_compare_s,neon_fp_compare_s_q,\
++                  neon_fp_compare_d,neon_fp_compare_d_q,\
++                  neon_fp_cvt_widen_s,neon_fp_to_int_s,\
++                  neon_fp_to_int_s_q,neon_fp_to_int_d,\
++                  neon_fp_to_int_d_q,neon_fp_minmax_s,\
++                  neon_fp_minmax_s_q,neon_fp_minmax_d,\
++                  neon_fp_minmax_d_q,neon_fp_round_s,\
++                  neon_fp_round_s_q,neon_fp_cvt_narrow_d_q,\
++                  neon_fp_round_d,neon_fp_round_d_q,\
++                  neon_fp_cvt_narrow_s_q")
++           (const_string "hip09_neon_fp_arith")
++         (eq_attr "type" "neon_sat_mul_h,neon_sat_mul_h_q,\
++                  neon_sat_mul_s,neon_sat_mul_s_q,\
++                  neon_sat_mul_h_scalar,neon_sat_mul_s_scalar,\
++                  neon_sat_mul_h_scalar_q,neon_sat_mul_h_long,\
++                  neon_sat_mul_s_long,neon_sat_mul_h_scalar_long,\
++                  neon_sat_mul_s_scalar_long,neon_mul_h,neon_mul_h_q,\
++                  neon_mul_s,neon_mul_s_q,neon_mul_h_long,\
++                  neon_mul_s_long,neon_mul_h_scalar_long,\
++                  neon_mul_s_scalar_long,neon_mla_h,neon_mla_h_q,\
++                  neon_mla_s,neon_mla_h_scalar,\
++                  neon_mla_h_scalar_q,neon_mla_s_scalar,\
++                  neon_mla_h_long,\
++                  neon_mla_s_long,neon_sat_mla_h_long,\
++                  neon_sat_mla_s_long,neon_sat_mla_h_scalar_long,\
++                  neon_sat_mla_s_scalar_long,neon_mla_s_scalar_long,\
++                  neon_mla_h_scalar_long,neon_mla_s_scalar_q,\
++                  neon_shift_acc,neon_shift_acc_q,neon_shift_reg,\
++                  neon_shift_reg_q,neon_sat_shift_reg,\
++                  neon_sat_shift_reg_q,neon_sat_shift_imm_narrow_q,\
++                  neon_tbl3,neon_tbl3_q,neon_fp_reduc_add_s,\
++                  neon_fp_reduc_add_s_q,neon_fp_reduc_add_d,\
++                  neon_fp_reduc_add_d_q,neon_fp_reduc_minmax_s,\
++                  neon_fp_reduc_minmax_d,neon_fp_reduc_minmax_s_q,\
++                  neon_fp_reduc_minmax_d_q,\
++                  neon_fp_mul_s_q,\
++                  neon_fp_mul_d,neon_fp_mul_d_q,\
++                  neon_fp_mul_d_scalar_q,neon_fp_mul_s_scalar,\
++                  neon_fp_mul_s_scalar_q")
++           (const_string "hip09_neon_mul")
++         (eq_attr "type" "neon_mla_s_q,neon_reduc_minmax,\
++                  neon_reduc_minmax_q,neon_fp_recps_s,\
++                  neon_fp_recps_s_q,neon_fp_recps_d,\
++                  neon_fp_recps_d_q,neon_tbl4,neon_tbl4_q,\
++                  neon_fp_mla_s,\
++                  neon_fp_mla_d,neon_fp_mla_d_q,\
++                  neon_fp_mla_s_scalar,neon_fp_mla_s_scalar_q,\
++                  neon_fp_mla_d_scalar_q")
++           (const_string "hip09_neon_mla")
++         (eq_attr "type" "neon_dot,neon_dot_q")
++           (const_string "hip09_neon_dot")
++         (eq_attr "type" "neon_fp_div_s,neon_fp_div_s_q,\
++                   neon_fp_div_d,neon_fp_div_d_q")
++           (const_string "hip09_neon_fp_div")
++         (eq_attr "type" "neon_fp_sqrt_s,neon_fp_sqrt_s_q,\
++                   neon_fp_sqrt_d,neon_fp_sqrt_d_q")
++           (const_string "hip09_neon_fp_sqrt")
++         (eq_attr "type" "neon_dup,neon_dup_q,\
++                   neon_ins,neon_ins_q")
++           (const_string "hip09_neon_ins")
++         (eq_attr "type" "neon_load1_1reg,neon_load1_1reg_q,\
++                   neon_load1_2reg,neon_load1_2reg_q,\
++                   neon_load1_3reg,neon_load1_3reg_q,\
++                   neon_load1_4reg,neon_load1_4reg_q")
++           (const_string "hip09_neon_load1")
++         (eq_attr "type" "neon_load1_one_lane,\
++                   neon_load1_one_lane_q,\
++                   neon_load1_all_lanes,neon_load1_all_lanes_q")
++           (const_string "hip09_neon_load1_lanes")
++         (eq_attr "type" "neon_load2_all_lanes,\
++                   neon_load2_all_lanes_q,\
++                   neon_load2_one_lane,neon_load2_2reg,\
++                   neon_load2_2reg_q,neon_load3_one_lane,\
++                   neon_load3_all_lanes,neon_load3_all_lanes_q,\
++                   neon_load4_one_lane,neon_load4_all_lanes,\
++                   neon_load4_all_lanes_q")
++           (const_string "hip09_neon_load2and4")
++         (eq_attr "type" "neon_load3_3reg,neon_load3_3reg_q")
++           (const_string "hip09_neon_load3_3reg")
++         (eq_attr "type" "neon_load4_4reg,neon_load4_4reg_q")
++           (const_string "hip09_neon_load4_4reg")
++         (eq_attr "type" "neon_store1_one_lane,\
++                   neon_store1_one_lane_q,neon_store2_one_lane,\
++                   neon_store2_one_lane_q,neon_store2_2reg,\
++                   neon_store2_2reg_q")
++           (const_string "hip09_neon_store1and2")
++         (eq_attr "type" "neon_store1_1reg,neon_store1_1reg_q")
++           (const_string "hip09_neon_store1_1reg")
++         (eq_attr "type" "neon_store1_2reg,neon_store1_2reg_q")
++           (const_string "hip09_neon_store1_2reg")
++         (eq_attr "type" "neon_store1_3reg,neon_store1_3reg_q")
++           (const_string "hip09_neon_store1_3reg")
++         (eq_attr "type" "neon_store1_4reg,neon_store1_4reg_q")
++           (const_string "hip09_neon_store1_4reg")
++         (eq_attr "type" "neon_store3_one_lane,\
++                   neon_store3_one_lane_q,neon_store4_one_lane,\
++                   neon_store4_one_lane_q")
++           (const_string "hip09_neon_store3and4_lane")
++         (eq_attr "type" "neon_store3_3reg,\
++                  neon_store3_3reg_q")
++           (const_string "hip09_neon_store3_3reg")
++         (eq_attr "type" "neon_store4_4reg,\
++                   neon_store4_4reg_q")
++           (const_string "hip09_neon_store4_4reg")]
++  (const_string "unknown")))
++
++; The hip09 core is modelled as issues pipeline that has
++; the following functional units.
++; 1.  Two pipelines for branch micro operations: BRU1, BRU2
++
++(define_cpu_unit "hip09_bru0" "hip09")
++(define_cpu_unit "hip09_bru1" "hip09")
++
++(define_reservation "hip09_bru01" "hip09_bru0|hip09_bru1")
++
++; 2.  Four pipelines for single cycle integer micro operations: ALUs1, ALUs2, ALUs3, ALUs4
++
++(define_cpu_unit "hip09_alus0" "hip09")
++(define_cpu_unit "hip09_alus1" "hip09")
++(define_cpu_unit "hip09_alus2" "hip09")
++(define_cpu_unit "hip09_alus3" "hip09")
++
++(define_reservation "hip09_alus0123" "hip09_alus0|hip09_alus1|hip09_alus2|hip09_alus3")
++(define_reservation "hip09_alus01" "hip09_alus0|hip09_alus1")
++(define_reservation "hip09_alus23" "hip09_alus2|hip09_alus3")
++
++; 3. Two pipelines for multi cycles integer micro operations: ALUm1, ALUm2
++
++(define_cpu_unit "hip09_alum0" "hip09")
++(define_cpu_unit "hip09_alum1" "hip09")
++
++(define_reservation "hip09_alum01" "hip09_alum0|hip09_alum1")
++
++; 4. Two pipelines for load micro opetations: Load1, Load2
++
++(define_cpu_unit "hip09_load0" "hip09_ldst")
++(define_cpu_unit "hip09_load1" "hip09_ldst")
++
++(define_reservation "hip09_ld01" "hip09_load0|hip09_load1")
++
++; 5. Two pipelines for store micro operations: Store1, Store2
++
++(define_cpu_unit "hip09_store0" "hip09_ldst")
++(define_cpu_unit "hip09_store1" "hip09_ldst")
++
++(define_reservation "hip09_st01" "hip09_store0|hip09_store1")
++
++; 6. Two pipelines for store data micro operations: STD0,STD1
++
++(define_cpu_unit "hip09_store_data0" "hip09_ldst")
++(define_cpu_unit "hip09_store_data1" "hip09_ldst")
++
++(define_reservation "hip09_std01" "hip09_store_data0|hip09_store_data1")
++
++; 7.  Four asymmetric pipelines for Asimd and FP micro operations: FSU1, FSU2, FSU3, FSU4
++
++(define_cpu_unit "hip09_fsu0" "hip09_fsu")
++(define_cpu_unit "hip09_fsu1" "hip09_fsu")
++(define_cpu_unit "hip09_fsu2" "hip09_fsu")
++(define_cpu_unit "hip09_fsu3" "hip09_fsu")
++
++(define_reservation "hip09_fsu0123" "hip09_fsu0|hip09_fsu1|hip09_fsu2|hip09_fsu3")
++(define_reservation "hip09_fsu02" "hip09_fsu0|hip09_fsu2")
++
++
++; 8. Two pipelines for sve operations but same with fsu1 and fsu3: SVE1, SVE2
++
++;; Simple Execution Unit:
++;
++;; Simple ALU without shift
++(define_insn_reservation "hip09_alu" 1
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "alu_imm,logic_imm,\
++            adc_imm,adc_reg,\
++            alu_sreg,logic_reg,\
++            mov_imm,mov_reg,\
++            csel,rotate_imm,bfm,mov_imm,\
++            clz,rbit,rev"))
++  "hip09_alus0123")
++
++(define_insn_reservation "hip09_alus" 1
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "alus_sreg,alus_imm,\
++            adcs_reg,adcs_imm,\
++            logics_imm,logics_reg,adr"))
++  "hip09_alus23")
++
++;; ALU ops with shift and extend
++(define_insn_reservation "hip09_alu_ext_shift" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "alu_ext,alus_ext,\
++        logics_shift_imm,logics_shift_reg,\
++        logic_shift_reg,logic_shift_imm,\
++        "))
++  "hip09_alum01")
++
++;; Multiplies instructions
++(define_insn_reservation "hip09_mult" 3
++  (and (eq_attr "tune" "hip09")
++       (ior (eq_attr "mul32" "yes")
++       (eq_attr "widen_mul64" "yes")))
++  "hip09_alum01")
++
++;; Integer divide
++(define_insn_reservation "hip09_div" 10
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "udiv,sdiv"))
++  "hip09_alum0")
++
++;; Branch execution Unit
++;
++; Branches take two issue slot.
++; No latency as there is no result
++(define_insn_reservation "hip09_branch" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "branch,call"))
++  "hip09_bru01 + hip09_alus23")
++
++;; Load execution Unit
++;
++; Loads of up to two words.
++(define_insn_reservation "hip09_load1" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "load_4,load_8"))
++  "hip09_ld01")
++
++; Stores of up to two words.
++(define_insn_reservation "hip09_store1" 1
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "store_4,store_8"))
++  "hip09_st01")
++
++;; FP data processing instructions.
++
++(define_insn_reservation "hip09_fp_arith" 1
++   (and (eq_attr "tune" "hip09")
++        (eq_attr "type" "ffariths,ffarithd,fmov,fconsts,fconstd,\
++         f_mrc"))
++   "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_cmp" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fcmps,fcmpd"))
++  "hip09_fsu0123+hip09_alus23")
++
++(define_insn_reservation "hip09_fp_ccmp" 7
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fccmps,fccmpd"))
++  "hip09_alus01+hip09_fsu0123+hip09_alus23")
++
++(define_insn_reservation "hip09_fp_csel" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fcsel,f_mcr"))
++  "hip09_alus01+hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_divs" 7
++  (and (eq_attr "tune" "hip09")
++  (eq_attr "type" "fdivs"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_divd" 10
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fdivd"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_sqrts" 9
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fsqrts"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_sqrtd" 15
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fsqrtd"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_mul" 3
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fmuls,fmuld"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_add" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fadds,faddd,f_minmaxs,f_minmaxd,f_cvt,\
++       f_rints,f_rintd"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_fp_mac" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "fmacs,fmacd"))
++  "hip09_fsu0123")
++
++;; FP miscellaneous instructions.
++
++(define_insn_reservation "hip09_fp_cvt" 5
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "f_cvtf2i"))
++  "hip09_fsu0123+hip09_alus23")
++
++(define_insn_reservation "hip09_fp_cvt2" 5
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "f_cvti2f"))
++  "hip09_alus01+hip09_fsu0123")
++
++;; FP Load Instructions 
++
++(define_insn_reservation "hip09_fp_load" 7
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "f_loads,f_loadd"))
++  "hip09_ld01")
++
++(define_insn_reservation "hip09_fp_load2" 6
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "neon_ldp_q,neon_ldp"))
++  "hip09_ld01+hip09_alus01")
++
++;; FP store instructions
++
++(define_insn_reservation "hip09_fp_store" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "f_stores,f_stored"))
++  "hip09_st01+hip09_std01")
++
++;; ASIMD integer instructions
++
++(define_insn_reservation "hip09_asimd_base1" 1
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_abs"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_base2" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_fp_arith"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_base3" 3
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_mul"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_base4" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_mla"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_base5" 5
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "neon_fp_mul_s"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_dot" 6
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_dot"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_bfmmla" 9
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "neon_fp_mla_s_q"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_fdiv" 15
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_fp_div"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_fsqrt" 25
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_fp_sqrt"))
++  "hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_pmull" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "crypto_pmull"))
++  "hip09_fsu2")
++
++(define_insn_reservation "hip09_asimd_dup" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_ins"))
++  "hip09_alus01+hip09_fsu0123")
++
++;; ASIMD load instructions
++
++(define_insn_reservation "hip09_asimd_ld1_reg" 6
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_load1"))
++  "hip09_ld01")
++
++(define_insn_reservation "hip09_asimd_ld1_lane" 7
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_load1_lanes"))
++  "hip09_ld01+hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_ld23" 8
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_load2and4"))
++"hip09_ld01+hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_ld3_mtp" 9
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_load3_3reg"))
++  "hip09_ld01+hip09_fsu0123")
++
++(define_insn_reservation "hip09_asimd_ld4_mtp" 13
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_load4_4reg"))
++  "hip09_ld01+hip09_fsu0123")
++
++;; ASIMD store instructions
++
++(define_insn_reservation "hip09_asimd_st12" 1
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store1and2"))
++  "hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st1_1reg" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store1_1reg"))
++  "hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st1_2reg" 3
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store1_2reg"))
++  "hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st1_3reg" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store1_3reg"))
++  "hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st1_4reg" 5
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store1_4reg"))
++  "hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st34_lane" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store3and4_lane"))
++  "hip09_fsu0123+hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st3_mtp" 7
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store3_3reg"))
++  "hip09_fsu0123+hip09_st01+hip09_std01")
++
++(define_insn_reservation "hip09_asimd_st4_mtp" 10
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "hip09_type" "hip09_neon_store4_4reg"))
++  "hip09_fsu0123+hip09_st01+hip09_std01")
++
++;; Cryptography extensions
++
++(define_insn_reservation "hip09_asimd_aes" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "crypto_aese,crypto_aesmc"))
++  "hip09_fsu02")
++
++(define_insn_reservation "hip09_asimd_sha3" 1
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "crypto_sha3"))
++  "hip09_fsu2")
++
++(define_insn_reservation "hip09_asimd_sha1" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "crypto_sha1_fast,crypto_sha1_xor,\
++       crypto_sha256_fast,crypto_sha512,\
++       crypto_sm3"))
++  "hip09_fsu2")
++
++(define_insn_reservation "hip09_asimd_sha1_and256" 4
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "crypto_sha1_slow,crypto_sha256_slow,\
++       crypto_sm4"))
++  "hip09_fsu2")
++
++;; CRC extension.
++
++(define_insn_reservation "hip09_crc" 2
++  (and (eq_attr "tune" "hip09")
++       (eq_attr "type" "crc"))
++  "hip09_alum01")
+-- 
+2.33.0
+
diff --git a/0101-Add-hip11-CPU-pipeline-scheduling.patch b/0101-Add-hip11-CPU-pipeline-scheduling.patch
new file mode 100644
index 0000000..7b89890
--- /dev/null
+++ b/0101-Add-hip11-CPU-pipeline-scheduling.patch
@@ -0,0 +1,755 @@
+From 824fccdab1d3c5e87fb88b31f0eeb7abd1b35c1f Mon Sep 17 00:00:00 2001
+From: XingYuShuai <1150775134@qq.com>
+Date: Mon, 26 Feb 2024 20:34:06 +0800
+Subject: [PATCH 002/157] Add hip11 CPU pipeline scheduling
+
+This patch adds an mcpu: hip11. It has been tested on aarch64
+and no regressions from this patch.
+---
+ gcc/config/aarch64/aarch64-cores.def     |   1 +
+ gcc/config/aarch64/aarch64-cost-tables.h | 104 ++++++
+ gcc/config/aarch64/aarch64-tune.md       |   2 +-
+ gcc/config/aarch64/aarch64.cc            | 108 ++++++
+ gcc/config/aarch64/aarch64.md            |   1 +
+ gcc/config/aarch64/hip11.md              | 418 +++++++++++++++++++++++
+ gcc/doc/invoke.texi                      |   2 +-
+ 7 files changed, 634 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/config/aarch64/hip11.md
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index a854bdb24..601b72abb 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -173,6 +173,7 @@ AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, 9A,  AARCH64_FL_FOR_ARCH9 |
+ 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)
+ 
+ AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
++AARCH64_CORE("hip11", hip11, hip11, 8_5A, AARCH64_FL_FOR_ARCH8_5| AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_F16, hip11, 0x48, 0xd22, -1)
+ 
+ AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+ AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+diff --git a/gcc/config/aarch64/aarch64-cost-tables.h b/gcc/config/aarch64/aarch64-cost-tables.h
+index fc5a3cbe4..0ee427b61 100644
+--- a/gcc/config/aarch64/aarch64-cost-tables.h
++++ b/gcc/config/aarch64/aarch64-cost-tables.h
+@@ -561,6 +561,110 @@ const struct cpu_cost_table tsv110_extra_costs =
+   }
+ };
+ 
++const struct cpu_cost_table hip11_extra_costs =
++{
++  /* ALU */
++  {
++    0,                 /* arith.  */
++    0,                 /* logical.  */
++    0,                 /* shift.  */
++    0,                 /* shift_reg.  */
++    COSTS_N_INSNS (1), /* arith_shift.  */
++    COSTS_N_INSNS (1), /* arith_shift_reg.  */
++    COSTS_N_INSNS (1), /* log_shift.  */
++    COSTS_N_INSNS (1), /* log_shift_reg.  */
++    0,                 /* extend.  */
++    COSTS_N_INSNS (1), /* extend_arith.  */
++    0,                 /* bfi.  */
++    0,                 /* bfx.  */
++    0,                 /* clz.  */
++    0,                 /* rev.  */
++    0,                 /* non_exec.  */
++    true               /* non_exec_costs_exec.  */
++  },
++
++  {
++    /* MULT SImode */
++    {
++      COSTS_N_INSNS (2),       /* simple.  */
++      COSTS_N_INSNS (2),       /* flag_setting.  */
++      COSTS_N_INSNS (2),       /* extend.  */
++      COSTS_N_INSNS (2),       /* add.  */
++      COSTS_N_INSNS (2),       /* extend_add.  */
++      COSTS_N_INSNS (11)       /* idiv.  */
++    },
++    /* MULT DImode */
++    {
++      COSTS_N_INSNS (3),       /* simple.  */
++      0,                       /* flag_setting (N/A).  */
++      COSTS_N_INSNS (3),       /* extend.  */
++      COSTS_N_INSNS (3),       /* add.  */
++      COSTS_N_INSNS (3),       /* extend_add.  */
++      COSTS_N_INSNS (19)       /* idiv.  */
++    }
++  },
++  /* LD/ST */
++  {
++    COSTS_N_INSNS (3),         /* load.  */
++    COSTS_N_INSNS (4),         /* load_sign_extend.  */
++    COSTS_N_INSNS (3),         /* ldrd.  */
++    COSTS_N_INSNS (3),         /* ldm_1st.  */
++    1,                         /* ldm_regs_per_insn_1st.  */
++    2,                         /* ldm_regs_per_insn_subsequent.  */
++    COSTS_N_INSNS (4),         /* loadf.  */
++    COSTS_N_INSNS (4),         /* loadd.  */
++    COSTS_N_INSNS (4),         /* load_unaligned.  */
++    0,                         /* store.  */
++    0,                         /* strd.  */
++    0,                         /* stm_1st.  */
++    1,                         /* stm_regs_per_insn_1st.  */
++    2,                         /* stm_regs_per_insn_subsequent.  */
++    0,                         /* storef.  */
++    0,                         /* stored.  */
++    COSTS_N_INSNS (1),         /* store_unaligned.  */
++    COSTS_N_INSNS (4),         /* loadv.  */
++    COSTS_N_INSNS (4)          /* storev.  */
++  },
++  {
++    /* FP SFmode */
++    {
++      COSTS_N_INSNS (10),      /* div.  */
++      COSTS_N_INSNS (4),       /* mult.  */
++      COSTS_N_INSNS (4),       /* mult_addsub.  */
++      COSTS_N_INSNS (4),       /* fma.  */
++      COSTS_N_INSNS (4),       /* addsub.  */
++      COSTS_N_INSNS (1),       /* fpconst.  */
++      COSTS_N_INSNS (1),       /* neg.  */
++      COSTS_N_INSNS (1),       /* compare.  */
++      COSTS_N_INSNS (2),       /* widen.  */
++      COSTS_N_INSNS (2),       /* narrow.  */
++      COSTS_N_INSNS (2),       /* toint.  */
++      COSTS_N_INSNS (1),       /* fromint.  */
++      COSTS_N_INSNS (2)        /* roundint.  */
++    },
++    /* FP DFmode */
++    {
++      COSTS_N_INSNS (17),      /* div.  */
++      COSTS_N_INSNS (4),       /* mult.  */
++      COSTS_N_INSNS (6),       /* mult_addsub.  */
++      COSTS_N_INSNS (6),       /* fma.  */
++      COSTS_N_INSNS (3),       /* addsub.  */
++      COSTS_N_INSNS (1),       /* fpconst.  */
++      COSTS_N_INSNS (1),       /* neg.  */
++      COSTS_N_INSNS (1),       /* compare.  */
++      COSTS_N_INSNS (2),       /* widen.  */
++      COSTS_N_INSNS (2),       /* narrow.  */
++      COSTS_N_INSNS (2),       /* toint.  */
++      COSTS_N_INSNS (1),       /* fromint.  */
++      COSTS_N_INSNS (2)        /* roundint.  */
++    }
++  },
++  /* Vector */
++  {
++    COSTS_N_INSNS (1)  /* alu.  */
++  }
++};
++
+ const struct cpu_cost_table a64fx_extra_costs =
+ {
+   /* ALU */
+diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
+index 238bb6e31..511422081 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,ampere1,ampere1a,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,hip09,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2,neoversen2,demeter,neoversev2"
++	"cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,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,hip09,thunderx3t110,zeus,neoversev1,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexx2,neoversen2,hip11,demeter,neoversev2"
+ 	(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index e9b3980c4..7c62ddb2a 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -481,6 +481,22 @@ static const struct cpu_addrcost_table hip09_addrcost_table =
+   0, /* imm_offset  */
+ };
+ 
++static const struct cpu_addrcost_table hip11_addrcost_table =
++{
++    {
++      1, /* hi  */
++      0, /* si  */
++      0, /* di  */
++      1, /* ti  */
++    },
++  0, /* pre_modify  */
++  0, /* post_modify  */
++  0, /* register_offset  */
++  1, /* register_sextend  */
++  1, /* register_zextend  */
++  0, /* imm_offset  */
++};
++
+ static const struct cpu_addrcost_table qdf24xx_addrcost_table =
+ {
+     {
+@@ -666,6 +682,16 @@ static const struct cpu_regmove_cost tsv110_regmove_cost =
+   2  /* FP2FP  */
+ };
+ 
++static const struct cpu_regmove_cost hip11_regmove_cost =
++{
++  1, /* GP2GP  */
++  /* Avoid the use of slow int<->fp moves for spilling by setting
++     their cost higher than memmov_cost.  */
++  2, /* GP2FP  */
++  3, /* FP2GP  */
++  2  /* FP2FP  */
++};
++
+ static const struct cpu_regmove_cost a64fx_regmove_cost =
+ {
+   1, /* GP2GP  */
+@@ -1010,6 +1036,43 @@ static const struct cpu_vector_cost hip09_vector_cost =
+   nullptr /* issue_info  */
+ };
+ 
++static const advsimd_vec_cost hip11_advsimd_vector_cost =
++{
++  2, /* int_stmt_cost  */
++  2, /* fp_stmt_cost  */
++  0, /* ld2_st2_permute_cost  */
++  0, /* ld3_st3_permute_cost  */
++  0, /* ld4_st4_permute_cost  */
++  2, /* permute_cost  */
++  3, /* reduc_i8_cost  */
++  3, /* reduc_i16_cost  */
++  3, /* reduc_i32_cost  */
++  3, /* reduc_i64_cost  */
++  3, /* reduc_f16_cost  */
++  3, /* reduc_f32_cost  */
++  3, /* reduc_f64_cost  */
++  3, /* store_elt_extra_cost  */
++  5, /* vec_to_scalar_cost  */
++  5, /* scalar_to_vec_cost  */
++  5, /* align_load_cost  */
++  5, /* unalign_load_cost  */
++  1, /* unalign_store_cost  */
++  1  /* store_cost  */
++};
++
++static const struct cpu_vector_cost hip11_vector_cost =
++{
++  1, /* scalar_int_stmt_cost  */
++  1, /* scalar_fp_stmt_cost  */
++  5, /* scalar_load_cost  */
++  1, /* scalar_store_cost  */
++  1, /* cond_taken_branch_cost  */
++  1, /* cond_not_taken_branch_cost  */
++  &hip11_advsimd_vector_cost, /* advsimd  */
++  nullptr, /* sve  */
++  nullptr /* issue_info  */
++};
++
+ static const advsimd_vec_cost cortexa57_advsimd_vector_cost =
+ {
+   2, /* int_stmt_cost  */
+@@ -1368,6 +1431,17 @@ static const cpu_prefetch_tune hip09_prefetch_tune =
+   -1                    /* default_opt_level  */
+ };
+ 
++static const cpu_prefetch_tune hip11_prefetch_tune =
++{
++  0,                    /* num_slots  */
++  64,                   /* l1_cache_size  */
++  64,                   /* l1_cache_line_size  */
++  512,                  /* l2_cache_size  */
++  true,                 /* prefetch_dynamic_strides */
++  -1,                   /* minimum_stride */
++  -1                    /* default_opt_level  */
++};
++
+ static const cpu_prefetch_tune xgene1_prefetch_tune =
+ {
+   8,			/* num_slots  */
+@@ -1767,6 +1841,40 @@ static const struct tune_params hip09_tunings =
+   &hip09_prefetch_tune
+ };
+ 
++static const struct tune_params hip11_tunings =
++{
++  &hip11_extra_costs,
++  &hip11_addrcost_table,
++  &hip11_regmove_cost,
++  &hip11_vector_cost,
++  &generic_branch_cost,
++  &generic_approx_modes,
++  SVE_512, /* sve_width  */
++  { 4, /* load_int.  */
++    4, /* store_int.  */
++    4, /* load_fp.  */
++    4, /* store_fp.  */
++    4, /* load_pred.  */
++    4 /* store_pred.  */
++  }, /* memmov_cost.  */
++  4,    /* issue_rate  */
++  (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_ALU_BRANCH
++   | AARCH64_FUSE_ALU_CBZ), /* fusible_ops  */
++  "16", /* function_align.  */
++  "4",  /* jump_align.  */
++  "8",  /* loop_align.  */
++  2,    /* int_reassoc_width.  */
++  4,    /* fp_reassoc_width.  */
++  1,    /* vec_reassoc_width.  */
++  2,    /* min_div_recip_mul_sf.  */
++  2,    /* min_div_recip_mul_df.  */
++  0,    /* max_case_values.  */
++  tune_params::AUTOPREFETCHER_WEAK,     /* autoprefetcher_model.  */
++  (AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS
++   | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT),     /* tune_flags.  */
++  &hip11_prefetch_tune
++};
++
+ static const struct tune_params xgene1_tunings =
+ {
+   &xgene1_extra_costs,
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index cf699e4c7..c0c64a798 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -478,6 +478,7 @@
+ (include "tsv110.md")
+ (include "thunderx3t110.md")
+ (include "hip09.md")
++(include "hip11.md")
+ 
+ ;; -------------------------------------------------------------------
+ ;; Jumps and other miscellaneous insns
+diff --git a/gcc/config/aarch64/hip11.md b/gcc/config/aarch64/hip11.md
+new file mode 100644
+index 000000000..45f91e65b
+--- /dev/null
++++ b/gcc/config/aarch64/hip11.md
+@@ -0,0 +1,418 @@
++;; hip11 pipeline description
++;; Copyright (C) 2018-2024 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
++;; .
++
++(define_automaton "hip11")
++
++;; The hip11 core is modelled as issues pipeline that has
++;; the following functional units.
++;; 1.  Three pipelines for integer operations: ALU1, ALU2, ALU3
++
++(define_cpu_unit "hip11_alu1_issue" "hip11")
++(define_reservation "hip11_alu1" "hip11_alu1_issue")
++
++(define_cpu_unit "hip11_alu2_issue" "hip11")
++(define_reservation "hip11_alu2" "hip11_alu2_issue")
++
++(define_cpu_unit "hip11_alu3_issue" "hip11")
++(define_reservation "hip11_alu3" "hip11_alu3_issue")
++
++(define_reservation "hip11alu" "hip11_alu1|hip11_alu2|hip11_alu3")
++
++;; 2.  One pipeline for complex integer operations: MDU
++
++(define_cpu_unit "hip11_mdu_issue" "hip11")
++(define_reservation "hip11_mdu" "hip11_mdu_issue")
++
++;; 3.  Two asymmetric pipelines for Asimd and FP operations: FSU1, FSU2
++(define_automaton "hip11_fsu")
++
++(define_cpu_unit "hip11_fsu1_issue"
++		 "hip11_fsu")
++(define_cpu_unit "hip11_fsu2_issue"
++		 "hip11_fsu")
++
++(define_reservation "hip11_fsu1" "hip11_fsu1_issue")
++(define_reservation "hip11_fsu2" "hip11_fsu2_issue")
++(define_reservation "hip11_fsu_pipe" "hip11_fsu1|hip11_fsu2")
++
++;; 4.  Two pipeline for branch operations but same with alu2 and alu3: BRU1, BRU2
++
++;; 5.  Two pipelines for load and store operations: LS1, LS2.
++
++(define_cpu_unit "hip11_ls1_issue" "hip11")
++(define_cpu_unit "hip11_ls2_issue" "hip11")
++(define_reservation "hip11_ls1" "hip11_ls1_issue")
++(define_reservation "hip11_ls2" "hip11_ls2_issue")
++
++;; Block all issue queues.
++
++(define_reservation "hip11_block" "hip11_fsu1_issue + hip11_fsu2_issue
++				  + hip11_mdu_issue + hip11_alu1_issue
++				  + hip11_alu2_issue + hip11_alu3_issue + hip11_ls1_issue + hip11_ls2_issue")
++
++;; Branch execution Unit
++;;
++(define_insn_reservation "hip11_branch" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "branch"))
++  "hip11_alu2|hip11_alu3")
++
++(define_insn_reservation "hip11_return_from_subroutine" 6
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "branch")
++       (eq_attr "sls_length" "retbr"))
++  "hip11_mdu,(hip11_alu2|hip11_alu3)")
++
++  ;; Simple Execution Unit:
++;;
++;; Simple ALU without shift
++(define_insn_reservation "hip11_alu" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "alu_imm,logic_imm,\
++			alu_sreg,logic_reg,\
++			adc_imm,adc_reg,\
++			adr,bfm,clz,rbit,rev,\
++			shift_imm,shift_reg,\
++			mov_imm,mov_reg,\
++			mvn_imm,mvn_reg,\
++			mrs,multiple,csel,\
++            rotate_imm"))
++  "hip11_alu1|hip11_alu2|hip11_alu3")
++  
++(define_insn_reservation "hip11_alus" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "alus_imm,logics_imm,\
++			alus_sreg,logics_reg,\
++			adcs_imm,adcs_reg"))
++  "hip11_alu2|hip11_alu3")
++
++;; ALU ops with shift
++(define_insn_reservation "hip11_alu_shift" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "extend,\
++			alu_shift_imm_lsl_1to4,alu_shift_imm_other,alu_shift_reg,\
++			crc,logic_shift_imm,logic_shift_reg,\
++			mov_shift,mvn_shift,\
++			mov_shift_reg,mvn_shift_reg"))
++  "hip11_mdu")
++  
++(define_insn_reservation "hip11_alus_shift" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "alus_shift_imm,alus_shift_reg,\
++			logics_shift_imm,logics_shift_reg"))
++  "hip11_alu2|hip11_alu3")
++
++;; Multiplies instructions
++(define_insn_reservation "hip11_mult" 3
++  (and (eq_attr "tune" "hip11")
++       (ior (eq_attr "mul32" "yes")
++	    (eq_attr "widen_mul64" "yes")))
++  "hip11_mdu")
++
++;; Integer divide
++(define_insn_reservation "hip11_div" 10
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "udiv,sdiv"))
++  "hip11_mdu")
++
++(define_insn_reservation "hip11_mla" 4
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "mla,smlal,umlal,smull,umull"))
++  "hip11_mdu")
++
++;; Block all issue pipes for a cycle
++(define_insn_reservation "hip11_block" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "block"))
++  "hip11_block")
++
++;; Load-store execution Unit
++;;
++(define_insn_reservation "hip11_load1" 4
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "load_4,load_8,load_16"))
++  "hip11_ls1|hip11_ls2")
++
++(define_insn_reservation "hip11_fp_load" 5
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "f_loads,f_loadd"))
++  "hip11_ls1|hip11_ls2")
++
++(define_insn_reservation "hip11_neon_ld1_single" 7
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load1_one_lane,neon_load1_one_lane_q,\
++       neon_load1_all_lanes,neon_load1_all_lanes_q"))
++  "(hip11_ls1|hip11_ls2)+hip11_fsu1")
++
++(define_insn_reservation "hip11_neon_ld1_1reg" 5
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load1_1reg,neon_load1_1reg_q"))
++  "hip11_ls1|hip11_ls2")
++
++(define_insn_reservation "hip11_neon_ld1_2reg" 6
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load1_2reg,neon_load1_2reg_q"))
++  "hip11_ls1|hip11_ls2")
++
++(define_insn_reservation "hip11_neon_ld1_3reg" 7
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load1_3reg,neon_load1_3reg_q"))
++  "hip11_ls1|hip11_ls2")
++
++(define_insn_reservation "hip11_neon_ld1_4reg" 8
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load1_4reg,neon_load1_4reg_q"))
++  "hip11_ls1|hip11_ls2")
++
++(define_insn_reservation "hip11_neon_ld2" 8
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load2_one_lane,neon_load2_one_lane_q,\
++       neon_load2_all_lanes,neon_load2_all_lanes_q,\
++       neon_load2_2reg,neon_load2_2reg_q,\
++       neon_load2_4reg,neon_load2_4reg_q"))
++  "(hip11_ls1|hip11_ls2)+hip11_fsu1")
++
++(define_insn_reservation "hip11_neon_ld3_single" 9
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load3_one_lane,neon_load3_one_lane_q,\
++       neon_load3_all_lanes,neon_load3_all_lanes_q"))
++  "(hip11_ls1|hip11_ls2)+hip11_fsu1")
++
++(define_insn_reservation "hip11_neon_ld3_multiple" 13
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load3_3reg,neon_load3_3reg_q"))
++  "(hip11_ls1|hip11_ls2)+hip11_fsu1")
++
++(define_insn_reservation "hip11_neon_ld4_single" 10
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load4_one_lane,neon_load4_one_lane_q,\
++       neon_load4_all_lanes,neon_load4_all_lanes_q"))
++  "(hip11_ls1|hip11_ls2)+hip11_fsu1")
++
++(define_insn_reservation "hip11_neon_ld4_multiple" 11
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_load4_4reg,neon_load4_4reg_q"))
++  "(hip11_ls1|hip11_ls2)+hip11_fsu1")
++
++;; Stores of up to two words.
++(define_insn_reservation "hip11_store1" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "store_4,store_8,store_16,\
++       f_stored,f_stores"))
++  "hip11_ls1|hip11_ls2")
++
++;; Floating-Point Operations.
++(define_insn_reservation "hip11_fp_arith" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "ffariths,ffarithd,f_minmaxs,\
++       f_minmaxd,fadds,faddd,neon_fcadd"))
++  "hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_fp_mul" 3
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_fp_mul_d,neon_fp_mul_d_q,\
++       neon_fp_mul_s_scalar,neon_fp_mul_s_scalar_q,\
++       neon_fp_mul_d_scalar_q,fmuld,fmuls"))
++  "hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_fp_cmp" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fccmpd,fccmps"))
++  "hip11alu,hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_fp_csel" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fcsel"))
++  "hip11alu,hip11_fsu1")
++
++(define_insn_reservation "hip11_fp_fcmp" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fcmpd,fcmps"))
++  "hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_fp_divs" 7
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fdivs"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_fp_divd" 10
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fdivd"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_fp_sqrts" 9
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fsqrts"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_fp_sqrtd" 15
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fsqrtd"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_fp_mac" 4
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fmacs,ffmas,fmacd,ffmad"))
++  "hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_fp_mov" 1
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "fmov,neon_dup,neon_dup_q,\
++       neon_from_gp,neon_from_gp_q,\
++       neon_ins,neon_ins_q,\
++       neon_to_gp,neon_to_gp_q,\
++       neon_move,neon_move_q,\
++       neon_rev,neon_rev_q,\
++       neon_permute,neon_permute_q,\
++       neon_shift_imm_narrow_q,\
++       neon_ext,neon_ext_q,\
++       neon_rbit,\
++       crypto_sha3,neon_tbl1,neon_tbl1_q,\
++       neon_tbl2_q,f_mcr,neon_tst,neon_tst_q,\
++       neon_move_narrow_q"))
++  "hip11_fsu1")
++
++;; ASIMD instructions
++(define_insn_reservation "hip11_asimd_simple_arithmetic" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_abs,neon_abs_q,neon_neg,neon_neg_q,\
++       neon_abd,neon_abd_q,\
++       neon_add_long,neon_sub_long,neon_sub_widen,neon_add_widen,\
++       neon_add_halve_narrow_q,neon_sub_halve_narrow_q,\
++       neon_arith_acc,neon_arith_acc_q,\
++       neon_compare,neon_compare_q,\
++       neon_compare_zero,neon_compare_zero_q,\
++       neon_minmax,neon_minmax_q,\
++       neon_logic,neon_logic_q,\
++       neon_reduc_add,neon_reduc_add_q,\
++       neon_reduc_minmax,neon_reduc_minmax_q,\
++       neon_fp_to_int_s,neon_fp_to_int_s_q,\
++       neon_fp_to_int_d,neon_fp_to_int_d_q,\
++       neon_fp_cvt_widen_s,\
++       neon_fp_cvt_narrow_d_q,\
++       neon_cls,neon_cls_q,\
++       neon_cnt,neon_cnt_q,\
++       f_rints,f_rintd,f_cvtf2i,f_cvt,\
++       neon_tbl3,neon_fp_round_s,neon_fp_round_s_q,\
++       neon_fp_round_d,neon_fp_round_d_q,\
++       neon_int_to_fp_s,neon_fp_recpe_s,neon_fp_recpe_s_q,\
++       neon_fp_recpe_d,neon_fp_recpe_d_q,\
++       neon_fp_cvt_narrow_s_q,\
++       crypto_aese,crypto_aesmc,\
++       crypto_sha1_fast,crypto_sha1_xor,\
++       crypto_sha1_slow,\
++       crypto_sha256_fast,\
++       crypto_sha512,crypto_sm3,\
++       neon_qabs,neon_qabs_q,\
++       neon_qneg,neon_qneg_q,\
++       neon_qadd,neon_qadd_q,\
++       neon_qsub,neon_qsub_q,\
++       neon_add_halve,neon_add_halve_q,\
++       neon_sub_halve,neon_sub_halve_q,\
++       neon_fp_reduc_minmax_s,neon_fp_reduc_minmax_s_q,\
++       neon_fp_reduc_minmax_d,neon_fp_reduc_minmax_d_q,\
++       neon_fp_rsqrte_s,neon_fp_rsqrte_s_q,\
++       neon_fp_rsqrte_d,neon_fp_rsqrte_d_q"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_asimd_complex_arithmetic" 4
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_mul_b,neon_mul_b_q,\
++       neon_mul_h,neon_mul_h_q,\
++       neon_mul_s,neon_mul_s_q,\
++       neon_mla_b,neon_mla_b_q,\
++       neon_mla_h,neon_mla_h_q,\
++       neon_mla_s,\
++       neon_mla_h_scalar,neon_mla_h_scalar_q,\
++       neon_mla_s_scalar,neon_mla_s_scalar_q,\
++       neon_sat_mul_h_scalar,neon_sat_mul_h_scalar_q,\
++       neon_sat_mul_s_scalar,neon_sat_mul_s_scalar_q,\
++       neon_sat_mul_b,neon_sat_mul_b_q,\
++       neon_sat_mul_h,neon_sat_mul_h_q,\
++       neon_sat_mul_s,neon_sat_mul_s_q,\
++       neon_mla_b_long,neon_mla_h_long,neon_mla_s_long,\
++       neon_mul_b_long,neon_mul_h_long,neon_mul_s_long,\
++       neon_sat_mla_b_long,neon_sat_mla_h_long,neon_sat_mla_s_long,\
++       neon_sat_mla_h_scalar_long,neon_sat_mla_s_scalar_long,\
++       neon_sat_mul_b_long,neon_sat_mul_h_long,neon_sat_mul_s_long,\
++       neon_sat_mul_h_scalar_long,neon_sat_mul_s_scalar_long,\
++       crypto_pmull,\
++       neon_sat_shift_reg,neon_sat_shift_reg_q,\
++       neon_shift_reg,neon_shift_reg_q,\
++       neon_shift_imm,neon_shift_imm_q,\
++       neon_shift_imm_long,\
++       neon_sat_shift_imm,neon_sat_shift_imm_q,\
++       neon_sat_shift_imm_narrow_q,\
++       neon_shift_acc,neon_shift_acc_q,\
++       crypto_sha256_slow"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_asimd_fp_compare" 2
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_fp_abs_s,neon_fp_abs_s_q,\
++       neon_fp_abs_d,neon_fp_abs_d_q,\
++       neon_fp_neg_s,neon_fp_neg_s_q,\
++       neon_fp_neg_d,neon_fp_neg_d_q,\
++       neon_fp_compare_s,neon_fp_compare_s_q,\
++       neon_fp_compare_d,neon_fp_compare_d_q,\
++       neon_fp_minmax_s,neon_fp_minmax_s_q,\
++       neon_fp_minmax_d,neon_fp_minmax_d_q,\
++       neon_fp_addsub_s,neon_fp_addsub_s_q,\
++       neon_fp_addsub_d,neon_fp_addsub_d_q,\
++       neon_fp_reduc_add_s,neon_fp_reduc_add_s_q,\
++       neon_fp_reduc_add_d,neon_fp_reduc_add_d_q,\
++       neon_fp_abd_s,neon_fp_abd_s_q,\
++       neon_fp_abd_d,neon_fp_abd_d_q"))
++  "hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_asimd_fdiv" 10
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_fp_div_s,neon_fp_div_s_q,\
++       neon_fp_div_d,neon_fp_div_d_q"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_asimd_fsqrt" 15
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_fp_sqrt_s,neon_fp_sqrt_s_q,\
++       neon_fp_sqrt_d,neon_fp_sqrt_d_q"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_asimd_fp_multiply_add" 4
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_fp_mla_s,neon_fp_mla_s_q,\
++       neon_fp_mla_d,neon_fp_mla_d_q,\
++       neon_fp_mla_s_scalar,neon_fp_mla_s_scalar_q,\
++       neon_fp_mul_s,neon_fp_mul_s_q,neon_fcmla,\
++       neon_fp_recps_s,neon_fp_recps_s_q,\
++       neon_fp_recps_d,neon_fp_recps_d_q,\
++       neon_fp_rsqrts_s,neon_fp_rsqrts_s_q,\
++       neon_fp_rsqrts_d,neon_fp_rsqrts_d_q"))
++  "hip11_fsu_pipe")
++
++(define_insn_reservation "hip11_asimd_frecpx" 3
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_fp_recpx_s,neon_fp_recpx_s_q,\
++       neon_fp_recpx_d,neon_fp_recpx_d_q,neon_tbl4,\
++       neon_dot,neon_dot_q"))
++  "hip11_fsu1")
++
++(define_insn_reservation "hip11_asimd_mmla" 6
++  (and (eq_attr "tune" "hip11")
++       (eq_attr "type" "neon_mla_s_q"))
++  "hip11_fsu1")
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 7ca60dd64..17d9e4126 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -19212,7 +19212,7 @@ performance of the code.  Permissible values for this option are:
+ @samp{octeontx2}, @samp{octeontx2t98}, @samp{octeontx2t96}
+ @samp{octeontx2t93}, @samp{octeontx2f95}, @samp{octeontx2f95n},
+ @samp{octeontx2f95mm},
+-@samp{a64fx},
++@samp{a64fx},@samp{hip11}
+ @samp{thunderx}, @samp{thunderxt88},
+ @samp{thunderxt88p1}, @samp{thunderxt81}, @samp{tsv110},
+ @samp{thunderxt83}, @samp{thunderx2t99}, @samp{thunderx3t110}, @samp{zeus},
+-- 
+2.33.0
+
diff --git a/0102-Add-Crc32-Optimization-in-Gzip-For-crc32-algorithm-i.patch b/0102-Add-Crc32-Optimization-in-Gzip-For-crc32-algorithm-i.patch
new file mode 100644
index 0000000..6fb0cef
--- /dev/null
+++ b/0102-Add-Crc32-Optimization-in-Gzip-For-crc32-algorithm-i.patch
@@ -0,0 +1,2164 @@
+From 8fa9788ac64a9ea5dc92c61c8f2ec11075cd17ec Mon Sep 17 00:00:00 2001
+From: XingYushuai 
+Date: Thu, 15 Dec 2022 14:34:16 +0800
+Subject: [PATCH 003/157] Add Crc32 Optimization in Gzip For crc32 algorithm in
+ APBC int_gzip.
+
+Match crc32 lookup table algorithm. An example for crc32 lookup table
+elg: ```c do { c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); } while (--n);
+
+Usage: `gcc -O3 -march=armv8.1-a -floop-crc yourfile.c`
+Node: The cpu you use needs to support the crc32 instructions
+---
+ gcc/Makefile.in                               |    1 +
+ gcc/common.opt                                |    4 +
+ gcc/config/aarch64/aarch64-builtins.cc        |   30 +
+ gcc/config/aarch64/aarch64-protos.h           |    1 +
+ gcc/config/aarch64/aarch64.cc                 |   12 +
+ gcc/doc/invoke.texi                           |    6 +-
+ gcc/doc/tm.texi                               |    9 +
+ gcc/doc/tm.texi.in                            |    2 +
+ gcc/match.pd                                  |   23 +
+ gcc/passes.def                                |    1 +
+ gcc/target.def                                |   14 +
+ .../tree-ssa/loop-crc-loop-condition-fail.c   |   85 ++
+ .../tree-ssa/loop-crc-loop-form-fail-2.c      |   90 ++
+ .../gcc.dg/tree-ssa/loop-crc-loop-form-fail.c |  112 ++
+ .../gcc.dg/tree-ssa/loop-crc-sucess.c         |   83 +
+ .../tree-ssa/loop-crc-table-check-fail.c      |  114 ++
+ gcc/timevar.def                               |    1 +
+ gcc/tree-pass.h                               |    1 +
+ gcc/tree-ssa-loop-crc.cc                      | 1333 +++++++++++++++++
+ 19 files changed, 1921 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-condition-fail.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-crc-sucess.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/loop-crc-table-check-fail.c
+ create mode 100644 gcc/tree-ssa-loop-crc.cc
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 5cd838270..2b9f025dc 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1649,6 +1649,7 @@ OBJS = \
+ 	tree-ssa-ifcombine.o \
+ 	tree-ssa-live.o \
+ 	tree-ssa-loop-ch.o \
++	tree-ssa-loop-crc.o \
+ 	tree-ssa-loop-im.o \
+ 	tree-ssa-loop-ivcanon.o \
+ 	tree-ssa-loop-ivopts.o \
+diff --git a/gcc/common.opt b/gcc/common.opt
+index b18f0b944..42fb2fc19 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1119,6 +1119,10 @@ fcrypto-accel-aes
+ Common Var(flag_crypto_accel_aes) Init(0) Optimization
+ Perform crypto acceleration AES pattern matching.
+ 
++floop-crc
++Common Var(flag_loop_crc) Optimization
++Do the loop crc conversion.
++
+ fauto-inc-dec
+ Common Var(flag_auto_inc_dec) Init(1) Optimization
+ Generate auto-inc/dec instructions.
+diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
+index 42276e7ca..3b952ef39 100644
+--- a/gcc/config/aarch64/aarch64-builtins.cc
++++ b/gcc/config/aarch64/aarch64-builtins.cc
+@@ -551,6 +551,12 @@ typedef struct
+ #define VAR1(T, N, MAP, FLAG, A) \
+   AARCH64_SIMD_BUILTIN_##T##_##N##A,
+ 
++enum aarch64_crc_builtins{
++  AARCH64_BUILTIN_CRC32B,
++  AARCH64_BUILTIN_CRC32H,
++  AARCH64_BUILTIN_CRC32W,
++};
++
+ enum aarch64_builtins
+ {
+   AARCH64_BUILTIN_MIN,
+@@ -1812,6 +1818,30 @@ aarch64_general_builtin_decl (unsigned code, bool)
+   return aarch64_builtin_decls[code];
+ }
+ 
++/* Implement TARGET_GET_CRC_BUILTIN_CODE  */
++unsigned 
++get_crc_builtin_code(unsigned code, bool)
++{
++  if (code > AARCH64_BUILTIN_CRC32W)
++    return AARCH64_BUILTIN_MIN;
++
++  unsigned res = AARCH64_BUILTIN_MIN;
++  switch (code) {
++    case AARCH64_BUILTIN_CRC32B:
++      res = AARCH64_BUILTIN_crc32b;
++      break;
++    case AARCH64_BUILTIN_CRC32H:
++      res = AARCH64_BUILTIN_crc32h;
++      break;
++    case AARCH64_BUILTIN_CRC32W:
++      res = AARCH64_BUILTIN_crc32w;
++      break;
++    default:
++      break;
++  }
++  return res;
++}
++
+ typedef enum
+ {
+   SIMD_ARG_COPY_TO_REG,
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 475d174dd..853197ee9 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -994,6 +994,7 @@ gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *,
+ 					     gimple_stmt_iterator *);
+ rtx aarch64_general_expand_builtin (unsigned int, tree, rtx, int);
+ tree aarch64_general_builtin_decl (unsigned, bool);
++unsigned  get_crc_builtin_code(unsigned , bool);
+ tree aarch64_general_builtin_rsqrt (unsigned int);
+ tree aarch64_builtin_vectorized_function (unsigned int, tree, tree);
+ void handle_arm_acle_h (void);
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 5537a537c..280e0b618 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -15210,6 +15210,15 @@ aarch64_builtin_decl (unsigned int code, bool initialize_p)
+   gcc_unreachable ();
+ }
+ 
++/* Implement TARGET_GET_CRC_BUILTIN_CODE.  */
++static unsigned 
++aarch64_get_crc_builtin_code(unsigned code, bool initialize_p)
++{
++  unsigned subcode = get_crc_builtin_code(code,initialize_p);
++  unsigned res = subcode << AARCH64_BUILTIN_SHIFT;
++  return res;
++}
++
+ /* Return true if it is safe and beneficial to use the approximate rsqrt optabs
+    to optimize 1.0/sqrt.  */
+ 
+@@ -27677,6 +27686,9 @@ aarch64_get_v16qi_mode ()
+ #undef TARGET_BUILTIN_DECL
+ #define TARGET_BUILTIN_DECL aarch64_builtin_decl
+ 
++#undef TARGET_GET_CRC_BUILTIN_CODE
++#define TARGET_GET_CRC_BUILTIN_CODE aarch64_get_crc_builtin_code
++
+ #undef TARGET_BUILTIN_RECIPROCAL
+ #define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
+ 
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 7ca60dd64..c3ce148b0 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -537,7 +537,7 @@ Objective-C and Objective-C++ Dialects}.
+ -fisolate-erroneous-paths-dereference  -fisolate-erroneous-paths-attribute @gol
+ -fivopts  -fkeep-inline-functions  -fkeep-static-functions @gol
+ -fkeep-static-consts  -flimit-function-alignment  -flive-range-shrinkage @gol
+--floop-block  -floop-interchange  -floop-strip-mine @gol
++-floop-block  -floop-crc  -floop-interchange  -floop-strip-mine @gol
+ -floop-unroll-and-jam  -floop-nest-optimize @gol
+ -floop-parallelize-all  -flra-remat  -flto  -flto-compression-level @gol
+ -flto-partition=@var{alg}  -fmerge-all-constants @gol
+@@ -12159,6 +12159,10 @@ GIMPLE -> GRAPHITE -> GIMPLE transformation.  Some minimal optimizations
+ are also performed by the code generator isl, like index splitting and
+ dead code elimination in loops.
+ 
++@item -floop-crc 
++@opindex floop-crc
++Do the loop crc conversion
++
+ @item -floop-nest-optimize
+ @opindex floop-nest-optimize
+ Enable the isl based loop nest optimizer.  This is a generic loop nest
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 851d31c18..5a1e0fe43 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -11658,6 +11658,15 @@ If @var{code} is out of range the function should return
+ @code{error_mark_node}.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} unsigned TARGET_GET_CRC_BUILTIN_CODE (unsigned @var{code}, bool @var{initialize_p})
++Define this hook to get crc32 builtin code.  It should be a function that
++returns the crc32 builtin function code @var{code}.
++If there is no such builtin and it cannot be initialized at this time
++if @var{initialize_p} is true the function should return @code{NULL_TREE}.
++If @var{code} is out of range the function should return
++@code{error_mark_node}.
++@end deftypefn
++
+ @deftypefn {Target Hook} rtx TARGET_EXPAND_BUILTIN (tree @var{exp}, rtx @var{target}, rtx @var{subtarget}, machine_mode @var{mode}, int @var{ignore})
+ 
+ Expand a call to a machine specific built-in function that was set up by
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index ac95cdf7a..6ff0eff66 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -7704,6 +7704,8 @@ to by @var{ce_info}.
+ 
+ @hook TARGET_BUILTIN_DECL
+ 
++@hook TARGET_GET_CRC_BUILTIN_CODE
++
+ @hook TARGET_EXPAND_BUILTIN
+ 
+ @hook TARGET_RESOLVE_OVERLOADED_BUILTIN
+diff --git a/gcc/match.pd b/gcc/match.pd
+index aee58e47b..1f42090a2 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -4409,6 +4409,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+ )
+ #endif
+ 
++#if GIMPLE
++/* Try to match
++     _4 = (int) _3;      NOP_EXPR (SSA_NAME @2)
++     _5 = _4 ^ c_10;     BIT_XOR_EXPR (SSA_NAME@1, SSA_NAME)
++     _6 = _5 & 255;      BIT_AND_EXPR (SSA_NAME, INTEGER_CST@3)
++*/
++(match (crc_match_index @1 @2 @3)
++   (bit_and (bit_xor (nop SSA_NAME@2) SSA_NAME@1) INTEGER_CST@3)
++   (if (INTEGRAL_TYPE_P (type) && tree_to_uhwi(@3) == 255))
++)
++#endif
++
++#if GIMPLE
++/* Try to match
++     _8 = c_12 >> 8;      RSHIFT_EXPR (SSA_NAME @1, INTEGER_CST @2)
++     c_19 = _7 ^ _8;      BIT_XOR_EXPR (SSA_NAME@3, SSA_NAME)
++*/
++(match (crc_match_res @1 @2 @3)
++   (bit_xor SSA_NAME@3  (rshift SSA_NAME@1 INTEGER_CST@2))
++   (if (INTEGRAL_TYPE_P (type) && tree_to_uhwi(@2) == 8))
++)
++#endif
++
+ /* Simplification moved from fold_cond_expr_with_comparison.  It may also
+    be extended.  */
+ /* This pattern implements two kinds simplification:
+diff --git a/gcc/passes.def b/gcc/passes.def
+index cdc600298..89d6889e5 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -95,6 +95,7 @@ along with GCC; see the file COPYING3.  If not see
+ 	  NEXT_PASS (pass_cd_dce, false /* update_address_taken_p */);
+ 	  NEXT_PASS (pass_phiopt, true /* early_p */);
+ 	  NEXT_PASS (pass_array_widen_compare);
++	  NEXT_PASS (pass_loop_crc);
+ 	  NEXT_PASS (pass_tail_recursion);
+ 	  NEXT_PASS (pass_if_to_switch);
+ 	  NEXT_PASS (pass_convert_switch);
+diff --git a/gcc/target.def b/gcc/target.def
+index c9bb2b4c2..8abf49f0a 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -2413,6 +2413,20 @@ If @var{code} is out of range the function should return\n\
+ @code{error_mark_node}.",
+  tree, (unsigned code, bool initialize_p), NULL)
+ 
++/* Initialize (if INITIALIZE_P is true) and return the real code of
++   target-specific built-in function.
++   Return NULL if that is not possible.  Return error_mark_node if CODE
++   is outside of the range of valid crc32 codes.  */
++DEFHOOK
++(get_crc_builtin_code,
++ "Define this hook to get crc32 builtin code.  It should be a function that\n\
++returns the crc32 builtin function code @var{code}.\n\
++If there is no such builtin and it cannot be initialized at this time\n\
++if @var{initialize_p} is true the function should return @code{NULL_TREE}.\n\
++If @var{code} is out of range the function should return\n\
++@code{error_mark_node}.",
++ unsigned , (unsigned code, bool initialize_p), NULL)
++
+ /* Expand a target-specific builtin.  */
+ DEFHOOK
+ (expand_builtin,
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-condition-fail.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-condition-fail.c
+new file mode 100644
+index 000000000..3620e92f7
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-condition-fail.c
+@@ -0,0 +1,85 @@
++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */
++/* { dg-options "-O3 -march=armv8.1-a -mabi=lp64 -floop-crc -fdump-tree-loop_crc-details" } */
++
++#include 
++#include 
++typedef unsigned long ulg;
++typedef unsigned char uch;
++
++static const ulg crc_32_tab[] = {
++  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++  0x2d02ef8dL
++};
++
++ulg updcrc (s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) 
++        if (n) do {
++            c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
++        } while (--n || c != 0) ;
++    }
++    crc = c;
++exit1:
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++/* { dg-final { scan-tree-dump-times "Wrong loop form for crc matching." 1 "loop_crc"} } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail-2.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail-2.c
+new file mode 100644
+index 000000000..fac759c67
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail-2.c
+@@ -0,0 +1,90 @@
++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */
++/* { dg-options "-O3 -march=armv8.1-a -mabi=lp64 -floop-crc -fdump-tree-loop_crc-details" } */
++
++#include 
++#include 
++typedef unsigned long ulg;
++typedef unsigned char uch;
++
++static const ulg crc_32_tab[] = {
++  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++  0x2d02ef8dL
++};
++int test[5] = {0};
++
++ulg updcrc (s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) 
++        if (n) do {
++            c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
++        } while (--n) ;
++    }
++    do {
++        c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8);
++        test[c%5] = c;
++    } while (--n) ;
++    crc = c;
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++/* { dg-final { scan-tree-dump-times "Table check fail. not only single array is read." 1 "loop_crc"} } */
++/* { dg-final { scan-tree-dump-times "Wrong crc table for crc matching." 1 "loop_crc"} } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail.c
+new file mode 100644
+index 000000000..ba9e5bb95
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-loop-form-fail.c
+@@ -0,0 +1,112 @@
++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */
++/* { dg-options "-O3 -march=armv8.1-a -mabi=lp64 -floop-crc -fdump-tree-loop_crc-details" } */
++
++#include 
++#include 
++typedef unsigned long ulg;
++typedef unsigned char uch;
++
++static const ulg crc_32_tab[] = {
++  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++  0x2d02ef8dL
++};
++
++/* check when the loop have a innor loop, should fail.  */
++ulg updcrc (s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) 
++        do {
++            c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8);
++            for (int i = 0; i < 5; i++) {
++                c++;
++            }
++            
++        } while (--n);
++    }
++    crc = c;
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++
++/* check when the loop have a second backedge, should fail.  */
++ulg updcrc1(s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) 
++        do {
++            c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8);     
++        } while (--n || c != 0) ;
++    }
++    crc = c;
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++/* { dg-final { scan-tree-dump-times "Wrong crc table for crc matching." 1 "loop_crc"} } */
++/* { dg-final { scan-tree-dump-times "Table check fail. not only single array is read." 1 "loop_crc"} } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-sucess.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-sucess.c
+new file mode 100644
+index 000000000..dad7bdbfc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-sucess.c
+@@ -0,0 +1,83 @@
++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */
++/* { dg-options "-O3 -march=armv8.1-a -mabi=lp64 -floop-crc -fdump-tree-loop_crc-details" } */
++
++#include 
++#include 
++typedef unsigned long ulg;
++typedef unsigned char uch;
++
++static const ulg crc_32_tab[] = {
++  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++  0x2d02ef8dL
++};
++
++ulg updcrc (s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) do {
++            c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
++        } while (--n);
++    }
++    crc = c;
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++/* { dg-final { scan-tree-dump-times "The 1th loop form is success matched,and the loop can be optimized." 1 "loop_crc"} } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-table-check-fail.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-table-check-fail.c
+new file mode 100644
+index 000000000..523a7740c
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-crc-table-check-fail.c
+@@ -0,0 +1,114 @@
++/* { dg-do compile { target {{ aarch64*-*-linux* } && lp64 } } } */
++/* { dg-options "-O3 -march=armv8.1-a -mabi=lp64 -floop-crc -fdump-tree-loop_crc-details" } */
++
++#include 
++#include 
++typedef unsigned long ulg;
++typedef unsigned char uch;
++
++static const ulg crc_32_tab[] = {
++  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++  0x37d83bf1L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++  0x2d02ef8dL
++};
++int test[5] = {0};
++
++/* check when the loop is doing more then 1 array read or writing an array, both should fail.  */
++ulg updcrc (s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) 
++        do {
++            c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8) * test[c%5];
++        } while (--n) ;
++    }
++    do {
++        c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8);
++        test[c%5] = c;
++    } while (--n) ;
++    crc = c;
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++
++/* check when the loop is not working on a correct crc_table. should fail.  */
++ulg updcrc1(s, n)
++    uch *s;                 /* pointer to bytes to pump through */
++    unsigned n;             /* number of bytes in s[] */
++{
++    register ulg c;         /* temporary variable */
++
++    static ulg crc = (ulg)0xffffffffL; /* shift register contents */
++
++    if (s == NULL) {
++        c = 0xffffffffL;
++    } else {
++        c = crc;
++        if (n) 
++        do {
++            c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8);
++        } while (--n) ;
++    }
++    crc = c;
++    return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
++}
++/* { dg-final { scan-tree-dump-times "Table check fail. not only single array is read." 2 "loop_crc"} } */
++/* { dg-final { scan-tree-dump-times "Wrong crc table for crc matching." 3 "loop_crc"} } */
++/* { dg-final { scan-tree-dump-times "Table check fail.  Table not matching." 1 "loop_crc"} } */
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 8e7510eb3..8341b9ffd 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -220,6 +220,7 @@ DEFTIMEVAR (TV_TREE_COPY_RENAME	     , "tree rename SSA copies")
+ DEFTIMEVAR (TV_TREE_SSA_VERIFY       , "tree SSA verifier")
+ DEFTIMEVAR (TV_TREE_STMT_VERIFY      , "tree STMT verifier")
+ DEFTIMEVAR (TV_TREE_ARRAY_WIDEN_COMPARE, "tree array widen compare")
++DEFTIMEVAR (TV_TREE_LOOP_CRC         , "tree loop crc")
+ DEFTIMEVAR (TV_TREE_SWITCH_CONVERSION, "tree switch conversion")
+ DEFTIMEVAR (TV_TREE_SWITCH_LOWERING,   "tree switch lowering")
+ DEFTIMEVAR (TV_TREE_RECIP            , "gimple CSE reciprocals")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 34e60bc38..6cd679e10 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -454,6 +454,7 @@ extern gimple_opt_pass *make_pass_phiopt (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_forwprop (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_phiprop (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_array_widen_compare (gcc::context *ctxt);
++extern gimple_opt_pass *make_pass_loop_crc (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_tree_ifcombine (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_dse (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_nrv (gcc::context *ctxt);
+diff --git a/gcc/tree-ssa-loop-crc.cc b/gcc/tree-ssa-loop-crc.cc
+new file mode 100644
+index 000000000..b9c2f71ca
+--- /dev/null
++++ b/gcc/tree-ssa-loop-crc.cc
+@@ -0,0 +1,1333 @@
++/* This pass converts special loops where do CRC algorithms to
++   simple CRC instructions in AArch64.
++   Copyright (C) 2023-2023 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
++.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "backend.h"
++#include "target.h"
++#include "tree.h"
++#include "gimple.h"
++#include "tree-pass.h"
++#include "gimple-ssa.h"
++#include "tree-pretty-print.h"
++#include "fold-const.h"
++#include "gimplify.h"
++#include "gimple-iterator.h"
++#include "tree-ssa-loop-manip.h"
++#include "tree-ssa-loop.h"
++#include "ssa.h"
++#include "tree-into-ssa.h"
++#include "cfganal.h"
++#include "cfgloop.h"
++#include "gimple-pretty-print.h"
++#include "tree-cfg.h"
++#include "cgraph.h"
++#include "print-tree.h"
++#include "cfghooks.h"
++#include "gimple-fold.h"
++#include "diagnostic-core.h"
++
++/* This pass handles scenarios similar to the following:
++ulg updcrc (s, n)
++    uch *s;
++    unsigned n;
++{
++    register ulg c;
++
++    static ulg crc = (ulg)0xffffffffL; 
++
++    if (s == NULL)
++    {
++        c = 0xffffffffL;
++    }
++    else
++    {
++        c = crc;
++        if (n)
++        do
++        {
++            c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
++        } while (--n);
++    }
++    crc = c;
++    return c ^ 0xffffffffL;
++}
++
++If the hardware supports the crc instruction, then the pass completes the
++conversion of the above scenario into:
++
++#define SIZE_U32 sizeof(uint32_t)
++unsigned long updcrc(s, n)
++    unsigned char *s;
++    unsigned n;
++{
++  register unsigned long c;
++
++  static unsigned long crc = (unsigned long)0xffffffffL;
++
++  if (s == NULL)
++  {
++    c = 0xffffffffL;
++  }
++  else
++  {
++    c = crc;
++    if (n)
++    {
++      uint32_t nn = n/SIZE_U32;
++      do
++      {
++        c = __crc32w (c,*((uint32_t *)s));
++        s += SIZE_U32;
++      } while(--nn);
++    }
++  }
++  if (n & sizeof (uint16_t))
++  {
++    c = __crc32h (c, *((uint16_t *)s));
++    s += sizeof (uint16_t);
++  }
++  if (n & sizeof (uint8_t))
++    c = __crc32b (c, *s);
++  crc = c;
++  return c ^ 0xffffffffL;
++}
++
++This pass is to complete the conversion of such scenarios from
++the internal perspective of the compiler:
++1) match_crc_loop: The function completes the screening of such
++   scenarios;
++2) convert_to_new_loop: The function completes the conversion of
++   origin_loop to new loops, and removes origin_loop;
++3) origin_loop_info: The structure is used to record important
++   information of origin_loop: such as loop exit, initial value
++   of induction variable, etc;
++4) create_new_loops: The function is used as the key content
++   of the pass to complete the creation of new loops.  */
++
++extern bool gimple_crc_match_index (tree, tree *, tree (*)(tree));
++extern bool gimple_crc_match_res (tree, tree *, tree (*)(tree));
++
++static gimple *crc_table_read_stmt = NULL;
++
++static gphi *phi_s = NULL;
++static gphi *phi_c = NULL;
++static tree nn_tree = NULL;
++
++enum aarch64_crc_builtins
++{
++  AARCH64_BUILTIN_CRC32B,
++  AARCH64_BUILTIN_CRC32H,
++  AARCH64_BUILTIN_CRC32W,
++};
++
++/* The useful information of origin loop.  */
++struct origin_loop_info
++{
++  tree limit;       /* The limit index of the array in the old loop.  */
++  tree base_n;      /* The initial value of the old loop.  */
++  tree base_s;      /* The initial value of the old loop.  */
++  tree base_c;      /* The initial value of the old loop.  */
++  edge entry_edge;  /* The edge into the old loop.  */
++  edge exit_edge;   /* The edge outto the old loop.  */
++  basic_block exit_bb;
++};
++
++typedef struct origin_loop_info origin_loop_info;
++
++static origin_loop_info origin_loop;
++hash_map  n_map;
++hash_map  nn_map;
++hash_map  s_map;
++hash_map  c_map;
++hash_map  crc_map;
++
++/* Initialize the origin_loop structure.  */
++static void
++init_origin_loop_structure ()
++{
++  origin_loop.entry_edge = NULL;
++  origin_loop.exit_edge = NULL;
++  origin_loop.exit_bb = NULL;
++  origin_loop.limit = NULL;
++  origin_loop.base_n = NULL;
++  origin_loop.base_s = NULL;
++  origin_loop.base_c = NULL;
++}
++
++/* Get the edge that first entered the loop.  */
++static edge
++get_loop_preheader_edge (class loop *loop)
++{
++  edge e;
++  edge_iterator ei;
++
++  FOR_EACH_EDGE (e, ei, loop->header->preds)
++    if (e->src != loop->latch)
++      break;
++
++  return e;
++}
++
++/* Returns true if t is SSA_NAME and user variable exists.  */
++
++static bool
++ssa_name_var_p (tree t)
++{
++  if (!t || TREE_CODE (t) != SSA_NAME)
++    return false;
++  if (SSA_NAME_VAR (t))
++    return true;
++  return false;
++}
++
++/* Returns true if t1 and t2 are SSA_NAME and belong to the same variable.  */
++
++static bool
++same_ssa_name_var_p (tree t1, tree t2)
++{
++  if (!ssa_name_var_p (t1) || !ssa_name_var_p (t2))
++    return false;
++  if (SSA_NAME_VAR (t1) == SSA_NAME_VAR (t2))
++    return true;
++  return false;
++}
++
++/* Get origin loop induction variable upper bound.  */
++
++static bool
++get_iv_upper_bound (gimple *stmt)
++{
++  if (origin_loop.limit != NULL || origin_loop.base_n != NULL)
++    return false;
++
++  tree lhs = gimple_cond_lhs (stmt);
++  tree rhs = gimple_cond_rhs (stmt);
++
++  if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE
++      || TREE_CODE (TREE_TYPE (rhs)) != INTEGER_TYPE)
++    return false;
++
++  /* TODO: Currently, the input restrictions on lhs and rhs are implemented
++     through PARM_DECL.  We may consider relax the restrictions later, and
++     we need to consider the overall adaptation scenario and adding test
++     cases.  */
++  if (ssa_name_var_p (lhs) && TREE_CODE (SSA_NAME_VAR (lhs)) == PARM_DECL)
++  {
++    origin_loop.limit = rhs;
++    origin_loop.base_n = lhs;
++  }
++  else
++    return false;
++
++  if (origin_loop.limit != NULL && origin_loop.base_n != NULL)
++    return true;
++
++  return false;
++}
++
++/* Get origin loop info.  */
++static bool
++get_origin_loop_info (class loop *loop)
++{
++  auto_vec edges = get_loop_exit_edges (loop);
++  origin_loop.exit_edge = edges[0];
++  origin_loop.exit_bb = origin_loop.exit_edge->dest;
++  origin_loop.entry_edge = get_loop_preheader_edge (loop);
++  origin_loop.base_s = PHI_ARG_DEF_FROM_EDGE (phi_s,origin_loop.entry_edge);
++  origin_loop.base_c = PHI_ARG_DEF_FROM_EDGE (phi_c,origin_loop.entry_edge);
++
++  basic_block preheader_bb = origin_loop.entry_edge->src;
++
++  if (preheader_bb->preds->length () != 1)
++    return false;
++
++  edge entry_pre_bb_edge = EDGE_PRED (preheader_bb, 0);
++
++  basic_block pre_preheader_bb = entry_pre_bb_edge->src;
++
++  gimple_stmt_iterator gsi;
++  gimple *stmt;
++  bool get_upper_bound = false;
++  for (gsi = gsi_start_bb (pre_preheader_bb); !gsi_end_p (gsi); gsi_next (&gsi))
++    {
++      stmt = gsi_stmt (gsi);
++      if (stmt && gimple_code (stmt) == GIMPLE_COND
++          && get_iv_upper_bound (stmt))
++        {
++          get_upper_bound = true;
++          break;
++        }
++    }
++
++  return get_upper_bound;
++}
++
++/* The loop form check will check the entire loop control flow
++   It should be a loop that:
++   1. a do-while loop with header and latch only with no other control flow
++      inside the loop
++   2. have only one exiting edge
++   3. have only one back edge and one entry edge
++*/
++static bool
++crc_loop_form_check (class loop *loop)
++{
++  if (loop->num_nodes > 2 || loop->inner)
++    return false;
++  // Should only have 1 exit edge
++  auto_vec edges = get_loop_exit_edges (loop);
++  if (edges.length() != 1)
++    return false;
++
++  // The header should have only 2 incoming edges
++  // One of them is the preheader edge and the other is the backedge from the
++  // latch
++  if (EDGE_COUNT (loop->header->preds) != 2)
++    return false;
++  edge e1 = EDGE_PRED (loop->header, 0);
++  edge e2 = EDGE_PRED (loop->header, 1);
++
++  if ((e1->src == loop->latch && e2->src->loop_father != loop)
++      || (e2->src == loop->latch && e1->src->loop_father != loop))
++    return true;
++
++  return false;
++}
++
++/* Check there is only one array is read in the loop.
++   Return the only array as crc_table.  */
++static bool
++only_one_array_read (class loop *loop, tree &crc_table)
++{
++  gimple_stmt_iterator gsi;
++  gimple *stmt;
++  bool res = false;
++  for (gsi = gsi_start_bb (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
++    {
++      stmt = gsi_stmt (gsi);
++      if (stmt == NULL)
++        return false;
++
++      if (gimple_code (stmt) == GIMPLE_ASSIGN
++          && TREE_CODE (gimple_assign_lhs (stmt)) == ARRAY_REF)
++        return false;
++
++      /* Only one-dimensional integer arrays meet the condition.  */
++      if (gimple_code (stmt) == GIMPLE_ASSIGN
++          && TREE_CODE (gimple_assign_rhs1 (stmt)) == ARRAY_REF
++          && TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (stmt), 0)) == VAR_DECL
++          && TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (stmt))) == INTEGER_TYPE)
++        {
++          if (crc_table == NULL
++              && TREE_READONLY (gimple_assign_rhs1 (stmt)))
++            {
++              crc_table = gimple_assign_rhs1 (stmt);
++              crc_table_read_stmt = stmt;
++              res = true;
++            }
++          else
++            return false;
++        }
++    }
++  return res;
++}
++
++static const unsigned HOST_WIDE_INT crc_32_tab[] = {
++  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
++  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
++  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
++  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
++  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
++  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
++  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
++  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
++  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
++  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
++  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
++  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
++  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
++  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
++  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
++  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
++  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
++  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
++  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
++  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
++  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
++  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
++  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
++  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
++  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
++  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
++  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
++  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
++  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
++  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
++  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
++  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
++  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
++  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
++  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
++  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
++  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
++  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
++  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
++  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
++  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
++  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
++  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
++  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
++  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
++  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
++  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
++  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
++  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
++  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
++  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
++  0x2d02ef8dL
++};
++
++/* Check the content of the array.  */
++static bool
++match_crc_table (tree crc_table)
++{
++  const unsigned LOW_BOUND = 0;
++  const unsigned UP_BOUND = 255;
++  const unsigned ELEMENT_SIZE = 8;
++  tree low_bound = array_ref_low_bound (crc_table);
++  tree up_bound = array_ref_up_bound (crc_table);
++  tree element_size = array_ref_element_size (crc_table);
++  if (!tree_fits_uhwi_p(low_bound) || !tree_fits_uhwi_p(up_bound) ||
++      !tree_fits_uhwi_p(element_size))
++    return false;
++  unsigned HOST_WIDE_INT lb = tree_to_uhwi (low_bound);
++  unsigned HOST_WIDE_INT ub = tree_to_uhwi (up_bound);
++  unsigned HOST_WIDE_INT es = tree_to_uhwi (element_size);
++  if (lb != LOW_BOUND || ub != UP_BOUND || es != ELEMENT_SIZE)
++    return false;
++
++  tree decl = TREE_OPERAND (crc_table, 0);
++  tree ctor = ctor_for_folding(decl);
++  for (int i = lb; i <= ub; i++)
++    {
++      unsigned HOST_WIDE_INT val = tree_to_uhwi (CONSTRUCTOR_ELT (ctor,
++                                                                  i)->value);
++      if (crc_32_tab[i] != val)
++        return false;
++    }
++  return true;
++}
++
++/* Check the crc table.  The loop should have only one data reference. 
++   And match the data reference with the predefined array.  */
++static bool
++crc_table_check (class loop *loop)
++{
++  tree crc_table = NULL;
++  if (!only_one_array_read (loop, crc_table))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\nTable check fail. not only single array "
++                            "is read.\n");
++      return false;
++    }
++  if (!match_crc_table (crc_table))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\nTable check fail.  Table not matching.\n");
++      return false;
++    }
++  return  true;
++}
++
++/* Check whether the evolution pattern of phi is phi = SSA_NAME + target*/
++static bool
++evolution_pattern_plus_with_p (class loop *loop, gphi *phi,
++                               unsigned HOST_WIDE_INT target)
++{
++  edge backedge = find_edge (loop->latch, loop->header);
++  if (backedge == NULL)
++    return false;
++  tree evolution_node = PHI_ARG_DEF_FROM_EDGE (phi, backedge);
++  gimple *evolution_expr = SSA_NAME_DEF_STMT (evolution_node);
++
++  if (evolution_expr && (gimple_assign_rhs_code (evolution_expr) == PLUS_EXPR ||
++                         gimple_assign_rhs_code (evolution_expr)
++                             == POINTER_PLUS_EXPR))
++    {
++      tree rhs1 = gimple_assign_rhs1 (evolution_expr);
++      tree rhs2 = gimple_assign_rhs2 (evolution_expr);
++      if (TREE_CODE (rhs1) == SSA_NAME && TREE_CODE (rhs2) == INTEGER_CST
++          && tree_to_uhwi (rhs2) == target)
++        return true;
++    }
++  return false;
++}
++
++/* Check whether there are only 3 phi nodes in the header block.
++   Return 3 phi nodes in the capture.  */
++static bool
++check_num_of_phi (basic_block header,  gphi *capture[])
++{
++  gphi *phi;
++  gphi_iterator gsi;
++  int num_of_phi = 0;
++
++  for (gsi = gsi_start_phis (header); !gsi_end_p (gsi); gsi_next (&gsi))
++    {
++      phi = gsi.phi ();
++      if (phi)
++        num_of_phi++;
++      if (num_of_phi > 3)
++        return false;
++      capture[num_of_phi - 1] = phi;
++    }
++  /* Phi node should be exactly 3.  */
++  return num_of_phi == 3;   
++}
++
++/* Check the evolution pattern of three phi nodes.
++   Should be one of the node +1 every time (s), one of the node -1
++   every time (n), and a 3rd one neither (c).  Return 3 phi nodes in
++   the capture with the order of s,n,c.*/
++static bool
++check_evolution_pattern (class loop *loop,  gphi *capture[])
++{
++  gphi *s = NULL;
++  gphi *n = NULL;
++  gphi *c = NULL;
++
++  for (int i = 0; i < 3; i++)
++    {
++      if (evolution_pattern_plus_with_p (loop, capture[i], 1))
++        {
++          if (s != NULL)
++            return false;
++          s = capture[i];
++          phi_s = s;
++        }
++      else if (evolution_pattern_plus_with_p (loop, capture[i], 4294967295))
++        {
++          if (n != NULL)
++            return false;
++          n = capture[i];
++        }
++      else
++        {
++          if (c != NULL)
++            return false;
++          c = capture[i];
++          phi_c = c;
++        }
++    }
++
++  // Some envolution pattern cannot find 
++  if (!n || !s || !c)
++    return false;
++
++  capture[0] = s;
++  capture[1] = n;
++  capture[2] = c;
++  return true;
++}
++/* Check the calculation pattern before and after the crc_table array read stmt.
++   _7 = crc_32_tab[_6];
++   The caculation of index _6 should be the result of a sequency of calculation
++   by the s and c 
++   The result of the array read _7 should be used to calculate the new c.  */
++static bool
++check_calculation_pattern (class loop *loop,  gphi *capture[])
++{
++  gphi *s = capture[0];
++  gphi *c = capture[2];
++  tree res_ops[3];
++  tree index = TREE_OPERAND (gimple_assign_rhs1 (crc_table_read_stmt), 1);
++
++  /* Try to match
++  _4 = (int) _3; //NOP_EXPR (SSA_NAME @2)
++  _5 =  _4 ^ c_10; //BIT_XOR_EXPR (SSA_NAME, PHI @1)
++  _6 = _5 & 255; //BIT_XOR_EXPR (SSA_NAME, INTEGER_CST@3)
++  */
++  if (!gimple_crc_match_index (index, res_ops, NULL))
++    return false;
++  gimple *s_res_stmt = SSA_NAME_DEF_STMT (res_ops[0]);
++  if (!s_res_stmt)
++    return false;
++  gimple *s_def_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (s_res_stmt));
++  if (!s_def_stmt)
++    return false;
++  tree s_res = TREE_OPERAND (gimple_assign_rhs1 (s_def_stmt), 0);
++  if (res_ops[1] != gimple_phi_result (c) || s_res != gimple_phi_result (s))
++    return false;
++
++  /* Try to match 
++  _8 = c_12 >> 8; // RSHIFT_EXPR (SSA_NAME @1, INTEGER_CST @2)
++  c_19 = _7 ^ _8; // BIT_XOR_EXPR (SSA_NAME@3, SSA_NAME)
++  */
++  edge backedge = find_edge (loop->latch, loop->header);
++  tree updated_c = PHI_ARG_DEF_FROM_EDGE (c, backedge);
++  if (!gimple_crc_match_res (updated_c, res_ops, NULL))
++    return false;
++  if (res_ops[0] != gimple_phi_result (c)
++      || res_ops[2] != gimple_assign_lhs (crc_table_read_stmt))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\n gimple_crc_match_res pattern check failed.\n");
++      return false;
++    }
++
++  return true;
++}
++
++/* Check the exit condition is n != 0.  */
++static bool
++check_exit_condition (class loop *loop,  gphi *n)
++{
++  edge backedge = find_edge (loop->latch, loop->header);
++  gimple *cond_stmt = gsi_stmt (gsi_last_bb (loop->header));
++  if (!cond_stmt || gimple_code (cond_stmt) != GIMPLE_COND 
++      || gimple_cond_code (cond_stmt) != NE_EXPR
++      || gimple_cond_lhs (cond_stmt) != PHI_ARG_DEF_FROM_EDGE (n, backedge)
++      || tree_to_uhwi (gimple_cond_rhs (cond_stmt)) != 0)
++    return false;
++  
++  return  true;
++}
++
++/* Check the loop body. The loop body we are trying to match is
++
++# s_10 = PHI 
++# n_11 = PHI 
++# c_12 = PHI 
++_1 = (int) c_12;
++s_18 = s_10 + 1;
++_3 = *s_10;
++_4 = (int) _3;
++_5 = _1 ^ _4;
++_6 = _5 & 255;
++_7 = crc_32_tab[_6];
++_8 = c_12 >> 8;
++c_19 = _7 ^ _8;
++n_20 = n_11 + 4294967295;
++if (n_20 != 0)
++  goto ; [INV]
++else
++  goto ; [INV]
++
++which is doing a very simple calculation
++do {
++        c = crc_32_tab[(c ^ (*s++)) & 0xff] ^ (c >> 8);
++} while (--n);
++
++In this case ,we don't want this loop to have any other operation inside.
++so the matching condition is 
++1. There are only 3 loop variant during each itoration, namely s,c,n,  
++   which is limited by the condition that the loop have exactly 3 phi nodes.
++2. The 3 loop variants should have evolution pattern as 1 of the 3 nodes is
++   increased by 1 every itoration, 1 of the 3 nodes is decreased by 1 every itor
++   and the 3rd one is neither. These three tree node SSA value will be captured
++   for the later arithmatic pattern matching
++3. Pattern matching for the index of crc_table
++4. pattern matching for the result of c calcuation after read from crc_table
++5. The exit condition matching. 
++  */
++static bool
++crc_loop_body_check (class loop *loop)
++{
++  basic_block header = loop->header;
++  gphi *capture[3];
++  if (!check_num_of_phi(header, capture))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\n num of phi noeds check failed.\n");
++      return false;
++    }
++  if (!check_evolution_pattern (loop, capture))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\n evolution pattern check failed.\n");
++      return false;
++    }
++  if (!check_calculation_pattern (loop, capture))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\n calculation pattern check failed.\n");
++      return false;
++    }
++  if (!check_exit_condition (loop, capture[1]))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\n exit condition check failed.\n");
++      return false;
++    }
++  return true;
++}
++
++static bool check_prev_bb (basic_block prev_bb, enum tree_code code)
++{
++  gimple_stmt_iterator gsi;
++  gimple *stmt;
++  for (gsi = gsi_start_bb (prev_bb); !gsi_end_p (gsi);
++       gsi_next (&gsi))
++    {
++      stmt = gsi_stmt (gsi);
++      if (stmt == NULL)
++        return false;
++
++      if (gimple_code (stmt) == GIMPLE_COND
++          && gimple_cond_code (stmt) == code
++          && TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST
++          && tree_int_cst_sgn (gimple_cond_rhs (stmt)) == 0)
++        return true;
++    }
++  return false;
++}
++
++/* Check the prev_bb of prev_bb of loop header.  The prev_bb we are trying to
++match is
++
++c_15 = crc;
++if (n_16 (D) != 0)
++  goto ; [INV]
++else
++  goto ; [INV]
++
++  In this case , we must be sure that the n is not zero.
++  so the match condition is
++  1 the n is not zero.
++
++   :
++if (s_13 (D) == 0B)
++  goto ; [INV]
++else
++  goto ; [INV]
++
++  In this case, we must be sure the s is not NULL.
++  so the match condition is
++  1 the s is not NULL.
++*/
++static bool
++crc_prev_bb_of_loop_header_check (class loop *loop)
++{
++  basic_block header = loop->header;
++  basic_block prev_header_bb = header->prev_bb;
++  if (NULL == prev_header_bb)
++    return false;
++
++  basic_block prev_prev_header_bb = prev_header_bb->prev_bb;
++  if (NULL == prev_prev_header_bb)
++    return false;
++
++  if (!check_prev_bb (prev_prev_header_bb, NE_EXPR))
++    return false;
++
++  basic_block first_bb = prev_prev_header_bb->prev_bb;
++  if (NULL == first_bb)
++    return false;
++
++  if (!check_prev_bb (first_bb, EQ_EXPR))
++    return false;
++
++  return true;
++}
++
++static bool
++match_crc_loop (class loop *loop)
++{
++  if (!crc_loop_form_check (loop))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\nWrong loop form for crc matching.\n");
++      return false;
++    }
++  if (!crc_table_check (loop))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\nWrong crc table for crc matching.\n");
++      return false;
++    }
++  if (!crc_loop_body_check (loop))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\nWrong loop body for crc matching.\n");
++      return false;
++    }
++  if (!crc_prev_bb_of_loop_header_check (loop))
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "\nWrong prev basic_blocks of loop header for"
++                            " crc matching.\n");
++      return false;
++    }
++    
++  init_origin_loop_structure ();
++  if (!get_origin_loop_info (loop))
++    return false;
++
++  return true;
++}
++
++static void
++create_new_bb (basic_block &new_bb, basic_block after_bb,
++               basic_block dominator_bb, class loop *outer)
++{
++  new_bb = create_empty_bb (after_bb);
++  add_bb_to_loop (new_bb, outer);
++  set_immediate_dominator (CDI_DOMINATORS, new_bb, dominator_bb);
++}
++
++static void
++change_preheader_bb (edge entry_edge)
++{
++  gimple_seq stmts = NULL;
++  gimple_stmt_iterator gsi;
++  gimple *g;
++  tree lhs1;
++
++  lhs1 = create_tmp_var (TREE_TYPE (origin_loop.base_n),"nn");
++  lhs1 = make_ssa_name (lhs1);
++  gsi = gsi_last_bb (entry_edge->src);
++  g = gimple_build_assign (lhs1, RSHIFT_EXPR, origin_loop.base_n,
++                           build_int_cst (TREE_TYPE (origin_loop.base_n), 2));
++  gimple_seq_add_stmt (&stmts, g);
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++  nn_tree = lhs1;
++  set_current_def (nn_tree, lhs1);
++  nn_map.put (entry_edge->src, lhs1);
++}
++
++static gphi *
++create_phi_node_for_bb (tree old_name, basic_block bb)
++{
++  gphi *phi = create_phi_node (NULL_TREE, bb);
++  create_new_def_for (old_name, phi, gimple_phi_result_ptr (phi));
++  return phi;
++}
++
++static gimple *
++call_builtin_fun (int code,tree &lhs, tree arg1, tree arg2)
++{
++  unsigned int builtin_code = targetm.get_crc_builtin_code (code, true);
++  // Get the decl of __builtin_aarch64_crc32w
++  tree fn = targetm.builtin_decl (builtin_code, true);
++  if (!fn || fn == error_mark_node)
++    fatal_error (input_location,
++                 "target specific builtin not available");
++  gimple *call_builtin = gimple_build_call (fn, 2, arg1, arg2);
++  lhs = make_ssa_name (unsigned_type_node);
++  gimple_call_set_lhs (call_builtin, lhs);
++
++  return call_builtin;
++}
++
++/* Create loop_header and loop_latch for new loop
++    :
++   # s_14 = PHI 
++   # c_16 = PHI 
++   # nn_19 = PHI 
++   _1 = (unsigned int) c_16;
++   _2 = MEM[(uint32_t *)s_14];
++   _40 = __builtin_aarch64_crc32w (_1, _2);
++   c_29 = (long unsigned int) _40;
++   s_30 = s_14 + 4;
++   nn_31 = nn_19 + 4294967295;
++   if (nn_31 != 0)
++   The IR of bb is as above.  */
++static void
++create_loop_bb (basic_block &loop_bb, basic_block after_bb,
++                basic_block dominator_bb, class loop *outer, edge entry_edge)
++{
++  gimple_seq stmts = NULL;
++  gimple_stmt_iterator gsi;
++  gimple *g;
++  gphi *phi_s_loop;
++  gphi *phi_c_loop;
++  gphi *phi_nn_loop;
++
++  create_new_bb (loop_bb, after_bb, dominator_bb, outer);
++  redirect_edge_and_branch (entry_edge, loop_bb);
++  gsi = gsi_last_bb (loop_bb);
++  tree entry_nn = get_current_def (nn_tree);
++  phi_s_loop = create_phi_node_for_bb (origin_loop.base_s, loop_bb);
++  phi_c_loop = create_phi_node_for_bb (origin_loop.base_c, loop_bb);
++  phi_nn_loop = create_phi_node_for_bb (entry_nn, loop_bb);
++
++  tree res_s = gimple_phi_result (phi_s_loop);
++  tree res_nn = gimple_phi_result (phi_nn_loop);
++  tree lhs1 = gimple_build (&stmts, NOP_EXPR, unsigned_type_node,
++                            gimple_phi_result (phi_c_loop));
++  g = gimple_build_assign (make_ssa_name (unsigned_type_node),
++                           fold_build2 (MEM_REF, unsigned_type_node, res_s,
++                                        build_int_cst (
++                                            build_pointer_type (
++                                                unsigned_type_node),0)));
++  gimple_seq_add_stmt (&stmts, g);
++  tree lhs2 = gimple_assign_lhs (g);  // _2 = MEM[(uint32_t *)s_14];
++  unsigned int code = AARCH64_BUILTIN_CRC32W;
++  tree lhs3;
++  gimple *build_crc32w = call_builtin_fun (code, lhs3, lhs1, lhs2);
++  crc_map.put (loop_bb, lhs3);
++  gimple_seq_add_stmt (&stmts, build_crc32w);
++
++  tree lhs4 = copy_ssa_name (origin_loop.base_c);
++  g = gimple_build_assign (lhs4, NOP_EXPR, lhs3);
++  gimple_seq_add_stmt (&stmts, g);
++  c_map.put (loop_bb, lhs4);
++
++  tree lhs5 = copy_ssa_name (origin_loop.base_s);
++  g = gimple_build_assign (lhs5, POINTER_PLUS_EXPR, res_s,
++                           build_int_cst (sizetype, 4));
++  gimple_seq_add_stmt (&stmts, g);
++  s_map.put (loop_bb, lhs5);
++
++  tree lhs6 = copy_ssa_name (nn_tree);
++  g = gimple_build_assign (lhs6, PLUS_EXPR, res_nn,
++                           build_int_cst (TREE_TYPE (res_nn), 4294967295));
++  gimple_seq_add_stmt (&stmts,g);
++  nn_map.put (loop_bb, lhs6);
++
++  gcond *cond_stmt = gimple_build_cond (NE_EXPR, lhs6, origin_loop.limit,
++                                        NULL_TREE, NULL_TREE);
++  gimple_seq_add_stmt (&stmts, cond_stmt);
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++}
++
++/*   :
++    # c_6 = PHI 
++    # s_46 = PHI 
++    _44 = n_26(D) & 2;
++    if (_44 != 0)
++    The IR of bb is as above.  */
++static void
++create_cond_bb (basic_block &cond_bb, basic_block after_bb,
++                basic_block dominator_bb, class loop *outer)
++{
++  gimple_seq stmts = NULL;
++  gimple_stmt_iterator gsi;
++  gphi *phi_s_loop;
++  gphi *phi_c_loop;
++
++  create_new_bb (cond_bb, after_bb, dominator_bb, outer);
++  gsi = gsi_last_bb (cond_bb);
++  tree entry_nn = get_current_def (nn_tree);
++  phi_s_loop = create_phi_node_for_bb (origin_loop.base_s, cond_bb);
++  phi_c_loop = create_phi_node_for_bb (origin_loop.base_c, cond_bb);
++  tree res_s = gimple_phi_result (phi_s_loop);
++  set_current_def (origin_loop.base_s, res_s);
++  s_map.put (cond_bb, res_s);
++  tree res_c = gimple_phi_result (phi_c_loop);
++  set_current_def (origin_loop.base_c, res_c);
++  c_map.put (cond_bb, res_c);
++
++  tree lhs1 = gimple_build (&stmts, BIT_AND_EXPR,
++                            TREE_TYPE (origin_loop.base_n), origin_loop.base_n,
++                            build_int_cst (TREE_TYPE (origin_loop.base_n), 2));
++  gcond *cond_stmt = gimple_build_cond (NE_EXPR, lhs1, origin_loop.limit,
++                                        NULL_TREE, NULL_TREE);
++  gimple_seq_add_stmt (&stmts, cond_stmt);
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++}
++
++/*   :
++    _7 = MEM[(uint16_t *)s_46];
++    _41 = __builtin_aarch64_crc32h (_8, _7);
++    c_33 = (long unsigned int) _41;
++    s_34 = s_30 + 2;
++    The IR of bb is as above.  */
++static void
++create_cond_true_bb (basic_block &cond_true_bb, basic_block after_bb,
++                     basic_block dominator_bb, class loop *outer)
++{
++  gimple_seq stmts = NULL;
++  gimple *g;
++  gimple_stmt_iterator gsi;
++
++  create_new_bb (cond_true_bb, after_bb, dominator_bb, outer);
++  gsi = gsi_last_bb (cond_true_bb);
++  tree s_46 = *(s_map.get (after_bb));
++  tree type = build_pointer_type (short_unsigned_type_node);
++  g = gimple_build_assign (make_ssa_name (short_unsigned_type_node),
++                           fold_build2 (MEM_REF, short_unsigned_type_node, s_46,
++                                        build_int_cst (type, 0)));
++  gimple_seq_add_stmt (&stmts,g);
++  tree lhs1 = gimple_assign_lhs (g);  // _7 = MEM[(uint16_t *)s_46];
++  unsigned int code = AARCH64_BUILTIN_CRC32H;
++  tree lhs2;
++  gimple *call_builtin = call_builtin_fun (code, lhs2,
++                             *(crc_map.get (
++                                  cond_true_bb->prev_bb->prev_bb)), lhs1);
++  crc_map.put (cond_true_bb,lhs2);
++  gimple_seq_add_stmt (&stmts, call_builtin);
++
++  tree lhs3 = copy_ssa_name (origin_loop.base_c);
++  g = gimple_build_assign (lhs3, NOP_EXPR, lhs2);
++  gimple_seq_add_stmt (&stmts, g);
++  c_map.put (cond_true_bb, lhs3);
++
++  tree lhs5 = copy_ssa_name (s_46);
++  g = gimple_build_assign (lhs5, POINTER_PLUS_EXPR, s_46,
++                           build_int_cst (sizetype, 2)); //  s_30 + 2;
++  gimple_seq_add_stmt (&stmts, g);
++  s_map.put (cond_true_bb, lhs5);
++
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++  s_map.put (cond_true_bb, lhs5);
++}
++
++/*  :
++  # s_15 = PHI 
++  # c_17 = PHI 
++  _3 = n_26(D) & 1;
++  if (_3 != 0)
++   The IR of bb is as above.  */
++static void
++create_cond_false_bb (basic_block &cond_false_bb, basic_block after_bb,
++                      basic_block dominator_bb, class loop *outer)
++{
++  gimple_seq stmts = NULL;
++  gimple_stmt_iterator gsi;
++  gphi *phi_s_cond_true_bb;
++  gphi *phi_c_cond_true_bb;
++
++  create_new_bb (cond_false_bb, after_bb, dominator_bb, outer);
++  make_single_succ_edge (after_bb, cond_false_bb, EDGE_FALLTHRU);
++
++  tree entry_s = get_current_def (origin_loop.base_s);
++  phi_s_cond_true_bb = create_phi_node_for_bb (entry_s, cond_false_bb);
++  tree entry_c = get_current_def (origin_loop.base_c);
++  phi_c_cond_true_bb = create_phi_node_for_bb (entry_c, cond_false_bb);
++  tree res_s = gimple_phi_result (phi_s_cond_true_bb);
++  set_current_def (origin_loop.base_s, res_s);
++  s_map.put (cond_false_bb, res_s);
++  tree res_c = gimple_phi_result (phi_c_cond_true_bb);
++  set_current_def (origin_loop.base_c, res_c);
++  c_map.put (cond_false_bb, res_c);
++
++  gsi = gsi_last_bb (cond_false_bb);
++  tree lhs1 = gimple_build (&stmts, BIT_AND_EXPR,
++                            TREE_TYPE (origin_loop.base_n), origin_loop.base_n,
++                            build_int_cst (TREE_TYPE (origin_loop.base_n), 1));
++  gcond *cond_stmt = gimple_build_cond (NE_EXPR, lhs1, origin_loop.limit,
++                                        NULL_TREE, NULL_TREE);
++  gimple_seq_add_stmt (&stmts, cond_stmt);
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++}
++
++/*   :
++  _11 = (unsigned int) c_17;
++  _12 = *s_15;
++  _42 = __builtin_aarch64_crc32b (_11, _12);
++  c_36 = (long unsigned int) _42;
++  The IR of bb is as above.  */
++static void
++create_lastcond_true_bb (basic_block &new_bb, basic_block after_bb,
++                         basic_block dominator_bb, class loop *outer)
++{
++  gimple_seq stmts = NULL;
++  gimple_stmt_iterator gsi;
++  gimple *g;
++
++  create_new_bb (new_bb, after_bb, dominator_bb, outer);
++  gsi = gsi_last_bb (new_bb);
++
++  tree lhs1 = gimple_build (&stmts, NOP_EXPR, unsigned_type_node,
++                            get_current_def (origin_loop.base_c));
++  tree lhs2;
++  tree s_15 = get_current_def (origin_loop.base_s);
++  g = gimple_build_assign (make_ssa_name (unsigned_char_type_node),
++                           fold_build2 (MEM_REF, unsigned_char_type_node, s_15,
++                                        build_int_cst (TREE_TYPE (s_15), 0)));
++  gimple_seq_add_stmt (&stmts, g);
++  lhs2 = gimple_assign_lhs (g);
++
++  unsigned int code = AARCH64_BUILTIN_CRC32B;
++  tree lhs3;
++  gimple *call_builtin = call_builtin_fun (code, lhs3, lhs1, lhs2);
++  crc_map.put (new_bb,lhs3);
++  gimple_seq_add_stmt (&stmts,call_builtin);
++
++  tree lhs4 = copy_ssa_name (origin_loop.base_c);
++  g = gimple_build_assign (lhs4, NOP_EXPR, lhs3);
++  gimple_seq_add_stmt (&stmts, g);
++  c_map.put (new_bb, lhs4);
++
++  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++}
++
++static bool
++optional_add_phi_arg (gphi * phi, tree phi_res, tree phi_arg, edge e)
++{
++  location_t loc;
++  if (same_ssa_name_var_p (phi_arg, phi_res))
++    {
++      if (virtual_operand_p (phi_arg))
++        loc = UNKNOWN_LOCATION;
++      else
++        loc = gimple_location (SSA_NAME_DEF_STMT (phi_arg));
++      add_phi_arg (phi, phi_arg, e, loc);
++
++      return true;
++    }
++
++  return false;
++}
++
++/* Add phi_arg for bb with phi node.  */
++static void
++update_phi_nodes (basic_block bb)
++{
++  edge e;
++  edge_iterator ei;
++  gphi *phi;
++  gphi_iterator gsi;
++  tree res;
++
++  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
++    {
++      phi = gsi.phi ();
++      res = gimple_phi_result (phi);
++
++      FOR_EACH_EDGE (e, ei, bb->preds)
++      {
++        if (PHI_ARG_DEF_FROM_EDGE (phi, e))
++          continue;
++        tree var_c;
++        tree *ptr_var_c = c_map.get (e->src);
++        if (ptr_var_c == NULL)
++          var_c = origin_loop.base_c;
++        else
++          var_c = *ptr_var_c;
++        if (optional_add_phi_arg (phi, res, var_c, e))
++          continue;
++
++        tree var_nn;
++        tree *ptr_var_nn = nn_map.get (e->src);
++        if (ptr_var_nn == NULL)
++          var_nn = nn_tree;
++        else
++          var_nn = *ptr_var_nn;
++        if (optional_add_phi_arg (phi, res, var_nn, e))
++          continue;
++
++        tree var_s;
++        tree *ptr_var_s = s_map.get (e->src);
++        if (ptr_var_s == NULL)
++          var_s = origin_loop.base_s;
++        else
++          var_s = *ptr_var_s;
++        if (optional_add_phi_arg (phi, res, var_s, e))
++          continue;
++      }
++    }
++}
++
++static void
++create_new_loops (edge entry_edge)
++{
++  class loop *new_loop = NULL;
++  basic_block loop_bb, cond_bb, cond_true_bb, cond_false_bb, lastcond_true_bb;
++  class loop *outer = entry_edge->src->loop_father;
++  change_preheader_bb (entry_edge);
++
++  create_loop_bb (loop_bb, entry_edge->src, entry_edge->src, outer, entry_edge);
++  create_cond_bb (cond_bb, loop_bb, loop_bb, outer);
++  make_edge (loop_bb, loop_bb, EDGE_TRUE_VALUE);
++  make_edge (loop_bb, cond_bb, EDGE_FALSE_VALUE);
++  update_phi_nodes (loop_bb);
++
++  new_loop = alloc_loop ();
++  new_loop->header = loop_bb;
++  new_loop->latch = loop_bb;
++  add_loop (new_loop, outer);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "\nPrint byte new loop %d:\n", new_loop->num);
++      flow_loop_dump (new_loop, dump_file, NULL, 1);
++      fprintf (dump_file, "\n\n");
++    }
++
++  create_cond_true_bb (cond_true_bb, cond_bb, cond_bb, outer);
++  make_edge (cond_bb, cond_true_bb, EDGE_TRUE_VALUE);
++  create_cond_false_bb (cond_false_bb, cond_true_bb, cond_bb, outer);
++  make_edge (cond_bb, cond_false_bb, EDGE_FALSE_VALUE);
++  update_phi_nodes (cond_bb);
++  update_phi_nodes (cond_false_bb);
++  create_lastcond_true_bb (lastcond_true_bb, cond_false_bb,
++                           cond_false_bb, outer);
++  make_edge (cond_false_bb, lastcond_true_bb, EDGE_TRUE_VALUE);
++  make_edge (cond_false_bb, origin_loop.exit_bb, EDGE_FALSE_VALUE);
++  make_single_succ_edge (lastcond_true_bb, origin_loop.exit_bb, EDGE_FALLTHRU);
++
++  update_phi_nodes (origin_loop.exit_bb);
++  remove_edge (origin_loop.exit_edge);
++}
++
++/* Clear information about the original loop.  */
++static void
++remove_origin_loop (class loop *loop)
++{
++  basic_block *body = get_loop_body_in_dom_order (loop);
++  unsigned n = loop->num_nodes;
++  for (int i = 0; i < n; ++i)
++    delete_basic_block (body[i]);
++  free (body);
++  delete_loop (loop);
++}
++
++/* Make sure that the dominance relationship of the newly inserted cfg
++   is not missing.  */
++static void
++update_loop_dominator (cdi_direction dir)
++{
++  gcc_assert (dom_info_available_p (dir));
++
++  basic_block bb;
++  FOR_EACH_BB_FN (bb, cfun)
++  {
++    basic_block imm_bb = get_immediate_dominator (dir, bb);
++    if (!imm_bb || bb == origin_loop.exit_bb)
++      {
++        set_immediate_dominator (CDI_DOMINATORS, bb,
++                               recompute_dominator (CDI_DOMINATORS, bb));
++        continue;
++      }
++  }
++}
++
++/* Perform the conversion of origin_loop to new_loop.  */
++static void
++convert_to_new_loop (class loop *loop)
++{
++  create_new_loops (origin_loop.entry_edge);
++  remove_origin_loop (loop);
++  update_loop_dominator (CDI_DOMINATORS);
++  update_ssa (TODO_update_ssa);
++}
++
++/* The main entry of loop crc optimizes.  */
++static unsigned int
++tree_ssa_loop_crc ()
++{
++  if (TARGET_CRC32 == false)
++    {
++      warning (OPT____,"The loop-crc optimization is not working." \
++                      "You should make sure that the specified architecture" \
++                      "supports crc:-march=armv8.1-a");
++      return 0;
++    }
++  unsigned int todo = 0;
++  class loop *loop;
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      flow_loops_dump (dump_file, NULL, 1);
++      fprintf (dump_file, "\nStarting the loop_crc pass\n");
++    }
++
++  enum li_flags LI = LI_FROM_INNERMOST;
++  for (auto loop : loops_list (cfun, LI))
++  {
++    if (dump_file && (dump_flags & TDF_DETAILS))
++      {
++        fprintf (dump_file, "======================================\n");
++        fprintf (dump_file, "Processing loop %d:\n", loop->num);
++        fprintf (dump_file, "======================================\n");
++        flow_loop_dump (loop, dump_file, NULL, 1);
++        fprintf (dump_file, "\n\n");
++      }
++
++    if (match_crc_loop (loop))
++      {
++        if (dump_file && (dump_flags & TDF_DETAILS))
++          {
++             fprintf (dump_file, "The %dth loop form is success matched,"
++                                "and the loop can be optimized.\n",
++                     loop->num);
++          }
++
++        convert_to_new_loop (loop);
++        todo |= (TODO_update_ssa);
++      }
++  }
++  return todo;
++}
++
++/* Loop crc.  */
++
++namespace {
++const pass_data pass_data_tree_loop_crc =
++{
++  GIMPLE_PASS,
++  "loop_crc",
++  OPTGROUP_LOOP,
++  TV_TREE_LOOP_CRC,
++  (PROP_cfg | PROP_ssa),
++  0,
++  0,
++  0,
++  (TODO_update_ssa | TODO_verify_all)
++};
++
++class pass_loop_crc : public gimple_opt_pass
++{
++public:
++  pass_loop_crc (gcc::context *ctxt)
++    : gimple_opt_pass (pass_data_tree_loop_crc, ctxt)
++  {}
++
++  /* Opt_pass methods: */
++  virtual bool gate (function *);
++  virtual unsigned int execute (function *);
++}; // Class pass_loop_crc
++
++bool
++pass_loop_crc::gate (function *)
++{
++  return (flag_loop_crc > 0 && optimize >= 3);
++}
++
++unsigned int
++pass_loop_crc::execute (function *fun)
++{
++  if (number_of_loops (fun) <= 1)
++    return 0;
++
++  /* Only supports LP64 data mode.  */
++  if (TYPE_PRECISION (long_integer_type_node) != 64
++      || POINTER_SIZE != 64 || TYPE_PRECISION (integer_type_node) != 32)
++    {
++      if (dump_file && (dump_flags & TDF_DETAILS))
++        fprintf (dump_file, "The current data mode is not supported,"
++                            "only the LP64 date mode is supported.\n");
++      return 0;
++    }
++
++  return tree_ssa_loop_crc ();
++}
++
++} // Anon namespace
++
++gimple_opt_pass *
++make_pass_loop_crc (gcc::context *ctxt)
++{
++  return new pass_loop_crc (ctxt);
++}
+-- 
+2.33.0
+
diff --git a/0103-SME-Remove-hip09-and-hip11-in-aarch64-cores.def-to-b.patch b/0103-SME-Remove-hip09-and-hip11-in-aarch64-cores.def-to-b.patch
new file mode 100644
index 0000000..5589f82
--- /dev/null
+++ b/0103-SME-Remove-hip09-and-hip11-in-aarch64-cores.def-to-b.patch
@@ -0,0 +1,34 @@
+From 72c48ade495ef99ef032a6c44365eb102b74888e Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Fri, 23 Aug 2024 15:14:04 +0800
+Subject: [PATCH 004/157] [SME] Remove hip09 and hip11 in aarch64-cores.def to
+ backport SME
+
+Will apply it in the end.
+---
+ gcc/config/aarch64/aarch64-cores.def | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 601b72abb..70b11eb80 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -130,7 +130,6 @@ AARCH64_CORE("a64fx", a64fx, a64fx, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F
+ 
+ /* HiSilicon ('H') cores. */
+ AARCH64_CORE("tsv110",  tsv110, tsv110, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
+-AARCH64_CORE("hip09", hip09, hip09, 8_5A, AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_I8MM | AARCH64_FL_F32MM | AARCH64_FL_F64MM | AARCH64_FL_PROFILE | AARCH64_FL_PREDRES, hip09, 0x48, 0xd02, 0x0)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+@@ -173,7 +172,6 @@ AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, 9A,  AARCH64_FL_FOR_ARCH9 |
+ 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)
+ 
+ AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
+-AARCH64_CORE("hip11", hip11, hip11, 8_5A, AARCH64_FL_FOR_ARCH8_5| AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_F16, hip11, 0x48, 0xd22, -1)
+ 
+ AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+ AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+-- 
+2.33.0
+
diff --git a/0104-Backport-SME-AArch64-Cleanup-CPU-option-processing-c.patch b/0104-Backport-SME-AArch64-Cleanup-CPU-option-processing-c.patch
new file mode 100644
index 0000000..1f506ac
--- /dev/null
+++ b/0104-Backport-SME-AArch64-Cleanup-CPU-option-processing-c.patch
@@ -0,0 +1,336 @@
+From 9a36ca4e9188ee402327ec908d4f6860f2ee67eb Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra 
+Date: Wed, 18 May 2022 16:02:12 +0100
+Subject: [PATCH 005/157] [Backport][SME] AArch64: Cleanup CPU option
+ processing code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1be715f31605976d8e4336973d3b81c5b7cea79f
+
+The --with-cpu/--with-arch configure option processing not only checks valid
+arguments but also sets TARGET_CPU_DEFAULT with a CPU and extension bitmask.
+This isn't used however since a --with-cpu is translated into a -mcpu option
+which is processed as if written on the command-line (so TARGET_CPU_DEFAULT
+is never accessed).
+
+So remove all the complex processing and bitmask, and just validate the
+option. Fix a bug that always reports valid architecture extensions as invalid.
+As a result the CPU processing in aarch64.c can be simplified.
+
+gcc/
+	* config.gcc (aarch64*-*-*): Simplify --with-cpu and --with-arch
+	processing.  Add support for architectural extensions.
+	* config/aarch64/aarch64.h (TARGET_CPU_DEFAULT): Remove
+	AARCH64_CPU_DEFAULT_FLAGS.
+	(TARGET_CPU_NBITS): Remove.
+	(TARGET_CPU_MASK): Remove.
+	* config/aarch64/aarch64.cc (AARCH64_CPU_DEFAULT_FLAGS): Remove define.
+	(get_tune_cpu): Assert CPU is always valid.
+	(get_arch): Assert architecture is always valid.
+	(aarch64_override_options): Cleanup CPU selection code and simplify logic.
+	(aarch64_option_restore): Remove unnecessary checks on tune.
+---
+ gcc/config.gcc                |  43 +------------
+ gcc/config/aarch64/aarch64.cc | 115 +++++++++-------------------------
+ gcc/config/aarch64/aarch64.h  |   9 +--
+ 3 files changed, 32 insertions(+), 135 deletions(-)
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 8fdde1576..3be450471 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -4190,8 +4190,6 @@ case "${target}" in
+ 			  pattern=AARCH64_CORE
+ 			fi
+ 
+-			ext_mask=AARCH64_CPU_DEFAULT_FLAGS
+-
+ 			# Find the base CPU or ARCH id in aarch64-cores.def or
+ 			# aarch64-arches.def
+ 			if [ x"$base_val" = x ] \
+@@ -4199,23 +4197,6 @@ case "${target}" in
+ 				    ${srcdir}/config/aarch64/$def \
+ 				    > /dev/null; then
+ 
+-			  if [ $which = arch ]; then
+-				base_id=`grep "^$pattern(\"$base_val\"," \
+-				  ${srcdir}/config/aarch64/$def | \
+-				  sed -e 's/^[^,]*,[ 	]*//' | \
+-				  sed -e 's/,.*$//'`
+-				# Extract the architecture flags from aarch64-arches.def
+-				ext_mask=`grep "^$pattern(\"$base_val\"," \
+-				   ${srcdir}/config/aarch64/$def | \
+-				   sed -e 's/)$//' | \
+-				   sed -e 's/^.*,//'`
+-			  else
+-				base_id=`grep "^$pattern(\"$base_val\"," \
+-				  ${srcdir}/config/aarch64/$def | \
+-				  sed -e 's/^[^,]*,[ 	]*//' | \
+-				  sed -e 's/,.*$//'`
+-			  fi
+-
+ 			  # Disallow extensions in --with-tune=cortex-a53+crc.
+ 			  if [ $which = tune ] && [ x"$ext_val" != x ]; then
+ 			    echo "Architecture extensions not supported in --with-$which=$val" 1>&2
+@@ -4246,25 +4227,7 @@ case "${target}" in
+ 					grep "^\"$base_ext\""`
+ 
+ 				if [ x"$base_ext" = x ] \
+-				    || [[ -n $opt_line ]]; then
+-
+-				  # These regexp extract the elements based on
+-				  # their group match index in the regexp.
+-				  ext_canon=`echo -e "$opt_line" | \
+-					sed -e "s/$sed_patt/\2/"`
+-				  ext_on=`echo -e "$opt_line" | \
+-					sed -e "s/$sed_patt/\3/"`
+-				  ext_off=`echo -e "$opt_line" | \
+-					sed -e "s/$sed_patt/\4/"`
+-
+-				  if [ $ext = $base_ext ]; then
+-					# Adding extension
+-					ext_mask="("$ext_mask") | ("$ext_on" | "$ext_canon")"
+-				  else
+-					# Removing extension
+-					ext_mask="("$ext_mask") & ~("$ext_off" | "$ext_canon")"
+-				  fi
+-
++				    || [ x"$opt_line" != x ]; then
+ 				  true
+ 				else
+ 				  echo "Unknown extension used in --with-$which=$val" 1>&2
+@@ -4273,10 +4236,6 @@ case "${target}" in
+ 				ext_val=`echo $ext_val | sed -e 's/[a-z0-9]\+//'`
+ 			  done
+ 
+-			  ext_mask="(("$ext_mask") << TARGET_CPU_NBITS)"
+-			  if [ x"$base_id" != x ]; then
+-				target_cpu_cname="TARGET_CPU_$base_id | $ext_mask"
+-			  fi
+ 			  true
+ 			else
+ 			  # Allow --with-$which=native.
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 7c62ddb2a..ba888beb0 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -3014,8 +3014,6 @@ static const struct attribute_spec aarch64_attribute_table[] =
+   { NULL,                 0, 0, false, false, false, false, NULL, NULL }
+ };
+ 
+-#define AARCH64_CPU_DEFAULT_FLAGS ((selected_cpu) ? selected_cpu->flags : 0)
+-
+ /* An ISA extension in the co-processor and main instruction set space.  */
+ struct aarch64_option_extension
+ {
+@@ -18411,39 +18409,24 @@ aarch64_validate_mtune (const char *str, const struct processor **res)
+   return false;
+ }
+ 
+-static_assert (TARGET_CPU_generic < TARGET_CPU_MASK,
+-	       "TARGET_CPU_NBITS is big enough");
+-
+-/* Return the CPU corresponding to the enum CPU.
+-   If it doesn't specify a cpu, return the default.  */
++/* Return the CPU corresponding to the enum CPU.  */
+ 
+ static const struct processor *
+ aarch64_get_tune_cpu (enum aarch64_processor cpu)
+ {
+-  if (cpu != aarch64_none)
+-    return &all_cores[cpu];
++  gcc_assert (cpu != aarch64_none);
+ 
+-  /* The & TARGET_CPU_MASK is to extract the bottom TARGET_CPU_NBITS bits that
+-     encode the default cpu as selected by the --with-cpu GCC configure option
+-     in config.gcc.
+-     ???: The whole TARGET_CPU_DEFAULT and AARCH64_CPU_DEFAULT_FLAGS
+-     flags mechanism should be reworked to make it more sane.  */
+-  return &all_cores[TARGET_CPU_DEFAULT & TARGET_CPU_MASK];
++  return &all_cores[cpu];
+ }
+ 
+-/* Return the architecture corresponding to the enum ARCH.
+-   If it doesn't specify a valid architecture, return the default.  */
++/* Return the architecture corresponding to the enum ARCH.  */
+ 
+ static const struct processor *
+ aarch64_get_arch (enum aarch64_arch arch)
+ {
+-  if (arch != aarch64_no_arch)
+-    return &all_architectures[arch];
+-
+-  const struct processor *cpu
+-    = &all_cores[TARGET_CPU_DEFAULT & TARGET_CPU_MASK];
++  gcc_assert (arch != aarch64_no_arch);
+ 
+-  return &all_architectures[cpu->arch];
++  return &all_architectures[arch];
+ }
+ 
+ /* Return the VG value associated with -msve-vector-bits= value VALUE.  */
+@@ -18481,10 +18464,6 @@ aarch64_override_options (void)
+   uint64_t arch_isa = 0;
+   aarch64_isa_flags = 0;
+ 
+-  bool valid_cpu = true;
+-  bool valid_tune = true;
+-  bool valid_arch = true;
+-
+   selected_cpu = NULL;
+   selected_arch = NULL;
+   selected_tune = NULL;
+@@ -18499,77 +18478,56 @@ aarch64_override_options (void)
+      If either of -march or -mtune is given, they override their
+      respective component of -mcpu.  */
+   if (aarch64_cpu_string)
+-    valid_cpu = aarch64_validate_mcpu (aarch64_cpu_string, &selected_cpu,
+-					&cpu_isa);
++    aarch64_validate_mcpu (aarch64_cpu_string, &selected_cpu, &cpu_isa);
+ 
+   if (aarch64_arch_string)
+-    valid_arch = aarch64_validate_march (aarch64_arch_string, &selected_arch,
+-					  &arch_isa);
++    aarch64_validate_march (aarch64_arch_string, &selected_arch, &arch_isa);
+ 
+   if (aarch64_tune_string)
+-    valid_tune = aarch64_validate_mtune (aarch64_tune_string, &selected_tune);
++    aarch64_validate_mtune (aarch64_tune_string, &selected_tune);
+ 
+ #ifdef SUBTARGET_OVERRIDE_OPTIONS
+   SUBTARGET_OVERRIDE_OPTIONS;
+ #endif
+ 
+-  /* If the user did not specify a processor, choose the default
+-     one for them.  This will be the CPU set during configuration using
+-     --with-cpu, otherwise it is "generic".  */
+-  if (!selected_cpu)
+-    {
+-      if (selected_arch)
+-	{
+-	  selected_cpu = &all_cores[selected_arch->ident];
+-	  aarch64_isa_flags = arch_isa;
+-	  explicit_arch = selected_arch->arch;
+-	}
+-      else
+-	{
+-	  /* Get default configure-time CPU.  */
+-	  selected_cpu = aarch64_get_tune_cpu (aarch64_none);
+-	  aarch64_isa_flags = TARGET_CPU_DEFAULT >> TARGET_CPU_NBITS;
+-	}
+-
+-      if (selected_tune)
+-	explicit_tune_core = selected_tune->ident;
+-    }
+-  /* If both -mcpu and -march are specified check that they are architecturally
+-     compatible, warn if they're not and prefer the -march ISA flags.  */
+-  else if (selected_arch)
++  if (selected_cpu && selected_arch)
+     {
++      /* If both -mcpu and -march are specified, warn if they are not
++	 architecturally compatible and prefer the -march ISA flags.  */
+       if (selected_arch->arch != selected_cpu->arch)
+ 	{
+ 	  warning (0, "switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch",
+ 		       aarch64_cpu_string,
+ 		       aarch64_arch_string);
+ 	}
++
+       aarch64_isa_flags = arch_isa;
+-      explicit_arch = selected_arch->arch;
+-      explicit_tune_core = selected_tune ? selected_tune->ident
+-					  : selected_cpu->ident;
+     }
+-  else
++  else if (selected_cpu)
+     {
+-      /* -mcpu but no -march.  */
+-      aarch64_isa_flags = cpu_isa;
+-      explicit_tune_core = selected_tune ? selected_tune->ident
+-					  : selected_cpu->ident;
+-      gcc_assert (selected_cpu);
+       selected_arch = &all_architectures[selected_cpu->arch];
+-      explicit_arch = selected_arch->arch;
++      aarch64_isa_flags = cpu_isa;
+     }
+-
+-  /* Set the arch as well as we will need it when outputing
+-     the .arch directive in assembly.  */
+-  if (!selected_arch)
++  else if (selected_arch)
+     {
+-      gcc_assert (selected_cpu);
++      selected_cpu = &all_cores[selected_arch->ident];
++      aarch64_isa_flags = arch_isa;
++    }
++  else
++    {
++      /* No -mcpu or -march specified, so use the default CPU.  */
++      selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
+       selected_arch = &all_architectures[selected_cpu->arch];
++      aarch64_isa_flags = selected_cpu->flags;
+     }
+ 
++  explicit_arch = selected_arch->arch;
+   if (!selected_tune)
+     selected_tune = selected_cpu;
++  explicit_tune_core = selected_tune->ident;
++
++  gcc_assert (explicit_tune_core != aarch64_none);
++  gcc_assert (explicit_arch != aarch64_no_arch);
+ 
+   if (aarch64_enable_bti == 2)
+     {
+@@ -18605,15 +18563,6 @@ aarch64_override_options (void)
+   if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+     sorry ("return address signing is only supported for %<-mabi=lp64%>");
+ 
+-  /* Make sure we properly set up the explicit options.  */
+-  if ((aarch64_cpu_string && valid_cpu)
+-       || (aarch64_tune_string && valid_tune))
+-    gcc_assert (explicit_tune_core != aarch64_none);
+-
+-  if ((aarch64_cpu_string && valid_cpu)
+-       || (aarch64_arch_string && valid_arch))
+-    gcc_assert (explicit_arch != aarch64_no_arch);
+-
+   /* The pass to insert speculation tracking runs before
+      shrink-wrapping and the latter does not know how to update the
+      tracking status.  So disable it in this case.  */
+@@ -18719,11 +18668,7 @@ aarch64_option_restore (struct gcc_options *opts,
+   opts->x_explicit_arch = ptr->x_explicit_arch;
+   selected_arch = aarch64_get_arch (ptr->x_explicit_arch);
+   opts->x_explicit_tune_core = ptr->x_explicit_tune_core;
+-  if (opts->x_explicit_tune_core == aarch64_none
+-      && opts->x_explicit_arch != aarch64_no_arch)
+-    selected_tune = &all_cores[selected_arch->ident];
+-  else
+-    selected_tune = aarch64_get_tune_cpu (ptr->x_explicit_tune_core);
++  selected_tune = aarch64_get_tune_cpu (ptr->x_explicit_tune_core);
+   opts->x_aarch64_override_tune_string = ptr->x_aarch64_override_tune_string;
+   opts->x_aarch64_branch_protection_string
+     = ptr->x_aarch64_branch_protection_string;
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 6834c3e99..14e2af054 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -811,16 +811,9 @@ enum target_cpus
+   TARGET_CPU_generic
+ };
+ 
+-/* Define how many bits are used to represent the CPU in TARGET_CPU_DEFAULT.
+-   This needs to be big enough to fit the value of TARGET_CPU_generic.
+-   All bits after this are used to represent the AARCH64_CPU_DEFAULT_FLAGS.  */
+-#define TARGET_CPU_NBITS 8
+-#define TARGET_CPU_MASK ((1 << TARGET_CPU_NBITS) - 1)
+-
+ /* If there is no CPU defined at configure, use generic as default.  */
+ #ifndef TARGET_CPU_DEFAULT
+-#define TARGET_CPU_DEFAULT \
+-  (TARGET_CPU_generic | (AARCH64_CPU_DEFAULT_FLAGS << TARGET_CPU_NBITS))
++# define TARGET_CPU_DEFAULT TARGET_CPU_generic
+ #endif
+ 
+ /* If inserting NOP before a mult-accumulate insn remember to adjust the
+-- 
+2.33.0
+
diff --git a/0105-Backport-SME-AArch64-Cleanup-option-processing-code.patch b/0105-Backport-SME-AArch64-Cleanup-option-processing-code.patch
new file mode 100644
index 0000000..c945c81
--- /dev/null
+++ b/0105-Backport-SME-AArch64-Cleanup-option-processing-code.patch
@@ -0,0 +1,528 @@
+From ba32885874fc6caa90f6ae5e264bc3d51f64a26e Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra 
+Date: Wed, 1 Jun 2022 16:46:36 +0100
+Subject: [PATCH 006/157] [Backport][SME] AArch64: Cleanup option processing
+ code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ae54c1b09963779c5c3914782324ff48af32e2f1
+
+Further cleanup option processing. Remove the duplication of global
+variables for CPU and tune settings so that CPU option processing is
+simplified even further. Move global variables that need save and
+restore due to target option processing into aarch64.opt. This removes
+the need for explicit saving/restoring and unnecessary reparsing of
+options.
+
+gcc/
+	* config/aarch64/aarch64.opt (explicit_tune_core): Rename to
+	selected_tune.
+	(explicit_arch): Rename to selected_arch.
+	(x_aarch64_override_tune_string): Remove.
+	(aarch64_ra_sign_key): Add as TargetVariable so it gets saved/restored.
+	(aarch64_override_tune_string): Add Save so it gets saved/restored.
+	* config/aarch64/aarch64.h (aarch64_architecture_version): Remove.
+	* config/aarch64/aarch64.cc (aarch64_architecture_version): Remove.
+	(processor): Remove archtecture_version field.
+	(selected_arch): Remove global.
+	(selected_cpu): Remove global.
+	(selected_tune): Remove global.
+	(aarch64_ra_sign_key): Move global to aarch64.opt so it is saved.
+	(aarch64_override_options_internal): Use aarch64_get_tune_cpu.
+	(aarch64_override_options): Further simplify code to only set
+	selected_arch and selected_tune globals.
+	(aarch64_option_save): Remove now that target options are saved.
+	(aarch64_option_restore): Remove redundant target option restores.
+	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Use
+	AARCH64_ISA_V9.
+	* config/aarch64/aarch64-opts.h (aarch64_key_type): Add, moved from...
+	* config/aarch64/aarch64-protos.h (aarch64_key_type): Remove.
+	(aarch64_ra_sign_key): Remove.
+---
+ gcc/config/aarch64/aarch64-c.cc     |   2 +-
+ gcc/config/aarch64/aarch64-opts.h   |   6 +
+ gcc/config/aarch64/aarch64-protos.h |   8 --
+ gcc/config/aarch64/aarch64.cc       | 183 ++++++++++------------------
+ gcc/config/aarch64/aarch64.h        |   3 -
+ gcc/config/aarch64/aarch64.opt      |  12 +-
+ 6 files changed, 76 insertions(+), 138 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index a4c407724..90d45e45d 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -82,7 +82,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ {
+   aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile);
+ 
+-  builtin_define_with_int_value ("__ARM_ARCH", aarch64_architecture_version);
++  builtin_define_with_int_value ("__ARM_ARCH", AARCH64_ISA_V9 ? 9 : 8);
+ 
+   builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
+ 				 flag_short_enums ? 1 : 4);
+diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
+index 93572fe83..421648a15 100644
+--- a/gcc/config/aarch64/aarch64-opts.h
++++ b/gcc/config/aarch64/aarch64-opts.h
+@@ -98,4 +98,10 @@ enum stack_protector_guard {
+   SSP_GLOBAL			/* global canary */
+ };
+ 
++/* The key type that -msign-return-address should use.  */
++enum aarch64_key_type {
++  AARCH64_KEY_A,
++  AARCH64_KEY_B
++};
++
+ #endif
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 475d174dd..e60ce3c36 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -672,14 +672,6 @@ enum simd_immediate_check {
+   AARCH64_CHECK_MOV  = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
+ };
+ 
+-/* The key type that -msign-return-address should use.  */
+-enum aarch64_key_type {
+-  AARCH64_KEY_A,
+-  AARCH64_KEY_B
+-};
+-
+-extern enum aarch64_key_type aarch64_ra_sign_key;
+-
+ extern struct tune_params aarch64_tune_params;
+ 
+ /* The available SVE predicate patterns, known in the ACLE as "svpattern".  */
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index ba888beb0..254ecfaa2 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -306,9 +306,6 @@ static bool aarch64_print_address_internal (FILE*, machine_mode, rtx,
+ 					    aarch64_addr_query_type);
+ static HOST_WIDE_INT aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val);
+ 
+-/* Major revision number of the ARM Architecture implemented by the target.  */
+-unsigned aarch64_architecture_version;
+-
+ /* The processor for which instructions should be scheduled.  */
+ enum aarch64_processor aarch64_tune = cortexa53;
+ 
+@@ -2931,7 +2928,6 @@ struct processor
+   enum aarch64_processor ident;
+   enum aarch64_processor sched_core;
+   enum aarch64_arch arch;
+-  unsigned architecture_version;
+   const uint64_t flags;
+   const struct tune_params *const tune;
+ };
+@@ -2940,9 +2936,9 @@ struct processor
+ static const struct processor all_architectures[] =
+ {
+ #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
+-  {NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, ARCH_REV, FLAGS, NULL},
++  {NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, FLAGS, NULL},
+ #include "aarch64-arches.def"
+-  {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, 0, NULL}
++  {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
+ };
+ 
+ /* Processor cores implementing AArch64.  */
+@@ -2950,23 +2946,13 @@ static const struct processor all_cores[] =
+ {
+ #define AARCH64_CORE(NAME, IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
+   {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH,				\
+-  all_architectures[AARCH64_ARCH_##ARCH].architecture_version,	\
+   FLAGS, &COSTS##_tunings},
+ #include "aarch64-cores.def"
+-  {"generic", generic, cortexa53, AARCH64_ARCH_8A, 8,
++  {"generic", generic, cortexa53, AARCH64_ARCH_8A,
+     AARCH64_FL_FOR_ARCH8, &generic_tunings},
+-  {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, 0, NULL}
++  {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
+ };
+ 
+-
+-/* Target specification.  These are populated by the -march, -mtune, -mcpu
+-   handling code or by target attributes.  */
+-static const struct processor *selected_arch;
+-static const struct processor *selected_cpu;
+-static const struct processor *selected_tune;
+-
+-enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A;
+-
+ /* The current tuning set.  */
+ struct tune_params aarch64_tune_params = generic_tunings;
+ 
+@@ -10633,8 +10619,8 @@ aarch64_case_values_threshold (void)
+   /* Use the specified limit for the number of cases before using jump
+      tables at higher optimization levels.  */
+   if (optimize > 2
+-      && selected_cpu->tune->max_case_values != 0)
+-    return selected_cpu->tune->max_case_values;
++      && aarch64_tune_params.max_case_values != 0)
++    return aarch64_tune_params.max_case_values;
+   else
+     return optimize_size ? 8 : 11;
+ }
+@@ -17769,6 +17755,26 @@ initialize_aarch64_tls_size (struct gcc_options *opts)
+   return;
+ }
+ 
++/* Return the CPU corresponding to the enum CPU.  */
++
++static const struct processor *
++aarch64_get_tune_cpu (enum aarch64_processor cpu)
++{
++  gcc_assert (cpu != aarch64_none);
++
++  return &all_cores[cpu];
++}
++
++/* Return the architecture corresponding to the enum ARCH.  */
++
++static const struct processor *
++aarch64_get_arch (enum aarch64_arch arch)
++{
++  gcc_assert (arch != aarch64_no_arch);
++
++  return &all_architectures[arch];
++}
++
+ /* Parse STRING looking for options in the format:
+      string	:: option:string
+      option	:: name=substring
+@@ -17879,18 +17885,18 @@ aarch64_override_options_after_change_1 (struct gcc_options *opts)
+ void
+ aarch64_override_options_internal (struct gcc_options *opts)
+ {
+-  aarch64_tune_flags = selected_tune->flags;
+-  aarch64_tune = selected_tune->sched_core;
++  const struct processor *tune = aarch64_get_tune_cpu (opts->x_selected_tune);
++  aarch64_tune_flags = tune->flags;
++  aarch64_tune = tune->sched_core;
+   /* Make a copy of the tuning parameters attached to the core, which
+      we may later overwrite.  */
+-  aarch64_tune_params = *(selected_tune->tune);
+-  aarch64_architecture_version = selected_arch->architecture_version;
+-  if (selected_tune->tune == &generic_tunings)
++  aarch64_tune_params = *(tune->tune);
++  if (tune->tune == &generic_tunings)
+     aarch64_adjust_generic_arch_tuning (aarch64_tune_params);
+ 
+   if (opts->x_aarch64_override_tune_string)
+     aarch64_parse_override_string (opts->x_aarch64_override_tune_string,
+-				  &aarch64_tune_params);
++				   &aarch64_tune_params);
+ 
+   /* This target defaults to strict volatile bitfields.  */
+   if (opts->x_flag_strict_volatile_bitfields < 0 && abi_version_at_least (2))
+@@ -18051,13 +18057,6 @@ aarch64_override_options_internal (struct gcc_options *opts)
+       && opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level)
+     opts->x_flag_prefetch_loop_arrays = 1;
+ 
+-  if (opts->x_aarch64_arch_string == NULL)
+-    opts->x_aarch64_arch_string = selected_arch->name;
+-  if (opts->x_aarch64_cpu_string == NULL)
+-    opts->x_aarch64_cpu_string = selected_cpu->name;
+-  if (opts->x_aarch64_tune_string == NULL)
+-    opts->x_aarch64_tune_string = selected_tune->name;
+-
+   aarch64_override_options_after_change_1 (opts);
+ }
+ 
+@@ -18409,26 +18408,6 @@ aarch64_validate_mtune (const char *str, const struct processor **res)
+   return false;
+ }
+ 
+-/* Return the CPU corresponding to the enum CPU.  */
+-
+-static const struct processor *
+-aarch64_get_tune_cpu (enum aarch64_processor cpu)
+-{
+-  gcc_assert (cpu != aarch64_none);
+-
+-  return &all_cores[cpu];
+-}
+-
+-/* Return the architecture corresponding to the enum ARCH.  */
+-
+-static const struct processor *
+-aarch64_get_arch (enum aarch64_arch arch)
+-{
+-  gcc_assert (arch != aarch64_no_arch);
+-
+-  return &all_architectures[arch];
+-}
+-
+ /* Return the VG value associated with -msve-vector-bits= value VALUE.  */
+ 
+ static poly_uint16
+@@ -18464,9 +18443,9 @@ aarch64_override_options (void)
+   uint64_t arch_isa = 0;
+   aarch64_isa_flags = 0;
+ 
+-  selected_cpu = NULL;
+-  selected_arch = NULL;
+-  selected_tune = NULL;
++  const struct processor *cpu = NULL;
++  const struct processor *arch = NULL;
++  const struct processor *tune = NULL;
+ 
+   if (aarch64_harden_sls_string)
+     aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
+@@ -18478,56 +18457,52 @@ aarch64_override_options (void)
+      If either of -march or -mtune is given, they override their
+      respective component of -mcpu.  */
+   if (aarch64_cpu_string)
+-    aarch64_validate_mcpu (aarch64_cpu_string, &selected_cpu, &cpu_isa);
++    aarch64_validate_mcpu (aarch64_cpu_string, &cpu, &cpu_isa);
+ 
+   if (aarch64_arch_string)
+-    aarch64_validate_march (aarch64_arch_string, &selected_arch, &arch_isa);
++    aarch64_validate_march (aarch64_arch_string, &arch, &arch_isa);
+ 
+   if (aarch64_tune_string)
+-    aarch64_validate_mtune (aarch64_tune_string, &selected_tune);
++    aarch64_validate_mtune (aarch64_tune_string, &tune);
+ 
+ #ifdef SUBTARGET_OVERRIDE_OPTIONS
+   SUBTARGET_OVERRIDE_OPTIONS;
+ #endif
+ 
+-  if (selected_cpu && selected_arch)
++  if (cpu && arch)
+     {
+       /* If both -mcpu and -march are specified, warn if they are not
+ 	 architecturally compatible and prefer the -march ISA flags.  */
+-      if (selected_arch->arch != selected_cpu->arch)
++      if (arch->arch != cpu->arch)
+ 	{
+ 	  warning (0, "switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch",
+ 		       aarch64_cpu_string,
+ 		       aarch64_arch_string);
+ 	}
+ 
++      selected_arch = arch->arch;
+       aarch64_isa_flags = arch_isa;
+     }
+-  else if (selected_cpu)
++  else if (cpu)
+     {
+-      selected_arch = &all_architectures[selected_cpu->arch];
++      selected_arch = cpu->arch;
+       aarch64_isa_flags = cpu_isa;
+     }
+-  else if (selected_arch)
++  else if (arch)
+     {
+-      selected_cpu = &all_cores[selected_arch->ident];
++      cpu = &all_cores[arch->ident];
++      selected_arch = arch->arch;
+       aarch64_isa_flags = arch_isa;
+     }
+   else
+     {
+       /* No -mcpu or -march specified, so use the default CPU.  */
+-      selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
+-      selected_arch = &all_architectures[selected_cpu->arch];
+-      aarch64_isa_flags = selected_cpu->flags;
++      cpu = &all_cores[TARGET_CPU_DEFAULT];
++      selected_arch = cpu->arch;
++      aarch64_isa_flags = cpu->flags;
+     }
+ 
+-  explicit_arch = selected_arch->arch;
+-  if (!selected_tune)
+-    selected_tune = selected_cpu;
+-  explicit_tune_core = selected_tune->ident;
+-
+-  gcc_assert (explicit_tune_core != aarch64_none);
+-  gcc_assert (explicit_arch != aarch64_no_arch);
++  selected_tune = tune ? tune->ident : cpu->ident;
+ 
+   if (aarch64_enable_bti == 2)
+     {
+@@ -18646,38 +18621,14 @@ initialize_aarch64_code_model (struct gcc_options *opts)
+     }
+ }
+ 
+-/* Implement TARGET_OPTION_SAVE.  */
+-
+-static void
+-aarch64_option_save (struct cl_target_option *ptr, struct gcc_options *opts,
+-		     struct gcc_options */* opts_set */)
+-{
+-  ptr->x_aarch64_override_tune_string = opts->x_aarch64_override_tune_string;
+-  ptr->x_aarch64_branch_protection_string
+-    = opts->x_aarch64_branch_protection_string;
+-}
+-
+ /* Implements TARGET_OPTION_RESTORE.  Restore the backend codegen decisions
+    using the information saved in PTR.  */
+ 
+ static void
+ aarch64_option_restore (struct gcc_options *opts,
+-			struct gcc_options */* opts_set */,
+-			struct cl_target_option *ptr)
++			struct gcc_options * /* opts_set */,
++			struct cl_target_option * /* ptr */)
+ {
+-  opts->x_explicit_arch = ptr->x_explicit_arch;
+-  selected_arch = aarch64_get_arch (ptr->x_explicit_arch);
+-  opts->x_explicit_tune_core = ptr->x_explicit_tune_core;
+-  selected_tune = aarch64_get_tune_cpu (ptr->x_explicit_tune_core);
+-  opts->x_aarch64_override_tune_string = ptr->x_aarch64_override_tune_string;
+-  opts->x_aarch64_branch_protection_string
+-    = ptr->x_aarch64_branch_protection_string;
+-  if (opts->x_aarch64_branch_protection_string)
+-    {
+-      aarch64_parse_branch_protection (opts->x_aarch64_branch_protection_string,
+-					NULL);
+-    }
+-
+   aarch64_override_options_internal (opts);
+ }
+ 
+@@ -18687,11 +18638,11 @@ static void
+ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
+ {
+   const struct processor *cpu
+-    = aarch64_get_tune_cpu (ptr->x_explicit_tune_core);
+-  uint64_t isa_flags = ptr->x_aarch64_isa_flags;
+-  const struct processor *arch = aarch64_get_arch (ptr->x_explicit_arch);
++    = aarch64_get_tune_cpu (ptr->x_selected_tune);
++  const struct processor *arch = aarch64_get_arch (ptr->x_selected_arch);
+   std::string extension
+-    = aarch64_get_extension_string_for_isa_flags (isa_flags, arch->flags);
++    = aarch64_get_extension_string_for_isa_flags (ptr->x_aarch64_isa_flags,
++						  arch->flags);
+ 
+   fprintf (file, "%*sselected tune = %s\n", indent, "", cpu->name);
+   fprintf (file, "%*sselected arch = %s%s\n", indent, "",
+@@ -18804,8 +18755,7 @@ aarch64_handle_attr_arch (const char *str)
+   if (parse_res == AARCH64_PARSE_OK)
+     {
+       gcc_assert (tmp_arch);
+-      selected_arch = tmp_arch;
+-      explicit_arch = selected_arch->arch;
++      selected_arch = tmp_arch->arch;
+       return true;
+     }
+ 
+@@ -18843,11 +18793,8 @@ aarch64_handle_attr_cpu (const char *str)
+   if (parse_res == AARCH64_PARSE_OK)
+     {
+       gcc_assert (tmp_cpu);
+-      selected_tune = tmp_cpu;
+-      explicit_tune_core = selected_tune->ident;
+-
+-      selected_arch = &all_architectures[tmp_cpu->arch];
+-      explicit_arch = selected_arch->arch;
++      selected_tune = tmp_cpu->ident;
++      selected_arch = tmp_cpu->arch;
+       return true;
+     }
+ 
+@@ -18915,8 +18862,7 @@ aarch64_handle_attr_tune (const char *str)
+   if (parse_res == AARCH64_PARSE_OK)
+     {
+       gcc_assert (tmp_tune);
+-      selected_tune = tmp_tune;
+-      explicit_tune_core = selected_tune->ident;
++      selected_tune = tmp_tune->ident;
+       return true;
+     }
+ 
+@@ -22821,7 +22767,7 @@ aarch64_declare_function_name (FILE *stream, const char* name,
+   gcc_assert (targ_options);
+ 
+   const struct processor *this_arch
+-    = aarch64_get_arch (targ_options->x_explicit_arch);
++    = aarch64_get_arch (targ_options->x_selected_arch);
+ 
+   uint64_t isa_flags = targ_options->x_aarch64_isa_flags;
+   std::string extension
+@@ -22840,7 +22786,7 @@ aarch64_declare_function_name (FILE *stream, const char* name,
+      useful to readers of the generated asm.  Do it only when it changes
+      from function to function and verbose assembly is requested.  */
+   const struct processor *this_tune
+-    = aarch64_get_tune_cpu (targ_options->x_explicit_tune_core);
++    = aarch64_get_tune_cpu (targ_options->x_selected_tune);
+ 
+   if (flag_debug_asm && aarch64_last_printed_tune_string != this_tune->name)
+     {
+@@ -22952,7 +22898,7 @@ aarch64_start_file (void)
+     = TREE_TARGET_OPTION (target_option_default_node);
+ 
+   const struct processor *default_arch
+-    = aarch64_get_arch (default_options->x_explicit_arch);
++    = aarch64_get_arch (default_options->x_selected_arch);
+   uint64_t default_isa_flags = default_options->x_aarch64_isa_flags;
+   std::string extension
+     = aarch64_get_extension_string_for_isa_flags (default_isa_flags,
+@@ -27950,9 +27896,6 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_OFFLOAD_OPTIONS
+ #define TARGET_OFFLOAD_OPTIONS aarch64_offload_options
+ 
+-#undef TARGET_OPTION_SAVE
+-#define TARGET_OPTION_SAVE aarch64_option_save
+-
+ #undef TARGET_OPTION_RESTORE
+ #define TARGET_OPTION_RESTORE aarch64_option_restore
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 14e2af054..7d73689e4 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -144,9 +144,6 @@
+ 
+ #define PCC_BITFIELD_TYPE_MATTERS	1
+ 
+-/* Major revision number of the ARM Architecture implemented by the target.  */
+-extern unsigned aarch64_architecture_version;
+-
+ /* Instruction tuning/selection flags.  */
+ 
+ /* Bit values used to identify processor capabilities.  */
+diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
+index 101664c7c..836a3c784 100644
+--- a/gcc/config/aarch64/aarch64.opt
++++ b/gcc/config/aarch64/aarch64.opt
+@@ -22,13 +22,10 @@ HeaderInclude
+ config/aarch64/aarch64-opts.h
+ 
+ TargetVariable
+-enum aarch64_processor explicit_tune_core = aarch64_none
++enum aarch64_processor selected_tune = aarch64_none
+ 
+ TargetVariable
+-enum aarch64_arch explicit_arch = aarch64_no_arch
+-
+-TargetSave
+-const char *x_aarch64_override_tune_string
++enum aarch64_arch selected_arch = aarch64_no_arch
+ 
+ TargetVariable
+ uint64_t aarch64_isa_flags = 0
+@@ -36,6 +33,9 @@ uint64_t aarch64_isa_flags = 0
+ TargetVariable
+ unsigned aarch64_enable_bti = 2
+ 
++TargetVariable
++enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A
++
+ ; The TLS dialect names to use with -mtls-dialect.
+ 
+ Enum
+@@ -139,7 +139,7 @@ Target RejectNegative Joined Enum(aarch64_abi) Var(aarch64_abi) Init(AARCH64_ABI
+ Generate code that conforms to the specified ABI.
+ 
+ moverride=
+-Target RejectNegative ToLower Joined Var(aarch64_override_tune_string)
++Target RejectNegative ToLower Joined Var(aarch64_override_tune_string) Save
+ -moverride=	Power users only! Override CPU optimization parameters.
+ 
+ Enum
+-- 
+2.33.0
+
diff --git a/0106-Backport-SME-aarch64-Add-march-support-for-Armv9.1-A.patch b/0106-Backport-SME-aarch64-Add-march-support-for-Armv9.1-A.patch
new file mode 100644
index 0000000..1655fab
--- /dev/null
+++ b/0106-Backport-SME-aarch64-Add-march-support-for-Armv9.1-A.patch
@@ -0,0 +1,108 @@
+From 0bfb7b0b745d0a9af13772ad48ccc102e557f95a Mon Sep 17 00:00:00 2001
+From: Kyrylo Tkachov 
+Date: Mon, 26 Sep 2022 10:10:25 +0100
+Subject: [PATCH 007/157] [Backport][SME] aarch64: Add -march support for
+ Armv9.1-A, Armv9.2-A, Armv9.3-A
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c33e12fa479c01848f4a288883bf1ef848c94ca3
+
+This is a straightforward patch that allows targeting the architecture revisions mentioned in the subject
+through -march. These are already supported in binutils.
+
+Bootstrapped and tested on aarch64-none-linux-gnu.
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64-arches.def (armv9.1-a): Define.
+	(armv9.2-a): Likewise.
+	(armv9.3-a): Likewise.
+	* config/aarch64/aarch64.h (AARCH64_FL_V9_1): Likewise.
+	(AARCH64_FL_V9_2): Likewise.
+	(AARCH64_FL_V9_3): Likewise.
+	(AARCH64_FL_FOR_ARCH9_1): Likewise.
+	(AARCH64_FL_FOR_ARCH9_2): Likewise.
+	(AARCH64_FL_FOR_ARCH9_3): Likewise.
+	(AARCH64_ISA_V9_1): Likewise.
+	(AARCH64_ISA_V9_2): Likewise.
+	(AARCH64_ISA_V9_3): Likewise.
+	* doc/invoke.texi (AArch64 Options): Document armv9.1-a, armv9.2-a,
+	armv9.3-a values to -march.
+---
+ gcc/config/aarch64/aarch64-arches.def |  3 +++
+ gcc/config/aarch64/aarch64.h          | 18 ++++++++++++++++++
+ gcc/doc/invoke.texi                   |  3 +++
+ 3 files changed, 24 insertions(+)
+
+diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
+index 3c2b16588..6150448dc 100644
+--- a/gcc/config/aarch64/aarch64-arches.def
++++ b/gcc/config/aarch64/aarch64-arches.def
+@@ -41,5 +41,8 @@ AARCH64_ARCH("armv8.7-a",     generic,       8_7A,      8,  AARCH64_FL_FOR_ARCH8
+ AARCH64_ARCH("armv8.8-a",     generic,       8_8A,      8,  AARCH64_FL_FOR_ARCH8_8)
+ AARCH64_ARCH("armv8-r",       generic,	     8R  ,	8,  AARCH64_FL_FOR_ARCH8_R)
+ AARCH64_ARCH("armv9-a",       generic,	     9A  ,	9,  AARCH64_FL_FOR_ARCH9)
++AARCH64_ARCH("armv9.1-a",     generic,       9_1A,      9,  AARCH64_FL_FOR_ARCH9_1)
++AARCH64_ARCH("armv9.2-a",     generic,       9_2A,      9,  AARCH64_FL_FOR_ARCH9_2)
++AARCH64_ARCH("armv9.3-a",     generic,       9_3A,      9,  AARCH64_FL_FOR_ARCH9_3)
+ 
+ #undef AARCH64_ARCH
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 7d73689e4..42aae37ef 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -239,6 +239,15 @@
+ /* Armv8.8-a architecture extensions.  */
+ #define AARCH64_FL_V8_8       (1ULL << 45)
+ 
++/* Armv9.1-A.  */
++#define AARCH64_FL_V9_1       (1ULL << 46)
++
++/* Armv9.2-A.  */
++#define AARCH64_FL_V9_2       (1ULL << 47)
++
++/* Armv9.3-A.  */
++#define AARCH64_FL_V9_3       (1ULL << 48)
++
+ /* Has FP and SIMD.  */
+ #define AARCH64_FL_FPSIMD     (AARCH64_FL_FP | AARCH64_FL_SIMD)
+ 
+@@ -274,6 +283,12 @@
+ #define AARCH64_FL_FOR_ARCH9       \
+   (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9 \
+    | AARCH64_FL_F16)
++#define AARCH64_FL_FOR_ARCH9_1	\
++  (AARCH64_FL_FOR_ARCH9 | AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V9_1)
++#define AARCH64_FL_FOR_ARCH9_2	\
++  (AARCH64_FL_FOR_ARCH9_1 | AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V9_2)
++#define AARCH64_FL_FOR_ARCH9_3	\
++  (AARCH64_FL_FOR_ARCH9_2 | AARCH64_FL_FOR_ARCH8_8 | AARCH64_FL_V9_3)
+ 
+ /* Macros to test ISA flags.  */
+ 
+@@ -314,6 +329,9 @@
+ #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)
++#define AARCH64_ISA_V9_1           (aarch64_isa_flags & AARCH64_FL_V9_1)
++#define AARCH64_ISA_V9_2           (aarch64_isa_flags & AARCH64_FL_V9_2)
++#define AARCH64_ISA_V9_3           (aarch64_isa_flags & AARCH64_FL_V9_3)
+ #define AARCH64_ISA_MOPS	   (aarch64_isa_flags & AARCH64_FL_MOPS)
+ #define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
+ 
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 17d9e4126..53709b246 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -19176,6 +19176,9 @@ and the features that they enable by default:
+ @item @samp{armv8.7-a} @tab Armv8.7-A @tab @samp{armv8.6-a}, @samp{+ls64}
+ @item @samp{armv8.8-a} @tab Armv8.8-a @tab @samp{armv8.7-a}, @samp{+mops}
+ @item @samp{armv9-a} @tab Armv9-A @tab @samp{armv8.5-a}, @samp{+sve}, @samp{+sve2}
++@item @samp{armv9.1-a} @tab Armv9.1-A @tab @samp{armv9-a}, @samp{+bf16}, @samp{+i8mm}
++@item @samp{armv9.2-a} @tab Armv9.2-A @tab @samp{armv9.1-a}, @samp{+ls64}
++@item @samp{armv9.3-a} @tab Armv9.3-A @tab @samp{armv9.2-a}, @samp{+mops}
+ @item @samp{armv8-r} @tab Armv8-R @tab @samp{armv8-r}
+ @end multitable
+ 
+-- 
+2.33.0
+
diff --git a/0107-Backport-SME-Revert-aarch64-Define-__ARM_FEATURE_RCP.patch b/0107-Backport-SME-Revert-aarch64-Define-__ARM_FEATURE_RCP.patch
new file mode 100644
index 0000000..4de737c
--- /dev/null
+++ b/0107-Backport-SME-Revert-aarch64-Define-__ARM_FEATURE_RCP.patch
@@ -0,0 +1,112 @@
+From b36c8c41cab42d3df45197bb287f06381d660001 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Mon, 19 Feb 2024 19:27:29 +0800
+Subject: [PATCH 008/157] [Backport][SME] Revert "aarch64: Define
+ __ARM_FEATURE_RCPC"
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=40a727379f3e8e6a83aea4e94c38dfa5dd8ef33d
+
+Revert this commit to solve conflicts with later patches,
+and will apply it later.
+---
+ gcc/config/aarch64/aarch64-c.cc               |  1 -
+ gcc/config/aarch64/aarch64-cores.def          | 10 +++++-----
+ gcc/config/aarch64/aarch64.h                  |  4 +---
+ .../gcc.target/aarch64/pragma_cpp_predefs_1.c | 20 -------------------
+ 4 files changed, 6 insertions(+), 29 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 90d45e45d..3d2fb5ec2 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -202,7 +202,6 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ 			"__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile);
+   aarch64_def_or_undef (TARGET_LS64,
+ 			"__ARM_FEATURE_LS64", pfile);
+-  aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile);
+ 
+   /* Not for ACLE, but required to keep "float.h" correct if we switch
+      target between implementations that do or do not support ARMv8.2-A
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 70b11eb80..842d64932 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -134,17 +134,17 @@ AARCH64_CORE("tsv110",  tsv110, tsv110, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, 8_3A,  AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_CRYPTO | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, 8_3A,  AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores.  */
+-AARCH64_CORE("zeus", zeus, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
++AARCH64_CORE("zeus", zeus, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("saphira",     saphira,    saphira,    8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_CRYPTO, saphira,   0x51, 0xC01, -1)
++AARCH64_CORE("saphira",     saphira,    saphira,    8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
+ 
+ /* ARMv8-A big.LITTLE implementations.  */
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 42aae37ef..7c090c8f2 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -262,8 +262,7 @@
+ #define AARCH64_FL_FOR_ARCH8_2			\
+   (AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2)
+ #define AARCH64_FL_FOR_ARCH8_3			\
+-  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3 | AARCH64_FL_PAUTH \
+-   | AARCH64_FL_RCPC)
++  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3 | AARCH64_FL_PAUTH)
+ #define AARCH64_FL_FOR_ARCH8_4			\
+   (AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_V8_4 | AARCH64_FL_F16FML \
+    | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4 | AARCH64_FL_FLAGM)
+@@ -314,7 +313,6 @@
+ #define AARCH64_ISA_SM4	           (aarch64_isa_flags & AARCH64_FL_SM4)
+ #define AARCH64_ISA_SHA3	   (aarch64_isa_flags & AARCH64_FL_SHA3)
+ #define AARCH64_ISA_F16FML	   (aarch64_isa_flags & AARCH64_FL_F16FML)
+-#define AARCH64_ISA_RCPC	   (aarch64_isa_flags & AARCH64_FL_RCPC)
+ #define AARCH64_ISA_RCPC8_4	   (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
+ #define AARCH64_ISA_RNG		   (aarch64_isa_flags & AARCH64_FL_RNG)
+ #define AARCH64_ISA_V8_5	   (aarch64_isa_flags & AARCH64_FL_V8_5)
+diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c
+index 307fa3d67..bfb044f5d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c
+@@ -248,26 +248,6 @@
+ #error "__ARM_FEATURE_CRC32 is not defined but should be!"
+ #endif
+ 
+-#pragma GCC target ("arch=armv8.2-a")
+-#ifdef __ARM_FEATURE_RCPC
+-#error "__ARM_FEATURE_RCPC is defined but should not be!"
+-#endif
+-
+-#pragma GCC target ("arch=armv8.2-a+rcpc")
+-#ifndef __ARM_FEATURE_RCPC
+-#error "__ARM_FEATURE_RCPC is not defined but should be!"
+-#endif
+-
+-#pragma GCC target ("+norcpc")
+-#ifdef __ARM_FEATURE_RCPC
+-#error "__ARM_FEATURE_RCPC is defined but should not be!"
+-#endif
+-
+-#pragma GCC target ("arch=armv8.3-a")
+-#ifndef __ARM_FEATURE_RCPC
+-#error "__ARM_FEATURE_RCPC is not defined but should be!"
+-#endif
+-
+ int
+ foo (int a)
+ {
+-- 
+2.33.0
+
diff --git a/0108-Backport-SME-Revert-Ampere-1-and-Ampere-1A-core-defi.patch b/0108-Backport-SME-Revert-Ampere-1-and-Ampere-1A-core-defi.patch
new file mode 100644
index 0000000..a70376d
--- /dev/null
+++ b/0108-Backport-SME-Revert-Ampere-1-and-Ampere-1A-core-defi.patch
@@ -0,0 +1,39 @@
+From 34374de5edde59f27a1b3b443e8a163fc5b528d7 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Tue, 20 Feb 2024 10:13:06 +0800
+Subject: [PATCH 009/157] [Backport][SME] Revert "Ampere-1 and Ampere-1A core
+ definition in aarch64-cores.def"
+
+Revert it to solve conflicts with later patches, and will apply it
+later. It's introduced by commit 3668a59ae22a and e9f0d974600e.
+---
+ gcc/config/aarch64/aarch64-cores.def | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 842d64932..0402bfb74 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -69,8 +69,7 @@ AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  8A,  AARCH64_FL_FOR_ARCH
+ AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+ /* Ampere Computing ('\xC0') cores. */
+-AARCH64_CORE("ampere1", ampere1, cortexa57, 8_6A, AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_RNG | AARCH64_FL_SHA3, ampere1, 0xC0, 0xac3, -1)
+-AARCH64_CORE("ampere1a", ampere1a, cortexa57, 8_6A, AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_RNG | AARCH64_FL_SHA3 | AARCH64_FL_MEMTAG, ampere1a, 0xC0, 0xac4, -1)
++AARCH64_CORE("ampere1", ampere1, cortexa57, 8_6A, AARCH64_FL_FOR_ARCH8_6, ampere1, 0xC0, 0xac3, -1)
+ /* Do not swap around "emag" and "xgene1",
+    this order is required to handle variant correctly. */
+ AARCH64_CORE("emag",        emag,      xgene1,    8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
+@@ -164,8 +163,7 @@ AARCH64_CORE("cortex-r82", cortexr82, cortexa53, 8R, AARCH64_FL_FOR_ARCH8_R, cor
+ /* 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-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)
+ 
+-- 
+2.33.0
+
diff --git a/0109-Backport-SME-aarch64-Rename-AARCH64_ISA-architecture.patch b/0109-Backport-SME-aarch64-Rename-AARCH64_ISA-architecture.patch
new file mode 100644
index 0000000..9b541de
--- /dev/null
+++ b/0109-Backport-SME-aarch64-Rename-AARCH64_ISA-architecture.patch
@@ -0,0 +1,157 @@
+From 244780570ebc85c44806559ba165d4a70a2333d1 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:50 +0100
+Subject: [PATCH 010/157] [Backport][SME] aarch64: Rename AARCH64_ISA
+ architecture-level macros
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2a4788ac3bae1467b0379852d5a6690a8496d0c9
+
+All AARCH64_ISA_* architecture-level macros except AARCH64_ISA_V8_R
+are for the A profile: they cause __ARM_ARCH_PROFILE to be set to
+'A' and they are associated with architecture names like armv8.4-a.
+
+It's convenient for later patches if we make this explicit
+by adding an "A" to the name.  Also, rather than add an underscore
+(as for V8_R) it's more convenient to add the profile directly
+to the number, like we already do in the ARCH_IDENT field of the
+aarch64-arches.def entries.
+
+gcc/
+	* config/aarch64/aarch64.h (AARCH64_ISA_V8_2, AARCH64_ISA_V8_3)
+	(AARCH64_ISA_V8_4, AARCH64_ISA_V8_5, AARCH64_ISA_V8_6)
+	(AARCH64_ISA_V9, AARCH64_ISA_V9_1, AARCH64_ISA_V9_2)
+	(AARCH64_ISA_V9_3): Add "A" to the end of the name.
+	(AARCH64_ISA_V8_R): Rename to AARCH64_ISA_V8R.
+	(TARGET_ARMV8_3, TARGET_JSCVT, TARGET_FRINT, TARGET_MEMTAG): Update
+	accordingly.
+	* common/config/aarch64/aarch64-common.cc
+	(aarch64_get_extension_string_for_isa_flags): Likewise.
+	* config/aarch64/aarch64-c.cc
+	(aarch64_define_unconditional_macros): Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc |  2 +-
+ gcc/config/aarch64/aarch64-c.cc             |  4 +--
+ gcc/config/aarch64/aarch64.h                | 28 ++++++++++-----------
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 85ce8133b..3dc020f0c 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -506,7 +506,7 @@ aarch64_get_extension_string_for_isa_flags (uint64_t isa_flags,
+ 
+       Note that assemblers with Armv8-R AArch64 support should not have this
+       issue, so we don't need this fix when targeting Armv8-R.  */
+-  if ((isa_flags & AARCH64_ISA_CRC) && !AARCH64_ISA_V8_R)
++  if ((isa_flags & AARCH64_ISA_CRC) && !AARCH64_ISA_V8R)
+     isa_flag_bits |= AARCH64_ISA_CRC;
+ 
+   /* Pass Two:
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 3d2fb5ec2..18c9b975b 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -64,7 +64,7 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
+   builtin_define ("__ARM_ARCH_8A");
+ 
+   builtin_define_with_int_value ("__ARM_ARCH_PROFILE",
+-      AARCH64_ISA_V8_R ? 'R' : 'A');
++      AARCH64_ISA_V8R ? 'R' : 'A');
+   builtin_define ("__ARM_FEATURE_CLZ");
+   builtin_define ("__ARM_FEATURE_IDIV");
+   builtin_define ("__ARM_FEATURE_UNALIGNED");
+@@ -82,7 +82,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ {
+   aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile);
+ 
+-  builtin_define_with_int_value ("__ARM_ARCH", AARCH64_ISA_V9 ? 9 : 8);
++  builtin_define_with_int_value ("__ARM_ARCH", AARCH64_ISA_V9A ? 9 : 8);
+ 
+   builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
+ 				 flag_short_enums ? 1 : 4);
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 7c090c8f2..356a263b2 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -297,7 +297,7 @@
+ #define AARCH64_ISA_SIMD           (aarch64_isa_flags & AARCH64_FL_SIMD)
+ #define AARCH64_ISA_LSE		   (aarch64_isa_flags & AARCH64_FL_LSE)
+ #define AARCH64_ISA_RDMA	   (aarch64_isa_flags & AARCH64_FL_RDMA)
+-#define AARCH64_ISA_V8_2	   (aarch64_isa_flags & AARCH64_FL_V8_2)
++#define AARCH64_ISA_V8_2A	   (aarch64_isa_flags & AARCH64_FL_V8_2)
+ #define AARCH64_ISA_F16		   (aarch64_isa_flags & AARCH64_FL_F16)
+ #define AARCH64_ISA_SVE            (aarch64_isa_flags & AARCH64_FL_SVE)
+ #define AARCH64_ISA_SVE2	   (aarch64_isa_flags & AARCH64_FL_SVE2)
+@@ -305,31 +305,31 @@
+ #define AARCH64_ISA_SVE2_BITPERM  (aarch64_isa_flags & AARCH64_FL_SVE2_BITPERM)
+ #define AARCH64_ISA_SVE2_SHA3	   (aarch64_isa_flags & AARCH64_FL_SVE2_SHA3)
+ #define AARCH64_ISA_SVE2_SM4	   (aarch64_isa_flags & AARCH64_FL_SVE2_SM4)
+-#define AARCH64_ISA_V8_3	   (aarch64_isa_flags & AARCH64_FL_V8_3)
++#define AARCH64_ISA_V8_3A	   (aarch64_isa_flags & AARCH64_FL_V8_3)
+ #define AARCH64_ISA_DOTPROD	   (aarch64_isa_flags & AARCH64_FL_DOTPROD)
+ #define AARCH64_ISA_AES	           (aarch64_isa_flags & AARCH64_FL_AES)
+ #define AARCH64_ISA_SHA2	   (aarch64_isa_flags & AARCH64_FL_SHA2)
+-#define AARCH64_ISA_V8_4	   (aarch64_isa_flags & AARCH64_FL_V8_4)
++#define AARCH64_ISA_V8_4A	   (aarch64_isa_flags & AARCH64_FL_V8_4)
+ #define AARCH64_ISA_SM4	           (aarch64_isa_flags & AARCH64_FL_SM4)
+ #define AARCH64_ISA_SHA3	   (aarch64_isa_flags & AARCH64_FL_SHA3)
+ #define AARCH64_ISA_F16FML	   (aarch64_isa_flags & AARCH64_FL_F16FML)
+ #define AARCH64_ISA_RCPC8_4	   (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
+ #define AARCH64_ISA_RNG		   (aarch64_isa_flags & AARCH64_FL_RNG)
+-#define AARCH64_ISA_V8_5	   (aarch64_isa_flags & AARCH64_FL_V8_5)
++#define AARCH64_ISA_V8_5A	   (aarch64_isa_flags & AARCH64_FL_V8_5)
+ #define AARCH64_ISA_TME		   (aarch64_isa_flags & AARCH64_FL_TME)
+ #define AARCH64_ISA_MEMTAG	   (aarch64_isa_flags & AARCH64_FL_MEMTAG)
+-#define AARCH64_ISA_V8_6	   (aarch64_isa_flags & AARCH64_FL_V8_6)
++#define AARCH64_ISA_V8_6A	   (aarch64_isa_flags & AARCH64_FL_V8_6)
+ #define AARCH64_ISA_I8MM	   (aarch64_isa_flags & AARCH64_FL_I8MM)
+ #define AARCH64_ISA_F32MM	   (aarch64_isa_flags & AARCH64_FL_F32MM)
+ #define AARCH64_ISA_F64MM	   (aarch64_isa_flags & AARCH64_FL_F64MM)
+ #define AARCH64_ISA_BF16	   (aarch64_isa_flags & AARCH64_FL_BF16)
+ #define AARCH64_ISA_SB		   (aarch64_isa_flags & AARCH64_FL_SB)
+-#define AARCH64_ISA_V8_R	   (aarch64_isa_flags & AARCH64_FL_V8_R)
++#define AARCH64_ISA_V8R		   (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)
+-#define AARCH64_ISA_V9_1           (aarch64_isa_flags & AARCH64_FL_V9_1)
+-#define AARCH64_ISA_V9_2           (aarch64_isa_flags & AARCH64_FL_V9_2)
+-#define AARCH64_ISA_V9_3           (aarch64_isa_flags & AARCH64_FL_V9_3)
++#define AARCH64_ISA_V9A		   (aarch64_isa_flags & AARCH64_FL_V9)
++#define AARCH64_ISA_V9_1A          (aarch64_isa_flags & AARCH64_FL_V9_1)
++#define AARCH64_ISA_V9_2A          (aarch64_isa_flags & AARCH64_FL_V9_2)
++#define AARCH64_ISA_V9_3A          (aarch64_isa_flags & AARCH64_FL_V9_3)
+ #define AARCH64_ISA_MOPS	   (aarch64_isa_flags & AARCH64_FL_MOPS)
+ #define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
+ 
+@@ -383,16 +383,16 @@
+ #define TARGET_SVE2_SM4 (TARGET_SVE2 && AARCH64_ISA_SVE2_SM4)
+ 
+ /* ARMv8.3-A features.  */
+-#define TARGET_ARMV8_3	(AARCH64_ISA_V8_3)
++#define TARGET_ARMV8_3	(AARCH64_ISA_V8_3A)
+ 
+ /* Javascript conversion instruction from Armv8.3-a.  */
+-#define TARGET_JSCVT	(TARGET_FLOAT && AARCH64_ISA_V8_3)
++#define TARGET_JSCVT	(TARGET_FLOAT && AARCH64_ISA_V8_3A)
+ 
+ /* Armv8.3-a Complex number extension to AdvSIMD extensions.  */
+ #define TARGET_COMPLEX (TARGET_SIMD && TARGET_ARMV8_3)
+ 
+ /* Floating-point rounding instructions from Armv8.5-a.  */
+-#define TARGET_FRINT (AARCH64_ISA_V8_5 && TARGET_FLOAT)
++#define TARGET_FRINT (AARCH64_ISA_V8_5A && TARGET_FLOAT)
+ 
+ /* TME instructions are enabled.  */
+ #define TARGET_TME (AARCH64_ISA_TME)
+@@ -401,7 +401,7 @@
+ #define TARGET_RNG (AARCH64_ISA_RNG)
+ 
+ /* Memory Tagging instructions optional to Armv8.5 enabled through +memtag.  */
+-#define TARGET_MEMTAG (AARCH64_ISA_V8_5 && AARCH64_ISA_MEMTAG)
++#define TARGET_MEMTAG (AARCH64_ISA_V8_5A && AARCH64_ISA_MEMTAG)
+ 
+ /* I8MM instructions are enabled through +i8mm.  */
+ #define TARGET_I8MM (AARCH64_ISA_I8MM)
+-- 
+2.33.0
+
diff --git a/0110-Backport-SME-aarch64-Rename-AARCH64_FL-architecture-.patch b/0110-Backport-SME-aarch64-Rename-AARCH64_FL-architecture-.patch
new file mode 100644
index 0000000..99317e4
--- /dev/null
+++ b/0110-Backport-SME-aarch64-Rename-AARCH64_FL-architecture-.patch
@@ -0,0 +1,220 @@
+From e1b067871c4c39565bf6059b4924a810923c6eeb Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:51 +0100
+Subject: [PATCH 011/157] [Backport][SME] aarch64: Rename AARCH64_FL
+ architecture-level macros
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=78aaafc3d4dc0ef997b4747349d3836ca2f7e301
+
+Following on from the previous AARCH64_ISA patch, this one adds the
+profile name directly to the end of architecture-level AARCH64_FL_*
+macros.
+
+gcc/
+	* config/aarch64/aarch64.h (AARCH64_FL_V8_1, AARCH64_FL_V8_2)
+	(AARCH64_FL_V8_3, AARCH64_FL_V8_4, AARCH64_FL_V8_5, AARCH64_FL_V8_6)
+	(AARCH64_FL_V9, AARCH64_FL_V8_7, AARCH64_FL_V8_8, AARCH64_FL_V9_1)
+	(AARCH64_FL_V9_2, AARCH64_FL_V9_3): Add "A" to the end of the name.
+	(AARCH64_FL_V8_R): Rename to AARCH64_FL_V8R.
+	(AARCH64_FL_FOR_ARCH8_1, AARCH64_FL_FOR_ARCH8_2): Update accordingly.
+	(AARCH64_FL_FOR_ARCH8_3, AARCH64_FL_FOR_ARCH8_4): Likewise.
+	(AARCH64_FL_FOR_ARCH8_5, AARCH64_FL_FOR_ARCH8_6): Likewise.
+	(AARCH64_FL_FOR_ARCH8_7, AARCH64_FL_FOR_ARCH8_8): Likewise.
+	(AARCH64_FL_FOR_ARCH8_R, AARCH64_FL_FOR_ARCH9): Likewise.
+	(AARCH64_FL_FOR_ARCH9_1, AARCH64_FL_FOR_ARCH9_2): Likewise.
+	(AARCH64_FL_FOR_ARCH9_3, AARCH64_ISA_V8_2A, AARCH64_ISA_V8_3A)
+	(AARCH64_ISA_V8_4A, AARCH64_ISA_V8_5A, AARCH64_ISA_V8_6A): Likewise.
+	(AARCH64_ISA_V8R, AARCH64_ISA_V9A, AARCH64_ISA_V9_1A): Likewise.
+	(AARCH64_ISA_V9_2A, AARCH64_ISA_V9_3A): Likewise.
+---
+ gcc/config/aarch64/aarch64.h | 72 ++++++++++++++++++------------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 356a263b2..5a91dfdd2 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -154,22 +154,22 @@
+ /* ARMv8.1-A architecture extensions.  */
+ #define AARCH64_FL_LSE	      (1 << 4)  /* Has Large System Extensions.  */
+ #define AARCH64_FL_RDMA       (1 << 5)  /* Has Round Double Multiply Add.  */
+-#define AARCH64_FL_V8_1       (1 << 6)  /* Has ARMv8.1-A extensions.  */
++#define AARCH64_FL_V8_1A      (1 << 6)  /* Has ARMv8.1-A extensions.  */
+ /* Armv8-R.  */
+-#define AARCH64_FL_V8_R       (1 << 7)  /* Armv8-R AArch64.  */
++#define AARCH64_FL_V8R        (1 << 7)  /* Armv8-R AArch64.  */
+ /* ARMv8.2-A architecture extensions.  */
+-#define AARCH64_FL_V8_2       (1 << 8)  /* Has ARMv8.2-A features.  */
++#define AARCH64_FL_V8_2A      (1 << 8)  /* Has ARMv8.2-A features.  */
+ #define AARCH64_FL_F16	      (1 << 9)  /* Has ARMv8.2-A FP16 extensions.  */
+ #define AARCH64_FL_SVE        (1 << 10) /* Has Scalable Vector Extensions.  */
+ /* ARMv8.3-A architecture extensions.  */
+-#define AARCH64_FL_V8_3       (1 << 11)  /* Has ARMv8.3-A features.  */
++#define AARCH64_FL_V8_3A      (1 << 11)  /* Has ARMv8.3-A features.  */
+ #define AARCH64_FL_RCPC       (1 << 12)  /* Has support for RCpc model.  */
+ #define AARCH64_FL_DOTPROD    (1 << 13)  /* Has ARMv8.2-A Dot Product ins.  */
+ /* New flags to split crypto into aes and sha2.  */
+ #define AARCH64_FL_AES	      (1 << 14)  /* Has Crypto AES.  */
+ #define AARCH64_FL_SHA2	      (1 << 15)  /* Has Crypto SHA2.  */
+ /* ARMv8.4-A architecture extensions.  */
+-#define AARCH64_FL_V8_4	      (1 << 16)  /* Has ARMv8.4-A features.  */
++#define AARCH64_FL_V8_4A      (1 << 16)  /* Has ARMv8.4-A features.  */
+ #define AARCH64_FL_SM4	      (1 << 17)  /* Has ARMv8.4-A SM3 and SM4.  */
+ #define AARCH64_FL_SHA3	      (1 << 18)  /* Has ARMv8.4-a SHA3 and SHA512.  */
+ #define AARCH64_FL_F16FML     (1 << 19)  /* Has ARMv8.4-a FP16 extensions.  */
+@@ -179,7 +179,7 @@
+ #define AARCH64_FL_PROFILE    (1 << 21)
+ 
+ /* ARMv8.5-A architecture extensions.  */
+-#define AARCH64_FL_V8_5	      (1 << 22)  /* Has ARMv8.5-A features.  */
++#define AARCH64_FL_V8_5A      (1 << 22)  /* Has ARMv8.5-A features.  */
+ #define AARCH64_FL_RNG	      (1 << 23)  /* ARMv8.5-A Random Number Insns.  */
+ #define AARCH64_FL_MEMTAG     (1 << 24)  /* ARMv8.5-A Memory Tagging
+ 					    Extensions.  */
+@@ -204,7 +204,7 @@
+ #define AARCH64_FL_TME	      (1ULL << 33)  /* Has TME instructions.  */
+ 
+ /* Armv8.6-A architecture extensions.  */
+-#define AARCH64_FL_V8_6	      (1ULL << 34)
++#define AARCH64_FL_V8_6A      (1ULL << 34)
+ 
+ /* 8-bit Integer Matrix Multiply (I8MM) extensions.  */
+ #define AARCH64_FL_I8MM	      (1ULL << 35)
+@@ -225,28 +225,28 @@
+ #define AARCH64_FL_PAUTH      (1ULL << 40)
+ 
+ /* Armv9.0-A.  */
+-#define AARCH64_FL_V9         (1ULL << 41)  /* Armv9.0-A Architecture.  */
++#define AARCH64_FL_V9A        (1ULL << 41)  /* Armv9.0-A Architecture.  */
+ 
+ /* 64-byte atomic load/store extensions.  */
+ #define AARCH64_FL_LS64      (1ULL << 42)
+ 
+ /* Armv8.7-a architecture extensions.  */
+-#define AARCH64_FL_V8_7       (1ULL << 43)
++#define AARCH64_FL_V8_7A      (1ULL << 43)
+ 
+ /* Hardware memory operation instructions.  */
+ #define AARCH64_FL_MOPS       (1ULL << 44)
+ 
+ /* Armv8.8-a architecture extensions.  */
+-#define AARCH64_FL_V8_8       (1ULL << 45)
++#define AARCH64_FL_V8_8A      (1ULL << 45)
+ 
+ /* Armv9.1-A.  */
+-#define AARCH64_FL_V9_1       (1ULL << 46)
++#define AARCH64_FL_V9_1A      (1ULL << 46)
+ 
+ /* Armv9.2-A.  */
+-#define AARCH64_FL_V9_2       (1ULL << 47)
++#define AARCH64_FL_V9_2A      (1ULL << 47)
+ 
+ /* Armv9.3-A.  */
+-#define AARCH64_FL_V9_3       (1ULL << 48)
++#define AARCH64_FL_V9_3A      (1ULL << 48)
+ 
+ /* Has FP and SIMD.  */
+ #define AARCH64_FL_FPSIMD     (AARCH64_FL_FP | AARCH64_FL_SIMD)
+@@ -258,36 +258,36 @@
+ #define AARCH64_FL_FOR_ARCH8       (AARCH64_FL_FPSIMD)
+ #define AARCH64_FL_FOR_ARCH8_1			       \
+   (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC \
+-   | AARCH64_FL_RDMA | AARCH64_FL_V8_1)
++   | AARCH64_FL_RDMA | AARCH64_FL_V8_1A)
+ #define AARCH64_FL_FOR_ARCH8_2			\
+-  (AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2)
++  (AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2A)
+ #define AARCH64_FL_FOR_ARCH8_3			\
+-  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3 | AARCH64_FL_PAUTH)
++  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3A | AARCH64_FL_PAUTH)
+ #define AARCH64_FL_FOR_ARCH8_4			\
+-  (AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_V8_4 | AARCH64_FL_F16FML \
++  (AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_V8_4A | AARCH64_FL_F16FML \
+    | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4 | AARCH64_FL_FLAGM)
+ #define AARCH64_FL_FOR_ARCH8_5			\
+-  (AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_5	\
++  (AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_5A	\
+    | AARCH64_FL_SB | AARCH64_FL_SSBS | AARCH64_FL_PREDRES)
+ #define AARCH64_FL_FOR_ARCH8_6			\
+-  (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_V8_6 | AARCH64_FL_FPSIMD \
++  (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_V8_6A | 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)
++  (AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V8_7A | AARCH64_FL_LS64)
+ #define AARCH64_FL_FOR_ARCH8_8			\
+-  (AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V8_8 | AARCH64_FL_MOPS)
++  (AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V8_8A | AARCH64_FL_MOPS)
+ 
+ #define AARCH64_FL_FOR_ARCH8_R     \
+-  (AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_R)
++  (AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8R)
+ #define AARCH64_FL_FOR_ARCH9       \
+-  (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9 \
++  (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9A \
+    | AARCH64_FL_F16)
+ #define AARCH64_FL_FOR_ARCH9_1	\
+-  (AARCH64_FL_FOR_ARCH9 | AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V9_1)
++  (AARCH64_FL_FOR_ARCH9 | AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V9_1A)
+ #define AARCH64_FL_FOR_ARCH9_2	\
+-  (AARCH64_FL_FOR_ARCH9_1 | AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V9_2)
++  (AARCH64_FL_FOR_ARCH9_1 | AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V9_2A)
+ #define AARCH64_FL_FOR_ARCH9_3	\
+-  (AARCH64_FL_FOR_ARCH9_2 | AARCH64_FL_FOR_ARCH8_8 | AARCH64_FL_V9_3)
++  (AARCH64_FL_FOR_ARCH9_2 | AARCH64_FL_FOR_ARCH8_8 | AARCH64_FL_V9_3A)
+ 
+ /* Macros to test ISA flags.  */
+ 
+@@ -297,7 +297,7 @@
+ #define AARCH64_ISA_SIMD           (aarch64_isa_flags & AARCH64_FL_SIMD)
+ #define AARCH64_ISA_LSE		   (aarch64_isa_flags & AARCH64_FL_LSE)
+ #define AARCH64_ISA_RDMA	   (aarch64_isa_flags & AARCH64_FL_RDMA)
+-#define AARCH64_ISA_V8_2A	   (aarch64_isa_flags & AARCH64_FL_V8_2)
++#define AARCH64_ISA_V8_2A	   (aarch64_isa_flags & AARCH64_FL_V8_2A)
+ #define AARCH64_ISA_F16		   (aarch64_isa_flags & AARCH64_FL_F16)
+ #define AARCH64_ISA_SVE            (aarch64_isa_flags & AARCH64_FL_SVE)
+ #define AARCH64_ISA_SVE2	   (aarch64_isa_flags & AARCH64_FL_SVE2)
+@@ -305,31 +305,31 @@
+ #define AARCH64_ISA_SVE2_BITPERM  (aarch64_isa_flags & AARCH64_FL_SVE2_BITPERM)
+ #define AARCH64_ISA_SVE2_SHA3	   (aarch64_isa_flags & AARCH64_FL_SVE2_SHA3)
+ #define AARCH64_ISA_SVE2_SM4	   (aarch64_isa_flags & AARCH64_FL_SVE2_SM4)
+-#define AARCH64_ISA_V8_3A	   (aarch64_isa_flags & AARCH64_FL_V8_3)
++#define AARCH64_ISA_V8_3A	   (aarch64_isa_flags & AARCH64_FL_V8_3A)
+ #define AARCH64_ISA_DOTPROD	   (aarch64_isa_flags & AARCH64_FL_DOTPROD)
+ #define AARCH64_ISA_AES	           (aarch64_isa_flags & AARCH64_FL_AES)
+ #define AARCH64_ISA_SHA2	   (aarch64_isa_flags & AARCH64_FL_SHA2)
+-#define AARCH64_ISA_V8_4A	   (aarch64_isa_flags & AARCH64_FL_V8_4)
++#define AARCH64_ISA_V8_4A	   (aarch64_isa_flags & AARCH64_FL_V8_4A)
+ #define AARCH64_ISA_SM4	           (aarch64_isa_flags & AARCH64_FL_SM4)
+ #define AARCH64_ISA_SHA3	   (aarch64_isa_flags & AARCH64_FL_SHA3)
+ #define AARCH64_ISA_F16FML	   (aarch64_isa_flags & AARCH64_FL_F16FML)
+ #define AARCH64_ISA_RCPC8_4	   (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
+ #define AARCH64_ISA_RNG		   (aarch64_isa_flags & AARCH64_FL_RNG)
+-#define AARCH64_ISA_V8_5A	   (aarch64_isa_flags & AARCH64_FL_V8_5)
++#define AARCH64_ISA_V8_5A	   (aarch64_isa_flags & AARCH64_FL_V8_5A)
+ #define AARCH64_ISA_TME		   (aarch64_isa_flags & AARCH64_FL_TME)
+ #define AARCH64_ISA_MEMTAG	   (aarch64_isa_flags & AARCH64_FL_MEMTAG)
+-#define AARCH64_ISA_V8_6A	   (aarch64_isa_flags & AARCH64_FL_V8_6)
++#define AARCH64_ISA_V8_6A	   (aarch64_isa_flags & AARCH64_FL_V8_6A)
+ #define AARCH64_ISA_I8MM	   (aarch64_isa_flags & AARCH64_FL_I8MM)
+ #define AARCH64_ISA_F32MM	   (aarch64_isa_flags & AARCH64_FL_F32MM)
+ #define AARCH64_ISA_F64MM	   (aarch64_isa_flags & AARCH64_FL_F64MM)
+ #define AARCH64_ISA_BF16	   (aarch64_isa_flags & AARCH64_FL_BF16)
+ #define AARCH64_ISA_SB		   (aarch64_isa_flags & AARCH64_FL_SB)
+-#define AARCH64_ISA_V8R		   (aarch64_isa_flags & AARCH64_FL_V8_R)
++#define AARCH64_ISA_V8R		   (aarch64_isa_flags & AARCH64_FL_V8R)
+ #define AARCH64_ISA_PAUTH	   (aarch64_isa_flags & AARCH64_FL_PAUTH)
+-#define AARCH64_ISA_V9A		   (aarch64_isa_flags & AARCH64_FL_V9)
+-#define AARCH64_ISA_V9_1A          (aarch64_isa_flags & AARCH64_FL_V9_1)
+-#define AARCH64_ISA_V9_2A          (aarch64_isa_flags & AARCH64_FL_V9_2)
+-#define AARCH64_ISA_V9_3A          (aarch64_isa_flags & AARCH64_FL_V9_3)
++#define AARCH64_ISA_V9A		   (aarch64_isa_flags & AARCH64_FL_V9A)
++#define AARCH64_ISA_V9_1A          (aarch64_isa_flags & AARCH64_FL_V9_1A)
++#define AARCH64_ISA_V9_2A          (aarch64_isa_flags & AARCH64_FL_V9_2A)
++#define AARCH64_ISA_V9_3A          (aarch64_isa_flags & AARCH64_FL_V9_3A)
+ #define AARCH64_ISA_MOPS	   (aarch64_isa_flags & AARCH64_FL_MOPS)
+ #define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
+ 
+-- 
+2.33.0
+
diff --git a/0111-Backport-SME-aarch64-Rename-AARCH64_FL_FOR_ARCH-macr.patch b/0111-Backport-SME-aarch64-Rename-AARCH64_FL_FOR_ARCH-macr.patch
new file mode 100644
index 0000000..77737f5
--- /dev/null
+++ b/0111-Backport-SME-aarch64-Rename-AARCH64_FL_FOR_ARCH-macr.patch
@@ -0,0 +1,398 @@
+From 7da27deb7413d7d1fd2c543617640e2de5b10db0 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:51 +0100
+Subject: [PATCH 012/157] [Backport][SME] aarch64: Rename AARCH64_FL_FOR_ARCH
+ macros
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0f833d1900176509e16b6f5563cfe58508fef5d2
+
+This patch renames AARCH64_FL_FOR_ARCH* macros to follow the
+same V names that we (now) use elsewhere.
+
+The names are only temporary -- a later patch will move the
+information to the .def file instead.  However, it helps with
+the sequencing to do this first.
+
+gcc/
+	* config/aarch64/aarch64.h (AARCH64_FL_FOR_ARCH8): Rename to...
+	(AARCH64_FL_FOR_V8A): ...this.
+	(AARCH64_FL_FOR_ARCH8_1): Rename to...
+	(AARCH64_FL_FOR_V8_1A): ...this.
+	(AARCH64_FL_FOR_ARCH8_2): Rename to...
+	(AARCH64_FL_FOR_V8_2A): ...this.
+	(AARCH64_FL_FOR_ARCH8_3): Rename to...
+	(AARCH64_FL_FOR_V8_3A): ...this.
+	(AARCH64_FL_FOR_ARCH8_4): Rename to...
+	(AARCH64_FL_FOR_V8_4A): ...this.
+	(AARCH64_FL_FOR_ARCH8_5): Rename to...
+	(AARCH64_FL_FOR_V8_5A): ...this.
+	(AARCH64_FL_FOR_ARCH8_6): Rename to...
+	(AARCH64_FL_FOR_V8_6A): ...this.
+	(AARCH64_FL_FOR_ARCH8_7): Rename to...
+	(AARCH64_FL_FOR_V8_7A): ...this.
+	(AARCH64_FL_FOR_ARCH8_8): Rename to...
+	(AARCH64_FL_FOR_V8_8A): ...this.
+	(AARCH64_FL_FOR_ARCH8_R): Rename to...
+	(AARCH64_FL_FOR_V8R): ...this.
+	(AARCH64_FL_FOR_ARCH9): Rename to...
+	(AARCH64_FL_FOR_V9A): ...this.
+	(AARCH64_FL_FOR_ARCH9_1): Rename to...
+	(AARCH64_FL_FOR_V9_1A): ...this.
+	(AARCH64_FL_FOR_ARCH9_2): Rename to...
+	(AARCH64_FL_FOR_V9_2A): ...this.
+	(AARCH64_FL_FOR_ARCH9_3): Rename to...
+	(AARCH64_FL_FOR_V9_3A): ...this.
+	* common/config/aarch64/aarch64-common.cc (all_cores): Update
+	accordingly.
+	* config/aarch64/aarch64-arches.def: Likewise.
+	* config/aarch64/aarch64-cores.def: Likewise.
+	* config/aarch64/aarch64.cc (all_cores): Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc |   2 +-
+ gcc/config/aarch64/aarch64-arches.def       |  28 ++---
+ gcc/config/aarch64/aarch64-cores.def        | 130 ++++++++++----------
+ gcc/config/aarch64/aarch64.cc               |   2 +-
+ gcc/config/aarch64/aarch64.h                |  56 ++++-----
+ 5 files changed, 109 insertions(+), 109 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 3dc020f0c..0461201a5 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -253,7 +253,7 @@ static const struct processor_name_to_arch all_cores[] =
+ #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \
+   {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS},
+ #include "config/aarch64/aarch64-cores.def"
+-  {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_ARCH8},
++  {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_V8A},
+   {"", aarch64_no_arch, 0}
+ };
+ 
+diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
+index 6150448dc..c6bf7d82c 100644
+--- a/gcc/config/aarch64/aarch64-arches.def
++++ b/gcc/config/aarch64/aarch64-arches.def
+@@ -30,19 +30,19 @@
+    Due to the assumptions about the positions of these fields in config.gcc,
+    the NAME should be kept as the first argument and FLAGS as the last.  */
+ 
+-AARCH64_ARCH("armv8-a",	      generic,	     8A,	8,  AARCH64_FL_FOR_ARCH8)
+-AARCH64_ARCH("armv8.1-a",     generic,	     8_1A,	8,  AARCH64_FL_FOR_ARCH8_1)
+-AARCH64_ARCH("armv8.2-a",     generic,	     8_2A,	8,  AARCH64_FL_FOR_ARCH8_2)
+-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.8-a",     generic,       8_8A,      8,  AARCH64_FL_FOR_ARCH8_8)
+-AARCH64_ARCH("armv8-r",       generic,	     8R  ,	8,  AARCH64_FL_FOR_ARCH8_R)
+-AARCH64_ARCH("armv9-a",       generic,	     9A  ,	9,  AARCH64_FL_FOR_ARCH9)
+-AARCH64_ARCH("armv9.1-a",     generic,       9_1A,      9,  AARCH64_FL_FOR_ARCH9_1)
+-AARCH64_ARCH("armv9.2-a",     generic,       9_2A,      9,  AARCH64_FL_FOR_ARCH9_2)
+-AARCH64_ARCH("armv9.3-a",     generic,       9_3A,      9,  AARCH64_FL_FOR_ARCH9_3)
++AARCH64_ARCH("armv8-a",	      generic,	     8A,	8,  AARCH64_FL_FOR_V8A)
++AARCH64_ARCH("armv8.1-a",     generic,	     8_1A,	8,  AARCH64_FL_FOR_V8_1A)
++AARCH64_ARCH("armv8.2-a",     generic,	     8_2A,	8,  AARCH64_FL_FOR_V8_2A)
++AARCH64_ARCH("armv8.3-a",     generic,	     8_3A,	8,  AARCH64_FL_FOR_V8_3A)
++AARCH64_ARCH("armv8.4-a",     generic,	     8_4A,	8,  AARCH64_FL_FOR_V8_4A)
++AARCH64_ARCH("armv8.5-a",     generic,	     8_5A,	8,  AARCH64_FL_FOR_V8_5A)
++AARCH64_ARCH("armv8.6-a",     generic,	     8_6A,	8,  AARCH64_FL_FOR_V8_6A)
++AARCH64_ARCH("armv8.7-a",     generic,       8_7A,      8,  AARCH64_FL_FOR_V8_7A)
++AARCH64_ARCH("armv8.8-a",     generic,       8_8A,      8,  AARCH64_FL_FOR_V8_8A)
++AARCH64_ARCH("armv8-r",       generic,	     8R  ,	8,  AARCH64_FL_FOR_V8R)
++AARCH64_ARCH("armv9-a",       generic,	     9A  ,	9,  AARCH64_FL_FOR_V9A)
++AARCH64_ARCH("armv9.1-a",     generic,       9_1A,      9,  AARCH64_FL_FOR_V9_1A)
++AARCH64_ARCH("armv9.2-a",     generic,       9_2A,      9,  AARCH64_FL_FOR_V9_2A)
++AARCH64_ARCH("armv9.3-a",     generic,       9_3A,      9,  AARCH64_FL_FOR_V9_3A)
+ 
+ #undef AARCH64_ARCH
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 0402bfb74..c4038c641 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -46,132 +46,132 @@
+ /* ARMv8-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
+-AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
+-AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
+-AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
+-AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
+-AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
++AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
++AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
++AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
++AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
++AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
++AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx",      thunderx,      thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("thunderx",      thunderx,      thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+ /* Do not swap around "thunderxt88p1" and "thunderxt88",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
+-AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
++AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
++AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
+ 
+ /* OcteonTX is the official name for T81/T83. */
+-AARCH64_CORE("octeontx",      octeontx,      thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+-AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("octeontx",      octeontx,      thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+-AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+ /* Ampere Computing ('\xC0') cores. */
+-AARCH64_CORE("ampere1", ampere1, cortexa57, 8_6A, AARCH64_FL_FOR_ARCH8_6, ampere1, 0xC0, 0xac3, -1)
++AARCH64_CORE("ampere1", ampere1, cortexa57, 8_6A, AARCH64_FL_FOR_V8_6A, ampere1, 0xC0, 0xac3, -1)
+ /* Do not swap around "emag" and "xgene1",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("emag",        emag,      xgene1,    8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
++AARCH64_CORE("emag",        emag,      xgene1,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
+ 
+ /* APM ('P') cores. */
+-AARCH64_CORE("xgene1",      xgene1,    xgene1,    8A,  AARCH64_FL_FOR_ARCH8, xgene1, 0x50, 0x000, -1)
++AARCH64_CORE("xgene1",      xgene1,    xgene1,    8A,  AARCH64_FL_FOR_V8A, xgene1, 0x50, 0x000, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("falkor",      falkor,    falkor,    8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+-AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("falkor",      falkor,    falkor,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+ 
+ /* Samsung ('S') cores. */
+-AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
++AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
+ 
+ /* HXT ('h') cores. */
+-AARCH64_CORE("phecda",      phecda,    falkor,    8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
++AARCH64_CORE("phecda",      phecda,    falkor,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
+ 
+ /* ARMv8.1-A Architecture Processors.  */
+ 
+ /* Broadcom ('B') cores. */
+-AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, 8_1A,  AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+-AARCH64_CORE("vulcan",  vulcan, thunderx2t99, 8_1A,  AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, 8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("vulcan",  vulcan, thunderx2t99, 8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, 8_1A,  AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
++AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, 8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
+ 
+ /* ARMv8.2-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
+-AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
+-AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
+-AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
+-AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
+-AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
+-AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
+-AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
+-AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
+-AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
+-AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
+-AARCH64_CORE("ares",  ares, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
++AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
++AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
++AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
++AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
++AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
++AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
++AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
++AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
++AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
++AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
++AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
++AARCH64_CORE("ares",  ares, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
+-AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
+-AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
++AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
++AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+ /* Note OcteonTX2 T93 is an alias to OcteonTX2 T96. */
+-AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+-AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
+-AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
+-AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
++AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
++AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
++AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
+ 
+ /* Fujitsu ('F') cores. */
+-AARCH64_CORE("a64fx", a64fx, a64fx, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
++AARCH64_CORE("a64fx", a64fx, a64fx, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
+ 
+ /* HiSilicon ('H') cores. */
+-AARCH64_CORE("tsv110",  tsv110, tsv110, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
++AARCH64_CORE("tsv110",  tsv110, tsv110, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, 8_3A,  AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, 8_3A,  AARCH64_FL_FOR_V8_3A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores.  */
+-AARCH64_CORE("zeus", zeus, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
++AARCH64_CORE("zeus", zeus, cortexa57, 8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("saphira",     saphira,    saphira,    8_4A,  AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
++AARCH64_CORE("saphira",     saphira,    saphira,    8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
+ 
+ /* ARMv8-A big.LITTLE implementations.  */
+ 
+-AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
+-AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
+-AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
+-AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
++AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
++AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
++AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
++AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
+ 
+ /* ARM DynamIQ big.LITTLE configurations.  */
+ 
+-AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
+-AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
++AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
++AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
+ 
+ /* Armv8-R Architecture Processors.  */
+-AARCH64_CORE("cortex-r82", cortexr82, cortexa53, 8R, AARCH64_FL_FOR_ARCH8_R, cortexa53, 0x41, 0xd15, -1)
++AARCH64_CORE("cortex-r82", cortexr82, cortexa53, 8R, AARCH64_FL_FOR_V8R, 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-a510",  cortexa510, cortexa55, 9A,  AARCH64_FL_FOR_V9A | 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-a710",  cortexa710, cortexa57, 9A,  AARCH64_FL_FOR_V9A | 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)
++AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, 9A,  AARCH64_FL_FOR_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
+ 
+-AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
++AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
+ 
+-AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+-AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, 9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+ 
+ #undef AARCH64_CORE
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 254ecfaa2..3714c1047 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2949,7 +2949,7 @@ static const struct processor all_cores[] =
+   FLAGS, &COSTS##_tunings},
+ #include "aarch64-cores.def"
+   {"generic", generic, cortexa53, AARCH64_ARCH_8A,
+-    AARCH64_FL_FOR_ARCH8, &generic_tunings},
++    AARCH64_FL_FOR_V8A, &generic_tunings},
+   {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
+ };
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 5a91dfdd2..918a14193 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -255,39 +255,39 @@
+ #define AARCH64_FL_FPQ16      (AARCH64_FL_FP & ~AARCH64_FL_SIMD)
+ 
+ /* Architecture flags that effect instruction selection.  */
+-#define AARCH64_FL_FOR_ARCH8       (AARCH64_FL_FPSIMD)
+-#define AARCH64_FL_FOR_ARCH8_1			       \
+-  (AARCH64_FL_FOR_ARCH8 | AARCH64_FL_LSE | AARCH64_FL_CRC \
++#define AARCH64_FL_FOR_V8A       (AARCH64_FL_FPSIMD)
++#define AARCH64_FL_FOR_V8_1A			       \
++  (AARCH64_FL_FOR_V8A | AARCH64_FL_LSE | AARCH64_FL_CRC \
+    | AARCH64_FL_RDMA | AARCH64_FL_V8_1A)
+-#define AARCH64_FL_FOR_ARCH8_2			\
+-  (AARCH64_FL_FOR_ARCH8_1 | AARCH64_FL_V8_2A)
+-#define AARCH64_FL_FOR_ARCH8_3			\
+-  (AARCH64_FL_FOR_ARCH8_2 | AARCH64_FL_V8_3A | AARCH64_FL_PAUTH)
+-#define AARCH64_FL_FOR_ARCH8_4			\
+-  (AARCH64_FL_FOR_ARCH8_3 | AARCH64_FL_V8_4A | AARCH64_FL_F16FML \
++#define AARCH64_FL_FOR_V8_2A			\
++  (AARCH64_FL_FOR_V8_1A | AARCH64_FL_V8_2A)
++#define AARCH64_FL_FOR_V8_3A			\
++  (AARCH64_FL_FOR_V8_2A | AARCH64_FL_V8_3A | AARCH64_FL_PAUTH)
++#define AARCH64_FL_FOR_V8_4A			\
++  (AARCH64_FL_FOR_V8_3A | AARCH64_FL_V8_4A | AARCH64_FL_F16FML \
+    | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4 | AARCH64_FL_FLAGM)
+-#define AARCH64_FL_FOR_ARCH8_5			\
+-  (AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8_5A	\
++#define AARCH64_FL_FOR_V8_5A			\
++  (AARCH64_FL_FOR_V8_4A | AARCH64_FL_V8_5A	\
+    | AARCH64_FL_SB | AARCH64_FL_SSBS | AARCH64_FL_PREDRES)
+-#define AARCH64_FL_FOR_ARCH8_6			\
+-  (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_V8_6A | AARCH64_FL_FPSIMD \
++#define AARCH64_FL_FOR_V8_6A			\
++  (AARCH64_FL_FOR_V8_5A | AARCH64_FL_V8_6A | AARCH64_FL_FPSIMD \
+    | AARCH64_FL_I8MM | AARCH64_FL_BF16)
+-#define AARCH64_FL_FOR_ARCH8_7			\
+-  (AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V8_7A | AARCH64_FL_LS64)
+-#define AARCH64_FL_FOR_ARCH8_8			\
+-  (AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V8_8A | AARCH64_FL_MOPS)
+-
+-#define AARCH64_FL_FOR_ARCH8_R     \
+-  (AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_V8R)
+-#define AARCH64_FL_FOR_ARCH9       \
+-  (AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9A \
++#define AARCH64_FL_FOR_V8_7A			\
++  (AARCH64_FL_FOR_V8_6A | AARCH64_FL_V8_7A | AARCH64_FL_LS64)
++#define AARCH64_FL_FOR_V8_8A			\
++  (AARCH64_FL_FOR_V8_7A | AARCH64_FL_V8_8A | AARCH64_FL_MOPS)
++
++#define AARCH64_FL_FOR_V8R     \
++  (AARCH64_FL_FOR_V8_4A | AARCH64_FL_V8R)
++#define AARCH64_FL_FOR_V9A       \
++  (AARCH64_FL_FOR_V8_5A | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9A \
+    | AARCH64_FL_F16)
+-#define AARCH64_FL_FOR_ARCH9_1	\
+-  (AARCH64_FL_FOR_ARCH9 | AARCH64_FL_FOR_ARCH8_6 | AARCH64_FL_V9_1A)
+-#define AARCH64_FL_FOR_ARCH9_2	\
+-  (AARCH64_FL_FOR_ARCH9_1 | AARCH64_FL_FOR_ARCH8_7 | AARCH64_FL_V9_2A)
+-#define AARCH64_FL_FOR_ARCH9_3	\
+-  (AARCH64_FL_FOR_ARCH9_2 | AARCH64_FL_FOR_ARCH8_8 | AARCH64_FL_V9_3A)
++#define AARCH64_FL_FOR_V9_1A	\
++  (AARCH64_FL_FOR_V9A | AARCH64_FL_FOR_V8_6A | AARCH64_FL_V9_1A)
++#define AARCH64_FL_FOR_V9_2A	\
++  (AARCH64_FL_FOR_V9_1A | AARCH64_FL_FOR_V8_7A | AARCH64_FL_V9_2A)
++#define AARCH64_FL_FOR_V9_3A	\
++  (AARCH64_FL_FOR_V9_2A | AARCH64_FL_FOR_V8_8A | AARCH64_FL_V9_3A)
+ 
+ /* Macros to test ISA flags.  */
+ 
+-- 
+2.33.0
+
diff --git a/0112-Backport-SME-aarch64-Add-V-to-aarch64-arches.def-nam.patch b/0112-Backport-SME-aarch64-Add-V-to-aarch64-arches.def-nam.patch
new file mode 100644
index 0000000..d1b1db8
--- /dev/null
+++ b/0112-Backport-SME-aarch64-Add-V-to-aarch64-arches.def-nam.patch
@@ -0,0 +1,315 @@
+From ed8ce0b31f2b608f0360af1ffd5375ea7809aba7 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:52 +0100
+Subject: [PATCH 013/157] [Backport][SME] aarch64: Add "V" to
+ aarch64-arches.def names
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=00c22ba69d8e738a4789b30165ff9c925c508fc1
+
+This patch completes the renaming of architecture-level related
+things by adding "V" to the name of the architecture in
+aarch64-arches.def.  Since the "V" is predictable, we can easily
+drop it when we don't need it (as when matching /proc/cpuinfo).
+
+Having a valid C identifier is necessary for later patches.
+
+gcc/
+	* config/aarch64/aarch64-arches.def: Add a leading "V" to the
+	ARCH_IDENT fields.
+	* config/aarch64/aarch64-cores.def: Update accordingly.
+	* common/config/aarch64/aarch64-common.cc (all_cores): Likewise.
+	* config/aarch64/aarch64.cc (all_cores): Likewise.
+	* config/aarch64/driver-aarch64.cc (aarch64_arches): Skip the
+	leading "V".
+---
+ gcc/common/config/aarch64/aarch64-common.cc |   2 +-
+ gcc/config/aarch64/aarch64-arches.def       |  28 ++---
+ gcc/config/aarch64/aarch64-cores.def        | 130 ++++++++++----------
+ gcc/config/aarch64/aarch64.cc               |   2 +-
+ gcc/config/aarch64/driver-aarch64.cc        |   3 +-
+ 5 files changed, 83 insertions(+), 82 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 0461201a5..6ca89d31f 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -253,7 +253,7 @@ static const struct processor_name_to_arch all_cores[] =
+ #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \
+   {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS},
+ #include "config/aarch64/aarch64-cores.def"
+-  {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_V8A},
++  {"generic", AARCH64_ARCH_V8A, AARCH64_FL_FOR_V8A},
+   {"", aarch64_no_arch, 0}
+ };
+ 
+diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
+index c6bf7d82c..e42202822 100644
+--- a/gcc/config/aarch64/aarch64-arches.def
++++ b/gcc/config/aarch64/aarch64-arches.def
+@@ -30,19 +30,19 @@
+    Due to the assumptions about the positions of these fields in config.gcc,
+    the NAME should be kept as the first argument and FLAGS as the last.  */
+ 
+-AARCH64_ARCH("armv8-a",	      generic,	     8A,	8,  AARCH64_FL_FOR_V8A)
+-AARCH64_ARCH("armv8.1-a",     generic,	     8_1A,	8,  AARCH64_FL_FOR_V8_1A)
+-AARCH64_ARCH("armv8.2-a",     generic,	     8_2A,	8,  AARCH64_FL_FOR_V8_2A)
+-AARCH64_ARCH("armv8.3-a",     generic,	     8_3A,	8,  AARCH64_FL_FOR_V8_3A)
+-AARCH64_ARCH("armv8.4-a",     generic,	     8_4A,	8,  AARCH64_FL_FOR_V8_4A)
+-AARCH64_ARCH("armv8.5-a",     generic,	     8_5A,	8,  AARCH64_FL_FOR_V8_5A)
+-AARCH64_ARCH("armv8.6-a",     generic,	     8_6A,	8,  AARCH64_FL_FOR_V8_6A)
+-AARCH64_ARCH("armv8.7-a",     generic,       8_7A,      8,  AARCH64_FL_FOR_V8_7A)
+-AARCH64_ARCH("armv8.8-a",     generic,       8_8A,      8,  AARCH64_FL_FOR_V8_8A)
+-AARCH64_ARCH("armv8-r",       generic,	     8R  ,	8,  AARCH64_FL_FOR_V8R)
+-AARCH64_ARCH("armv9-a",       generic,	     9A  ,	9,  AARCH64_FL_FOR_V9A)
+-AARCH64_ARCH("armv9.1-a",     generic,       9_1A,      9,  AARCH64_FL_FOR_V9_1A)
+-AARCH64_ARCH("armv9.2-a",     generic,       9_2A,      9,  AARCH64_FL_FOR_V9_2A)
+-AARCH64_ARCH("armv9.3-a",     generic,       9_3A,      9,  AARCH64_FL_FOR_V9_3A)
++AARCH64_ARCH("armv8-a",	      generic,	     V8A,	8,  AARCH64_FL_FOR_V8A)
++AARCH64_ARCH("armv8.1-a",     generic,	     V8_1A,	8,  AARCH64_FL_FOR_V8_1A)
++AARCH64_ARCH("armv8.2-a",     generic,	     V8_2A,	8,  AARCH64_FL_FOR_V8_2A)
++AARCH64_ARCH("armv8.3-a",     generic,	     V8_3A,	8,  AARCH64_FL_FOR_V8_3A)
++AARCH64_ARCH("armv8.4-a",     generic,	     V8_4A,	8,  AARCH64_FL_FOR_V8_4A)
++AARCH64_ARCH("armv8.5-a",     generic,	     V8_5A,	8,  AARCH64_FL_FOR_V8_5A)
++AARCH64_ARCH("armv8.6-a",     generic,	     V8_6A,	8,  AARCH64_FL_FOR_V8_6A)
++AARCH64_ARCH("armv8.7-a",     generic,       V8_7A,     8,  AARCH64_FL_FOR_V8_7A)
++AARCH64_ARCH("armv8.8-a",     generic,       V8_8A,     8,  AARCH64_FL_FOR_V8_8A)
++AARCH64_ARCH("armv8-r",       generic,	     V8R  ,	8,  AARCH64_FL_FOR_V8R)
++AARCH64_ARCH("armv9-a",       generic,	     V9A  ,	9,  AARCH64_FL_FOR_V9A)
++AARCH64_ARCH("armv9.1-a",     generic,       V9_1A,     9,  AARCH64_FL_FOR_V9_1A)
++AARCH64_ARCH("armv9.2-a",     generic,       V9_2A,     9,  AARCH64_FL_FOR_V9_2A)
++AARCH64_ARCH("armv9.3-a",     generic,       V9_3A,     9,  AARCH64_FL_FOR_V9_3A)
+ 
+ #undef AARCH64_ARCH
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index c4038c641..f4c2f4ea4 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -46,132 +46,132 @@
+ /* ARMv8-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
+-AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
+-AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
+-AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
+-AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
+-AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
++AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
++AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
++AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
++AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
++AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
++AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx",      thunderx,      thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("thunderx",      thunderx,      thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+ /* Do not swap around "thunderxt88p1" and "thunderxt88",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
+-AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
++AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
++AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
+ 
+ /* OcteonTX is the official name for T81/T83. */
+-AARCH64_CORE("octeontx",      octeontx,      thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+-AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("octeontx",      octeontx,      thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+-AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+ /* Ampere Computing ('\xC0') cores. */
+-AARCH64_CORE("ampere1", ampere1, cortexa57, 8_6A, AARCH64_FL_FOR_V8_6A, ampere1, 0xC0, 0xac3, -1)
++AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, AARCH64_FL_FOR_V8_6A, ampere1, 0xC0, 0xac3, -1)
+ /* Do not swap around "emag" and "xgene1",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("emag",        emag,      xgene1,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
++AARCH64_CORE("emag",        emag,      xgene1,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
+ 
+ /* APM ('P') cores. */
+-AARCH64_CORE("xgene1",      xgene1,    xgene1,    8A,  AARCH64_FL_FOR_V8A, xgene1, 0x50, 0x000, -1)
++AARCH64_CORE("xgene1",      xgene1,    xgene1,    V8A,  AARCH64_FL_FOR_V8A, xgene1, 0x50, 0x000, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("falkor",      falkor,    falkor,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+-AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("falkor",      falkor,    falkor,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+ 
+ /* Samsung ('S') cores. */
+-AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
++AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
+ 
+ /* HXT ('h') cores. */
+-AARCH64_CORE("phecda",      phecda,    falkor,    8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
++AARCH64_CORE("phecda",      phecda,    falkor,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
+ 
+ /* ARMv8.1-A Architecture Processors.  */
+ 
+ /* Broadcom ('B') cores. */
+-AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, 8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+-AARCH64_CORE("vulcan",  vulcan, thunderx2t99, 8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, V8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("vulcan",  vulcan, thunderx2t99, V8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, 8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
++AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, V8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
+ 
+ /* ARMv8.2-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
+-AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
+-AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
+-AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
+-AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
+-AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
+-AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
+-AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
+-AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
+-AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
+-AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
+-AARCH64_CORE("ares",  ares, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
++AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
++AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
++AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
++AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
++AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
++AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
++AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
++AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
++AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
++AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
++AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
++AARCH64_CORE("ares",  ares, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
+-AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
+-AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
++AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
++AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+ /* Note OcteonTX2 T93 is an alias to OcteonTX2 T96. */
+-AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+-AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
+-AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
+-AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
++AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
++AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
++AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
+ 
+ /* Fujitsu ('F') cores. */
+-AARCH64_CORE("a64fx", a64fx, a64fx, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
++AARCH64_CORE("a64fx", a64fx, a64fx, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
+ 
+ /* HiSilicon ('H') cores. */
+-AARCH64_CORE("tsv110",  tsv110, tsv110, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
++AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, 8_3A,  AARCH64_FL_FOR_V8_3A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  AARCH64_FL_FOR_V8_3A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores.  */
+-AARCH64_CORE("zeus", zeus, cortexa57, 8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, 8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
++AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("saphira",     saphira,    saphira,    8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
++AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
+ 
+ /* ARMv8-A big.LITTLE implementations.  */
+ 
+-AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
+-AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
+-AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
+-AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, 8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
++AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
++AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
++AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
++AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
+ 
+ /* ARM DynamIQ big.LITTLE configurations.  */
+ 
+-AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
+-AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, 8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
++AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
++AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
+ 
+ /* Armv8-R Architecture Processors.  */
+-AARCH64_CORE("cortex-r82", cortexr82, cortexa53, 8R, AARCH64_FL_FOR_V8R, cortexa53, 0x41, 0xd15, -1)
++AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, AARCH64_FL_FOR_V8R, cortexa53, 0x41, 0xd15, -1)
+ 
+ /* Armv9.0-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores. */
+-AARCH64_CORE("cortex-a510",  cortexa510, cortexa55, 9A,  AARCH64_FL_FOR_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, cortexa53, 0x41, 0xd46, -1)
++AARCH64_CORE("cortex-a510",  cortexa510, cortexa55, V9A,  AARCH64_FL_FOR_V9A | 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_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd47, -1)
++AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, V9A,  AARCH64_FL_FOR_V9A | 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_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
++AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, V9A,  AARCH64_FL_FOR_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
+ 
+-AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
++AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
+ 
+-AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+-AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, 9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("demeter", demeter, cortexa57, V9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+ 
+ #undef AARCH64_CORE
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 3714c1047..22b51e12f 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2948,7 +2948,7 @@ static const struct processor all_cores[] =
+   {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH,				\
+   FLAGS, &COSTS##_tunings},
+ #include "aarch64-cores.def"
+-  {"generic", generic, cortexa53, AARCH64_ARCH_8A,
++  {"generic", generic, cortexa53, AARCH64_ARCH_V8A,
+     AARCH64_FL_FOR_V8A, &generic_tunings},
+   {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
+ };
+diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
+index d714a8bda..644780ef2 100644
+--- a/gcc/config/aarch64/driver-aarch64.cc
++++ b/gcc/config/aarch64/driver-aarch64.cc
+@@ -78,8 +78,9 @@ struct aarch64_arch_driver_info
+   const uint64_t flags;
+ };
+ 
++/* Skip the leading "V" in the architecture name.  */
+ #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
+-  { #ARCH_IDENT, NAME, FLAGS },
++  { #ARCH_IDENT + 1, NAME, FLAGS },
+ 
+ static struct aarch64_arch_driver_info aarch64_arches[] =
+ {
+-- 
+2.33.0
+
diff --git a/0113-Backport-SME-aarch64-Small-config.gcc-cleanups.patch b/0113-Backport-SME-aarch64-Small-config.gcc-cleanups.patch
new file mode 100644
index 0000000..1b14c18
--- /dev/null
+++ b/0113-Backport-SME-aarch64-Small-config.gcc-cleanups.patch
@@ -0,0 +1,55 @@
+From aac2b2d4191d08a107c3ff8d98602355988a5558 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:52 +0100
+Subject: [PATCH 014/157] [Backport][SME] aarch64: Small config.gcc cleanups
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0af214b447529453b356e8e480d7d35b3e642f0e
+
+The aarch64-option-extensions.def parsing in config.gcc had
+some code left over from when it tried to parse the whole
+macro definition.  Also, config.gcc now only looks at the
+first fields of the aarch64-arches.def entries.
+
+gcc/
+	* config.gcc: Remove dead aarch64-option-extensions.def code.
+	* config/aarch64/aarch64-arches.def: Update comment.
+---
+ gcc/config.gcc                        | 8 --------
+ gcc/config/aarch64/aarch64-arches.def | 2 +-
+ 2 files changed, 1 insertion(+), 9 deletions(-)
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 3be450471..da66603cd 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -4210,14 +4210,6 @@ case "${target}" in
+ 			  options_parsed="`$ac_cv_prog_CPP -D"$opt_macro" -x c \
+ 				${srcdir}/config/aarch64/aarch64-option-extensions.def`"
+ 
+-			  # Match one element inside AARCH64_OPT_EXTENSION, we
+-			  # consume anything that's not a ,.
+-			  elem="[ 	]*\([^,]\+\)[ 	]*"
+-
+-			  # Repeat the pattern for the number of entries in the
+-			  # AARCH64_OPT_EXTENSION, currently 6 times.
+-			  sed_patt="^$elem,$elem,$elem,$elem,$elem,$elem"
+-
+ 			  while [ x"$ext_val" != x ]
+ 			  do
+ 				ext_val=`echo $ext_val | sed -e 's/\+//'`
+diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
+index e42202822..ece96e22a 100644
+--- a/gcc/config/aarch64/aarch64-arches.def
++++ b/gcc/config/aarch64/aarch64-arches.def
+@@ -28,7 +28,7 @@
+    ARCH_REV is an integer specifying the architecture major revision.
+    FLAGS are the flags implied by the architecture.
+    Due to the assumptions about the positions of these fields in config.gcc,
+-   the NAME should be kept as the first argument and FLAGS as the last.  */
++   NAME should be kept as the first argument.  */
+ 
+ AARCH64_ARCH("armv8-a",	      generic,	     V8A,	8,  AARCH64_FL_FOR_V8A)
+ AARCH64_ARCH("armv8.1-a",     generic,	     V8_1A,	8,  AARCH64_FL_FOR_V8_1A)
+-- 
+2.33.0
+
diff --git a/0114-Backport-SME-aarch64-Avoid-redundancy-in-aarch64-cor.patch b/0114-Backport-SME-aarch64-Avoid-redundancy-in-aarch64-cor.patch
new file mode 100644
index 0000000..ba9f2ab
--- /dev/null
+++ b/0114-Backport-SME-aarch64-Avoid-redundancy-in-aarch64-cor.patch
@@ -0,0 +1,273 @@
+From f6f28c50045f672a35f5b7344b556fc45dc0b3a1 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:53 +0100
+Subject: [PATCH 015/157] [Backport][SME] aarch64: Avoid redundancy in
+ aarch64-cores.def
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=198bb6ed327c74eb2b0450bf978e4e6a64a6406c
+
+The flags fields of the aarch64-cores.def always start with
+AARCH64_FL_FOR_.  After previous changes,  is always
+identical to the previous field, so we can drop the explicit
+AARCH64_FL_FOR_ and derive it programmatically.
+
+This isn't a big saving in itself, but it helps with later patches.
+
+gcc/
+	* config/aarch64/aarch64-cores.def: Remove AARCH64_FL_FOR_
+	from the flags field.
+	* common/config/aarch64/aarch64-common.cc (all_cores): Add it
+	here instead.
+	* config/aarch64/aarch64.cc (all_cores): Likewise.
+	* config/aarch64/driver-aarch64.cc (all_cores): Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc |   2 +-
+ gcc/config/aarch64/aarch64-cores.def        | 130 ++++++++++----------
+ gcc/config/aarch64/aarch64.cc               |   2 +-
+ gcc/config/aarch64/driver-aarch64.cc        |   2 +-
+ 4 files changed, 68 insertions(+), 68 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 6ca89d31f..a965ac660 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -251,7 +251,7 @@ struct arch_to_arch_name
+ static const struct processor_name_to_arch all_cores[] =
+ {
+ #define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \
+-  {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS},
++  {NAME, AARCH64_ARCH_##ARCH_IDENT, AARCH64_FL_FOR_##ARCH_IDENT | FLAGS},
+ #include "config/aarch64/aarch64-cores.def"
+   {"generic", AARCH64_ARCH_V8A, AARCH64_FL_FOR_V8A},
+   {"", aarch64_no_arch, 0}
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index f4c2f4ea4..008b0b8c1 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -46,132 +46,132 @@
+ /* ARMv8-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
+-AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
+-AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
+-AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
+-AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
+-AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
++AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, V8A,  AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
++AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, V8A,  AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
++AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
++AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, V8A,  AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
++AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, V8A,  AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
++AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, V8A,  AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx",      thunderx,      thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("thunderx",      thunderx,      thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+ /* Do not swap around "thunderxt88p1" and "thunderxt88",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
+-AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
++AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
++AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
+ 
+ /* OcteonTX is the official name for T81/T83. */
+-AARCH64_CORE("octeontx",      octeontx,      thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+-AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("octeontx",      octeontx,      thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+-AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
+ 
+ /* Ampere Computing ('\xC0') cores. */
+-AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, AARCH64_FL_FOR_V8_6A, ampere1, 0xC0, 0xac3, -1)
++AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, 0, ampere1, 0xC0, 0xac3, -1)
+ /* Do not swap around "emag" and "xgene1",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("emag",        emag,      xgene1,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
++AARCH64_CORE("emag",        emag,      xgene1,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
+ 
+ /* APM ('P') cores. */
+-AARCH64_CORE("xgene1",      xgene1,    xgene1,    V8A,  AARCH64_FL_FOR_V8A, xgene1, 0x50, 0x000, -1)
++AARCH64_CORE("xgene1",      xgene1,    xgene1,    V8A,  0, xgene1, 0x50, 0x000, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("falkor",      falkor,    falkor,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+-AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("falkor",      falkor,    falkor,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+ 
+ /* Samsung ('S') cores. */
+-AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
++AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
+ 
+ /* HXT ('h') cores. */
+-AARCH64_CORE("phecda",      phecda,    falkor,    V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
++AARCH64_CORE("phecda",      phecda,    falkor,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
+ 
+ /* ARMv8.1-A Architecture Processors.  */
+ 
+ /* Broadcom ('B') cores. */
+-AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, V8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+-AARCH64_CORE("vulcan",  vulcan, thunderx2t99, V8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, V8_1A,  AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("vulcan",  vulcan, thunderx2t99, V8_1A,  AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, V8_1A,  AARCH64_FL_FOR_V8_1A | AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
++AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, V8_1A,  AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
+ 
+ /* ARMv8.2-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
+-AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
+-AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
+-AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
+-AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
+-AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
+-AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
+-AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
+-AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
+-AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
+-AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
+-AARCH64_CORE("ares",  ares, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
++AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
++AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
++AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
++AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
++AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
++AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
++AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
++AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
++AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
++AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
++AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
++AARCH64_CORE("ares",  ares, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
+-AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
+-AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
++AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
++AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+ /* Note OcteonTX2 T93 is an alias to OcteonTX2 T96. */
+-AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+-AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
+-AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
+-AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
++AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
++AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
++AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
+ 
+ /* Fujitsu ('F') cores. */
+-AARCH64_CORE("a64fx", a64fx, a64fx, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
++AARCH64_CORE("a64fx", a64fx, a64fx, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
+ 
+ /* HiSilicon ('H') cores. */
+-AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
++AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  AARCH64_FL_FOR_V8_3A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores.  */
+-AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
++AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  AARCH64_FL_FOR_V8_4A | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
++AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
+ 
+ /* ARMv8-A big.LITTLE implementations.  */
+ 
+-AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
+-AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
+-AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
+-AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, V8A,  AARCH64_FL_FOR_V8A | AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
++AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
++AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
++AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, V8A,  AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
++AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
+ 
+ /* ARM DynamIQ big.LITTLE configurations.  */
+ 
+-AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
+-AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, V8_2A,  AARCH64_FL_FOR_V8_2A | AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
++AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
++AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
+ 
+ /* Armv8-R Architecture Processors.  */
+-AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, AARCH64_FL_FOR_V8R, cortexa53, 0x41, 0xd15, -1)
++AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, 0, cortexa53, 0x41, 0xd15, -1)
+ 
+ /* Armv9.0-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores. */
+-AARCH64_CORE("cortex-a510",  cortexa510, cortexa55, V9A,  AARCH64_FL_FOR_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, cortexa53, 0x41, 0xd46, -1)
++AARCH64_CORE("cortex-a510",  cortexa510, cortexa55, V9A,  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, cortexa53, 0x41, 0xd46, -1)
+ 
+-AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, V9A,  AARCH64_FL_FOR_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd47, -1)
++AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, V9A,  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd47, -1)
+ 
+-AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, V9A,  AARCH64_FL_FOR_V9A | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
++AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, V9A,  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
+ 
+-AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
++AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
+ 
+-AARCH64_CORE("demeter", demeter, cortexa57, V9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+-AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, AARCH64_FL_FOR_V9A | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("demeter", demeter, cortexa57, V9A, AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+ 
+ #undef AARCH64_CORE
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 22b51e12f..f975aad07 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2946,7 +2946,7 @@ static const struct processor all_cores[] =
+ {
+ #define AARCH64_CORE(NAME, IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
+   {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH,				\
+-  FLAGS, &COSTS##_tunings},
++  AARCH64_FL_FOR_##ARCH | FLAGS, &COSTS##_tunings},
+ #include "aarch64-cores.def"
+   {"generic", generic, cortexa53, AARCH64_ARCH_V8A,
+     AARCH64_FL_FOR_V8A, &generic_tunings},
+diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
+index 644780ef2..97690de62 100644
+--- a/gcc/config/aarch64/driver-aarch64.cc
++++ b/gcc/config/aarch64/driver-aarch64.cc
+@@ -62,7 +62,7 @@ struct aarch64_core_data
+ #define DEFAULT_ARCH "8A"
+ 
+ #define AARCH64_CORE(CORE_NAME, CORE_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
+-  { CORE_NAME, #ARCH, IMP, PART, VARIANT, FLAGS },
++  { CORE_NAME, #ARCH, IMP, PART, VARIANT, AARCH64_FL_FOR_##ARCH | FLAGS },
+ 
+ static struct aarch64_core_data aarch64_cpu_data[] =
+ {
+-- 
+2.33.0
+
diff --git a/0115-Backport-SME-aarch64-Remove-AARCH64_FL_RCPC8_4-PR107.patch b/0115-Backport-SME-aarch64-Remove-AARCH64_FL_RCPC8_4-PR107.patch
new file mode 100644
index 0000000..f65a31b
--- /dev/null
+++ b/0115-Backport-SME-aarch64-Remove-AARCH64_FL_RCPC8_4-PR107.patch
@@ -0,0 +1,83 @@
+From f6137d5be2761caea75dcc1c98d941ceec161456 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:53 +0100
+Subject: [PATCH 016/157] [Backport][SME] aarch64: Remove AARCH64_FL_RCPC8_4
+ [PR107025]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0f244d848cffeda68f0eb4c5bb9c7e629bf2e957
+
+AARCH64_FL_RCPC8_4 is an odd-one-out in that it has no associated
+entry in aarch64-option-extensions.def.  This means that, although
+it is internally separated from AARCH64_FL_V8_4A, there is no
+mechanism for turning it on and off individually, independently
+of armv8.4-a.
+
+The only place that the flag was used independently was in the
+entry for thunderx3t110, which enabled it alongside V8_3A.
+As noted in PR107025, this means that any use of the extension
+will fail to assemble.
+
+In the PR trail, Andrew suggested removing the core entry.
+That might be best long-term, but since the barrier for removing
+command-line options without a deprecation period is very high,
+this patch instead just drops the flag from the core entry.
+We'll still produce correct code.
+
+gcc/
+	PR target/107025
+	* config/aarch64/aarch64.h (oAARCH64_FL_RCPC8_4): Delete.
+	(AARCH64_FL_FOR_V8_4A): Update accordingly.
+	(AARCH64_ISA_RCPC8_4): Use AARCH64_FL_V8_4A directly.
+	* config/aarch64/aarch64-cores.def (thunderx3t110): Remove
+	AARCH64_FL_RCPC8_4.
+---
+ gcc/config/aarch64/aarch64-cores.def | 2 +-
+ gcc/config/aarch64/aarch64.h         | 5 ++---
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 008b0b8c1..cf500d0a9 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -133,7 +133,7 @@ AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_F
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML | AARCH64_FL_RCPC8_4, thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML, thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 918a14193..f4e0cd148 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -173,7 +173,6 @@
+ #define AARCH64_FL_SM4	      (1 << 17)  /* Has ARMv8.4-A SM3 and SM4.  */
+ #define AARCH64_FL_SHA3	      (1 << 18)  /* Has ARMv8.4-a SHA3 and SHA512.  */
+ #define AARCH64_FL_F16FML     (1 << 19)  /* Has ARMv8.4-a FP16 extensions.  */
+-#define AARCH64_FL_RCPC8_4    (1 << 20)  /* Has ARMv8.4-a RCPC extensions.  */
+ 
+ /* Statistical Profiling extensions.  */
+ #define AARCH64_FL_PROFILE    (1 << 21)
+@@ -265,7 +264,7 @@
+   (AARCH64_FL_FOR_V8_2A | AARCH64_FL_V8_3A | AARCH64_FL_PAUTH)
+ #define AARCH64_FL_FOR_V8_4A			\
+   (AARCH64_FL_FOR_V8_3A | AARCH64_FL_V8_4A | AARCH64_FL_F16FML \
+-   | AARCH64_FL_DOTPROD | AARCH64_FL_RCPC8_4 | AARCH64_FL_FLAGM)
++   | AARCH64_FL_DOTPROD | AARCH64_FL_FLAGM)
+ #define AARCH64_FL_FOR_V8_5A			\
+   (AARCH64_FL_FOR_V8_4A | AARCH64_FL_V8_5A	\
+    | AARCH64_FL_SB | AARCH64_FL_SSBS | AARCH64_FL_PREDRES)
+@@ -313,7 +312,7 @@
+ #define AARCH64_ISA_SM4	           (aarch64_isa_flags & AARCH64_FL_SM4)
+ #define AARCH64_ISA_SHA3	   (aarch64_isa_flags & AARCH64_FL_SHA3)
+ #define AARCH64_ISA_F16FML	   (aarch64_isa_flags & AARCH64_FL_F16FML)
+-#define AARCH64_ISA_RCPC8_4	   (aarch64_isa_flags & AARCH64_FL_RCPC8_4)
++#define AARCH64_ISA_RCPC8_4	   (aarch64_isa_flags & AARCH64_FL_V8_4A)
+ #define AARCH64_ISA_RNG		   (aarch64_isa_flags & AARCH64_FL_RNG)
+ #define AARCH64_ISA_V8_5A	   (aarch64_isa_flags & AARCH64_FL_V8_5A)
+ #define AARCH64_ISA_TME		   (aarch64_isa_flags & AARCH64_FL_TME)
+-- 
+2.33.0
+
diff --git a/0116-Backport-SME-aarch64-Fix-transitive-closure-of-featu.patch b/0116-Backport-SME-aarch64-Fix-transitive-closure-of-featu.patch
new file mode 100644
index 0000000..ed2a375
--- /dev/null
+++ b/0116-Backport-SME-aarch64-Fix-transitive-closure-of-featu.patch
@@ -0,0 +1,154 @@
+From c6698a5feb07fc0cda89a54a0ee4006295ac6dbe Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:53 +0100
+Subject: [PATCH 017/157] [Backport][SME] aarch64: Fix transitive closure of
+ features
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b754d32d3053a4ba2a82361ac0f2739797a811f1
+
+aarch64-option-extensions.def requires us to maintain the transitive
+closure of options by hand.  This patch fixes a few cases where a
+flag was missed.
+
++noaes and +nosha2 now disable +crypto, which IMO makes more
+sense and is consistent with the Clang behaviour.
+
+gcc/
+	* config/aarch64/aarch64-option-extensions.def (dotprod): Depend
+	on fp as well as simd.
+	(sha3): Likewise.
+	(aes): Likewise.  Make +noaes disable crypto.
+	(sha2): Likewise +nosha2.  Also make +nosha2 disable sha3 and
+	sve2-sha3.
+	(sve2-sha3): Depend on sha2 as well as sha3.
+
+gcc/testsuite/
+	* gcc.target/aarch64/options_set_6.c: Expect +crypto+nosha2 to
+	disable crypto but keep aes.
+	* gcc.target/aarch64/pragma_cpp_predefs_4.c: New test.
+---
+ .../aarch64/aarch64-option-extensions.def     | 16 ++++---
+ .../gcc.target/aarch64/options_set_6.c        |  5 +-
+ .../gcc.target/aarch64/pragma_cpp_predefs_4.c | 47 +++++++++++++++++++
+ 3 files changed, 58 insertions(+), 10 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
+
+diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
+index b4d0ac8b6..b98008127 100644
+--- a/gcc/config/aarch64/aarch64-option-extensions.def
++++ b/gcc/config/aarch64/aarch64-option-extensions.def
+@@ -113,28 +113,29 @@ AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, \
+ 
+ /* Enabling "dotprod" also enables "simd".
+    Disabling "dotprod" only disables "dotprod".  */
+-AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, \
++AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_FPSIMD, 0, \
+ 		      false, "asimddp")
+ 
+ /* Enabling "aes" also enables "simd".
+    Disabling "aes" disables "aes" and "sve2-aes'.  */
+-AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, \
+-		      AARCH64_FL_SVE2_AES, false, "aes")
++AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_FPSIMD, \
++		      AARCH64_FL_SVE2_AES | AARCH64_FL_CRYPTO, false, "aes")
+ 
+ /* Enabling "sha2" also enables "simd".
+    Disabling "sha2" just disables "sha2".  */
+-AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, false, \
+-		      "sha1 sha2")
++AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_FPSIMD, \
++		      AARCH64_FL_CRYPTO | AARCH64_FL_SHA3 | \
++		      AARCH64_FL_SVE2_SHA3, false, "sha1 sha2")
+ 
+ /* Enabling "sha3" enables "simd" and "sha2".
+    Disabling "sha3" disables "sha3" and "sve2-sha3".  */
+-AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD | \
++AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_FPSIMD | \
+ 		      AARCH64_FL_SHA2, AARCH64_FL_SVE2_SHA3, false, \
+ 		      "sha3 sha512")
+ 
+ /* Enabling "sm4" also enables "simd".
+    Disabling "sm4" disables "sm4" and "sve2-sm4".  */
+-AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, \
++AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_FPSIMD, \
+ 		      AARCH64_FL_SVE2_SM4, false, "sm3 sm4")
+ 
+ /* Enabling "fp16fml" also enables "fp" and "fp16".
+@@ -192,6 +193,7 @@ AARCH64_OPT_EXTENSION("sve2-aes", AARCH64_FL_SVE2_AES, AARCH64_FL_AES | \
+ /* Enabling "sve2-sha3" also enables "sha3", "simd", "fp16", "fp", "sve", and
+    "sve2". Disabling "sve2-sha3" just disables "sve2-sha3".  */
+ AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, AARCH64_FL_SHA3 | \
++		      AARCH64_FL_SHA2 | \
+ 		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+ 		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "svesha3")
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_6.c b/gcc/testsuite/gcc.target/aarch64/options_set_6.c
+index 90a055928..2a1d7fe5b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/options_set_6.c
++++ b/gcc/testsuite/gcc.target/aarch64/options_set_6.c
+@@ -6,7 +6,6 @@ int main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
++/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes} 1 } } */
+ 
+-/* Group as a whole was requested to be turned on, crypto itself is a bit and so
+-   just turning off one feature can't turn it off.   */
++/* +crypto turns on +aes and +sha2, but +nosha2 disables +crypto.   */
+diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
+new file mode 100644
+index 000000000..0e6461fa4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
+@@ -0,0 +1,47 @@
++#pragma GCC target "+nothing+dotprod"
++#ifndef __ARM_FEATURE_FMA
++#error Foo
++#endif
++
++#pragma GCC target "+nothing+aes"
++#ifndef __ARM_FEATURE_FMA
++#error Foo
++#endif
++
++#pragma GCC target "+nothing+sha2"
++#ifndef __ARM_FEATURE_FMA
++#error Foo
++#endif
++
++#pragma GCC target "+nothing+sha3"
++#ifndef __ARM_FEATURE_FMA
++#error Foo
++#endif
++
++#pragma GCC target "+nothing+sm4"
++#ifndef __ARM_FEATURE_FMA
++#error Foo
++#endif
++
++#pragma GCC target "+crypto+noaes"
++#ifdef __ARM_FEATURE_CRYPTO
++#error Foo
++#endif
++
++#pragma GCC target "+crypto+nosha2"
++#ifdef __ARM_FEATURE_CRYPTO
++#error Foo
++#endif
++
++#pragma GCC target "+nothing+sve2-sha3"
++#ifndef __ARM_FEATURE_SHA2
++#error Foo
++#endif
++
++#pragma GCC target "+sve2-sha3+nosha2"
++#ifdef __ARM_FEATURE_SHA3
++#error Foo
++#endif
++#ifdef __ARM_FEATURE_SVE2_SHA3
++#error Foo
++#endif
+-- 
+2.33.0
+
diff --git a/0117-Backport-SME-aarch64-Reorder-an-entry-in-aarch64-opt.patch b/0117-Backport-SME-aarch64-Reorder-an-entry-in-aarch64-opt.patch
new file mode 100644
index 0000000..f4ef844
--- /dev/null
+++ b/0117-Backport-SME-aarch64-Reorder-an-entry-in-aarch64-opt.patch
@@ -0,0 +1,194 @@
+From 4a2d0bdf5c9a5f4ee615c1d0768cb2e8a3dfef4a Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:54 +0100
+Subject: [PATCH 018/157] [Backport][SME] aarch64: Reorder an entry in
+ aarch64-option-extensions.def
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c067c474f85b1e9c56fb34dd51ef0eec9221b766
+
+aarch64-option-extensions.def was topologically sorted except
+for one case: crypto came before its aes and sha2 dependencies.
+This patch moves crypto after sha2 instead.
+
+gcc/
+	* config/aarch64/aarch64-option-extensions.def: Move crypto
+	after sha2.
+
+gcc/testsuite/
+	* gcc.target/aarch64/cpunative/native_cpu_0.c: Expect +crypto
+	to come after +crc.
+	* gcc.target/aarch64/cpunative/native_cpu_13.c: Likewise.
+	* gcc.target/aarch64/cpunative/native_cpu_16.c: Likewise.
+	* gcc.target/aarch64/cpunative/native_cpu_17.c: Likewise.
+	* gcc.target/aarch64/cpunative/native_cpu_6.c: Likewise.
+	* gcc.target/aarch64/cpunative/native_cpu_7.c: Likewise.
+	* gcc.target/aarch64/options_set_2.c: Likewise.
+	* gcc.target/aarch64/options_set_3.c: Likewise.
+	* gcc.target/aarch64/options_set_4.c: Likewise.
+---
+ .../aarch64/aarch64-option-extensions.def     | 20 +++++++++----------
+ .../aarch64/cpunative/native_cpu_0.c          |  2 +-
+ .../aarch64/cpunative/native_cpu_13.c         |  2 +-
+ .../aarch64/cpunative/native_cpu_16.c         |  2 +-
+ .../aarch64/cpunative/native_cpu_17.c         |  2 +-
+ .../aarch64/cpunative/native_cpu_6.c          |  2 +-
+ .../aarch64/cpunative/native_cpu_7.c          |  2 +-
+ .../gcc.target/aarch64/options_set_2.c        |  2 +-
+ .../gcc.target/aarch64/options_set_3.c        |  2 +-
+ .../gcc.target/aarch64/options_set_4.c        |  4 ++--
+ 10 files changed, 20 insertions(+), 20 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
+index b98008127..df2c8d19b 100644
+--- a/gcc/config/aarch64/aarch64-option-extensions.def
++++ b/gcc/config/aarch64/aarch64-option-extensions.def
+@@ -76,16 +76,6 @@ AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, \
+ 		      AARCH64_FL_I8MM | AARCH64_FL_F32MM | AARCH64_FL_F64MM, \
+ 		      false, "asimd")
+ 
+-/* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
+-   Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4",
+-   "sve2-aes", "sve2-sha3", "sve2-sm4".  */
+-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | \
+-		      AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, \
+-		      AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
+-		      AARCH64_FL_SM4 | AARCH64_FL_SVE2_AES | \
+-		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4, true, \
+-		      "aes pmull sha1 sha2")
+-
+ /* Enabling or disabling "crc" only changes "crc".  */
+ AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
+ 
+@@ -127,6 +117,16 @@ AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_FPSIMD, \
+ 		      AARCH64_FL_CRYPTO | AARCH64_FL_SHA3 | \
+ 		      AARCH64_FL_SVE2_SHA3, false, "sha1 sha2")
+ 
++/* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
++   Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4",
++   "sve2-aes", "sve2-sha3", "sve2-sm4".  */
++AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | \
++		      AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, \
++		      AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
++		      AARCH64_FL_SM4 | AARCH64_FL_SVE2_AES | \
++		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4, true, \
++		      "aes pmull sha1 sha2")
++
+ /* Enabling "sha3" enables "simd" and "sha2".
+    Disabling "sha3" disables "sha3" and "sve2-sha3".  */
+ AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_FPSIMD | \
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_0.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_0.c
+index f155f51ba..8499f87c3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_0.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_0.c
+@@ -7,6 +7,6 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+crypto\+crc\+dotprod} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+crc\+dotprod\+crypto} } } */
+ 
+ /* Test a normal looking procinfo.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_13.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_13.c
+index b7b3a8e13..551669091 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_13.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_13.c
+@@ -7,6 +7,6 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+crypto\+crc\+dotprod} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+crc\+dotprod\+crypto} } } */
+ 
+ /* Test one with mixed order of feature bits.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_16.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_16.c
+index a424e7c56..2f963bb23 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_16.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_16.c
+@@ -7,6 +7,6 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+crypto\+crc\+dotprod\+sve2} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+crc\+dotprod\+crypto\+sve2} } } */
+ 
+ /* Test a normal looking procinfo.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_17.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_17.c
+index c269c5fef..c68a697aa 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_17.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_17.c
+@@ -7,6 +7,6 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+crypto\+crc\+dotprod\+sve2} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+crc\+dotprod\+crypto\+sve2} } } */
+ 
+ /* Test a normal looking procinfo.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_6.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_6.c
+index da72052e6..7608e8845 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_6.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_6.c
+@@ -7,7 +7,7 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+crypto\+fp16} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+fp16\+crypto} } } */
+ 
+ /* Test one where the feature bits for crypto and fp16 are given in
+    same order as declared in options file.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_7.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_7.c
+index 96ad4c14d..72b14b4f6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_7.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_7.c
+@@ -7,7 +7,7 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+crypto\+fp16} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+fp16\+crypto} } } */
+ 
+ /* Test one where the crypto and fp16 options are specified in different
+    order from what is in the options file.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_2.c b/gcc/testsuite/gcc.target/aarch64/options_set_2.c
+index 3476febce..f82cb5f78 100644
+--- a/gcc/testsuite/gcc.target/aarch64/options_set_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/options_set_2.c
+@@ -6,6 +6,6 @@ int main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
++/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto} 1 } } */
+ 
+ /* Check to see if crc and crypto are maintained if crypto specified.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_3.c b/gcc/testsuite/gcc.target/aarch64/options_set_3.c
+index 4558339f1..7d350cfa3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/options_set_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/options_set_3.c
+@@ -6,6 +6,6 @@ int main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
++/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto} 1 } } */
+ 
+ /* Check if smallest set is maintained when outputting. */
+diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_4.c b/gcc/testsuite/gcc.target/aarch64/options_set_4.c
+index 15514bfe9..5370e02e1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/options_set_4.c
++++ b/gcc/testsuite/gcc.target/aarch64/options_set_4.c
+@@ -6,7 +6,7 @@ int main ()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
++/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto} 1 } } */
+ 
+ /* Check if individual bits that make up a grouping is specified that only the
+-   grouping is kept. */
+\ No newline at end of file
++   grouping is kept. */
+-- 
+2.33.0
+
diff --git a/0118-Backport-SME-aarch64-Simplify-feature-definitions.patch b/0118-Backport-SME-aarch64-Simplify-feature-definitions.patch
new file mode 100644
index 0000000..ffff47d
--- /dev/null
+++ b/0118-Backport-SME-aarch64-Simplify-feature-definitions.patch
@@ -0,0 +1,1176 @@
+From deb18d5083d8f9edbdafac184c010a6720dc8dda Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:54 +0100
+Subject: [PATCH 019/157] [Backport][SME] aarch64: Simplify feature definitions
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=11a113d501ff64fa4843e28d0a21b3f4e9d0d3de
+
+Currently the aarch64-option-extensions.def entries, the
+aarch64-cores.def entries, and the AARCH64_FL_FOR_* macros
+have a transitive closure of dependencies that is maintained by hand.
+This is a bit error-prone and is becoming less tenable as more features
+are added.  The main point of this patch is to maintain the closure
+automatically instead.
+
+For example, the +sve2-aes extension requires sve2 and aes.
+This is now described using:
+
+  AARCH64_OPT_EXTENSION("sve2-aes", SVE2_AES, (SVE2, AES), ...)
+
+If life was simple, we could just give the name of the feature
+and the list of features that it requires/depends on.  But sadly
+things are more complicated.  For example:
+
+- the legacy +crypto option enables aes and sha2 only, but +nocrypto
+  disables all crypto-related extensions, including sm4.
+
+- +fp16fml enables fp16, but armv8.4-a enables fp16fml without fp16.
+  fp16fml only has an effect when fp16 is also present; see the
+  comments for more details.
+
+- +bf16 enables simd, but +bf16+nosimd is valid and enables just the
+  scalar bf16 instructions.  rdma behaves similarly.
+
+To handle cases like these, the option entries have extra fields to
+specify what an explicit +foo enables and what an explicit +nofoo
+disables, in addition to the absolute dependencies.
+
+The other main changes are:
+
+- AARCH64_FL_* are now defined automatically.
+
+- the feature list for each architecture level moves from aarch64.h
+  to aarch64-arches.def.
+
+As a consequence, we now have a (redundant) V8A feature flag.
+
+While there, the patch uses a new typedef, aarch64_feature_flags,
+for the set of feature flags.  This should make it easier to switch
+to a class if we run out of bits in the uint64_t.
+
+For now the patch hardcodes the fact that crypto is the only
+synthetic option.  A later patch will remove this field.
+
+To test for things that might not be covered by the testsuite,
+I made the driver print out the all_extensions, all_cores and
+all_archs arrays before and after the patch, with the following
+tweaks:
+
+- renumber the old AARCH64_FL_* bit assignments to match the .def order
+- remove the new V8A flag when printing the new tables
+- treat CRYPTO and CRYPTO | AES | SHA2 the same way when printing the
+  core tables
+
+(On the last point: some cores enabled just CRYPTO while others enabled
+CRYPTO, AES and SHA2.  This doesn't cause a difference in behaviour
+because of how the dependent macros are defined.  With the new scheme,
+all entries with CRYPTO automatically get AES and SHA2 too.)
+
+The only difference is that +nofp now turns off dotprod.  This was
+another instance of an incomplete transitive closure, but unlike the
+instances fixed in a previous patch, it had no observable effect.
+
+gcc/
+	* config/aarch64/aarch64-option-extensions.def: Switch to a new format.
+	* config/aarch64/aarch64-cores.def: Use the same format to specify
+	lists of features.
+	* config/aarch64/aarch64-arches.def: Likewise, moving that information
+	from aarch64.h.
+	* config/aarch64/aarch64-opts.h (aarch64_feature_flags): New typedef.
+	* config/aarch64/aarch64.h (aarch64_feature): New class enum.
+	Turn AARCH64_FL_* macros into constexprs, getting the definitions
+	from aarch64-option-extensions.def.  Remove AARCH64_FL_FOR_* macros.
+	* common/config/aarch64/aarch64-common.cc: Include
+	aarch64-feature-deps.h.
+	(all_extensions): Update for new .def format.
+	(all_extensions_by_on, all_cores, all_architectures): Likewise.
+	* config/aarch64/driver-aarch64.cc: Include aarch64-feature-deps.h.
+	(aarch64_extensions): Update for new .def format.
+	(aarch64_cpu_data, aarch64_arches): Likewise.
+	* config/aarch64/aarch64.cc: Include aarch64-feature-deps.h.
+	(all_architectures, all_cores): Update for new .def format.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(check_required_extensions): Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc   |  29 +-
+ gcc/config/aarch64/aarch64-arches.def         |  28 +-
+ gcc/config/aarch64/aarch64-cores.def          | 130 +++----
+ gcc/config/aarch64/aarch64-feature-deps.h     | 121 +++++++
+ .../aarch64/aarch64-option-extensions.def     | 323 +++++++-----------
+ gcc/config/aarch64/aarch64-opts.h             |   4 +
+ gcc/config/aarch64/aarch64-sve-builtins.cc    |   5 +-
+ gcc/config/aarch64/aarch64.cc                 |  14 +-
+ gcc/config/aarch64/aarch64.h                  | 164 ++-------
+ gcc/config/aarch64/driver-aarch64.cc          |  10 +-
+ 10 files changed, 374 insertions(+), 454 deletions(-)
+ create mode 100644 gcc/config/aarch64/aarch64-feature-deps.h
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index a965ac660..74729bb30 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -30,6 +30,7 @@
+ #include "opts.h"
+ #include "flags.h"
+ #include "diagnostic.h"
++#include "config/aarch64/aarch64-feature-deps.h"
+ 
+ #ifdef  TARGET_BIG_ENDIAN_DEFAULT
+ #undef  TARGET_DEFAULT_TARGET_FLAGS
+@@ -214,9 +215,12 @@ struct aarch64_option_extension
+ /* ISA extensions in AArch64.  */
+ static const struct aarch64_option_extension all_extensions[] =
+ {
+-#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+-			      SYNTHETIC, Z) \
+-  {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, SYNTHETIC},
++#define AARCH64_OPT_EXTENSION(NAME, IDENT, C, D, E, F) \
++  {NAME, AARCH64_FL_##IDENT, \
++   feature_deps::IDENT ().explicit_on & ~AARCH64_FL_##IDENT, \
++   feature_deps::get_flags_off (feature_deps::root_off_##IDENT) \
++   & ~AARCH64_FL_##IDENT, \
++   AARCH64_FL_##IDENT == AARCH64_FL_CRYPTO},
+ #include "config/aarch64/aarch64-option-extensions.def"
+   {NULL, 0, 0, 0, false}
+ };
+@@ -225,9 +229,12 @@ static const struct aarch64_option_extension all_extensions[] =
+    bits and extension turned on.  Cached for efficiency.  */
+ static struct aarch64_option_extension all_extensions_by_on[] =
+ {
+-#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+-			      SYNTHETIC, Z) \
+-  {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, SYNTHETIC},
++#define AARCH64_OPT_EXTENSION(NAME, IDENT, C, D, E, F) \
++  {NAME, AARCH64_FL_##IDENT, \
++   feature_deps::IDENT ().explicit_on & ~AARCH64_FL_##IDENT, \
++   feature_deps::get_flags_off (feature_deps::root_off_##IDENT) \
++   & ~AARCH64_FL_##IDENT, \
++   AARCH64_FL_##IDENT == AARCH64_FL_CRYPTO},
+ #include "config/aarch64/aarch64-option-extensions.def"
+   {NULL, 0, 0, 0, false}
+ };
+@@ -250,18 +257,18 @@ struct arch_to_arch_name
+    the default set of architectural feature flags they support.  */
+ static const struct processor_name_to_arch all_cores[] =
+ {
+-#define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART, VARIANT) \
+-  {NAME, AARCH64_ARCH_##ARCH_IDENT, AARCH64_FL_FOR_##ARCH_IDENT | FLAGS},
++#define AARCH64_CORE(NAME, CORE_IDENT, C, ARCH_IDENT, E, F, G, H, I) \
++  {NAME, AARCH64_ARCH_##ARCH_IDENT, feature_deps::cpu_##CORE_IDENT},
+ #include "config/aarch64/aarch64-cores.def"
+-  {"generic", AARCH64_ARCH_V8A, AARCH64_FL_FOR_V8A},
++  {"generic", AARCH64_ARCH_V8A, feature_deps::V8A ().enable},
+   {"", aarch64_no_arch, 0}
+ };
+ 
+ /* Map architecture revisions to their string representation.  */
+ static const struct arch_to_arch_name all_architectures[] =
+ {
+-#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \
+-  {AARCH64_ARCH_##ARCH_IDENT, NAME, FLAGS},
++#define AARCH64_ARCH(NAME, B, ARCH_IDENT, D, E)	\
++  {AARCH64_ARCH_##ARCH_IDENT, NAME, feature_deps::ARCH_IDENT ().enable},
+ #include "config/aarch64/aarch64-arches.def"
+   {aarch64_no_arch, "", 0}
+ };
+diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
+index ece96e22a..9f8246618 100644
+--- a/gcc/config/aarch64/aarch64-arches.def
++++ b/gcc/config/aarch64/aarch64-arches.def
+@@ -30,19 +30,19 @@
+    Due to the assumptions about the positions of these fields in config.gcc,
+    NAME should be kept as the first argument.  */
+ 
+-AARCH64_ARCH("armv8-a",	      generic,	     V8A,	8,  AARCH64_FL_FOR_V8A)
+-AARCH64_ARCH("armv8.1-a",     generic,	     V8_1A,	8,  AARCH64_FL_FOR_V8_1A)
+-AARCH64_ARCH("armv8.2-a",     generic,	     V8_2A,	8,  AARCH64_FL_FOR_V8_2A)
+-AARCH64_ARCH("armv8.3-a",     generic,	     V8_3A,	8,  AARCH64_FL_FOR_V8_3A)
+-AARCH64_ARCH("armv8.4-a",     generic,	     V8_4A,	8,  AARCH64_FL_FOR_V8_4A)
+-AARCH64_ARCH("armv8.5-a",     generic,	     V8_5A,	8,  AARCH64_FL_FOR_V8_5A)
+-AARCH64_ARCH("armv8.6-a",     generic,	     V8_6A,	8,  AARCH64_FL_FOR_V8_6A)
+-AARCH64_ARCH("armv8.7-a",     generic,       V8_7A,     8,  AARCH64_FL_FOR_V8_7A)
+-AARCH64_ARCH("armv8.8-a",     generic,       V8_8A,     8,  AARCH64_FL_FOR_V8_8A)
+-AARCH64_ARCH("armv8-r",       generic,	     V8R  ,	8,  AARCH64_FL_FOR_V8R)
+-AARCH64_ARCH("armv9-a",       generic,	     V9A  ,	9,  AARCH64_FL_FOR_V9A)
+-AARCH64_ARCH("armv9.1-a",     generic,       V9_1A,     9,  AARCH64_FL_FOR_V9_1A)
+-AARCH64_ARCH("armv9.2-a",     generic,       V9_2A,     9,  AARCH64_FL_FOR_V9_2A)
+-AARCH64_ARCH("armv9.3-a",     generic,       V9_3A,     9,  AARCH64_FL_FOR_V9_3A)
++AARCH64_ARCH("armv8-a",       generic,       V8A,       8,  (SIMD))
++AARCH64_ARCH("armv8.1-a",     generic,       V8_1A,     8,  (V8A, LSE, CRC, RDMA))
++AARCH64_ARCH("armv8.2-a",     generic,       V8_2A,     8,  (V8_1A))
++AARCH64_ARCH("armv8.3-a",     generic,       V8_3A,     8,  (V8_2A, PAUTH))
++AARCH64_ARCH("armv8.4-a",     generic,       V8_4A,     8,  (V8_3A, F16FML, DOTPROD, FLAGM))
++AARCH64_ARCH("armv8.5-a",     generic,       V8_5A,     8,  (V8_4A, SB, SSBS, PREDRES))
++AARCH64_ARCH("armv8.6-a",     generic,       V8_6A,     8,  (V8_5A, I8MM, BF16))
++AARCH64_ARCH("armv8.7-a",     generic,       V8_7A,     8,  (V8_6A, LS64))
++AARCH64_ARCH("armv8.8-a",     generic,       V8_8A,     8,  (V8_7A, MOPS))
++AARCH64_ARCH("armv8-r",       generic,       V8R  ,     8,  (V8_4A))
++AARCH64_ARCH("armv9-a",       generic,       V9A  ,     9,  (V8_5A, SVE2))
++AARCH64_ARCH("armv9.1-a",     generic,       V9_1A,     9,  (V8_6A, V9A))
++AARCH64_ARCH("armv9.2-a",     generic,       V9_2A,     9,  (V8_7A, V9_1A))
++AARCH64_ARCH("armv9.3-a",     generic,       V9_3A,     9,  (V8_8A, V9_2A))
+ 
+ #undef AARCH64_ARCH
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index cf500d0a9..60299160b 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -46,132 +46,132 @@
+ /* ARMv8-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, V8A,  AARCH64_FL_CRC, cortexa35, 0x41, 0xd02, -1)
+-AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, V8A,  AARCH64_FL_CRC, cortexa35, 0x41, 0xd04, -1)
+-AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa53, 0x41, 0xd03, -1)
+-AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, V8A,  AARCH64_FL_CRC, cortexa57, 0x41, 0xd07, -1)
+-AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, V8A,  AARCH64_FL_CRC, cortexa72, 0x41, 0xd08, -1)
+-AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, V8A,  AARCH64_FL_CRC, cortexa73, 0x41, 0xd09, -1)
++AARCH64_CORE("cortex-a34",  cortexa34, cortexa53, V8A,  (CRC), cortexa35, 0x41, 0xd02, -1)
++AARCH64_CORE("cortex-a35",  cortexa35, cortexa53, V8A,  (CRC), cortexa35, 0x41, 0xd04, -1)
++AARCH64_CORE("cortex-a53",  cortexa53, cortexa53, V8A,  (CRC), cortexa53, 0x41, 0xd03, -1)
++AARCH64_CORE("cortex-a57",  cortexa57, cortexa57, V8A,  (CRC), cortexa57, 0x41, 0xd07, -1)
++AARCH64_CORE("cortex-a72",  cortexa72, cortexa57, V8A,  (CRC), cortexa72, 0x41, 0xd08, -1)
++AARCH64_CORE("cortex-a73",  cortexa73, cortexa57, V8A,  (CRC), cortexa73, 0x41, 0xd09, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx",      thunderx,      thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("thunderx",      thunderx,      thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a0, -1)
+ /* Do not swap around "thunderxt88p1" and "thunderxt88",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO,	thunderxt88,  0x43, 0x0a1, 0)
+-AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderxt88,  0x43, 0x0a1, -1)
++AARCH64_CORE("thunderxt88p1", thunderxt88p1, thunderx,  V8A,  (CRC, CRYPTO),	thunderxt88,  0x43, 0x0a1, 0)
++AARCH64_CORE("thunderxt88",   thunderxt88,   thunderx,  V8A,  (CRC, CRYPTO), thunderxt88,  0x43, 0x0a1, -1)
+ 
+ /* OcteonTX is the official name for T81/T83. */
+-AARCH64_CORE("octeontx",      octeontx,      thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a0, -1)
+-AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("octeontx",      octeontx,      thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a0, -1)
++AARCH64_CORE("octeontx81",    octeontxt81,   thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("octeontx83",    octeontxt83,   thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a3, -1)
+ 
+-AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a2, -1)
+-AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, thunderx,  0x43, 0x0a3, -1)
++AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a2, -1)
++AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a3, -1)
+ 
+ /* Ampere Computing ('\xC0') cores. */
+-AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, 0, ampere1, 0xC0, 0xac3, -1)
++AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, (), ampere1, 0xC0, 0xac3, -1)
+ /* Do not swap around "emag" and "xgene1",
+    this order is required to handle variant correctly. */
+-AARCH64_CORE("emag",        emag,      xgene1,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, emag, 0x50, 0x000, 3)
++AARCH64_CORE("emag",        emag,      xgene1,    V8A,  (CRC, CRYPTO), emag, 0x50, 0x000, 3)
+ 
+ /* APM ('P') cores. */
+-AARCH64_CORE("xgene1",      xgene1,    xgene1,    V8A,  0, xgene1, 0x50, 0x000, -1)
++AARCH64_CORE("xgene1",      xgene1,    xgene1,    V8A,  (), xgene1, 0x50, 0x000, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("falkor",      falkor,    falkor,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
+-AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("falkor",      falkor,    falkor,    V8A,  (CRC, CRYPTO, RDMA), qdf24xx,   0x51, 0xC00, -1)
++AARCH64_CORE("qdf24xx",     qdf24xx,   falkor,    V8A,  (CRC, CRYPTO, RDMA), qdf24xx,   0x51, 0xC00, -1)
+ 
+ /* Samsung ('S') cores. */
+-AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1,  0x53, 0x001, -1)
++AARCH64_CORE("exynos-m1",   exynosm1,  exynosm1,  V8A,  (CRC, CRYPTO), exynosm1,  0x53, 0x001, -1)
+ 
+ /* HXT ('h') cores. */
+-AARCH64_CORE("phecda",      phecda,    falkor,    V8A,  AARCH64_FL_CRC | AARCH64_FL_CRYPTO, qdf24xx,   0x68, 0x000, -1)
++AARCH64_CORE("phecda",      phecda,    falkor,    V8A,  (CRC, CRYPTO), qdf24xx,   0x68, 0x000, -1)
+ 
+ /* ARMv8.1-A Architecture Processors.  */
+ 
+ /* Broadcom ('B') cores. */
+-AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, V8_1A,  AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
+-AARCH64_CORE("vulcan",  vulcan, thunderx2t99, V8_1A,  AARCH64_FL_CRYPTO, thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("thunderx2t99p1",  thunderx2t99p1, thunderx2t99, V8_1A,  (CRYPTO), thunderx2t99, 0x42, 0x516, -1)
++AARCH64_CORE("vulcan",  vulcan, thunderx2t99, V8_1A,  (CRYPTO), thunderx2t99, 0x42, 0x516, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, V8_1A,  AARCH64_FL_CRYPTO, thunderx2t99, 0x43, 0x0af, -1)
++AARCH64_CORE("thunderx2t99",  thunderx2t99,  thunderx2t99, V8_1A,  (CRYPTO), thunderx2t99, 0x43, 0x0af, -1)
+ 
+ /* ARMv8.2-A Architecture Processors.  */
+ 
+ /* ARM ('A') cores. */
+-AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa53, 0x41, 0xd05, -1)
+-AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, 0xd0a, -1)
+-AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, 0xd0b, -1)
+-AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0e, -1)
+-AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, neoversen1, 0x41, 0xd0d, -1)
+-AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd41, -1)
+-AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd42, -1)
+-AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE | AARCH64_FL_FLAGM | AARCH64_FL_PAUTH, neoversen1, 0x41, 0xd4b, -1)
+-AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd06, -1)
+-AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd43, -1)
+-AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd44, -1)
+-AARCH64_CORE("ares",  ares, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_PROFILE, neoversen1, 0x41, 0xd0c, -1)
+-AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD | AARCH64_FL_SSBS, cortexa73, 0x41, 0xd4a, -1)
++AARCH64_CORE("cortex-a55",  cortexa55, cortexa53, V8_2A,  (F16, RCPC, DOTPROD), cortexa53, 0x41, 0xd05, -1)
++AARCH64_CORE("cortex-a75",  cortexa75, cortexa57, V8_2A,  (F16, RCPC, DOTPROD), cortexa73, 0x41, 0xd0a, -1)
++AARCH64_CORE("cortex-a76",  cortexa76, cortexa57, V8_2A,  (F16, RCPC, DOTPROD), neoversen1, 0x41, 0xd0b, -1)
++AARCH64_CORE("cortex-a76ae",  cortexa76ae, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, SSBS), neoversen1, 0x41, 0xd0e, -1)
++AARCH64_CORE("cortex-a77",  cortexa77, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, SSBS), neoversen1, 0x41, 0xd0d, -1)
++AARCH64_CORE("cortex-a78",  cortexa78, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, SSBS, PROFILE), neoversen1, 0x41, 0xd41, -1)
++AARCH64_CORE("cortex-a78ae",  cortexa78ae, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, SSBS, PROFILE), neoversen1, 0x41, 0xd42, -1)
++AARCH64_CORE("cortex-a78c",  cortexa78c, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, SSBS, PROFILE, FLAGM, PAUTH), neoversen1, 0x41, 0xd4b, -1)
++AARCH64_CORE("cortex-a65",  cortexa65, cortexa53, V8_2A,  (F16, RCPC, DOTPROD, SSBS), cortexa73, 0x41, 0xd06, -1)
++AARCH64_CORE("cortex-a65ae",  cortexa65ae, cortexa53, V8_2A,  (F16, RCPC, DOTPROD, SSBS), cortexa73, 0x41, 0xd43, -1)
++AARCH64_CORE("cortex-x1",  cortexx1, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, SSBS, PROFILE), neoversen1, 0x41, 0xd44, -1)
++AARCH64_CORE("ares",  ares, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, PROFILE), neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-n1",  neoversen1, cortexa57, V8_2A,  (F16, RCPC, DOTPROD, PROFILE), neoversen1, 0x41, 0xd0c, -1)
++AARCH64_CORE("neoverse-e1",  neoversee1, cortexa53, V8_2A,  (F16, RCPC, DOTPROD, SSBS), cortexa73, 0x41, 0xd4a, -1)
+ 
+ /* Cavium ('C') cores. */
+-AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b0, -1)
+-AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b1, -1)
+-AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2",      octeontx2,      cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b0, -1)
++AARCH64_CORE("octeontx2t98",   octeontx2t98,   cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b1, -1)
++AARCH64_CORE("octeontx2t96",   octeontx2t96,   cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b2, -1)
+ /* Note OcteonTX2 T93 is an alias to OcteonTX2 T96. */
+-AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b2, -1)
+-AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b3, -1)
+-AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b4, -1)
+-AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_PROFILE, cortexa57, 0x43, 0x0b5, -1)
++AARCH64_CORE("octeontx2t93",   octeontx2t93,   cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b2, -1)
++AARCH64_CORE("octeontx2f95",   octeontx2f95,   cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b3, -1)
++AARCH64_CORE("octeontx2f95n",  octeontx2f95n,  cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b4, -1)
++AARCH64_CORE("octeontx2f95mm", octeontx2f95mm, cortexa57, V8_2A,  (CRYPTO, PROFILE), cortexa57, 0x43, 0x0b5, -1)
+ 
+ /* Fujitsu ('F') cores. */
+-AARCH64_CORE("a64fx", a64fx, a64fx, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_SVE, a64fx, 0x46, 0x001, -1)
++AARCH64_CORE("a64fx", a64fx, a64fx, V8_2A,  (F16, SVE), a64fx, 0x46, 0x001, -1)
+ 
+ /* HiSilicon ('H') cores. */
+-AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2, tsv110,   0x48, 0xd01, -1)
++AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  (CRYPTO, F16), tsv110,   0x48, 0xd01, -1)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  AARCH64_FL_CRYPTO | AARCH64_FL_RCPC | AARCH64_FL_SM4 | AARCH64_FL_SHA3 | AARCH64_FL_F16FML, thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  (CRYPTO, RCPC, SM4, SHA3, F16FML), thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores.  */
+-AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  AARCH64_FL_SVE | AARCH64_FL_RCPC | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_PROFILE | AARCH64_FL_SSBS | AARCH64_FL_RNG, neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
++AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira,   0x51, 0xC01, -1)
++AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  (CRYPTO, RCPC), saphira,   0x51, 0xC01, -1)
+ 
+ /* ARMv8-A big.LITTLE implementations.  */
+ 
+-AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
+-AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
+-AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, V8A,  AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
+-AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, V8A,  AARCH64_FL_CRC, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
++AARCH64_CORE("cortex-a57.cortex-a53",  cortexa57cortexa53, cortexa53, V8A,  (CRC), cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
++AARCH64_CORE("cortex-a72.cortex-a53",  cortexa72cortexa53, cortexa53, V8A,  (CRC), cortexa72, 0x41, AARCH64_BIG_LITTLE (0xd08, 0xd03), -1)
++AARCH64_CORE("cortex-a73.cortex-a35",  cortexa73cortexa35, cortexa53, V8A,  (CRC), cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd04), -1)
++AARCH64_CORE("cortex-a73.cortex-a53",  cortexa73cortexa53, cortexa53, V8A,  (CRC), cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd09, 0xd03), -1)
+ 
+ /* ARM DynamIQ big.LITTLE configurations.  */
+ 
+-AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
+-AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, V8_2A,  AARCH64_FL_F16 | AARCH64_FL_RCPC | AARCH64_FL_DOTPROD, neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
++AARCH64_CORE("cortex-a75.cortex-a55",  cortexa75cortexa55, cortexa53, V8_2A,  (F16, RCPC, DOTPROD), cortexa73, 0x41, AARCH64_BIG_LITTLE (0xd0a, 0xd05), -1)
++AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, V8_2A,  (F16, RCPC, DOTPROD), neoversen1, 0x41, AARCH64_BIG_LITTLE (0xd0b, 0xd05), -1)
+ 
+ /* Armv8-R Architecture Processors.  */
+-AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, 0, cortexa53, 0x41, 0xd15, -1)
++AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, (), cortexa53, 0x41, 0xd15, -1)
+ 
+ /* Armv9.0-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores. */
+-AARCH64_CORE("cortex-a510",  cortexa510, cortexa55, V9A,  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, cortexa53, 0x41, 0xd46, -1)
++AARCH64_CORE("cortex-a510",  cortexa510, cortexa55, V9A,  (SVE2_BITPERM, MEMTAG, I8MM, BF16), cortexa53, 0x41, 0xd46, -1)
+ 
+-AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, V9A,  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd47, -1)
++AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, V9A,  (SVE2_BITPERM, MEMTAG, I8MM, BF16), neoversen2, 0x41, 0xd47, -1)
+ 
+-AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, V9A,  AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
++AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, V9A,  (SVE2_BITPERM, MEMTAG, I8MM, BF16), neoversen2, 0x41, 0xd48, -1)
+ 
+-AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
++AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversen2, 0x41, 0xd49, -1)
+ 
+-AARCH64_CORE("demeter", demeter, cortexa57, V9A, AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
+-AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1)
++AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1)
+ 
+ #undef AARCH64_CORE
+diff --git a/gcc/config/aarch64/aarch64-feature-deps.h b/gcc/config/aarch64/aarch64-feature-deps.h
+new file mode 100644
+index 000000000..3e33cb2ce
+--- /dev/null
++++ b/gcc/config/aarch64/aarch64-feature-deps.h
+@@ -0,0 +1,121 @@
++/* Feature dependency helpers for AArch64.
++   Copyright (C) 2022 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
++   .  */
++
++#ifndef AARCH64_FEATURE_DEPS_H
++#define AARCH64_FEATURE_DEPS_H 1
++
++namespace {
++namespace feature_deps {
++
++/* Together, these definitions of get_flags take a list of
++   feature names (representing functions that are defined below)
++   and return the set of associated flags.  */
++constexpr aarch64_feature_flags get_flags () { return 0; }
++
++template
++constexpr aarch64_feature_flags
++get_flags (T1 i, Ts... args)
++{
++  return i ().flag | get_flags (args...);
++}
++
++/* Like get_flags, but return the transitive closure of those features
++   and the ones that they rely on.  */
++constexpr aarch64_feature_flags get_enable () { return 0; }
++
++template
++constexpr aarch64_feature_flags
++get_enable (T1 i, Ts... args)
++{
++  return i ().enable | get_enable (args...);
++}
++
++/* Define info such that it has the following static constant
++   variables:
++
++   - flag: the aarch64_feature_flags bit associated with FEATURE
++
++   - enable: the transitive closure of the features that FEATURE requires,
++     plus FLAG itself
++
++   - explicit_on: the transitive closure of the features that an
++     explicit +FEATURE enables, including FLAG itself.  This is
++     always a superset of ENABLE
++
++   Also define a function FEATURE () that returns an info
++   (which is an empty structure, since all members are static).
++
++   Building up the list feature-by-feature ensures that the definition
++   files are in topological order.  */
++template struct info;
++
++#define HANDLE(IDENT, REQUIRES, EXPLICIT_ON)				\
++  template<> struct info {			\
++    static constexpr auto flag = AARCH64_FL_##IDENT;			\
++    static constexpr auto enable = flag | get_enable REQUIRES;		\
++    static constexpr auto explicit_on = enable | get_enable EXPLICIT_ON; \
++  };									\
++  constexpr info IDENT ()			\
++  {									\
++    return info ();				\
++  }
++#define AARCH64_OPT_EXTENSION(A, IDENT, REQUIRES, EXPLICIT_ON, E, F) \
++  HANDLE (IDENT, REQUIRES, EXPLICIT_ON)
++#define AARCH64_ARCH(A, B, IDENT, D, REQUIRES) HANDLE (IDENT, REQUIRES, ())
++#include "config/aarch64/aarch64-option-extensions.def"
++#include "config/aarch64/aarch64-arches.def"
++#undef HANDLE
++
++/* Return the set of all features that would need to be disabled if
++   the features in MASK are disabled.
++
++   Note that the size of the expression varies linearly with the number
++   of features, which means that invoking this function once per feature
++   is quadratic in the number of features.  However, collecting the same
++   information at compiler start-up is likely to be quadratic too, so
++   we're better off paying the cost once per compiler build rather than
++   once per compiler run.  */
++constexpr aarch64_feature_flags
++get_flags_off (aarch64_feature_flags mask)
++{
++  return (0
++#define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) \
++	  | (feature_deps::IDENT ().enable & mask ? AARCH64_FL_##IDENT : 0)
++#include "config/aarch64/aarch64-option-extensions.def"
++	  );
++}
++
++/* Define root_off_ variables for each feature, giving the set of
++   features that must be turned off by +noIDENT.  This set is not transitively
++   closed; use get_flags_off to complete the closure.  */
++#define AARCH64_OPT_EXTENSION(A, IDENT, C, D, EXPLICIT_OFF, F) \
++  constexpr auto root_off_##IDENT \
++    = AARCH64_FL_##IDENT | get_flags EXPLICIT_OFF;
++#include "config/aarch64/aarch64-option-extensions.def"
++
++/* Define cpu_ variables for each CPU, giving the transitive
++   closure of all the features that the CPU supports.  */
++#define AARCH64_CORE(A, CORE_IDENT, C, ARCH_IDENT, FEATURES, F, G, H, I) \
++  constexpr auto cpu_##CORE_IDENT = ARCH_IDENT ().enable | get_enable FEATURES;
++#include "config/aarch64/aarch64-cores.def"
++
++}
++}
++
++#endif
+diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
+index df2c8d19b..bdf4baf30 100644
+--- a/gcc/config/aarch64/aarch64-option-extensions.def
++++ b/gcc/config/aarch64/aarch64-option-extensions.def
+@@ -21,23 +21,34 @@
+ 
+    Before using #include to read this file, define a macro:
+ 
+-      AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF,
+-			    SYNTHETIC, FEATURE_STRING)
+-
+-   - EXT_NAME is the name of the extension, represented as a string constant.
+-   - FLAGS_CANONICAL is the canonical internal name for this flag.
+-   - FLAGS_ON are the bitwise-or of the features that enabling the extension
+-     adds, or zero if enabling this extension has no effect on other features.
+-   - FLAGS_OFF are the bitwise-or of the features that disabling the extension
+-     removes, or zero if disabling this extension has no effect on other
+-     features.
+-   - SYNTHETIC is a boolean to indicate whether the option is a purely synthetic
+-     grouping of options and that the option itself has no feature bit (e.g.
+-     crypto).  This is used to determine when sum of the individual options in
+-     FLAGS_ON can be replaced by FLAG_CANONICAL in options minimization.  If the
+-     group is synthetic then they can be replaced when all options in FLAGS_ON
+-     are enabled, otherwise they can only be replaced when
+-     FLAGS_ON | FLAG_CANONICAL are enabled.
++      AARCH64_OPT_EXTENSION(NAME, IDENT, REQUIRES, EXPLICIT_ON,
++			    EXPLICIT_OFF, FEATURE_STRING)
++
++   - NAME is the name of the extension, represented as a string constant.
++
++   - IDENT is the canonical internal name for this flag.
++
++   - REQUIRES is a list of features that must be enabled whenever this
++     feature is enabled.  The relationship is implicitly transitive:
++     if A appears in B's REQUIRES and B appears in C's REQUIRES then
++     A and B must be enabled whenever C is.  Thus, turning on C also
++     turns on A and B, while turning off A or B also turns off C.
++
++   - EXPLICIT_ON is a list of features that are enabled by an explicit
++     +NAME specification, in addition to those listed in REQUIRES.
++     Usually this is an empty list; comments below explain the exceptions.
++     The list is implicitly transitively closed wrt REQUIRES (but *not*
++     to EXPLICIT_ON, since NAME is the only thing explicit in +NAME).
++     Thus if A is in B's REQUIRES and B is in C's EXPLICIT_ON, +C will
++     enable both B and A.  B's EXPLICIT_ON has no effect on +C.
++
++   - EXPLICIT_OFF is a list of features that are disabled by an explicit
++     +noNAME specification, in addition to the features that are transitively
++     dependent on NAME (according to REQUIRES).  As with EXPLICIT_ON,
++     this is usually an empty list; comments below explain the exceptions.
++     If a feature A appears in this list then the list implicitly includes
++     any features that are transitively dependent on A (according to REQUIRES).
++
+    - FEAT_STRING is a string containing the entries in the 'Features' field of
+      /proc/cpuinfo on a GNU/Linux system that correspond to this architecture
+      extension being available.  Sometimes multiple entries are needed to enable
+@@ -47,197 +58,95 @@
+      that are required.  Their order is not important.  An empty string means
+      do not detect this feature during auto detection.
+ 
+-     NOTE: Any changes to the AARCH64_OPT_EXTENSION macro need to be mirrored in
+-     config.gcc.  */
+-
+-/* Enabling "fp" just enables "fp".
+-   Disabling "fp" also disables "simd", "crypto", "fp16", "aes", "sha2",
+-   "sha3", sm3/sm4, "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4",
+-   "sve2-bitperm", "i8mm", "f32mm", "f64mm", and "bf16".  */
+-AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | \
+-		      AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | \
+-		      AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | \
+-		      AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | \
+-		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | \
+-		      AARCH64_FL_SVE2_BITPERM | AARCH64_FL_I8MM | \
+-		      AARCH64_FL_F32MM | AARCH64_FL_F64MM | AARCH64_FL_BF16,
+-		       false, "fp")
+-
+-/* Enabling "simd" also enables "fp".
+-   Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2", "sha3",
+-   "sm3/sm4", "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4",
+-   "sve2-bitperm", "i8mm", "f32mm" and "f64mm".  */
+-AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, \
+-		      AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | \
+-		      AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
+-		      AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | \
+-		      AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
+-		      AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM | \
+-		      AARCH64_FL_I8MM | AARCH64_FL_F32MM | AARCH64_FL_F64MM, \
+-		      false, "asimd")
+-
+-/* Enabling or disabling "crc" only changes "crc".  */
+-AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
+-
+-/* Enabling or disabling "lse" only changes "lse".  */
+-AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics")
+-
+-/* Enabling "fp16" also enables "fp".
+-   Disabling "fp16" disables "fp16", "fp16fml", "sve", "sve2",
+-   "sve2-aes", "sve2-sha3", "sve2-sm4", "sve2-bitperm", "f32mm" and
+-    "f64mm".  */
+-AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, \
+-		      AARCH64_FL_F16FML | AARCH64_FL_SVE | AARCH64_FL_F32MM | \
+-		      AARCH64_FL_F64MM | AARCH64_FL_SVE2 | \
+-		      AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
+-		      AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, \
+-		      "fphp asimdhp")
+-
+-/* Enabling or disabling "rcpc" only changes "rcpc".  */
+-AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, false, "lrcpc")
+-
+-/* Enabling "rdma" also enables "fp", "simd".
+-   Disabling "rdma" just disables "rdma".  */
+-AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, \
+-		      AARCH64_FL_FP | AARCH64_FL_SIMD, 0, false, "asimdrdm")
+-
+-/* Enabling "dotprod" also enables "simd".
+-   Disabling "dotprod" only disables "dotprod".  */
+-AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_FPSIMD, 0, \
+-		      false, "asimddp")
+-
+-/* Enabling "aes" also enables "simd".
+-   Disabling "aes" disables "aes" and "sve2-aes'.  */
+-AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_FPSIMD, \
+-		      AARCH64_FL_SVE2_AES | AARCH64_FL_CRYPTO, false, "aes")
+-
+-/* Enabling "sha2" also enables "simd".
+-   Disabling "sha2" just disables "sha2".  */
+-AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_FPSIMD, \
+-		      AARCH64_FL_CRYPTO | AARCH64_FL_SHA3 | \
+-		      AARCH64_FL_SVE2_SHA3, false, "sha1 sha2")
+-
+-/* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
+-   Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4",
+-   "sve2-aes", "sve2-sha3", "sve2-sm4".  */
+-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | \
+-		      AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, \
+-		      AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | \
+-		      AARCH64_FL_SM4 | AARCH64_FL_SVE2_AES | \
+-		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4, true, \
++   The list of features must follow topological order wrt REQUIRES
++   and EXPLICIT_ON.  For example, if A is in B's REQUIRES list, A must
++   come before B.  This is enforced by aarch64-feature-deps.h.
++
++   NOTE: Any changes to the AARCH64_OPT_EXTENSION macro need to be mirrored in
++   config.gcc.  */
++
++AARCH64_OPT_EXTENSION("fp", FP, (), (), (), "fp")
++
++AARCH64_OPT_EXTENSION("simd", SIMD, (FP), (), (), "asimd")
++
++AARCH64_OPT_EXTENSION("crc", CRC, (), (), (), "crc32")
++
++AARCH64_OPT_EXTENSION("lse", LSE, (), (), (), "atomics")
++
++/* +nofp16 disables an implicit F16FML, even though an implicit F16FML
++   does not imply F16.  See F16FML for more details.  */
++AARCH64_OPT_EXTENSION("fp16", F16, (FP), (), (F16FML), "fphp asimdhp")
++
++AARCH64_OPT_EXTENSION("rcpc", RCPC, (), (), (), "lrcpc")
++
++/* An explicit +rdma implies +simd, but +rdma+nosimd still enables scalar
++   RDMA instructions.  */
++AARCH64_OPT_EXTENSION("rdma", RDMA, (), (SIMD), (), "asimdrdm")
++
++AARCH64_OPT_EXTENSION("dotprod", DOTPROD, (SIMD), (), (), "asimddp")
++
++AARCH64_OPT_EXTENSION("aes", AES, (SIMD), (), (), "aes")
++
++AARCH64_OPT_EXTENSION("sha2", SHA2, (SIMD), (), (), "sha1 sha2")
++
++/* +nocrypto disables AES, SHA2 and SM4, and anything that depends on them
++   (such as SHA3 and the SVE2 crypto extensions).  */
++AARCH64_OPT_EXTENSION("crypto", CRYPTO, (AES, SHA2), (), (AES, SHA2, SM4),
+ 		      "aes pmull sha1 sha2")
+ 
+-/* Enabling "sha3" enables "simd" and "sha2".
+-   Disabling "sha3" disables "sha3" and "sve2-sha3".  */
+-AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_FPSIMD | \
+-		      AARCH64_FL_SHA2, AARCH64_FL_SVE2_SHA3, false, \
+-		      "sha3 sha512")
+-
+-/* Enabling "sm4" also enables "simd".
+-   Disabling "sm4" disables "sm4" and "sve2-sm4".  */
+-AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_FPSIMD, \
+-		      AARCH64_FL_SVE2_SM4, false, "sm3 sm4")
+-
+-/* Enabling "fp16fml" also enables "fp" and "fp16".
+-   Disabling "fp16fml" just disables "fp16fml".  */
+-AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, \
+-		      AARCH64_FL_FP | AARCH64_FL_F16, 0, false, "asimdfhm")
+-
+-/* Enabling "sve" also enables "fp16", "fp" and "simd".
+-   Disabling "sve" disables "sve", "f32mm", "f64mm", "sve2", "sve2-aes",
+-   "sve2-sha3", "sve2-sm4" and "sve2-bitperm".  */
+-AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | \
+-		      AARCH64_FL_F16, AARCH64_FL_F32MM | AARCH64_FL_F64MM | \
+-		      AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | \
+-		      AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | \
+-		      AARCH64_FL_SVE2_BITPERM, false, "sve")
+-
+-/* Enabling/Disabling "profile" does not enable/disable any other feature.  */
+-AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, false, "")
+-
+-/* Enabling/Disabling "rng" only changes "rng".  */
+-AARCH64_OPT_EXTENSION("rng", AARCH64_FL_RNG, 0, 0, false, "rng")
+-
+-/* Enabling/Disabling "memtag" only changes "memtag".  */
+-AARCH64_OPT_EXTENSION("memtag", AARCH64_FL_MEMTAG, 0, 0, false, "")
+-
+-/* Enabling/Disabling "sb" only changes "sb".  */
+-AARCH64_OPT_EXTENSION("sb", AARCH64_FL_SB, 0, 0, false, "sb")
+-
+-/* Enabling/Disabling "ssbs" only changes "ssbs".  */
+-AARCH64_OPT_EXTENSION("ssbs", AARCH64_FL_SSBS, 0, 0, false, "ssbs")
+-
+-/* Enabling/Disabling "predres" only changes "predres".  */
+-AARCH64_OPT_EXTENSION("predres", AARCH64_FL_PREDRES, 0, 0, false, "")
+-
+-/* Enabling "sve2" also enables "sve", "fp16", "fp", and "simd".
+-   Disabling "sve2" disables "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and
+-   "sve2-bitperm".  */
+-AARCH64_OPT_EXTENSION("sve2", AARCH64_FL_SVE2, AARCH64_FL_SVE | \
+-		      AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, \
+-		      AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | \
+-		      AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "sve2")
+-
+-/* Enabling "sve2-sm4" also enables "sm4", "simd", "fp16", "fp", "sve", and
+-   "sve2". Disabling "sve2-sm4" just disables "sve2-sm4".  */
+-AARCH64_OPT_EXTENSION("sve2-sm4", AARCH64_FL_SVE2_SM4, AARCH64_FL_SM4 | \
+-		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+-		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "svesm4")
+-
+-/* Enabling "sve2-aes" also enables "aes", "simd", "fp16", "fp", "sve", and
+-   "sve2". Disabling "sve2-aes" just disables "sve2-aes".  */
+-AARCH64_OPT_EXTENSION("sve2-aes", AARCH64_FL_SVE2_AES, AARCH64_FL_AES | \
+-		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+-		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "sveaes")
+-
+-/* Enabling "sve2-sha3" also enables "sha3", "simd", "fp16", "fp", "sve", and
+-   "sve2". Disabling "sve2-sha3" just disables "sve2-sha3".  */
+-AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, AARCH64_FL_SHA3 | \
+-		      AARCH64_FL_SHA2 | \
+-		      AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | \
+-		      AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "svesha3")
+-
+-/* Enabling "sve2-bitperm" also enables "simd", "fp16", "fp", "sve", and
+-   "sve2".  Disabling "sve2-bitperm" just disables "sve2-bitperm".  */
+-AARCH64_OPT_EXTENSION("sve2-bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | \
+-		      AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | \
+-		      AARCH64_FL_SVE2, 0, false, "svebitperm")
+-
+-/* Enabling or disabling "tme" only changes "tme".  */
+-AARCH64_OPT_EXTENSION("tme", AARCH64_FL_TME, 0, 0, false, "")
+-
+-/* Enabling "i8mm" also enables "simd" and "fp".
+-   Disabling "i8mm" only disables "i8mm".  */
+-AARCH64_OPT_EXTENSION("i8mm", AARCH64_FL_I8MM, \
+-		      AARCH64_FL_SIMD | AARCH64_FL_FP, 0, false, "i8mm")
+-
+-/* Enabling "f32mm" also enables "sve", "fp16", "fp", and "simd".
+-   Disabling "f32mm" only disables "f32mm".  */
+-AARCH64_OPT_EXTENSION("f32mm", AARCH64_FL_F32MM, \
+-		      AARCH64_FL_SVE | AARCH64_FL_F16 | AARCH64_FL_FP | \
+-		      AARCH64_FL_SIMD, 0, false, "f32mm")
+-
+-/* Enabling "f64mm" also enables "sve", "fp16", "fp", and "simd".
+-   Disabling "f64mm" only disables "f64mm".  */
+-AARCH64_OPT_EXTENSION("f64mm", AARCH64_FL_F64MM, \
+-		      AARCH64_FL_SVE | AARCH64_FL_F16 | AARCH64_FL_FP | \
+-		      AARCH64_FL_SIMD, 0, false, "f64mm")
+-
+-/* Enabling "bf16" also enables "simd" and "fp".
+-   Disabling "bf16" only disables "bf16".  */
+-AARCH64_OPT_EXTENSION("bf16", AARCH64_FL_BF16, \
+-		      AARCH64_FL_SIMD | AARCH64_FL_FP, 0, false, "bf16")
+-
+-/* Enabling/Disabling "flagm" only changes "flagm".  */
+-AARCH64_OPT_EXTENSION("flagm", AARCH64_FL_FLAGM, 0, 0, false, "flagm")
+-
+-/* Enabling/Disabling "pauth" only changes "pauth".  */
+-AARCH64_OPT_EXTENSION("pauth", AARCH64_FL_PAUTH, 0, 0, false, "paca pacg")
+-
+-/* Enabling/Disabling "ls64" only changes "ls64".  */
+-AARCH64_OPT_EXTENSION("ls64", AARCH64_FL_LS64, 0, 0, false, "")
+-
+-/* Enabling/disabling "mops" only changes "mops".  */
+-AARCH64_OPT_EXTENSION("mops", AARCH64_FL_MOPS, 0, 0, false, "")
++AARCH64_OPT_EXTENSION("sha3", SHA3, (SHA2), (), (), "sha3 sha512")
++
++AARCH64_OPT_EXTENSION("sm4", SM4, (SIMD), (), (), "sm3 sm4")
++
++/* An explicit +fp16fml implies +fp16, but a dependence on it does not.
++   Thus -march=armv8.4-a implies F16FML but not F16.  -march=armv8.4-a+fp16
++   and -march=armv8.4-a+fp16fml are equivalent and enable both F16FML and F16.
++   -march=armv8.4-a+nofp16+fp16 enables F16 but not F16FML.  */
++AARCH64_OPT_EXTENSION("fp16fml", F16FML, (), (F16), (), "asimdfhm")
++
++AARCH64_OPT_EXTENSION("sve", SVE, (SIMD, F16), (), (), "sve")
++
++AARCH64_OPT_EXTENSION("profile", PROFILE, (), (), (), "")
++
++AARCH64_OPT_EXTENSION("rng", RNG, (), (), (), "rng")
++
++AARCH64_OPT_EXTENSION("memtag", MEMTAG, (), (), (), "")
++
++AARCH64_OPT_EXTENSION("sb", SB, (), (), (), "sb")
++
++AARCH64_OPT_EXTENSION("ssbs", SSBS, (), (), (), "ssbs")
++
++AARCH64_OPT_EXTENSION("predres", PREDRES, (), (), (), "")
++
++AARCH64_OPT_EXTENSION("sve2", SVE2, (SVE), (), (), "sve2")
++
++AARCH64_OPT_EXTENSION("sve2-sm4", SVE2_SM4, (SVE2, SM4), (), (), "svesm4")
++
++AARCH64_OPT_EXTENSION("sve2-aes", SVE2_AES, (SVE2, AES), (), (), "sveaes")
++
++AARCH64_OPT_EXTENSION("sve2-sha3", SVE2_SHA3, (SVE2, SHA3), (), (), "svesha3")
++
++AARCH64_OPT_EXTENSION("sve2-bitperm", SVE2_BITPERM, (SVE2), (), (),
++		      "svebitperm")
++
++AARCH64_OPT_EXTENSION("tme", TME, (), (), (), "")
++
++AARCH64_OPT_EXTENSION("i8mm", I8MM, (SIMD), (), (), "i8mm")
++
++AARCH64_OPT_EXTENSION("f32mm", F32MM, (SVE), (), (), "f32mm")
++
++AARCH64_OPT_EXTENSION("f64mm", F64MM, (SVE), (), (), "f64mm")
++
++/* An explicit +bf16 implies +simd, but +bf16+nosimd still enables scalar BF16
++   instructions.  */
++AARCH64_OPT_EXTENSION("bf16", BF16, (FP), (SIMD), (), "bf16")
++
++AARCH64_OPT_EXTENSION("flagm", FLAGM, (), (), (), "flagm")
++
++AARCH64_OPT_EXTENSION("pauth", PAUTH, (), (), (), "paca pacg")
++
++AARCH64_OPT_EXTENSION("ls64", LS64, (), (), (), "")
++
++AARCH64_OPT_EXTENSION("mops", MOPS, (), (), (), "")
+ 
+ #undef AARCH64_OPT_EXTENSION
+diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h
+index 421648a15..ba23c90c4 100644
+--- a/gcc/config/aarch64/aarch64-opts.h
++++ b/gcc/config/aarch64/aarch64-opts.h
+@@ -22,6 +22,10 @@
+ #ifndef GCC_AARCH64_OPTS_H
+ #define GCC_AARCH64_OPTS_H
+ 
++#ifndef USED_FOR_TARGET
++typedef uint64_t aarch64_feature_flags;
++#endif
++
+ /* The various cores that implement AArch64.  */
+ enum aarch64_processor
+ {
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 12d9beee4..c06e99339 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -701,9 +701,8 @@ check_required_extensions (location_t location, tree fndecl,
+     return check_required_registers (location, fndecl);
+ 
+   static const struct { uint64_t flag; const char *name; } extensions[] = {
+-#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+-			      SYNTHETIC, FEATURE_STRING) \
+-    { FLAG_CANONICAL, EXT_NAME },
++#define AARCH64_OPT_EXTENSION(EXT_NAME, IDENT, C, D, E, F) \
++    { AARCH64_FL_##IDENT, EXT_NAME },
+ #include "aarch64-option-extensions.def"
+   };
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index f975aad07..1363873b1 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -81,6 +81,7 @@
+ #include "rtlanal.h"
+ #include "tree-dfa.h"
+ #include "asan.h"
++#include "aarch64-feature-deps.h"
+ 
+ /* This file should be included last.  */
+ #include "target-def.h"
+@@ -2935,8 +2936,9 @@ struct processor
+ /* Architectures implementing AArch64.  */
+ static const struct processor all_architectures[] =
+ {
+-#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
+-  {NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, FLAGS, NULL},
++#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, D, E) \
++  {NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, \
++   feature_deps::ARCH_IDENT ().enable, NULL},
+ #include "aarch64-arches.def"
+   {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
+ };
+@@ -2944,12 +2946,12 @@ static const struct processor all_architectures[] =
+ /* Processor cores implementing AArch64.  */
+ static const struct processor all_cores[] =
+ {
+-#define AARCH64_CORE(NAME, IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
+-  {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH,				\
+-  AARCH64_FL_FOR_##ARCH | FLAGS, &COSTS##_tunings},
++#define AARCH64_CORE(NAME, IDENT, SCHED, ARCH, E, COSTS, G, H, I) \
++  {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH, \
++   feature_deps::cpu_##IDENT, &COSTS##_tunings},
+ #include "aarch64-cores.def"
+   {"generic", generic, cortexa53, AARCH64_ARCH_V8A,
+-    AARCH64_FL_FOR_V8A, &generic_tunings},
++   feature_deps::V8A ().enable, &generic_tunings},
+   {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
+ };
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index f4e0cd148..50a2ef444 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -144,149 +144,27 @@
+ 
+ #define PCC_BITFIELD_TYPE_MATTERS	1
+ 
+-/* Instruction tuning/selection flags.  */
+-
+-/* Bit values used to identify processor capabilities.  */
+-#define AARCH64_FL_SIMD       (1 << 0)	/* Has SIMD instructions.  */
+-#define AARCH64_FL_FP         (1 << 1)	/* Has FP.  */
+-#define AARCH64_FL_CRYPTO     (1 << 2)	/* Has crypto.  */
+-#define AARCH64_FL_CRC        (1 << 3)	/* Has CRC.  */
+-/* ARMv8.1-A architecture extensions.  */
+-#define AARCH64_FL_LSE	      (1 << 4)  /* Has Large System Extensions.  */
+-#define AARCH64_FL_RDMA       (1 << 5)  /* Has Round Double Multiply Add.  */
+-#define AARCH64_FL_V8_1A      (1 << 6)  /* Has ARMv8.1-A extensions.  */
+-/* Armv8-R.  */
+-#define AARCH64_FL_V8R        (1 << 7)  /* Armv8-R AArch64.  */
+-/* ARMv8.2-A architecture extensions.  */
+-#define AARCH64_FL_V8_2A      (1 << 8)  /* Has ARMv8.2-A features.  */
+-#define AARCH64_FL_F16	      (1 << 9)  /* Has ARMv8.2-A FP16 extensions.  */
+-#define AARCH64_FL_SVE        (1 << 10) /* Has Scalable Vector Extensions.  */
+-/* ARMv8.3-A architecture extensions.  */
+-#define AARCH64_FL_V8_3A      (1 << 11)  /* Has ARMv8.3-A features.  */
+-#define AARCH64_FL_RCPC       (1 << 12)  /* Has support for RCpc model.  */
+-#define AARCH64_FL_DOTPROD    (1 << 13)  /* Has ARMv8.2-A Dot Product ins.  */
+-/* New flags to split crypto into aes and sha2.  */
+-#define AARCH64_FL_AES	      (1 << 14)  /* Has Crypto AES.  */
+-#define AARCH64_FL_SHA2	      (1 << 15)  /* Has Crypto SHA2.  */
+-/* ARMv8.4-A architecture extensions.  */
+-#define AARCH64_FL_V8_4A      (1 << 16)  /* Has ARMv8.4-A features.  */
+-#define AARCH64_FL_SM4	      (1 << 17)  /* Has ARMv8.4-A SM3 and SM4.  */
+-#define AARCH64_FL_SHA3	      (1 << 18)  /* Has ARMv8.4-a SHA3 and SHA512.  */
+-#define AARCH64_FL_F16FML     (1 << 19)  /* Has ARMv8.4-a FP16 extensions.  */
+-
+-/* Statistical Profiling extensions.  */
+-#define AARCH64_FL_PROFILE    (1 << 21)
+-
+-/* ARMv8.5-A architecture extensions.  */
+-#define AARCH64_FL_V8_5A      (1 << 22)  /* Has ARMv8.5-A features.  */
+-#define AARCH64_FL_RNG	      (1 << 23)  /* ARMv8.5-A Random Number Insns.  */
+-#define AARCH64_FL_MEMTAG     (1 << 24)  /* ARMv8.5-A Memory Tagging
+-					    Extensions.  */
+-
+-/* Speculation Barrier instruction supported.  */
+-#define AARCH64_FL_SB	      (1 << 25)
+-
+-/* Speculative Store Bypass Safe instruction supported.  */
+-#define AARCH64_FL_SSBS	      (1 << 26)
+-
+-/* Execution and Data Prediction Restriction instructions supported.  */
+-#define AARCH64_FL_PREDRES    (1 << 27)
+-
+-/* SVE2 instruction supported.  */
+-#define AARCH64_FL_SVE2		(1 << 28)
+-#define AARCH64_FL_SVE2_AES	(1 << 29)
+-#define AARCH64_FL_SVE2_SM4	(1 << 30)
+-#define AARCH64_FL_SVE2_SHA3	(1ULL << 31)
+-#define AARCH64_FL_SVE2_BITPERM	(1ULL << 32)
+-
+-/* Transactional Memory Extension.  */
+-#define AARCH64_FL_TME	      (1ULL << 33)  /* Has TME instructions.  */
+-
+-/* Armv8.6-A architecture extensions.  */
+-#define AARCH64_FL_V8_6A      (1ULL << 34)
+-
+-/* 8-bit Integer Matrix Multiply (I8MM) extensions.  */
+-#define AARCH64_FL_I8MM	      (1ULL << 35)
+-
+-/* Brain half-precision floating-point (BFloat16) Extension.  */
+-#define AARCH64_FL_BF16	      (1ULL << 36)
+-
+-/* 32-bit Floating-point Matrix Multiply (F32MM) extensions.  */
+-#define AARCH64_FL_F32MM      (1ULL << 37)
+-
+-/* 64-bit Floating-point Matrix Multiply (F64MM) extensions.  */
+-#define AARCH64_FL_F64MM      (1ULL << 38)
+-
+-/* Flag Manipulation Instructions (FLAGM) extension.  */
+-#define AARCH64_FL_FLAGM      (1ULL << 39)
+-
+-/* Pointer Authentication (PAUTH) extension.  */
+-#define AARCH64_FL_PAUTH      (1ULL << 40)
+-
+-/* Armv9.0-A.  */
+-#define AARCH64_FL_V9A        (1ULL << 41)  /* Armv9.0-A Architecture.  */
+-
+-/* 64-byte atomic load/store extensions.  */
+-#define AARCH64_FL_LS64      (1ULL << 42)
+-
+-/* Armv8.7-a architecture extensions.  */
+-#define AARCH64_FL_V8_7A      (1ULL << 43)
+-
+-/* Hardware memory operation instructions.  */
+-#define AARCH64_FL_MOPS       (1ULL << 44)
+-
+-/* Armv8.8-a architecture extensions.  */
+-#define AARCH64_FL_V8_8A      (1ULL << 45)
+-
+-/* Armv9.1-A.  */
+-#define AARCH64_FL_V9_1A      (1ULL << 46)
+-
+-/* Armv9.2-A.  */
+-#define AARCH64_FL_V9_2A      (1ULL << 47)
+-
+-/* Armv9.3-A.  */
+-#define AARCH64_FL_V9_3A      (1ULL << 48)
+-
+-/* Has FP and SIMD.  */
+-#define AARCH64_FL_FPSIMD     (AARCH64_FL_FP | AARCH64_FL_SIMD)
+-
+-/* Has FP without SIMD.  */
+-#define AARCH64_FL_FPQ16      (AARCH64_FL_FP & ~AARCH64_FL_SIMD)
+-
+-/* Architecture flags that effect instruction selection.  */
+-#define AARCH64_FL_FOR_V8A       (AARCH64_FL_FPSIMD)
+-#define AARCH64_FL_FOR_V8_1A			       \
+-  (AARCH64_FL_FOR_V8A | AARCH64_FL_LSE | AARCH64_FL_CRC \
+-   | AARCH64_FL_RDMA | AARCH64_FL_V8_1A)
+-#define AARCH64_FL_FOR_V8_2A			\
+-  (AARCH64_FL_FOR_V8_1A | AARCH64_FL_V8_2A)
+-#define AARCH64_FL_FOR_V8_3A			\
+-  (AARCH64_FL_FOR_V8_2A | AARCH64_FL_V8_3A | AARCH64_FL_PAUTH)
+-#define AARCH64_FL_FOR_V8_4A			\
+-  (AARCH64_FL_FOR_V8_3A | AARCH64_FL_V8_4A | AARCH64_FL_F16FML \
+-   | AARCH64_FL_DOTPROD | AARCH64_FL_FLAGM)
+-#define AARCH64_FL_FOR_V8_5A			\
+-  (AARCH64_FL_FOR_V8_4A | AARCH64_FL_V8_5A	\
+-   | AARCH64_FL_SB | AARCH64_FL_SSBS | AARCH64_FL_PREDRES)
+-#define AARCH64_FL_FOR_V8_6A			\
+-  (AARCH64_FL_FOR_V8_5A | AARCH64_FL_V8_6A | AARCH64_FL_FPSIMD \
+-   | AARCH64_FL_I8MM | AARCH64_FL_BF16)
+-#define AARCH64_FL_FOR_V8_7A			\
+-  (AARCH64_FL_FOR_V8_6A | AARCH64_FL_V8_7A | AARCH64_FL_LS64)
+-#define AARCH64_FL_FOR_V8_8A			\
+-  (AARCH64_FL_FOR_V8_7A | AARCH64_FL_V8_8A | AARCH64_FL_MOPS)
+-
+-#define AARCH64_FL_FOR_V8R     \
+-  (AARCH64_FL_FOR_V8_4A | AARCH64_FL_V8R)
+-#define AARCH64_FL_FOR_V9A       \
+-  (AARCH64_FL_FOR_V8_5A | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_V9A \
+-   | AARCH64_FL_F16)
+-#define AARCH64_FL_FOR_V9_1A	\
+-  (AARCH64_FL_FOR_V9A | AARCH64_FL_FOR_V8_6A | AARCH64_FL_V9_1A)
+-#define AARCH64_FL_FOR_V9_2A	\
+-  (AARCH64_FL_FOR_V9_1A | AARCH64_FL_FOR_V8_7A | AARCH64_FL_V9_2A)
+-#define AARCH64_FL_FOR_V9_3A	\
+-  (AARCH64_FL_FOR_V9_2A | AARCH64_FL_FOR_V8_8A | AARCH64_FL_V9_3A)
++#ifndef USED_FOR_TARGET
++
++/* Define an enum of all features (architectures and extensions).  */
++enum class aarch64_feature : unsigned char {
++#define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) IDENT,
++#define AARCH64_ARCH(A, B, IDENT, D, E) IDENT,
++#include "aarch64-option-extensions.def"
++#include "aarch64-arches.def"
++};
++
++/* Define unique flags for each of the above.  */
++#define HANDLE(IDENT) \
++  constexpr auto AARCH64_FL_##IDENT \
++    = aarch64_feature_flags (1) << int (aarch64_feature::IDENT);
++#define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) HANDLE (IDENT)
++#define AARCH64_ARCH(A, B, IDENT, D, E) HANDLE (IDENT)
++#include "aarch64-option-extensions.def"
++#include "aarch64-arches.def"
++#undef HANDLE
++
++#endif
+ 
+ /* Macros to test ISA flags.  */
+ 
+diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
+index 97690de62..ddfc9451f 100644
+--- a/gcc/config/aarch64/driver-aarch64.cc
++++ b/gcc/config/aarch64/driver-aarch64.cc
+@@ -26,6 +26,7 @@
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "aarch64-protos.h"
++#include "aarch64-feature-deps.h"
+ 
+ struct aarch64_arch_extension
+ {
+@@ -34,9 +35,8 @@ struct aarch64_arch_extension
+   const char *feat_string;
+ };
+ 
+-#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+-			      SYNTHETIC, FEATURE_STRING) \
+-  { EXT_NAME, FLAG_CANONICAL, FEATURE_STRING },
++#define AARCH64_OPT_EXTENSION(EXT_NAME, IDENT, C, D, E, FEATURE_STRING) \
++  { EXT_NAME, AARCH64_FL_##IDENT, FEATURE_STRING },
+ static struct aarch64_arch_extension aarch64_extensions[] =
+ {
+ #include "aarch64-option-extensions.def"
+@@ -62,7 +62,7 @@ struct aarch64_core_data
+ #define DEFAULT_ARCH "8A"
+ 
+ #define AARCH64_CORE(CORE_NAME, CORE_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
+-  { CORE_NAME, #ARCH, IMP, PART, VARIANT, AARCH64_FL_FOR_##ARCH | FLAGS },
++  { CORE_NAME, #ARCH, IMP, PART, VARIANT, feature_deps::cpu_##CORE_IDENT },
+ 
+ static struct aarch64_core_data aarch64_cpu_data[] =
+ {
+@@ -80,7 +80,7 @@ struct aarch64_arch_driver_info
+ 
+ /* Skip the leading "V" in the architecture name.  */
+ #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
+-  { #ARCH_IDENT + 1, NAME, FLAGS },
++  { #ARCH_IDENT + 1, NAME, feature_deps::ARCH_IDENT ().enable },
+ 
+ static struct aarch64_arch_driver_info aarch64_arches[] =
+ {
+-- 
+2.33.0
+
diff --git a/0119-Backport-SME-aarch64-Simplify-generation-of-.arch-st.patch b/0119-Backport-SME-aarch64-Simplify-generation-of-.arch-st.patch
new file mode 100644
index 0000000..fb3f7a8
--- /dev/null
+++ b/0119-Backport-SME-aarch64-Simplify-generation-of-.arch-st.patch
@@ -0,0 +1,467 @@
+From e7ebc54e809e8647ff054a02fbaf946b41414004 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:55 +0100
+Subject: [PATCH 020/157] [Backport][SME] aarch64: Simplify generation of .arch
+ strings
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=4ebf56f283ae5a98ae4c43079b7e8459945ef18d
+
+aarch64-common.cc has two arrays, one maintaining the original
+definition order and one sorted by population count.  Sorting
+by population count was a way of ensuring topological ordering,
+taking advantage of the fact that the entries are partially
+ordered by the subset relation.  However, the sorting is not
+needed now that the .def file is forced to have topological
+order from the outset.
+
+Other changes are:
+
+(1) The population count used:
+
+      uint64_t total_flags_a = opt_a->flag_canonical & opt_a->flags_on;
+      uint64_t total_flags_b = opt_b->flag_canonical & opt_b->flags_on;
+      int popcnt_a = popcount_hwi ((HOST_WIDE_INT)total_flags_a);
+      int popcnt_b = popcount_hwi ((HOST_WIDE_INT)total_flags_b);
+
+    where I think the & was supposed to be |.  This meant that the
+    counts would always be 1 in practice, since flag_canonical is
+    a single bit.  This led us to printing +nofp+nosimd even though
+    GCC "knows" (and GAS agrees) that +nofp disables simd.
+
+(2) The .arch output code converts +aes+sha2 to +crypto.  I think
+    the main reason for doing this is to support assemblers that
+    predate the individual per-feature crypto flags.  It therefore
+    seems more natural to treat it as a special case, rather than
+    as an instance of a general pattern.  Hopefully we won't do
+    something similar in future!
+
+    (There is already special handling of CRC, for different reasons.)
+
+(3) Previously, if the /proc/cpuinfo code saw a feature like sve,
+    it would assume the presence of all the features that sve
+    depends on.  It would be possible to keep that behaviour
+    if necessary, but it was simpler to assume the presence of
+    fp16 (say) only when fphp is present.  There's an argument
+    that that's more conservatively correct too.
+
+gcc/
+	* common/config/aarch64/aarch64-common.cc
+	(TARGET_OPTION_INIT_STRUCT): Delete.
+	(aarch64_option_extension): Remove is_synthetic_flag.
+	(all_extensions): Update accordingly.
+	(all_extensions_by_on, opt_ext, opt_ext_cmp): Delete.
+	(aarch64_option_init_struct, aarch64_contains_opt): Delete.
+	(aarch64_get_extension_string_for_isa_flags): Rewrite to use
+	all_extensions instead of all_extensions_on.
+
+gcc/testsuite/
+	* gcc.target/aarch64/cpunative/info_8: Add all dependencies of sve.
+	* gcc.target/aarch64/cpunative/info_9: Likewise svesm4.
+	* gcc.target/aarch64/cpunative/info_15: Likewise.
+	* gcc.target/aarch64/cpunative/info_16: Likewise sve2.
+	* gcc.target/aarch64/cpunative/info_17: Likewise.
+	* gcc.target/aarch64/cpunative/native_cpu_2.c: Expect just +nofp
+	rather than +nofp+nosimd.
+	* gcc.target/aarch64/cpunative/native_cpu_10.c: Likewise.
+	* gcc.target/aarch64/target_attr_15.c: Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc   | 244 ++++--------------
+ .../gcc.target/aarch64/cpunative/info_15      |   2 +-
+ .../gcc.target/aarch64/cpunative/info_16      |   2 +-
+ .../gcc.target/aarch64/cpunative/info_17      |   2 +-
+ .../gcc.target/aarch64/cpunative/info_8       |   2 +-
+ .../gcc.target/aarch64/cpunative/info_9       |   2 +-
+ .../aarch64/cpunative/native_cpu_10.c         |   2 +-
+ .../aarch64/cpunative/native_cpu_2.c          |   2 +-
+ .../gcc.target/aarch64/target_attr_15.c       |   2 +-
+ 9 files changed, 55 insertions(+), 205 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 74729bb30..057dc094d 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -42,8 +42,6 @@
+ 
+ #undef	TARGET_OPTION_OPTIMIZATION_TABLE
+ #define TARGET_OPTION_OPTIMIZATION_TABLE aarch_option_optimization_table
+-#undef TARGET_OPTION_INIT_STRUCT
+-#define TARGET_OPTION_INIT_STRUCT aarch64_option_init_struct
+ 
+ #define INVALID_IMP ((unsigned) -1)
+ 
+@@ -209,7 +207,6 @@ struct aarch64_option_extension
+   const uint64_t flag_canonical;
+   const uint64_t flags_on;
+   const uint64_t flags_off;
+-  const bool is_synthetic;
+ };
+ 
+ /* ISA extensions in AArch64.  */
+@@ -219,24 +216,9 @@ static const struct aarch64_option_extension all_extensions[] =
+   {NAME, AARCH64_FL_##IDENT, \
+    feature_deps::IDENT ().explicit_on & ~AARCH64_FL_##IDENT, \
+    feature_deps::get_flags_off (feature_deps::root_off_##IDENT) \
+-   & ~AARCH64_FL_##IDENT, \
+-   AARCH64_FL_##IDENT == AARCH64_FL_CRYPTO},
++   & ~AARCH64_FL_##IDENT},
+ #include "config/aarch64/aarch64-option-extensions.def"
+-  {NULL, 0, 0, 0, false}
+-};
+-
+-/* A copy of the ISA extensions list for AArch64 sorted by the popcount of
+-   bits and extension turned on.  Cached for efficiency.  */
+-static struct aarch64_option_extension all_extensions_by_on[] =
+-{
+-#define AARCH64_OPT_EXTENSION(NAME, IDENT, C, D, E, F) \
+-  {NAME, AARCH64_FL_##IDENT, \
+-   feature_deps::IDENT ().explicit_on & ~AARCH64_FL_##IDENT, \
+-   feature_deps::get_flags_off (feature_deps::root_off_##IDENT) \
+-   & ~AARCH64_FL_##IDENT, \
+-   AARCH64_FL_##IDENT == AARCH64_FL_CRYPTO},
+-#include "config/aarch64/aarch64-option-extensions.def"
+-  {NULL, 0, 0, 0, false}
++  {NULL, 0, 0, 0}
+ };
+ 
+ struct processor_name_to_arch
+@@ -353,79 +335,6 @@ aarch64_get_all_extension_candidates (auto_vec *candidates)
+     candidates->safe_push (opt->name);
+ }
+ 
+-/* Comparer to sort aarch64's feature extensions by population count. Largest
+-   first.  */
+-
+-typedef const struct aarch64_option_extension opt_ext;
+-
+-int opt_ext_cmp (const void* a, const void* b)
+-{
+-  opt_ext *opt_a = (opt_ext *)a;
+-  opt_ext *opt_b = (opt_ext *)b;
+-
+-  /* We consider the total set of bits an options turns on to be the union of
+-     the singleton set containing the option itself and the set of options it
+-     turns on as a dependency.  As an example +dotprod turns on FL_DOTPROD and
+-     FL_SIMD.  As such the set of bits represented by this option is
+-     {FL_DOTPROD, FL_SIMD}. */
+-  uint64_t total_flags_a = opt_a->flag_canonical & opt_a->flags_on;
+-  uint64_t total_flags_b = opt_b->flag_canonical & opt_b->flags_on;
+-  int popcnt_a = popcount_hwi ((HOST_WIDE_INT)total_flags_a);
+-  int popcnt_b = popcount_hwi ((HOST_WIDE_INT)total_flags_b);
+-  int order = popcnt_b - popcnt_a;
+-
+-  /* If they have the same amount of bits set, give it a more
+-     deterministic ordering by using the value of the bits themselves.  */
+-  if (order != 0)
+-    return order;
+-
+-  if (total_flags_a != total_flags_b)
+-    return total_flags_a < total_flags_b ? 1 : -1;
+-
+-  return 0;
+-}
+-
+-/* Implement TARGET_OPTION_INIT_STRUCT.  */
+-
+-static void
+-aarch64_option_init_struct (struct gcc_options *opts ATTRIBUTE_UNUSED)
+-{
+-    /* Sort the extensions based on how many bits they set, order the larger
+-       counts first.  We sort the list because this makes processing the
+-       feature bits O(n) instead of O(n^2).  While n is small, the function
+-       to calculate the feature strings is called on every options push,
+-       pop and attribute change (arm_neon headers, lto etc all cause this to
+-       happen quite frequently).  It is a trade-off between time and space and
+-       so time won.  */
+-    int n_extensions
+-      = sizeof (all_extensions) / sizeof (struct aarch64_option_extension);
+-    qsort (&all_extensions_by_on, n_extensions,
+-	   sizeof (struct aarch64_option_extension), opt_ext_cmp);
+-}
+-
+-/* Checks to see if enough bits from the option OPT are enabled in
+-   ISA_FLAG_BITS to be able to replace the individual options with the
+-   canonicalized version of the option.  This is done based on two rules:
+-
+-   1) Synthetic groups, such as +crypto we only care about the bits that are
+-      turned on. e.g. +aes+sha2 can be replaced with +crypto.
+-
+-   2) Options that themselves have a bit, such as +rdma, in this case, all the
+-      feature bits they turn on must be available and the bit for the option
+-      itself must be.  In this case it's effectively a reduction rather than a
+-      grouping. e.g. +fp+simd is not enough to turn on +rdma, for that you would
+-      need +rdma+fp+simd which is reduced down to +rdma.
+-*/
+-
+-static bool
+-aarch64_contains_opt (uint64_t isa_flag_bits, opt_ext *opt)
+-{
+-  uint64_t flags_check
+-    = opt->is_synthetic ? opt->flags_on : opt->flag_canonical;
+-
+-  return (isa_flag_bits & flags_check) == flags_check;
+-}
+-
+ /* Return a string representation of ISA_FLAGS.  DEFAULT_ARCH_FLAGS
+    gives the default set of flags which are implied by whatever -march
+    we'd put out.  Our job is to figure out the minimal set of "+" and
+@@ -436,118 +345,59 @@ std::string
+ aarch64_get_extension_string_for_isa_flags (uint64_t isa_flags,
+ 					    uint64_t default_arch_flags)
+ {
+-  const struct aarch64_option_extension *opt = NULL;
+   std::string outstr = "";
+ 
+-  uint64_t isa_flag_bits = isa_flags;
+-
+-  /* Pass one: Minimize the search space by reducing the set of options
+-     to the smallest set that still turns on the same features as before in
+-     conjunction with the bits that are turned on by default for the selected
+-     architecture.  */
+-  for (opt = all_extensions_by_on; opt->name != NULL; opt++)
++  aarch64_feature_flags current_flags = default_arch_flags;
++
++  /* As a special case, do not assume that the assembler will enable CRC
++     even if it is the default for the architecture.  This is required
++     because some CPUs had an incorrect specification in older assemblers:
++     even though CRC should be the default for these cases the -mcpu
++     values would not turn it on.
++
++     However, assemblers with Armv8-R AArch64 support should not have this
++     issue, so we don't need this fix when targeting Armv8-R.  */
++  auto explicit_flags = (!(current_flags & AARCH64_FL_V8R)
++			 ? AARCH64_FL_CRC : 0);
++
++  /* Add the features in isa_flags & ~current_flags using the smallest
++     possible number of extensions.  We can do this by iterating over the
++     array in reverse order, since the array is sorted topologically.
++     But in order to make the output more readable, it seems better
++     to add the strings in definition order.  */
++  aarch64_feature_flags added = 0;
++  for (unsigned int i = ARRAY_SIZE (all_extensions); i-- > 0; )
+     {
+-      /* If the bit is on by default, then all the options it turns on are also
+-	 on by default due to the transitive dependencies.
+-
+-         If the option is enabled explicitly in the set then we need to emit
+-	 an option for it.  Since this list is sorted by extensions setting the
+-	 largest number of featers first, we can be sure that nothing else will
+-	 ever need to set the bits we already set.  Consider the following
+-	 situation:
+-
+-	  Feat1 = A + B + C
+-	  Feat2 = A + B
+-	  Feat3 = A + D
+-	  Feat4 = B + C
+-	  Feat5 = C
+-
+-	The following results are expected:
+-
+-	  A + C = A + Feat5
+-	  B + C = Feat4
+-	  Feat4 + A = Feat1
+-	  Feat2 + Feat5 = Feat1
+-	  Feat1 + C = Feat1
+-          Feat3 + Feat4 = Feat1 + D
+-
+-	This search assumes that all invidual feature bits are use visible,
+-	in other words the user must be able to do +A, +B, +C and +D.  */
+-      if (aarch64_contains_opt (isa_flag_bits | default_arch_flags, opt))
+-      {
+-	/* We remove all the dependent bits, to prevent them from being turned
+-	   on twice.  This only works because we assume that all there are
+-	   individual options to set all bits standalone.  */
+-
+-	/* PR target/94396.
+-
+-	   For flags which would already imply a bit that's on by default (e.g
+-	   fp16fml which implies +fp,+fp16) we must emit the flags that are not
+-	   on by default.  i.e. in Armv8.4-a +fp16fml is default if +fp16.  So
+-	   if a user passes armv8.4-a+fp16 (or +fp16fml) then we need to emit
+-	   +fp16.  But if +fp16fml is used in an architecture where it is
+-	   completely optional we only have to emit the canonical flag.  */
+-	uint64_t toggle_bits = opt->flags_on & default_arch_flags;
+-	/* Now check to see if the canonical flag is on by default.  If it
+-	   is not then enabling it will enable all bits in flags_on.  */
+-	if ((opt->flag_canonical & default_arch_flags) == 0)
+-	  toggle_bits = opt->flags_on;
+-
+-	isa_flag_bits &= ~toggle_bits;
+-	isa_flag_bits |= opt->flag_canonical;
+-      }
+-    }
++      auto &opt = all_extensions[i];
+ 
+-   /* By toggling bits on and off, we may have set bits on that are already
+-      enabled by default.  So we mask the default set out so we don't emit an
+-      option for them.  Instead of checking for this each time during Pass One
+-      we just mask all default bits away at the end.  */
+-   isa_flag_bits &= ~default_arch_flags;
+-
+-   /* We now have the smallest set of features we need to process.  A subsequent
+-      linear scan of the bits in isa_flag_bits will allow us to print the ext
+-      names.  However as a special case if CRC was enabled before, always print
+-      it.  This is required because some CPUs have an incorrect specification
+-      in older assemblers.  Even though CRC should be the default for these
+-      cases the -mcpu values won't turn it on.
+-
+-      Note that assemblers with Armv8-R AArch64 support should not have this
+-      issue, so we don't need this fix when targeting Armv8-R.  */
+-  if ((isa_flags & AARCH64_ISA_CRC) && !AARCH64_ISA_V8R)
+-    isa_flag_bits |= AARCH64_ISA_CRC;
+-
+-  /* Pass Two:
+-     Print the option names that we're sure we must turn on.  These are only
+-     optional extension names.  Mandatory ones have already been removed and
+-     ones we explicitly want off have been too.  */
+-  for (opt = all_extensions_by_on; opt->name != NULL; opt++)
+-    {
+-      if (isa_flag_bits & opt->flag_canonical)
+-	{
+-	  outstr += "+";
+-	  outstr += opt->name;
+-	}
+-    }
++      /* As a special case, emit +crypto rather than +aes+sha2,
++	 in order to support assemblers that predate the separate
++	 per-feature crypto flags.  */
++      auto flags = opt.flag_canonical;
++      if (flags == AARCH64_FL_CRYPTO)
++	flags = AARCH64_FL_AES | AARCH64_FL_SHA2;
+ 
+-  /* Pass Three:
+-     Print out a +no for any mandatory extension that we are
+-     turning off.  By this point aarch64_parse_extension would have ensured
+-     that any optional extensions are turned off.  The only things left are
+-     things that can't be turned off usually, e.g. something that is on by
+-     default because it's mandatory and we want it off.  For turning off bits
+-     we don't guarantee the smallest set of flags, but instead just emit all
+-     options the user has specified.
+-
+-     The assembler requires all + to be printed before +no.  */
+-  for (opt = all_extensions_by_on; opt->name != NULL; opt++)
+-    {
+-      if ((~isa_flags) & opt->flag_canonical
+-		&& !((~default_arch_flags) & opt->flag_canonical))
++      if ((flags & isa_flags & (explicit_flags | ~current_flags)) == flags)
+ 	{
+-	  outstr += "+no";
+-	  outstr += opt->name;
++	  current_flags |= opt.flag_canonical | opt.flags_on;
++	  added |= opt.flag_canonical;
+ 	}
+     }
++  for (auto &opt : all_extensions)
++    if (added & opt.flag_canonical)
++      {
++	outstr += "+";
++	outstr += opt.name;
++      }
++
++  /* Remove the features in current_flags & ~isa_flags.  */
++  for (auto &opt : all_extensions)
++    if (opt.flag_canonical & current_flags & ~isa_flags)
++      {
++	current_flags &= ~(opt.flag_canonical | opt.flags_off);
++	outstr += "+no";
++	outstr += opt.name;
++      }
+ 
+   return outstr;
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_15 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_15
+index bc6453945..6b425ea20 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/info_15
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_15
+@@ -1,6 +1,6 @@
+ processor	: 0
+ BogoMIPS	: 100.00
+-Features	: Lorem ipsum dolor sit ametd rebum expetendis per at Dolor lucilius referrentur ei mei virtute eruditi eum ne Iisque verter svesm4 asimd fp
++Features	: Lorem ipsum dolor sit ametd rebum expetendis per at Dolor lucilius referrentur ei mei virtute eruditi eum ne Iisque verter svesm4 asimd fp sve sve2 fphp asimdhp sm3 sm4
+ CPU implementer	: 0x41
+ CPU architecture: 8
+ CPU variant	: 0x0
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_16 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_16
+index 2c04ff19c..26f01c496 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/info_16
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_16
+@@ -1,6 +1,6 @@
+ processor	: 0
+ BogoMIPS	: 100.00
+-Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 asimddp sve sve2
++Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 asimddp sve sve2 fphp asimdhp
+ CPU implementer	: 0xfe
+ CPU architecture: 8
+ CPU variant	: 0x0
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_17 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_17
+index 2c04ff19c..26f01c496 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/info_17
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_17
+@@ -1,6 +1,6 @@
+ processor	: 0
+ BogoMIPS	: 100.00
+-Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 asimddp sve sve2
++Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 asimddp sve sve2 fphp asimdhp
+ CPU implementer	: 0xfe
+ CPU architecture: 8
+ CPU variant	: 0x0
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_8 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_8
+index d6d9d03a2..76da16c57 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/info_8
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_8
+@@ -1,6 +1,6 @@
+ processor	: 0
+ BogoMIPS	: 100.00
+-Features	: asimd sve fp
++Features	: asimd sve fp fphp asimdhp
+ CPU implementer	: 0x41
+ CPU architecture: 8
+ CPU variant	: 0x0
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/info_9 b/gcc/testsuite/gcc.target/aarch64/cpunative/info_9
+index c9aa4a9a0..14703dd1d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/info_9
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/info_9
+@@ -1,6 +1,6 @@
+ processor	: 0
+ BogoMIPS	: 100.00
+-Features	: asimd fp svesm4
++Features	: asimd fp svesm4 sve sve2 fphp asimdhp sm3 sm4
+ CPU implementer	: 0x41
+ CPU architecture: 8
+ CPU variant	: 0x0
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_10.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_10.c
+index 6a753965c..ddb06b822 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_10.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_10.c
+@@ -7,6 +7,6 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+nofp\+nosimd} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+nofp} } } */
+ 
+ /* Test one with no entry in feature list.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_2.c b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_2.c
+index aad71f434..edbdb5626 100644
+--- a/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/cpunative/native_cpu_2.c
+@@ -7,6 +7,6 @@ int main()
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler {\.arch armv8-a\+nofp\+nosimd} } } */
++/* { dg-final { scan-assembler {\.arch armv8-a\+nofp} } } */
+ 
+ /* Test one where asimd is provided byt no fp.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
+index 108b372e4..069a00108 100644
+--- a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
++++ b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c
+@@ -10,4 +10,4 @@ foo (int a)
+   return a + 1;
+ }
+ 
+-/* { dg-final { scan-assembler-times "\\.arch armv8-a\\+nofp\\+nosimd\n" 1 } } */
++/* { dg-final { scan-assembler-times "\\.arch armv8-a\\+nofp\n" 1 } } */
+-- 
+2.33.0
+
diff --git a/0120-Backport-SME-aarch64-Avoid-std-string-in-static-data.patch b/0120-Backport-SME-aarch64-Avoid-std-string-in-static-data.patch
new file mode 100644
index 0000000..619342b
--- /dev/null
+++ b/0120-Backport-SME-aarch64-Avoid-std-string-in-static-data.patch
@@ -0,0 +1,43 @@
+From 7096be1673a10da5218a8620fb40b4b26e61c1d4 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:55 +0100
+Subject: [PATCH 021/157] [Backport][SME] aarch64: Avoid std::string in static
+ data
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=13af9e9fda391f4f0566ad8f0b4d0448a7e984d0
+
+Just a minor patch to avoid having to construct std::strings
+in static data.
+
+gcc/
+	* common/config/aarch64/aarch64-common.cc (processor_name_to_arch)
+	(arch_to_arch_name): Use const char * instead of std::string.
+---
+ gcc/common/config/aarch64/aarch64-common.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 057dc094d..2bdf51b8b 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -223,7 +223,7 @@ static const struct aarch64_option_extension all_extensions[] =
+ 
+ struct processor_name_to_arch
+ {
+-  const std::string processor_name;
++  const char *const processor_name;
+   const enum aarch64_arch arch;
+   const uint64_t flags;
+ };
+@@ -231,7 +231,7 @@ struct processor_name_to_arch
+ struct arch_to_arch_name
+ {
+   const enum aarch64_arch arch;
+-  const std::string arch_name;
++  const char *const arch_name;
+   const uint64_t flags;
+ };
+ 
+-- 
+2.33.0
+
diff --git a/0121-Backport-SME-aarch64-Tweak-constness-of-option-relat.patch b/0121-Backport-SME-aarch64-Tweak-constness-of-option-relat.patch
new file mode 100644
index 0000000..4ababc2
--- /dev/null
+++ b/0121-Backport-SME-aarch64-Tweak-constness-of-option-relat.patch
@@ -0,0 +1,195 @@
+From 99c5eb58e898417632b6d9a7b2b3d288b50e9b65 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:55 +0100
+Subject: [PATCH 022/157] [Backport][SME] aarch64: Tweak constness of
+ option-related data
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=60dee638c8a7ae59c033868de7e7638c88b38ed2
+
+Some of the option structures have all-const member variables.
+That doesn't seem necessary: we can just use const on the objects
+that are supposed to be read-only.
+
+Also, with the new, more C++-heavy option handling, it seems
+better to use constexpr for the static data, to make sure that
+we're not adding unexpected overhead.
+
+gcc/
+	* common/config/aarch64/aarch64-common.cc (aarch64_option_extension)
+	(processor_name_to_arch, arch_to_arch_name): Remove const from
+	member variables.
+	(all_extensions, all_cores, all_architectures): Make a constexpr.
+	* config/aarch64/aarch64.cc (processor): Remove const from
+	member variables.
+	(all_architectures): Make a constexpr.
+	* config/aarch64/driver-aarch64.cc (aarch64_core_data)
+	(aarch64_arch_driver_info): Remove const from member variables.
+	(aarch64_cpu_data, aarch64_arches): Make a constexpr.
+	(get_arch_from_id): Return a pointer to const.
+	(host_detect_local_cpu): Update accordingly.
+---
+ gcc/common/config/aarch64/aarch64-common.cc | 26 ++++++++++-----------
+ gcc/config/aarch64/aarch64.cc               | 14 +++++------
+ gcc/config/aarch64/driver-aarch64.cc        | 15 ++++++------
+ 3 files changed, 27 insertions(+), 28 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 2bdf51b8b..ac3486d71 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -203,14 +203,14 @@ aarch64_handle_option (struct gcc_options *opts,
+ /* An ISA extension in the co-processor and main instruction set space.  */
+ struct aarch64_option_extension
+ {
+-  const char *const name;
+-  const uint64_t flag_canonical;
+-  const uint64_t flags_on;
+-  const uint64_t flags_off;
++  const char *name;
++  uint64_t flag_canonical;
++  uint64_t flags_on;
++  uint64_t flags_off;
+ };
+ 
+ /* ISA extensions in AArch64.  */
+-static const struct aarch64_option_extension all_extensions[] =
++static constexpr aarch64_option_extension all_extensions[] =
+ {
+ #define AARCH64_OPT_EXTENSION(NAME, IDENT, C, D, E, F) \
+   {NAME, AARCH64_FL_##IDENT, \
+@@ -223,21 +223,21 @@ static const struct aarch64_option_extension all_extensions[] =
+ 
+ struct processor_name_to_arch
+ {
+-  const char *const processor_name;
+-  const enum aarch64_arch arch;
+-  const uint64_t flags;
++  const char *processor_name;
++  aarch64_arch arch;
++  uint64_t flags;
+ };
+ 
+ struct arch_to_arch_name
+ {
+-  const enum aarch64_arch arch;
+-  const char *const arch_name;
+-  const uint64_t flags;
++  aarch64_arch arch;
++  const char *arch_name;
++  uint64_t flags;
+ };
+ 
+ /* Map processor names to the architecture revision they implement and
+    the default set of architectural feature flags they support.  */
+-static const struct processor_name_to_arch all_cores[] =
++static constexpr processor_name_to_arch all_cores[] =
+ {
+ #define AARCH64_CORE(NAME, CORE_IDENT, C, ARCH_IDENT, E, F, G, H, I) \
+   {NAME, AARCH64_ARCH_##ARCH_IDENT, feature_deps::cpu_##CORE_IDENT},
+@@ -247,7 +247,7 @@ static const struct processor_name_to_arch all_cores[] =
+ };
+ 
+ /* Map architecture revisions to their string representation.  */
+-static const struct arch_to_arch_name all_architectures[] =
++static constexpr arch_to_arch_name all_architectures[] =
+ {
+ #define AARCH64_ARCH(NAME, B, ARCH_IDENT, D, E)	\
+   {AARCH64_ARCH_##ARCH_IDENT, NAME, feature_deps::ARCH_IDENT ().enable},
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 1363873b1..71db7ace1 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2925,16 +2925,16 @@ aarch64_tuning_override_functions[] =
+ /* A processor implementing AArch64.  */
+ struct processor
+ {
+-  const char *const name;
+-  enum aarch64_processor ident;
+-  enum aarch64_processor sched_core;
+-  enum aarch64_arch arch;
+-  const uint64_t flags;
+-  const struct tune_params *const tune;
++  const char *name;
++  aarch64_processor ident;
++  aarch64_processor sched_core;
++  aarch64_arch arch;
++  uint64_t flags;
++  const tune_params *tune;
+ };
+ 
+ /* Architectures implementing AArch64.  */
+-static const struct processor all_architectures[] =
++static constexpr processor all_architectures[] =
+ {
+ #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, D, E) \
+   {NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, \
+diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
+index ddfc9451f..ee9cb65a5 100644
+--- a/gcc/config/aarch64/driver-aarch64.cc
++++ b/gcc/config/aarch64/driver-aarch64.cc
+@@ -50,7 +50,7 @@ struct aarch64_core_data
+   unsigned char implementer_id; /* Exactly 8 bits */
+   unsigned int part_no; /* 12 bits + 12 bits */
+   unsigned variant;
+-  const uint64_t flags;
++  uint64_t flags;
+ };
+ 
+ #define AARCH64_BIG_LITTLE(BIG, LITTLE) \
+@@ -64,7 +64,7 @@ struct aarch64_core_data
+ #define AARCH64_CORE(CORE_NAME, CORE_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \
+   { CORE_NAME, #ARCH, IMP, PART, VARIANT, feature_deps::cpu_##CORE_IDENT },
+ 
+-static struct aarch64_core_data aarch64_cpu_data[] =
++static constexpr aarch64_core_data aarch64_cpu_data[] =
+ {
+ #include "aarch64-cores.def"
+   { NULL, NULL, INVALID_IMP, INVALID_CORE, ALL_VARIANTS, 0 }
+@@ -75,14 +75,14 @@ struct aarch64_arch_driver_info
+ {
+   const char* id;
+   const char* name;
+-  const uint64_t flags;
++  uint64_t flags;
+ };
+ 
+ /* Skip the leading "V" in the architecture name.  */
+ #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
+   { #ARCH_IDENT + 1, NAME, feature_deps::ARCH_IDENT ().enable },
+ 
+-static struct aarch64_arch_driver_info aarch64_arches[] =
++static constexpr aarch64_arch_driver_info aarch64_arches[] =
+ {
+ #include "aarch64-arches.def"
+   {NULL, NULL, 0}
+@@ -92,7 +92,7 @@ static struct aarch64_arch_driver_info aarch64_arches[] =
+ /* Return an aarch64_arch_driver_info for the architecture described
+    by ID, or NULL if ID describes something we don't know about.  */
+ 
+-static struct aarch64_arch_driver_info*
++static const aarch64_arch_driver_info *
+ get_arch_from_id (const char* id)
+ {
+   unsigned int i = 0;
+@@ -396,8 +396,7 @@ host_detect_local_cpu (int argc, const char **argv)
+ 
+       if (aarch64_cpu_data[i].name == NULL)
+ 	{
+-	  aarch64_arch_driver_info* arch_info
+-	    = get_arch_from_id (DEFAULT_ARCH);
++	  auto arch_info = get_arch_from_id (DEFAULT_ARCH);
+ 
+ 	  gcc_assert (arch_info);
+ 
+@@ -407,7 +406,7 @@ host_detect_local_cpu (int argc, const char **argv)
+       else if (arch)
+ 	{
+ 	  const char *arch_id = aarch64_cpu_data[i].arch;
+-	  aarch64_arch_driver_info* arch_info = get_arch_from_id (arch_id);
++	  auto arch_info = get_arch_from_id (arch_id);
+ 
+ 	  /* We got some arch indentifier that's not in aarch64-arches.def?  */
+ 	  if (!arch_info)
+-- 
+2.33.0
+
diff --git a/0122-Backport-SME-aarch64-Make-more-use-of-aarch64_featur.patch b/0122-Backport-SME-aarch64-Make-more-use-of-aarch64_featur.patch
new file mode 100644
index 0000000..31f8b7a
--- /dev/null
+++ b/0122-Backport-SME-aarch64-Make-more-use-of-aarch64_featur.patch
@@ -0,0 +1,394 @@
+From bdb91009cf250fb22c21ae7f5072263492f2b08c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:56 +0100
+Subject: [PATCH 023/157] [Backport][SME] aarch64: Make more use of
+ aarch64_feature_flags
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=fed55a60e5b230bc159617f26e33611073c672fd
+
+A previous patch added a aarch64_feature_flags typedef, to abstract
+the representation of the feature flags.  This patch makes existing
+code use the typedef too.  Hope I've caught them all!
+
+gcc/
+	* common/config/aarch64/aarch64-common.cc: Use aarch64_feature_flags
+	for feature flags throughout.
+	* config/aarch64/aarch64-protos.h: Likewise.
+	* config/aarch64/aarch64-sve-builtins.h: Likewise.
+	* config/aarch64/aarch64-sve-builtins.cc: Likewise.
+	* config/aarch64/aarch64.cc: Likewise.
+	* config/aarch64/aarch64.opt: Likewise.
+	* config/aarch64/driver-aarch64.cc: Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc | 19 +++++++-------
+ gcc/config/aarch64/aarch64-protos.h         |  5 ++--
+ gcc/config/aarch64/aarch64-sve-builtins.cc  | 29 ++++++++++++---------
+ gcc/config/aarch64/aarch64-sve-builtins.h   |  9 ++++---
+ gcc/config/aarch64/aarch64.cc               | 29 +++++++++++----------
+ gcc/config/aarch64/aarch64.opt              |  2 +-
+ gcc/config/aarch64/driver-aarch64.cc        | 10 +++----
+ 7 files changed, 56 insertions(+), 47 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index ac3486d71..3efa57b26 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -204,9 +204,9 @@ aarch64_handle_option (struct gcc_options *opts,
+ struct aarch64_option_extension
+ {
+   const char *name;
+-  uint64_t flag_canonical;
+-  uint64_t flags_on;
+-  uint64_t flags_off;
++  aarch64_feature_flags flag_canonical;
++  aarch64_feature_flags flags_on;
++  aarch64_feature_flags flags_off;
+ };
+ 
+ /* ISA extensions in AArch64.  */
+@@ -225,14 +225,14 @@ struct processor_name_to_arch
+ {
+   const char *processor_name;
+   aarch64_arch arch;
+-  uint64_t flags;
++  aarch64_feature_flags flags;
+ };
+ 
+ struct arch_to_arch_name
+ {
+   aarch64_arch arch;
+   const char *arch_name;
+-  uint64_t flags;
++  aarch64_feature_flags flags;
+ };
+ 
+ /* Map processor names to the architecture revision they implement and
+@@ -262,7 +262,7 @@ static constexpr arch_to_arch_name all_architectures[] =
+    a copy of the string is created and stored to INVALID_EXTENSION.  */
+ 
+ enum aarch64_parse_opt_result
+-aarch64_parse_extension (const char *str, uint64_t *isa_flags,
++aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
+ 			 std::string *invalid_extension)
+ {
+   /* The extension string is parsed left to right.  */
+@@ -342,8 +342,9 @@ aarch64_get_all_extension_candidates (auto_vec *candidates)
+    that all the "+" flags come before the "+no" flags.  */
+ 
+ std::string
+-aarch64_get_extension_string_for_isa_flags (uint64_t isa_flags,
+-					    uint64_t default_arch_flags)
++aarch64_get_extension_string_for_isa_flags
++  (aarch64_feature_flags isa_flags,
++   aarch64_feature_flags default_arch_flags)
+ {
+   std::string outstr = "";
+ 
+@@ -451,7 +452,7 @@ aarch64_rewrite_selected_cpu (const char *name)
+       || a_to_an->arch == aarch64_no_arch)
+     fatal_error (input_location, "unknown value %qs for %<-mcpu%>", name);
+ 
+-  uint64_t extensions = p_to_a->flags;
++  aarch64_feature_flags extensions = p_to_a->flags;
+   aarch64_parse_extension (extension_str.c_str (), &extensions, NULL);
+ 
+   std::string outstr = a_to_an->arch_name
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index e60ce3c36..ef84df731 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -1037,10 +1037,11 @@ bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
+ 			     const struct cl_decoded_option *, location_t);
+ const char *aarch64_rewrite_selected_cpu (const char *name);
+ enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
+-						       uint64_t *,
++						       aarch64_feature_flags *,
+ 						       std::string *);
+ void aarch64_get_all_extension_candidates (auto_vec *candidates);
+-std::string aarch64_get_extension_string_for_isa_flags (uint64_t, uint64_t);
++std::string aarch64_get_extension_string_for_isa_flags (aarch64_feature_flags,
++							aarch64_feature_flags);
+ 
+ rtl_opt_pass *make_pass_fma_steering (gcc::context *);
+ rtl_opt_pass *make_pass_track_speculation (gcc::context *);
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index c06e99339..b927a886e 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -82,7 +82,7 @@ public:
+ 
+   /* The architecture extensions that the function requires, as a set of
+      AARCH64_FL_* flags.  */
+-  uint64_t required_extensions;
++  aarch64_feature_flags required_extensions;
+ 
+   /* True if the decl represents an overloaded function that needs to be
+      resolved by function_resolver.  */
+@@ -694,13 +694,16 @@ check_required_registers (location_t location, tree fndecl)
+    Report an error against LOCATION if not.  */
+ static bool
+ check_required_extensions (location_t location, tree fndecl,
+-			   uint64_t required_extensions)
++			   aarch64_feature_flags required_extensions)
+ {
+-  uint64_t missing_extensions = required_extensions & ~aarch64_isa_flags;
++  auto missing_extensions = required_extensions & ~aarch64_isa_flags;
+   if (missing_extensions == 0)
+     return check_required_registers (location, fndecl);
+ 
+-  static const struct { uint64_t flag; const char *name; } extensions[] = {
++  static const struct {
++    aarch64_feature_flags flag;
++    const char *name;
++  } extensions[] = {
+ #define AARCH64_OPT_EXTENSION(EXT_NAME, IDENT, C, D, E, F) \
+     { AARCH64_FL_##IDENT, EXT_NAME },
+ #include "aarch64-option-extensions.def"
+@@ -992,7 +995,7 @@ function_builder::get_attributes (const function_instance &instance)
+ registered_function &
+ function_builder::add_function (const function_instance &instance,
+ 				const char *name, tree fntype, tree attrs,
+-				uint64_t required_extensions,
++				aarch64_feature_flags required_extensions,
+ 				bool overloaded_p,
+ 				bool placeholder_p)
+ {
+@@ -1034,11 +1037,12 @@ function_builder::add_function (const function_instance &instance,
+    one-to-one mapping between "short" and "full" names, and if standard
+    overload resolution therefore isn't necessary.  */
+ void
+-function_builder::add_unique_function (const function_instance &instance,
+-				       tree return_type,
+-				       vec &argument_types,
+-				       uint64_t required_extensions,
+-				       bool force_direct_overloads)
++function_builder::
++add_unique_function (const function_instance &instance,
++		     tree return_type,
++		     vec &argument_types,
++		     aarch64_feature_flags required_extensions,
++		     bool force_direct_overloads)
+ {
+   /* Add the function under its full (unique) name.  */
+   char *name = get_name (instance, false);
+@@ -1081,8 +1085,9 @@ function_builder::add_unique_function (const function_instance &instance,
+    features are available as part of resolving the function to the
+    relevant unique function.  */
+ void
+-function_builder::add_overloaded_function (const function_instance &instance,
+-					   uint64_t required_extensions)
++function_builder::
++add_overloaded_function (const function_instance &instance,
++			 aarch64_feature_flags required_extensions)
+ {
+   char *name = get_name (instance, true);
+   if (registered_function **map_value = m_overload_names.get (name))
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 24594d584..63d1db776 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -263,7 +263,7 @@ struct function_group_info
+ 
+   /* The architecture extensions that the functions require, as a set of
+      AARCH64_FL_* flags.  */
+-  uint64_t required_extensions;
++  aarch64_feature_flags required_extensions;
+ };
+ 
+ /* Describes a single fully-resolved function (i.e. one that has a
+@@ -321,8 +321,9 @@ public:
+   ~function_builder ();
+ 
+   void add_unique_function (const function_instance &, tree,
+-			    vec &, uint64_t, bool);
+-  void add_overloaded_function (const function_instance &, uint64_t);
++			    vec &, aarch64_feature_flags, bool);
++  void add_overloaded_function (const function_instance &,
++				aarch64_feature_flags);
+   void add_overloaded_functions (const function_group_info &,
+ 				 mode_suffix_index);
+ 
+@@ -338,7 +339,7 @@ private:
+ 
+   registered_function &add_function (const function_instance &,
+ 				     const char *, tree, tree,
+-				     uint64_t, bool, bool);
++				     aarch64_feature_flags, bool, bool);
+ 
+   /* The function type to use for functions that are resolved by
+      function_resolver.  */
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 71db7ace1..8cb820767 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2929,7 +2929,7 @@ struct processor
+   aarch64_processor ident;
+   aarch64_processor sched_core;
+   aarch64_arch arch;
+-  uint64_t flags;
++  aarch64_feature_flags flags;
+   const tune_params *tune;
+ };
+ 
+@@ -17428,7 +17428,8 @@ static void initialize_aarch64_code_model (struct gcc_options *);
+ 
+ static enum aarch64_parse_opt_result
+ aarch64_parse_arch (const char *to_parse, const struct processor **res,
+-		    uint64_t *isa_flags, std::string *invalid_extension)
++		    aarch64_feature_flags *isa_flags,
++		    std::string *invalid_extension)
+ {
+   const char *ext;
+   const struct processor *arch;
+@@ -17451,7 +17452,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
+       if (strlen (arch->name) == len
+ 	  && strncmp (arch->name, to_parse, len) == 0)
+ 	{
+-	  uint64_t isa_temp = arch->flags;
++	  auto isa_temp = arch->flags;
+ 
+ 	  if (ext != NULL)
+ 	    {
+@@ -17483,7 +17484,8 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
+ 
+ static enum aarch64_parse_opt_result
+ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
+-		   uint64_t *isa_flags, std::string *invalid_extension)
++		   aarch64_feature_flags *isa_flags,
++		   std::string *invalid_extension)
+ {
+   const char *ext;
+   const struct processor *cpu;
+@@ -17505,8 +17507,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
+     {
+       if (strlen (cpu->name) == len && strncmp (cpu->name, to_parse, len) == 0)
+ 	{
+-	  uint64_t isa_temp = cpu->flags;
+-
++	  auto isa_temp = cpu->flags;
+ 
+ 	  if (ext != NULL)
+ 	    {
+@@ -18137,7 +18138,7 @@ aarch64_print_hint_for_extensions (const std::string &str)
+ 
+ static bool
+ aarch64_validate_mcpu (const char *str, const struct processor **res,
+-		       uint64_t *isa_flags)
++		       aarch64_feature_flags *isa_flags)
+ {
+   std::string invalid_extension;
+   enum aarch64_parse_opt_result parse_res
+@@ -18351,7 +18352,7 @@ aarch64_validate_mbranch_protection (const char *const_str)
+ 
+ static bool
+ aarch64_validate_march (const char *str, const struct processor **res,
+-			 uint64_t *isa_flags)
++			aarch64_feature_flags *isa_flags)
+ {
+   std::string invalid_extension;
+   enum aarch64_parse_opt_result parse_res
+@@ -18441,8 +18442,8 @@ aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits_enum value)
+ static void
+ aarch64_override_options (void)
+ {
+-  uint64_t cpu_isa = 0;
+-  uint64_t arch_isa = 0;
++  aarch64_feature_flags cpu_isa = 0;
++  aarch64_feature_flags arch_isa = 0;
+   aarch64_isa_flags = 0;
+ 
+   const struct processor *cpu = NULL;
+@@ -18890,7 +18891,7 @@ static bool
+ aarch64_handle_attr_isa_flags (char *str)
+ {
+   enum aarch64_parse_opt_result parse_res;
+-  uint64_t isa_flags = aarch64_isa_flags;
++  auto isa_flags = aarch64_isa_flags;
+ 
+   /* We allow "+nothing" in the beginning to clear out all architectural
+      features if the user wants to handpick specific features.  */
+@@ -19162,7 +19163,7 @@ aarch64_process_target_attr (tree args)
+ 	{
+ 	  /* Check if token is possibly an arch extension without
+ 	     leading '+'.  */
+-	  uint64_t isa_temp = 0;
++	  aarch64_feature_flags isa_temp = 0;
+ 	  auto with_plus = std::string ("+") + token;
+ 	  enum aarch64_parse_opt_result ext_res
+ 	    = aarch64_parse_extension (with_plus.c_str (), &isa_temp, nullptr);
+@@ -22771,7 +22772,7 @@ aarch64_declare_function_name (FILE *stream, const char* name,
+   const struct processor *this_arch
+     = aarch64_get_arch (targ_options->x_selected_arch);
+ 
+-  uint64_t isa_flags = targ_options->x_aarch64_isa_flags;
++  auto isa_flags = targ_options->x_aarch64_isa_flags;
+   std::string extension
+     = aarch64_get_extension_string_for_isa_flags (isa_flags,
+ 						  this_arch->flags);
+@@ -22901,7 +22902,7 @@ aarch64_start_file (void)
+ 
+   const struct processor *default_arch
+     = aarch64_get_arch (default_options->x_selected_arch);
+-  uint64_t default_isa_flags = default_options->x_aarch64_isa_flags;
++  auto default_isa_flags = default_options->x_aarch64_isa_flags;
+   std::string extension
+     = aarch64_get_extension_string_for_isa_flags (default_isa_flags,
+ 						  default_arch->flags);
+diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
+index 836a3c784..47ec7824f 100644
+--- a/gcc/config/aarch64/aarch64.opt
++++ b/gcc/config/aarch64/aarch64.opt
+@@ -28,7 +28,7 @@ TargetVariable
+ enum aarch64_arch selected_arch = aarch64_no_arch
+ 
+ TargetVariable
+-uint64_t aarch64_isa_flags = 0
++aarch64_feature_flags aarch64_isa_flags = 0
+ 
+ TargetVariable
+ unsigned aarch64_enable_bti = 2
+diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
+index ee9cb65a5..2ae47c020 100644
+--- a/gcc/config/aarch64/driver-aarch64.cc
++++ b/gcc/config/aarch64/driver-aarch64.cc
+@@ -31,7 +31,7 @@
+ struct aarch64_arch_extension
+ {
+   const char *ext;
+-  uint64_t flag;
++  aarch64_feature_flags flag;
+   const char *feat_string;
+ };
+ 
+@@ -50,7 +50,7 @@ struct aarch64_core_data
+   unsigned char implementer_id; /* Exactly 8 bits */
+   unsigned int part_no; /* 12 bits + 12 bits */
+   unsigned variant;
+-  uint64_t flags;
++  aarch64_feature_flags flags;
+ };
+ 
+ #define AARCH64_BIG_LITTLE(BIG, LITTLE) \
+@@ -75,7 +75,7 @@ struct aarch64_arch_driver_info
+ {
+   const char* id;
+   const char* name;
+-  uint64_t flags;
++  aarch64_feature_flags flags;
+ };
+ 
+ /* Skip the leading "V" in the architecture name.  */
+@@ -261,8 +261,8 @@ host_detect_local_cpu (int argc, const char **argv)
+   unsigned int variants[2] = { ALL_VARIANTS, ALL_VARIANTS };
+   unsigned int n_variants = 0;
+   bool processed_exts = false;
+-  uint64_t extension_flags = 0;
+-  uint64_t default_flags = 0;
++  aarch64_feature_flags extension_flags = 0;
++  aarch64_feature_flags default_flags = 0;
+   std::string buf;
+   size_t sep_pos = -1;
+   char *fcpu_info;
+-- 
+2.33.0
+
diff --git a/0123-Backport-SME-aarch64-Tweak-contents-of-flags_on-off-.patch b/0123-Backport-SME-aarch64-Tweak-contents-of-flags_on-off-.patch
new file mode 100644
index 0000000..ec1c5f6
--- /dev/null
+++ b/0123-Backport-SME-aarch64-Tweak-contents-of-flags_on-off-.patch
@@ -0,0 +1,70 @@
+From eb92c185c1c71edcbd83b1c66fe4f9e7d52a98b3 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:56 +0100
+Subject: [PATCH 024/157] [Backport][SME] aarch64: Tweak contents of
+ flags_on/off fields
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=bb7f43b62a58a0f0326fd3060f0bd43e6f3ef971
+
+After previous changes, it's more convenient if the flags_on and
+flags_off fields of all_extensions include the feature flag itself.
+
+gcc/
+	* common/config/aarch64/aarch64-common.cc (all_extensions):
+	Include the feature flag in flags_on and flags_off.
+	(aarch64_parse_extension): Update accordingly.
+	(aarch64_get_extension_string_for_isa_flags): Likewise.
+---
+ gcc/common/config/aarch64/aarch64-common.cc | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 3efa57b26..752ba5632 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -213,10 +213,8 @@ struct aarch64_option_extension
+ static constexpr aarch64_option_extension all_extensions[] =
+ {
+ #define AARCH64_OPT_EXTENSION(NAME, IDENT, C, D, E, F) \
+-  {NAME, AARCH64_FL_##IDENT, \
+-   feature_deps::IDENT ().explicit_on & ~AARCH64_FL_##IDENT, \
+-   feature_deps::get_flags_off (feature_deps::root_off_##IDENT) \
+-   & ~AARCH64_FL_##IDENT},
++  {NAME, AARCH64_FL_##IDENT, feature_deps::IDENT ().explicit_on, \
++   feature_deps::get_flags_off (feature_deps::root_off_##IDENT)},
+ #include "config/aarch64/aarch64-option-extensions.def"
+   {NULL, 0, 0, 0}
+ };
+@@ -304,9 +302,9 @@ aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
+ 	    {
+ 	      /* Add or remove the extension.  */
+ 	      if (adding_ext)
+-		*isa_flags |= (opt->flags_on | opt->flag_canonical);
++		*isa_flags |= opt->flags_on;
+ 	      else
+-		*isa_flags &= ~(opt->flags_off | opt->flag_canonical);
++		*isa_flags &= ~opt->flags_off;
+ 	      break;
+ 	    }
+ 	}
+@@ -380,7 +378,7 @@ aarch64_get_extension_string_for_isa_flags
+ 
+       if ((flags & isa_flags & (explicit_flags | ~current_flags)) == flags)
+ 	{
+-	  current_flags |= opt.flag_canonical | opt.flags_on;
++	  current_flags |= opt.flags_on;
+ 	  added |= opt.flag_canonical;
+ 	}
+     }
+@@ -395,7 +393,7 @@ aarch64_get_extension_string_for_isa_flags
+   for (auto &opt : all_extensions)
+     if (opt.flag_canonical & current_flags & ~isa_flags)
+       {
+-	current_flags &= ~(opt.flag_canonical | opt.flags_off);
++	current_flags &= ~opt.flags_off;
+ 	outstr += "+no";
+ 	outstr += opt.name;
+       }
+-- 
+2.33.0
+
diff --git a/0124-Backport-SME-aarch64-Tweak-handling-of-mgeneral-regs.patch b/0124-Backport-SME-aarch64-Tweak-handling-of-mgeneral-regs.patch
new file mode 100644
index 0000000..55c27b3
--- /dev/null
+++ b/0124-Backport-SME-aarch64-Tweak-handling-of-mgeneral-regs.patch
@@ -0,0 +1,370 @@
+From 91f7471cbc7dec42673b58a1896330d64eb6be2a Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:57 +0100
+Subject: [PATCH 025/157] [Backport][SME] aarch64: Tweak handling of
+ -mgeneral-regs-only
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2a269bda9e7b8f9353699d0c965e7e9246500aa0
+
+-mgeneral-regs-only is effectively "+nofp for the compiler without
+changing the assembler's ISA flags".  Currently that's implemented
+by making TARGET_FLOAT, TARGET_SIMD and TARGET_SVE depend on
+!TARGET_GENERAL_REGS_ONLY and then making any feature that needs FP
+registers depend (directly or indirectly) on one of those three TARGET
+macros.  The problem is that it's easy to forgot to do the last bit.
+
+This patch instead represents the distinction between "assemnbler
+ISA flags" and "compiler ISA flags" more directly, funnelling
+all updates through a new function that sets both sets of flags
+together.
+
+gcc/
+	* config/aarch64/aarch64.opt (aarch64_asm_isa_flags): New variable.
+	* config/aarch64/aarch64.h (aarch64_asm_isa_flags)
+	(aarch64_isa_flags): Redefine as read-only macros.
+	(TARGET_SIMD, TARGET_FLOAT, TARGET_SVE): Don't depend on
+	!TARGET_GENERAL_REGS_ONLY.
+	* common/config/aarch64/aarch64-common.cc
+	(aarch64_set_asm_isa_flags): New function.
+	(aarch64_handle_option): Call it when updating -mgeneral-regs.
+	* config/aarch64/aarch64-protos.h (aarch64_simd_switcher): Replace
+	m_old_isa_flags with m_old_asm_isa_flags.
+	(aarch64_set_asm_isa_flags): Declare.
+	* config/aarch64/aarch64-builtins.cc
+	(aarch64_simd_switcher::aarch64_simd_switcher)
+	(aarch64_simd_switcher::~aarch64_simd_switcher): Save and restore
+	aarch64_asm_isa_flags instead of aarch64_isa_flags.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(check_required_extensions): Use aarch64_asm_isa_flags instead
+	of aarch64_isa_flags.
+	* config/aarch64/aarch64.cc (aarch64_set_asm_isa_flags): New function.
+	(aarch64_override_options, aarch64_handle_attr_arch)
+	(aarch64_handle_attr_cpu, aarch64_handle_attr_isa_flags): Use
+	aarch64_set_asm_isa_flags to set the ISA flags.
+	(aarch64_option_print, aarch64_declare_function_name)
+	(aarch64_start_file): Use aarch64_asm_isa_flags instead
+	of aarch64_isa_flags.
+	(aarch64_can_inline_p): Check aarch64_asm_isa_flags as well as
+	aarch64_isa_flags.
+---
+ gcc/common/config/aarch64/aarch64-common.cc | 12 ++++++
+ gcc/config/aarch64/aarch64-builtins.cc      |  6 +--
+ gcc/config/aarch64/aarch64-protos.h         |  5 ++-
+ gcc/config/aarch64/aarch64-sve-builtins.cc  |  2 +-
+ gcc/config/aarch64/aarch64.cc               | 45 ++++++++++++++-------
+ gcc/config/aarch64/aarch64.h                | 17 ++++++--
+ gcc/config/aarch64/aarch64.opt              |  3 ++
+ 7 files changed, 68 insertions(+), 22 deletions(-)
+
+diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
+index 752ba5632..c64b4987e 100644
+--- a/gcc/common/config/aarch64/aarch64-common.cc
++++ b/gcc/common/config/aarch64/aarch64-common.cc
+@@ -137,6 +137,17 @@ reset_tsv110_option ()
+     }
+ }
+ 
++/* Set OPTS->x_aarch64_asm_isa_flags to FLAGS and update
++   OPTS->x_aarch64_isa_flags accordingly.  */
++void
++aarch64_set_asm_isa_flags (gcc_options *opts, aarch64_feature_flags flags)
++{
++  opts->x_aarch64_asm_isa_flags = flags;
++  opts->x_aarch64_isa_flags = flags;
++  if (opts->x_target_flags & MASK_GENERAL_REGS_ONLY)
++    opts->x_aarch64_isa_flags &= ~feature_deps::get_flags_off (AARCH64_FL_FP);
++}
++
+ /* Implement TARGET_HANDLE_OPTION.
+    This function handles the target specific options for CPU/target selection.
+ 
+@@ -174,6 +185,7 @@ aarch64_handle_option (struct gcc_options *opts,
+ 
+     case OPT_mgeneral_regs_only:
+       opts->x_target_flags |= MASK_GENERAL_REGS_ONLY;
++      aarch64_set_asm_isa_flags (opts, opts->x_aarch64_asm_isa_flags);
+       return true;
+ 
+     case OPT_mfix_cortex_a53_835769:
+diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
+index 42276e7ca..015e9d975 100644
+--- a/gcc/config/aarch64/aarch64-builtins.cc
++++ b/gcc/config/aarch64/aarch64-builtins.cc
+@@ -1336,20 +1336,20 @@ aarch64_scalar_builtin_type_p (aarch64_simd_type t)
+ /* Enable AARCH64_FL_* flags EXTRA_FLAGS on top of the base Advanced SIMD
+    set.  */
+ aarch64_simd_switcher::aarch64_simd_switcher (unsigned int extra_flags)
+-  : m_old_isa_flags (aarch64_isa_flags),
++  : m_old_asm_isa_flags (aarch64_asm_isa_flags),
+     m_old_general_regs_only (TARGET_GENERAL_REGS_ONLY)
+ {
+   /* Changing the ISA flags should be enough here.  We shouldn't need to
+      pay the compile-time cost of a full target switch.  */
+-  aarch64_isa_flags = AARCH64_FL_FP | AARCH64_FL_SIMD | extra_flags;
+   global_options.x_target_flags &= ~MASK_GENERAL_REGS_ONLY;
++  aarch64_set_asm_isa_flags (AARCH64_FL_FP | AARCH64_FL_SIMD | extra_flags);
+ }
+ 
+ aarch64_simd_switcher::~aarch64_simd_switcher ()
+ {
+   if (m_old_general_regs_only)
+     global_options.x_target_flags |= MASK_GENERAL_REGS_ONLY;
+-  aarch64_isa_flags = m_old_isa_flags;
++  aarch64_set_asm_isa_flags (m_old_asm_isa_flags);
+ }
+ 
+ /* Implement #pragma GCC aarch64 "arm_neon.h".  */
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index ef84df731..86e444a60 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -747,7 +747,7 @@ public:
+   ~aarch64_simd_switcher ();
+ 
+ private:
+-  unsigned long m_old_isa_flags;
++  unsigned long m_old_asm_isa_flags;
+   bool m_old_general_regs_only;
+ };
+ 
+@@ -1032,7 +1032,10 @@ extern bool aarch64_classify_address (struct aarch64_address_info *, rtx,
+ 				      machine_mode, bool,
+ 				      aarch64_addr_query_type = ADDR_QUERY_M);
+ 
++void aarch64_set_asm_isa_flags (aarch64_feature_flags);
++
+ /* Defined in common/config/aarch64-common.cc.  */
++void aarch64_set_asm_isa_flags (gcc_options *, aarch64_feature_flags);
+ bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
+ 			     const struct cl_decoded_option *, location_t);
+ const char *aarch64_rewrite_selected_cpu (const char *name);
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index b927a886e..a70e3a6b4 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -696,7 +696,7 @@ static bool
+ check_required_extensions (location_t location, tree fndecl,
+ 			   aarch64_feature_flags required_extensions)
+ {
+-  auto missing_extensions = required_extensions & ~aarch64_isa_flags;
++  auto missing_extensions = required_extensions & ~aarch64_asm_isa_flags;
+   if (missing_extensions == 0)
+     return check_required_registers (location, fndecl);
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 8cb820767..3e83e48ec 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -18432,10 +18432,19 @@ aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits_enum value)
+     return (int) value / 64;
+ }
+ 
++/* Set the global aarch64_asm_isa_flags to FLAGS and update
++   aarch64_isa_flags accordingly.  */
++
++void
++aarch64_set_asm_isa_flags (aarch64_feature_flags flags)
++{
++  aarch64_set_asm_isa_flags (&global_options, flags);
++}
++
+ /* Implement TARGET_OPTION_OVERRIDE.  This is called once in the beginning
+    and is used to parse the -m{cpu,tune,arch} strings and setup the initial
+    tuning structs.  In particular it must set selected_tune and
+-   aarch64_isa_flags that define the available ISA features and tuning
++   aarch64_asm_isa_flags that define the available ISA features and tuning
+    decisions.  It must also set selected_arch as this will be used to
+    output the .arch asm tags for each function.  */
+ 
+@@ -18444,7 +18453,7 @@ aarch64_override_options (void)
+ {
+   aarch64_feature_flags cpu_isa = 0;
+   aarch64_feature_flags arch_isa = 0;
+-  aarch64_isa_flags = 0;
++  aarch64_set_asm_isa_flags (0);
+ 
+   const struct processor *cpu = NULL;
+   const struct processor *arch = NULL;
+@@ -18484,25 +18493,25 @@ aarch64_override_options (void)
+ 	}
+ 
+       selected_arch = arch->arch;
+-      aarch64_isa_flags = arch_isa;
++      aarch64_set_asm_isa_flags (arch_isa);
+     }
+   else if (cpu)
+     {
+       selected_arch = cpu->arch;
+-      aarch64_isa_flags = cpu_isa;
++      aarch64_set_asm_isa_flags (cpu_isa);
+     }
+   else if (arch)
+     {
+       cpu = &all_cores[arch->ident];
+       selected_arch = arch->arch;
+-      aarch64_isa_flags = arch_isa;
++      aarch64_set_asm_isa_flags (arch_isa);
+     }
+   else
+     {
+       /* No -mcpu or -march specified, so use the default CPU.  */
+       cpu = &all_cores[TARGET_CPU_DEFAULT];
+       selected_arch = cpu->arch;
+-      aarch64_isa_flags = cpu->flags;
++      aarch64_set_asm_isa_flags (cpu->flags);
+     }
+ 
+   selected_tune = tune ? tune->ident : cpu->ident;
+@@ -18644,7 +18653,7 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
+     = aarch64_get_tune_cpu (ptr->x_selected_tune);
+   const struct processor *arch = aarch64_get_arch (ptr->x_selected_arch);
+   std::string extension
+-    = aarch64_get_extension_string_for_isa_flags (ptr->x_aarch64_isa_flags,
++    = aarch64_get_extension_string_for_isa_flags (ptr->x_aarch64_asm_isa_flags,
+ 						  arch->flags);
+ 
+   fprintf (file, "%*sselected tune = %s\n", indent, "", cpu->name);
+@@ -18752,13 +18761,15 @@ aarch64_handle_attr_arch (const char *str)
+ {
+   const struct processor *tmp_arch = NULL;
+   std::string invalid_extension;
++  aarch64_feature_flags tmp_flags;
+   enum aarch64_parse_opt_result parse_res
+-    = aarch64_parse_arch (str, &tmp_arch, &aarch64_isa_flags, &invalid_extension);
++    = aarch64_parse_arch (str, &tmp_arch, &tmp_flags, &invalid_extension);
+ 
+   if (parse_res == AARCH64_PARSE_OK)
+     {
+       gcc_assert (tmp_arch);
+       selected_arch = tmp_arch->arch;
++      aarch64_set_asm_isa_flags (tmp_flags);
+       return true;
+     }
+ 
+@@ -18790,14 +18801,16 @@ aarch64_handle_attr_cpu (const char *str)
+ {
+   const struct processor *tmp_cpu = NULL;
+   std::string invalid_extension;
++  aarch64_feature_flags tmp_flags;
+   enum aarch64_parse_opt_result parse_res
+-    = aarch64_parse_cpu (str, &tmp_cpu, &aarch64_isa_flags, &invalid_extension);
++    = aarch64_parse_cpu (str, &tmp_cpu, &tmp_flags, &invalid_extension);
+ 
+   if (parse_res == AARCH64_PARSE_OK)
+     {
+       gcc_assert (tmp_cpu);
+       selected_tune = tmp_cpu->ident;
+       selected_arch = tmp_cpu->arch;
++      aarch64_set_asm_isa_flags (tmp_flags);
+       return true;
+     }
+ 
+@@ -18891,7 +18904,7 @@ static bool
+ aarch64_handle_attr_isa_flags (char *str)
+ {
+   enum aarch64_parse_opt_result parse_res;
+-  auto isa_flags = aarch64_isa_flags;
++  auto isa_flags = aarch64_asm_isa_flags;
+ 
+   /* We allow "+nothing" in the beginning to clear out all architectural
+      features if the user wants to handpick specific features.  */
+@@ -18906,7 +18919,7 @@ aarch64_handle_attr_isa_flags (char *str)
+ 
+   if (parse_res == AARCH64_PARSE_OK)
+     {
+-      aarch64_isa_flags = isa_flags;
++      aarch64_set_asm_isa_flags (isa_flags);
+       return true;
+     }
+ 
+@@ -19328,8 +19341,12 @@ aarch64_can_inline_p (tree caller, tree callee)
+ 					   : target_option_default_node);
+ 
+   /* Callee's ISA flags should be a subset of the caller's.  */
++  if ((caller_opts->x_aarch64_asm_isa_flags
++       & callee_opts->x_aarch64_asm_isa_flags)
++      != callee_opts->x_aarch64_asm_isa_flags)
++    return false;
+   if ((caller_opts->x_aarch64_isa_flags & callee_opts->x_aarch64_isa_flags)
+-       != callee_opts->x_aarch64_isa_flags)
++      != callee_opts->x_aarch64_isa_flags)
+     return false;
+ 
+   /* Allow non-strict aligned functions inlining into strict
+@@ -22772,7 +22789,7 @@ aarch64_declare_function_name (FILE *stream, const char* name,
+   const struct processor *this_arch
+     = aarch64_get_arch (targ_options->x_selected_arch);
+ 
+-  auto isa_flags = targ_options->x_aarch64_isa_flags;
++  auto isa_flags = targ_options->x_aarch64_asm_isa_flags;
+   std::string extension
+     = aarch64_get_extension_string_for_isa_flags (isa_flags,
+ 						  this_arch->flags);
+@@ -22902,7 +22919,7 @@ aarch64_start_file (void)
+ 
+   const struct processor *default_arch
+     = aarch64_get_arch (default_options->x_selected_arch);
+-  auto default_isa_flags = default_options->x_aarch64_isa_flags;
++  auto default_isa_flags = default_options->x_aarch64_asm_isa_flags;
+   std::string extension
+     = aarch64_get_extension_string_for_isa_flags (default_isa_flags,
+ 						  default_arch->flags);
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 50a2ef444..521031efe 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -22,6 +22,17 @@
+ #ifndef GCC_AARCH64_H
+ #define GCC_AARCH64_H
+ 
++/* Make these flags read-only so that all uses go via
++   aarch64_set_asm_isa_flags.  */
++#ifndef GENERATOR_FILE
++#undef aarch64_asm_isa_flags
++#define aarch64_asm_isa_flags \
++  ((aarch64_feature_flags) global_options.x_aarch64_asm_isa_flags)
++#undef aarch64_isa_flags
++#define aarch64_isa_flags \
++  ((aarch64_feature_flags) global_options.x_aarch64_isa_flags)
++#endif
++
+ /* Target CPU builtins.  */
+ #define TARGET_CPU_CPP_BUILTINS()	\
+   aarch64_cpu_cpp_builtins (pfile)
+@@ -51,8 +62,8 @@
+ 
+ /* AdvSIMD is supported in the default configuration, unless disabled by
+    -mgeneral-regs-only or by the +nosimd extension.  */
+-#define TARGET_SIMD (!TARGET_GENERAL_REGS_ONLY && AARCH64_ISA_SIMD)
+-#define TARGET_FLOAT (!TARGET_GENERAL_REGS_ONLY && AARCH64_ISA_FP)
++#define TARGET_SIMD (AARCH64_ISA_SIMD)
++#define TARGET_FLOAT (AARCH64_ISA_FP)
+ 
+ #define UNITS_PER_WORD		8
+ 
+@@ -242,7 +253,7 @@ enum class aarch64_feature : unsigned char {
+ #define TARGET_DOTPROD (TARGET_SIMD && AARCH64_ISA_DOTPROD)
+ 
+ /* SVE instructions, enabled through +sve.  */
+-#define TARGET_SVE (!TARGET_GENERAL_REGS_ONLY && AARCH64_ISA_SVE)
++#define TARGET_SVE (AARCH64_ISA_SVE)
+ 
+ /* SVE2 instructions, enabled through +sve2.  */
+ #define TARGET_SVE2 (TARGET_SVE && AARCH64_ISA_SVE2)
+diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
+index 47ec7824f..5f507abd4 100644
+--- a/gcc/config/aarch64/aarch64.opt
++++ b/gcc/config/aarch64/aarch64.opt
+@@ -27,6 +27,9 @@ enum aarch64_processor selected_tune = aarch64_none
+ TargetVariable
+ enum aarch64_arch selected_arch = aarch64_no_arch
+ 
++TargetVariable
++aarch64_feature_flags aarch64_asm_isa_flags = 0
++
+ TargetVariable
+ aarch64_feature_flags aarch64_isa_flags = 0
+ 
+-- 
+2.33.0
+
diff --git a/0125-Backport-SME-aarch64-Remove-redundant-TARGET_-checks.patch b/0125-Backport-SME-aarch64-Remove-redundant-TARGET_-checks.patch
new file mode 100644
index 0000000..f935069
--- /dev/null
+++ b/0125-Backport-SME-aarch64-Remove-redundant-TARGET_-checks.patch
@@ -0,0 +1,453 @@
+From 77a86d955dd1c9cd8c7fc35e6caf0cb707799129 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:57 +0100
+Subject: [PATCH 026/157] [Backport][SME] aarch64: Remove redundant TARGET_*
+ checks
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a31641840af2c40cf36036fa472df34d4a4402c3
+
+After previous patches, it's possible to remove TARGET_*
+options that are redundant due to (IMO) obvious dependencies.
+
+gcc/
+	* config/aarch64/aarch64.h (TARGET_CRYPTO, TARGET_SHA3, TARGET_SM4)
+	(TARGET_DOTPROD): Don't depend on TARGET_SIMD.
+	(TARGET_AES, TARGET_SHA2): Likewise.  Remove TARGET_CRYPTO test.
+	(TARGET_FP_F16INST): Don't depend on TARGET_FLOAT.
+	(TARGET_SVE2, TARGET_SVE_F32MM, TARGET_SVE_F64MM): Don't depend
+	on TARGET_SVE.
+	(TARGET_SVE2_AES, TARGET_SVE2_BITPERM, TARGET_SVE2_SHA3)
+	(TARGET_SVE2_SM4): Don't depend on TARGET_SVE2.
+	(TARGET_F32MM, TARGET_F64MM): Delete.
+	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Guard
+	float macros with just TARGET_FLOAT rather than TARGET_FLOAT
+	|| TARGET_SIMD.
+	* config/aarch64/aarch64-simd.md (copysign3): Depend
+	only on TARGET_SIMD, rather than TARGET_FLOAT && TARGET_SIMD.
+	(aarch64_crypto_aesv16qi): Depend only on TARGET_AES,
+	rather than TARGET_SIMD && TARGET_AES.
+	(aarch64_crypto_aesv16qi): Likewise.
+	(*aarch64_crypto_aese_fused): Likewise.
+	(*aarch64_crypto_aesd_fused): Likewise.
+	(aarch64_crypto_pmulldi): Likewise.
+	(aarch64_crypto_pmullv2di): Likewise.
+	(aarch64_crypto_sha1hsi): Likewise TARGET_SHA2.
+	(aarch64_crypto_sha1hv4si): Likewise.
+	(aarch64_be_crypto_sha1hv4si): Likewise.
+	(aarch64_crypto_sha1su1v4si): Likewise.
+	(aarch64_crypto_sha1v4si): Likewise.
+	(aarch64_crypto_sha1su0v4si): Likewise.
+	(aarch64_crypto_sha256hv4si): Likewise.
+	(aarch64_crypto_sha256su0v4si): Likewise.
+	(aarch64_crypto_sha256su1v4si): Likewise.
+	(aarch64_crypto_sha512hqv2di): Likewise TARGET_SHA3.
+	(aarch64_crypto_sha512su0qv2di): Likewise.
+	(aarch64_crypto_sha512su1qv2di, eor3q4): Likewise.
+	(aarch64_rax1qv2di, aarch64_xarqv2di, bcaxq4): Likewise.
+	(aarch64_sm3ss1qv4si): Likewise TARGET_SM4.
+	(aarch64_sm3ttqv4si): Likewise.
+	(aarch64_sm3partwqv4si): Likewise.
+	(aarch64_sm4eqv4si, aarch64_sm4ekeyqv4si): Likewise.
+	* config/aarch64/aarch64.md (dihf2)
+	(copysign3, copysign3_insn)
+	(xorsign3): Remove redundant TARGET_FLOAT condition.
+---
+ gcc/config/aarch64/aarch64-c.cc    |  2 +-
+ gcc/config/aarch64/aarch64-simd.md | 56 +++++++++++++++---------------
+ gcc/config/aarch64/aarch64.h       | 30 ++++++++--------
+ gcc/config/aarch64/aarch64.md      |  8 ++---
+ 4 files changed, 47 insertions(+), 49 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 18c9b975b..2dfe2b8f8 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -92,7 +92,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ 
+   aarch64_def_or_undef (TARGET_FLOAT, "__ARM_FEATURE_FMA", pfile);
+ 
+-  if (TARGET_FLOAT || TARGET_SIMD)
++  if (TARGET_FLOAT)
+     {
+       builtin_define_with_int_value ("__ARM_FP", 0x0E);
+       builtin_define ("__ARM_FP16_FORMAT_IEEE");
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index de92802f5..a47b39281 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -693,7 +693,7 @@
+   [(match_operand:VHSDF 0 "register_operand")
+    (match_operand:VHSDF 1 "register_operand")
+    (match_operand:VHSDF 2 "register_operand")]
+-  "TARGET_FLOAT && TARGET_SIMD"
++  "TARGET_SIMD"
+ {
+   rtx v_bitmask = gen_reg_rtx (mode);
+   int bits = GET_MODE_UNIT_BITSIZE (mode) - 1;
+@@ -8352,7 +8352,7 @@
+ 		 (match_operand:V16QI 1 "register_operand" "%0")
+ 		 (match_operand:V16QI 2 "register_operand" "w"))]
+          CRYPTO_AES))]
+-  "TARGET_SIMD && TARGET_AES"
++  "TARGET_AES"
+   "aes\\t%0.16b, %2.16b"
+   [(set_attr "type" "crypto_aese")]
+ )
+@@ -8361,7 +8361,7 @@
+   [(set (match_operand:V16QI 0 "register_operand" "=w")
+ 	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "w")]
+ 	 CRYPTO_AESMC))]
+-  "TARGET_SIMD && TARGET_AES"
++  "TARGET_AES"
+   "aes\\t%0.16b, %1.16b"
+   [(set_attr "type" "crypto_aesmc")]
+ )
+@@ -8380,7 +8380,7 @@
+ 		(match_operand:V16QI 2 "register_operand" "w"))]
+ 	     UNSPEC_AESE)]
+ 	UNSPEC_AESMC))]
+-  "TARGET_SIMD && TARGET_AES
++  "TARGET_AES
+    && aarch64_fusion_enabled_p (AARCH64_FUSE_AES_AESMC)"
+   "aese\\t%0.16b, %2.16b\;aesmc\\t%0.16b, %0.16b"
+   [(set_attr "type" "crypto_aese")
+@@ -8401,7 +8401,7 @@
+ 			(match_operand:V16QI 2 "register_operand" "w"))]
+ 		UNSPEC_AESD)]
+ 	  UNSPEC_AESIMC))]
+-  "TARGET_SIMD && TARGET_AES
++  "TARGET_AES
+    && aarch64_fusion_enabled_p (AARCH64_FUSE_AES_AESMC)"
+   "aesd\\t%0.16b, %2.16b\;aesimc\\t%0.16b, %0.16b"
+   [(set_attr "type" "crypto_aese")
+@@ -8415,7 +8415,7 @@
+         (unspec:SI [(match_operand:SI 1
+                        "register_operand" "w")]
+          UNSPEC_SHA1H))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha1h\\t%s0, %s1"
+   [(set_attr "type" "crypto_sha1_fast")]
+ )
+@@ -8425,7 +8425,7 @@
+ 	(unspec:SI [(vec_select:SI (match_operand:V4SI 1 "register_operand" "w")
+ 		     (parallel [(const_int 0)]))]
+ 	 UNSPEC_SHA1H))]
+-  "TARGET_SIMD && TARGET_SHA2 && !BYTES_BIG_ENDIAN"
++  "TARGET_SHA2 && !BYTES_BIG_ENDIAN"
+   "sha1h\\t%s0, %s1"
+   [(set_attr "type" "crypto_sha1_fast")]
+ )
+@@ -8435,7 +8435,7 @@
+ 	(unspec:SI [(vec_select:SI (match_operand:V4SI 1 "register_operand" "w")
+ 		     (parallel [(const_int 3)]))]
+ 	 UNSPEC_SHA1H))]
+-  "TARGET_SIMD && TARGET_SHA2 && BYTES_BIG_ENDIAN"
++  "TARGET_SHA2 && BYTES_BIG_ENDIAN"
+   "sha1h\\t%s0, %s1"
+   [(set_attr "type" "crypto_sha1_fast")]
+ )
+@@ -8445,7 +8445,7 @@
+         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0")
+                       (match_operand:V4SI 2 "register_operand" "w")]
+          UNSPEC_SHA1SU1))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha1su1\\t%0.4s, %2.4s"
+   [(set_attr "type" "crypto_sha1_fast")]
+ )
+@@ -8456,7 +8456,7 @@
+                       (match_operand:SI 2 "register_operand" "w")
+                       (match_operand:V4SI 3 "register_operand" "w")]
+          CRYPTO_SHA1))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha1\\t%q0, %s2, %3.4s"
+   [(set_attr "type" "crypto_sha1_slow")]
+ )
+@@ -8467,7 +8467,7 @@
+                       (match_operand:V4SI 2 "register_operand" "w")
+                       (match_operand:V4SI 3 "register_operand" "w")]
+          UNSPEC_SHA1SU0))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha1su0\\t%0.4s, %2.4s, %3.4s"
+   [(set_attr "type" "crypto_sha1_xor")]
+ )
+@@ -8480,7 +8480,7 @@
+                       (match_operand:V4SI 2 "register_operand" "w")
+                       (match_operand:V4SI 3 "register_operand" "w")]
+          CRYPTO_SHA256))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha256h\\t%q0, %q2, %3.4s"
+   [(set_attr "type" "crypto_sha256_slow")]
+ )
+@@ -8490,7 +8490,7 @@
+         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0")
+                       (match_operand:V4SI 2 "register_operand" "w")]
+          UNSPEC_SHA256SU0))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha256su0\\t%0.4s, %2.4s"
+   [(set_attr "type" "crypto_sha256_fast")]
+ )
+@@ -8501,7 +8501,7 @@
+                       (match_operand:V4SI 2 "register_operand" "w")
+                       (match_operand:V4SI 3 "register_operand" "w")]
+          UNSPEC_SHA256SU1))]
+-  "TARGET_SIMD && TARGET_SHA2"
++  "TARGET_SHA2"
+   "sha256su1\\t%0.4s, %2.4s, %3.4s"
+   [(set_attr "type" "crypto_sha256_slow")]
+ )
+@@ -8514,7 +8514,7 @@
+                       (match_operand:V2DI 2 "register_operand" "w")
+                       (match_operand:V2DI 3 "register_operand" "w")]
+          CRYPTO_SHA512))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "sha512h\\t%q0, %q2, %3.2d"
+   [(set_attr "type" "crypto_sha512")]
+ )
+@@ -8524,7 +8524,7 @@
+         (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "0")
+                       (match_operand:V2DI 2 "register_operand" "w")]
+          UNSPEC_SHA512SU0))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "sha512su0\\t%0.2d, %2.2d"
+   [(set_attr "type" "crypto_sha512")]
+ )
+@@ -8535,7 +8535,7 @@
+                       (match_operand:V2DI 2 "register_operand" "w")
+                       (match_operand:V2DI 3 "register_operand" "w")]
+          UNSPEC_SHA512SU1))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "sha512su1\\t%0.2d, %2.2d, %3.2d"
+   [(set_attr "type" "crypto_sha512")]
+ )
+@@ -8549,7 +8549,7 @@
+ 	  (match_operand:VQ_I 2 "register_operand" "w")
+ 	  (match_operand:VQ_I 3 "register_operand" "w"))
+ 	 (match_operand:VQ_I 1 "register_operand" "w")))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "eor3\\t%0.16b, %1.16b, %2.16b, %3.16b"
+   [(set_attr "type" "crypto_sha3")]
+ )
+@@ -8561,7 +8561,7 @@
+ 	  (match_operand:V2DI 2 "register_operand" "w")
+ 	  (const_int 1))
+ 	 (match_operand:V2DI 1 "register_operand" "w")))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "rax1\\t%0.2d, %1.2d, %2.2d"
+   [(set_attr "type" "crypto_sha3")]
+ )
+@@ -8573,7 +8573,7 @@
+ 	  (match_operand:V2DI 1 "register_operand" "%w")
+ 	  (match_operand:V2DI 2 "register_operand" "w"))
+ 	 (match_operand:SI 3 "aarch64_simd_shift_imm_di" "Usd")))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "xar\\t%0.2d, %1.2d, %2.2d, %3"
+   [(set_attr "type" "crypto_sha3")]
+ )
+@@ -8585,7 +8585,7 @@
+ 	  (not:VQ_I (match_operand:VQ_I 3 "register_operand" "w"))
+ 	  (match_operand:VQ_I 2 "register_operand" "w"))
+ 	 (match_operand:VQ_I 1 "register_operand" "w")))]
+-  "TARGET_SIMD && TARGET_SHA3"
++  "TARGET_SHA3"
+   "bcax\\t%0.16b, %1.16b, %2.16b, %3.16b"
+   [(set_attr "type" "crypto_sha3")]
+ )
+@@ -8598,7 +8598,7 @@
+ 		      (match_operand:V4SI 2 "register_operand" "w")
+ 		      (match_operand:V4SI 3 "register_operand" "w")]
+ 	 UNSPEC_SM3SS1))]
+-  "TARGET_SIMD && TARGET_SM4"
++  "TARGET_SM4"
+   "sm3ss1\\t%0.4s, %1.4s, %2.4s, %3.4s"
+   [(set_attr "type" "crypto_sm3")]
+ )
+@@ -8611,7 +8611,7 @@
+ 		      (match_operand:V4SI 3 "register_operand" "w")
+ 		      (match_operand:SI 4 "aarch64_imm2" "Ui2")]
+ 	 CRYPTO_SM3TT))]
+-  "TARGET_SIMD && TARGET_SM4"
++  "TARGET_SM4"
+   "sm3tt\\t%0.4s, %2.4s, %3.4s[%4]"
+   [(set_attr "type" "crypto_sm3")]
+ )
+@@ -8622,7 +8622,7 @@
+ 		      (match_operand:V4SI 2 "register_operand" "w")
+ 		      (match_operand:V4SI 3 "register_operand" "w")]
+ 	 CRYPTO_SM3PART))]
+-  "TARGET_SIMD && TARGET_SM4"
++  "TARGET_SM4"
+   "sm3partw\\t%0.4s, %2.4s, %3.4s"
+   [(set_attr "type" "crypto_sm3")]
+ )
+@@ -8634,7 +8634,7 @@
+ 	(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0")
+ 		      (match_operand:V4SI 2 "register_operand" "w")]
+ 	 UNSPEC_SM4E))]
+-  "TARGET_SIMD && TARGET_SM4"
++  "TARGET_SM4"
+   "sm4e\\t%0.4s, %2.4s"
+   [(set_attr "type" "crypto_sm4")]
+ )
+@@ -8644,7 +8644,7 @@
+ 	(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "w")
+ 		      (match_operand:V4SI 2 "register_operand" "w")]
+ 	 UNSPEC_SM4EKEY))]
+-  "TARGET_SIMD && TARGET_SM4"
++  "TARGET_SM4"
+   "sm4ekey\\t%0.4s, %1.4s, %2.4s"
+   [(set_attr "type" "crypto_sm4")]
+ )
+@@ -9230,7 +9230,7 @@
+         (unspec:TI  [(match_operand:DI 1 "register_operand" "w")
+ 		     (match_operand:DI 2 "register_operand" "w")]
+ 		    UNSPEC_PMULL))]
+- "TARGET_SIMD && TARGET_AES"
++ "TARGET_AES"
+  "pmull\\t%0.1q, %1.1d, %2.1d"
+   [(set_attr "type" "crypto_pmull")]
+ )
+@@ -9240,7 +9240,7 @@
+        (unspec:TI [(match_operand:V2DI 1 "register_operand" "w")
+ 		   (match_operand:V2DI 2 "register_operand" "w")]
+ 		  UNSPEC_PMULL2))]
+-  "TARGET_SIMD && TARGET_AES"
++  "TARGET_AES"
+   "pmull2\\t%0.1q, %1.2d, %2.2d"
+   [(set_attr "type" "crypto_pmull")]
+ )
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 521031efe..2a9d2d031 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -222,19 +222,19 @@ enum class aarch64_feature : unsigned char {
+ #define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
+ 
+ /* Crypto is an optional extension to AdvSIMD.  */
+-#define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
++#define TARGET_CRYPTO (AARCH64_ISA_CRYPTO)
+ 
+ /* SHA2 is an optional extension to AdvSIMD.  */
+-#define TARGET_SHA2 ((TARGET_SIMD && AARCH64_ISA_SHA2) || TARGET_CRYPTO)
++#define TARGET_SHA2 (AARCH64_ISA_SHA2)
+ 
+ /* SHA3 is an optional extension to AdvSIMD.  */
+-#define TARGET_SHA3 (TARGET_SIMD && AARCH64_ISA_SHA3)
++#define TARGET_SHA3 (AARCH64_ISA_SHA3)
+ 
+ /* AES is an optional extension to AdvSIMD.  */
+-#define TARGET_AES ((TARGET_SIMD && AARCH64_ISA_AES) || TARGET_CRYPTO)
++#define TARGET_AES (AARCH64_ISA_AES)
+ 
+ /* SM is an optional extension to AdvSIMD.  */
+-#define TARGET_SM4 (TARGET_SIMD && AARCH64_ISA_SM4)
++#define TARGET_SM4 (AARCH64_ISA_SM4)
+ 
+ /* FP16FML is an optional extension to AdvSIMD.  */
+ #define TARGET_F16FML (TARGET_SIMD && AARCH64_ISA_F16FML && TARGET_FP_F16INST)
+@@ -246,29 +246,29 @@ enum class aarch64_feature : unsigned char {
+ #define TARGET_LSE (AARCH64_ISA_LSE)
+ 
+ /* ARMv8.2-A FP16 support that can be enabled through the +fp16 extension.  */
+-#define TARGET_FP_F16INST (TARGET_FLOAT && AARCH64_ISA_F16)
++#define TARGET_FP_F16INST (AARCH64_ISA_F16)
+ #define TARGET_SIMD_F16INST (TARGET_SIMD && AARCH64_ISA_F16)
+ 
+ /* Dot Product is an optional extension to AdvSIMD enabled through +dotprod.  */
+-#define TARGET_DOTPROD (TARGET_SIMD && AARCH64_ISA_DOTPROD)
++#define TARGET_DOTPROD (AARCH64_ISA_DOTPROD)
+ 
+ /* SVE instructions, enabled through +sve.  */
+ #define TARGET_SVE (AARCH64_ISA_SVE)
+ 
+ /* SVE2 instructions, enabled through +sve2.  */
+-#define TARGET_SVE2 (TARGET_SVE && AARCH64_ISA_SVE2)
++#define TARGET_SVE2 (AARCH64_ISA_SVE2)
+ 
+ /* SVE2 AES instructions, enabled through +sve2-aes.  */
+-#define TARGET_SVE2_AES (TARGET_SVE2 && AARCH64_ISA_SVE2_AES)
++#define TARGET_SVE2_AES (AARCH64_ISA_SVE2_AES)
+ 
+ /* SVE2 BITPERM instructions, enabled through +sve2-bitperm.  */
+-#define TARGET_SVE2_BITPERM (TARGET_SVE2 && AARCH64_ISA_SVE2_BITPERM)
++#define TARGET_SVE2_BITPERM (AARCH64_ISA_SVE2_BITPERM)
+ 
+ /* SVE2 SHA3 instructions, enabled through +sve2-sha3.  */
+-#define TARGET_SVE2_SHA3 (TARGET_SVE2 && AARCH64_ISA_SVE2_SHA3)
++#define TARGET_SVE2_SHA3 (AARCH64_ISA_SVE2_SHA3)
+ 
+ /* SVE2 SM4 instructions, enabled through +sve2-sm4.  */
+-#define TARGET_SVE2_SM4 (TARGET_SVE2 && AARCH64_ISA_SVE2_SM4)
++#define TARGET_SVE2_SM4 (AARCH64_ISA_SVE2_SM4)
+ 
+ /* ARMv8.3-A features.  */
+ #define TARGET_ARMV8_3	(AARCH64_ISA_V8_3A)
+@@ -296,12 +296,10 @@ enum class aarch64_feature : unsigned char {
+ #define TARGET_SVE_I8MM (TARGET_SVE && AARCH64_ISA_I8MM)
+ 
+ /* F32MM instructions are enabled through +f32mm.  */
+-#define TARGET_F32MM (AARCH64_ISA_F32MM)
+-#define TARGET_SVE_F32MM (TARGET_SVE && AARCH64_ISA_F32MM)
++#define TARGET_SVE_F32MM (AARCH64_ISA_F32MM)
+ 
+ /* F64MM instructions are enabled through +f64mm.  */
+-#define TARGET_F64MM (AARCH64_ISA_F64MM)
+-#define TARGET_SVE_F64MM (TARGET_SVE && AARCH64_ISA_F64MM)
++#define TARGET_SVE_F64MM (AARCH64_ISA_F64MM)
+ 
+ /* BF16 instructions are enabled through +bf16.  */
+ #define TARGET_BF16_FP (AARCH64_ISA_BF16)
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index c0c64a798..7ee26284d 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -6417,7 +6417,7 @@
+ (define_expand "dihf2"
+   [(set (match_operand:HF 0 "register_operand")
+ 	(FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
+-  "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
++  "TARGET_FP_F16INST || TARGET_SIMD"
+ {
+   if (TARGET_FP_F16INST)
+     emit_insn (gen_aarch64_fp16_dihf2 (operands[0], operands[1]));
+@@ -6676,7 +6676,7 @@
+   [(match_operand:GPF 0 "register_operand")
+    (match_operand:GPF 1 "register_operand")
+    (match_operand:GPF 2 "register_operand")]
+-  "TARGET_FLOAT && TARGET_SIMD"
++  "TARGET_SIMD"
+ {
+   rtx bitmask = gen_reg_rtx (mode);
+   emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
+@@ -6693,7 +6693,7 @@
+ 		     (match_operand:GPF 2 "register_operand" "w,w,0,0")
+ 		     (match_operand: 3 "register_operand" "0,w,w,X")]
+ 	 UNSPEC_COPYSIGN))]
+-  "TARGET_FLOAT && TARGET_SIMD"
++  "TARGET_SIMD"
+   "@
+    bsl\\t%0., %2., %1.
+    bit\\t%0., %2., %3.
+@@ -6714,7 +6714,7 @@
+   [(match_operand:GPF 0 "register_operand")
+    (match_operand:GPF 1 "register_operand")
+    (match_operand:GPF 2 "register_operand")]
+-  "TARGET_FLOAT && TARGET_SIMD"
++  "TARGET_SIMD"
+ {
+ 
+   machine_mode imode = mode;
+-- 
+2.33.0
+
diff --git a/0126-Backport-SME-aarch64-Define-__ARM_FEATURE_RCPC.patch b/0126-Backport-SME-aarch64-Define-__ARM_FEATURE_RCPC.patch
new file mode 100644
index 0000000..8fe079c
--- /dev/null
+++ b/0126-Backport-SME-aarch64-Define-__ARM_FEATURE_RCPC.patch
@@ -0,0 +1,132 @@
+From 53a858c0c371cbea27ed4170a94fb3918b9fcdcf Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 4 Oct 2022 16:39:18 +0100
+Subject: [PATCH 027/157] [Backport][SME] aarch64: Define __ARM_FEATURE_RCPC
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c1b0a767f04a8ccbaff2a7b71d5c817cdb469630
+
+https://github.com/ARM-software/acle/pull/199 adds a new feature
+macro for RCPC, for use in things like inline assembly.  This patch
+adds the associated support to GCC.
+
+Also, RCPC is required for Armv8.3-A and later, but the armv8.3-a
+entry didn't include it.  This was probably harmless in practice
+since GCC simply ignored the extension until now.  (The GAS
+definition is OK.)
+
+gcc/
+	* config/aarch64/aarch64.h (AARCH64_ISA_RCPC): New macro.
+	* config/aarch64/aarch64-arches.def (armv8.3-a): Include RCPC.
+	* config/aarch64/aarch64-cores.def (thunderx3t110, zeus, neoverse-v1)
+	(neoverse-512tvb, saphira): Remove RCPC from these Armv8.3-A+ cores.
+	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Define
+	__ARM_FEATURE_RCPC when appropriate.
+
+gcc/testsuite/
+	* gcc.target/aarch64/pragma_cpp_predefs_1.c: Add RCPC tests.
+---
+ gcc/config/aarch64/aarch64-arches.def         |  2 +-
+ gcc/config/aarch64/aarch64-c.cc               |  1 +
+ gcc/config/aarch64/aarch64-cores.def          | 10 +++++-----
+ gcc/config/aarch64/aarch64.h                  |  1 +
+ .../gcc.target/aarch64/pragma_cpp_predefs_1.c | 20 +++++++++++++++++++
+ 5 files changed, 28 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def
+index 9f8246618..5a9eff336 100644
+--- a/gcc/config/aarch64/aarch64-arches.def
++++ b/gcc/config/aarch64/aarch64-arches.def
+@@ -33,7 +33,7 @@
+ AARCH64_ARCH("armv8-a",       generic,       V8A,       8,  (SIMD))
+ AARCH64_ARCH("armv8.1-a",     generic,       V8_1A,     8,  (V8A, LSE, CRC, RDMA))
+ AARCH64_ARCH("armv8.2-a",     generic,       V8_2A,     8,  (V8_1A))
+-AARCH64_ARCH("armv8.3-a",     generic,       V8_3A,     8,  (V8_2A, PAUTH))
++AARCH64_ARCH("armv8.3-a",     generic,       V8_3A,     8,  (V8_2A, PAUTH, RCPC))
+ AARCH64_ARCH("armv8.4-a",     generic,       V8_4A,     8,  (V8_3A, F16FML, DOTPROD, FLAGM))
+ AARCH64_ARCH("armv8.5-a",     generic,       V8_5A,     8,  (V8_4A, SB, SSBS, PREDRES))
+ AARCH64_ARCH("armv8.6-a",     generic,       V8_6A,     8,  (V8_5A, I8MM, BF16))
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 2dfe2b8f8..4085ad840 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -202,6 +202,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ 			"__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile);
+   aarch64_def_or_undef (TARGET_LS64,
+ 			"__ARM_FEATURE_LS64", pfile);
++  aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile);
+ 
+   /* Not for ACLE, but required to keep "float.h" correct if we switch
+      target between implementations that do or do not support ARMv8.2-A
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index 60299160b..b50628d6b 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -133,17 +133,17 @@ AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  (CRYPTO, F16), tsv110,   0x48, 0
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+ /* Marvell cores (TX3). */
+-AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  (CRYPTO, RCPC, SM4, SHA3, F16FML), thunderx3t110, 0x43, 0x0b8, 0x0a)
++AARCH64_CORE("thunderx3t110",  thunderx3t110,  thunderx3t110, V8_3A,  (CRYPTO, SM4, SHA3, F16FML), thunderx3t110, 0x43, 0x0b8, 0x0a)
+ 
+ /* ARMv8.4-A Architecture Processors.  */
+ 
+ /* Arm ('A') cores.  */
+-AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1)
+-AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  (SVE, RCPC, I8MM, BF16, PROFILE, SSBS, RNG), neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
++AARCH64_CORE("zeus", zeus, cortexa57, V8_4A,  (SVE, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-v1", neoversev1, cortexa57, V8_4A,  (SVE, I8MM, BF16, PROFILE, SSBS, RNG), neoversev1, 0x41, 0xd40, -1)
++AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, V8_4A,  (SVE, I8MM, BF16, PROFILE, SSBS, RNG), neoverse512tvb, INVALID_IMP, INVALID_CORE, -1)
+ 
+ /* Qualcomm ('Q') cores. */
+-AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  (CRYPTO, RCPC), saphira,   0x51, 0xC01, -1)
++AARCH64_CORE("saphira",     saphira,    saphira,    V8_4A,  (CRYPTO), saphira,   0x51, 0xC01, -1)
+ 
+ /* ARMv8-A big.LITTLE implementations.  */
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 2a9d2d031..19b82b4f3 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -201,6 +201,7 @@ enum class aarch64_feature : unsigned char {
+ #define AARCH64_ISA_SM4	           (aarch64_isa_flags & AARCH64_FL_SM4)
+ #define AARCH64_ISA_SHA3	   (aarch64_isa_flags & AARCH64_FL_SHA3)
+ #define AARCH64_ISA_F16FML	   (aarch64_isa_flags & AARCH64_FL_F16FML)
++#define AARCH64_ISA_RCPC	   (aarch64_isa_flags & AARCH64_FL_RCPC)
+ #define AARCH64_ISA_RCPC8_4	   (aarch64_isa_flags & AARCH64_FL_V8_4A)
+ #define AARCH64_ISA_RNG		   (aarch64_isa_flags & AARCH64_FL_RNG)
+ #define AARCH64_ISA_V8_5A	   (aarch64_isa_flags & AARCH64_FL_V8_5A)
+diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c
+index bfb044f5d..307fa3d67 100644
+--- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_1.c
+@@ -248,6 +248,26 @@
+ #error "__ARM_FEATURE_CRC32 is not defined but should be!"
+ #endif
+ 
++#pragma GCC target ("arch=armv8.2-a")
++#ifdef __ARM_FEATURE_RCPC
++#error "__ARM_FEATURE_RCPC is defined but should not be!"
++#endif
++
++#pragma GCC target ("arch=armv8.2-a+rcpc")
++#ifndef __ARM_FEATURE_RCPC
++#error "__ARM_FEATURE_RCPC is not defined but should be!"
++#endif
++
++#pragma GCC target ("+norcpc")
++#ifdef __ARM_FEATURE_RCPC
++#error "__ARM_FEATURE_RCPC is defined but should not be!"
++#endif
++
++#pragma GCC target ("arch=armv8.3-a")
++#ifndef __ARM_FEATURE_RCPC
++#error "__ARM_FEATURE_RCPC is not defined but should be!"
++#endif
++
+ int
+ foo (int a)
+ {
+-- 
+2.33.0
+
diff --git a/0127-Backport-SME-Add-Ampere-1-and-Ampere-1A-core-definit.patch b/0127-Backport-SME-Add-Ampere-1-and-Ampere-1A-core-definit.patch
new file mode 100644
index 0000000..d317791
--- /dev/null
+++ b/0127-Backport-SME-Add-Ampere-1-and-Ampere-1A-core-definit.patch
@@ -0,0 +1,29 @@
+From f6b2917888292c694bae1debe8abb0d6c2c6f59e Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Tue, 20 Feb 2024 11:03:47 +0800
+Subject: [PATCH 028/157] [Backport][SME] Add Ampere-1 and Ampere-1A core
+ definition in aarch64-cores.def
+
+From commit db2f5d661239737157cf131de7d4df1c17d8d88d and
+590a06afbf0e96813b5879742f38f3665512c854
+---
+ gcc/config/aarch64/aarch64-cores.def | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index b50628d6b..f069c81cf 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -69,7 +69,8 @@ AARCH64_CORE("thunderxt81",   thunderxt81,   thunderx,  V8A,  (CRC, CRYPTO), thu
+ AARCH64_CORE("thunderxt83",   thunderxt83,   thunderx,  V8A,  (CRC, CRYPTO), thunderx,  0x43, 0x0a3, -1)
+ 
+ /* Ampere Computing ('\xC0') cores. */
+-AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, (), ampere1, 0xC0, 0xac3, -1)
++AARCH64_CORE("ampere1", ampere1, cortexa57, V8_6A, (F16, RNG, AES, SHA3), ampere1, 0xC0, 0xac3, -1)
++AARCH64_CORE("ampere1a", ampere1a, cortexa57, V8_6A, (F16, RNG, AES, SHA3, MEMTAG), ampere1a, 0xC0, 0xac4, -1)
+ /* Do not swap around "emag" and "xgene1",
+    this order is required to handle variant correctly. */
+ AARCH64_CORE("emag",        emag,      xgene1,    V8A,  (CRC, CRYPTO), emag, 0x50, 0x000, 3)
+-- 
+2.33.0
+
diff --git a/0128-Backport-SME-aarch64-Fix-nosimd-handling-of-FPR-move.patch b/0128-Backport-SME-aarch64-Fix-nosimd-handling-of-FPR-move.patch
new file mode 100644
index 0000000..9ad166c
--- /dev/null
+++ b/0128-Backport-SME-aarch64-Fix-nosimd-handling-of-FPR-move.patch
@@ -0,0 +1,968 @@
+From 81a4b464d01cf00f8b355115588e67bf2c021acd Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Wed, 7 Sep 2022 10:52:04 +0100
+Subject: [PATCH 029/157] [Backport][SME] aarch64: Fix +nosimd handling of FPR
+ moves
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=d6106132907f6bd01109f2616d20a87edecc6fc6
+
+8-bit and 16-bit FPR moves would ICE for +nosimd+fp, and some other
+moves would handle FPR<-zero inefficiently.  This is very much a
+niche case at the moment, but something like it becomes more
+important with SME streaming mode.
+
+The si, di and vector tests already passed, they're just included for
+completeness.
+
+We're a bit inconsistent about whether alternatives involving FPRs
+are marked with arch==fp or arch=* (i.e. default).  E.g. FPR loads
+and stores are sometimes * and sometimes fp.
+
+IMO * makes more sense.  FPRs should not be used at all without
+TARGET_FLOAT, so TARGET_FLOAT represents the base architecture
+when FPRs are enabled.  I think it's more useful if non-default
+arches represent a genuine restriction.
+
+gcc/
+	* config/aarch64/aarch64.md (*mov_aarch64): Extend
+	w<-w, r<-w and w<-r alternatives to !simd, using 32-bit moves
+	in that case.  Extend w<-r to w<-Z.
+	(*mov_aarch64): Likewise, but with Y instead of Z.
+	(*movti_aarch64): Use an FMOV from XZR for w<-Z if MOVI is not
+	available.
+	(define_split): Do not apply the floating-point immediate-to-register
+	split to zeros, even if MOVI is not available.
+
+gcc/testsuite/
+	* gcc.target/aarch64/movqi_1.c: New test.
+	* gcc.target/aarch64/movhi_1.c: Likewise.
+	* gcc.target/aarch64/movsi_1.c: Likewise.
+	* gcc.target/aarch64/movdi_2.c: Likewise.
+	* gcc.target/aarch64/movti_2.c: Likewise.
+	* gcc.target/aarch64/movhf_1.c: Likewise.
+	* gcc.target/aarch64/movsf_1.c: Likewise.
+	* gcc.target/aarch64/movdf_1.c: Likewise.
+	* gcc.target/aarch64/movtf_2.c: Likewise.
+	* gcc.target/aarch64/movv8qi_1.c: Likewise.
+	* gcc.target/aarch64/movv16qi_1.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.md                 | 38 ++++----
+ gcc/testsuite/gcc.target/aarch64/movdf_1.c    | 53 ++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movdi_2.c    | 61 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movhf_1.c    | 53 ++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movhi_1.c    | 61 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movqi_1.c    | 61 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movsf_1.c    | 53 ++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movsi_1.c    | 61 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movtf_2.c    | 81 +++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movti_2.c    | 86 +++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movv16qi_1.c | 82 ++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movv8qi_1.c  | 55 ++++++++++++
+ 12 files changed, 729 insertions(+), 16 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movdf_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movdi_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movhf_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movhi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movqi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movsf_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movsi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movtf_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movti_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv16qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv8qi_1.c
+
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 7ee26284d..7267a74d6 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1201,7 +1201,7 @@
+ 
+ (define_insn "*mov_aarch64"
+   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,    w,r  ,r,w, m,m,r,w,w")
+-	(match_operand:SHORT 1 "aarch64_mov_operand"  " r,M,D,Usv,m,m,rZ,w,w,r,w"))]
++	(match_operand:SHORT 1 "aarch64_mov_operand"  " r,M,D,Usv,m,m,rZ,w,w,rZ,w"))]
+   "(register_operand (operands[0], mode)
+     || aarch64_reg_or_zero (operands[1], mode))"
+ {
+@@ -1225,11 +1225,11 @@
+      case 7:
+        return "str\t%1, %0";
+      case 8:
+-       return "umov\t%w0, %1.[0]";
++       return TARGET_SIMD ? "umov\t%w0, %1.[0]" : "fmov\t%w0, %s1";
+      case 9:
+-       return "dup\t%0., %w1";
++       return TARGET_SIMD ? "dup\t%0., %w1" : "fmov\t%s0, %w1";
+      case 10:
+-       return "dup\t%0, %1.[0]";
++       return TARGET_SIMD ? "dup\t%0, %1.[0]" : "fmov\t%s0, %s1";
+      default:
+        gcc_unreachable ();
+      }
+@@ -1237,7 +1237,7 @@
+   ;; The "mov_imm" type for CNT is just a placeholder.
+   [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
+ 		     store_4,neon_to_gp,neon_from_gp,neon_dup")
+-   (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
++   (set_attr "arch" "*,*,simd,sve,*,*,*,*,*,*,*")]
+ )
+ 
+ (define_expand "mov"
+@@ -1399,14 +1399,15 @@
+ 
+ (define_insn "*movti_aarch64"
+   [(set (match_operand:TI 0
+-	 "nonimmediate_operand"  "=   r,w,w, r,w,r,m,m,w,m")
++	 "nonimmediate_operand"  "=   r,w,w,w, r,w,r,m,m,w,m")
+ 	(match_operand:TI 1
+-	 "aarch64_movti_operand" " rUti,Z,r, w,w,m,r,Z,m,w"))]
++	 "aarch64_movti_operand" " rUti,Z,Z,r, w,w,m,r,Z,m,w"))]
+   "(register_operand (operands[0], TImode)
+     || aarch64_reg_or_zero (operands[1], TImode))"
+   "@
+    #
+    movi\\t%0.2d, #0
++   fmov\t%d0, xzr
+    #
+    #
+    mov\\t%0.16b, %1.16b
+@@ -1415,11 +1416,11 @@
+    stp\\txzr, xzr, %0
+    ldr\\t%q0, %1
+    str\\t%q1, %0"
+-  [(set_attr "type" "multiple,neon_move,f_mcr,f_mrc,neon_logic_q, \
++  [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q, \
+ 		             load_16,store_16,store_16,\
+                              load_16,store_16")
+-   (set_attr "length" "8,4,8,8,4,4,4,4,4,4")
+-   (set_attr "arch" "*,simd,*,*,simd,*,*,*,fp,fp")]
++   (set_attr "length" "8,4,4,8,8,4,4,4,4,4,4")
++   (set_attr "arch" "*,simd,*,*,*,simd,*,*,*,fp,fp")]
+ )
+ 
+ ;; Split a TImode register-register or register-immediate move into
+@@ -1458,16 +1459,19 @@
+ )
+ 
+ (define_insn "*mov_aarch64"
+-  [(set (match_operand:HFBF 0 "nonimmediate_operand" "=w,w  , w,?r,w,w  ,w  ,w,m,r,m ,r")
+-	(match_operand:HFBF 1 "general_operand"      "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
++  [(set (match_operand:HFBF 0 "nonimmediate_operand" "=w,w  ,w ,w  ,?r,?r,w,w,w  ,w  ,w,m,r,m ,r")
++	(match_operand:HFBF 1 "general_operand"      "Y ,?rY,?r,?rY, w, w,w,w,Ufc,Uvi,m,w,m,rY,r"))]
+   "TARGET_FLOAT && (register_operand (operands[0], mode)
+     || aarch64_reg_or_fp_zero (operands[1], mode))"
+   "@
+    movi\\t%0.4h, #0
+    fmov\\t%h0, %w1
+    dup\\t%w0.4h, %w1
++   fmov\\t%s0, %w1
+    umov\\t%w0, %1.h[0]
++   fmov\\t%w0, %s1
+    mov\\t%0.h[0], %1.h[0]
++   fmov\\t%s0, %s1
+    fmov\\t%h0, %1
+    * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
+    ldr\\t%h0, %1
+@@ -1475,9 +1479,10 @@
+    ldrh\\t%w0, %1
+    strh\\t%w1, %0
+    mov\\t%w0, %w1"
+-  [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
+-		     neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
+-   (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
++  [(set_attr "type" "neon_move,f_mcr,neon_move,f_mcr,neon_to_gp,f_mrc,
++		     neon_move,fmov,fconsts,neon_move,f_loads,f_stores,
++		     load_4,store_4,mov_reg")
++   (set_attr "arch" "simd,fp16,simd,*,simd,*,simd,*,fp16,simd,*,*,*,*,*")]
+ )
+ 
+ (define_insn "*movsf_aarch64"
+@@ -1530,10 +1535,11 @@
+ 
+ (define_split
+   [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
+-	(match_operand:GPF_HF 1 "general_operand"))]
++	(match_operand:GPF_HF 1 "const_double_operand"))]
+   "can_create_pseudo_p ()
+    && !aarch64_can_const_movi_rtx_p (operands[1], mode)
+    && !aarch64_float_const_representable_p (operands[1])
++   && !aarch64_float_const_zero_rtx_p (operands[1])
+    &&  aarch64_float_const_rtx_p (operands[1])"
+   [(const_int 0)]
+   {
+diff --git a/gcc/testsuite/gcc.target/aarch64/movdf_1.c b/gcc/testsuite/gcc.target/aarch64/movdf_1.c
+new file mode 100644
+index 000000000..a51ded1d6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movdf_1.c
+@@ -0,0 +1,53 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++/*
++** fpr_to_fpr:
++**	fmov	d0, d1
++**	ret
++*/
++double
++fpr_to_fpr (double q0, double q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	d0, x0
++**	ret
++*/
++double
++gpr_to_fpr ()
++{
++  register double x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++double
++zero_to_fpr ()
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	x0, d0
++**	ret
++*/
++void
++fpr_to_gpr (double q0)
++{
++  register double x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movdi_2.c b/gcc/testsuite/gcc.target/aarch64/movdi_2.c
+new file mode 100644
+index 000000000..dd3fc3e8a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movdi_2.c
+@@ -0,0 +1,61 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	d0, d1
++**	ret
++*/
++void
++fpr_to_fpr (void)
++{
++  register uint64_t q0 asm ("q0");
++  register uint64_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	d0, x0
++**	ret
++*/
++void
++gpr_to_fpr (uint64_t x0)
++{
++  register uint64_t q0 asm ("q0");
++  q0 = x0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++void
++zero_to_fpr ()
++{
++  register uint64_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	x0, d0
++**	ret
++*/
++uint64_t
++fpr_to_gpr ()
++{
++  register uint64_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movhf_1.c b/gcc/testsuite/gcc.target/aarch64/movhf_1.c
+new file mode 100644
+index 000000000..cae25d4e5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movhf_1.c
+@@ -0,0 +1,53 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++_Float16
++fpr_to_fpr (_Float16 q0, _Float16 q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++_Float16
++gpr_to_fpr ()
++{
++  register _Float16 w0 asm ("w0");
++  asm volatile ("" : "=r" (w0));
++  return w0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++_Float16
++zero_to_fpr ()
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++void
++fpr_to_gpr (_Float16 q0)
++{
++  register _Float16 w0 asm ("w0");
++  w0 = q0;
++  asm volatile ("" :: "r" (w0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movhi_1.c b/gcc/testsuite/gcc.target/aarch64/movhi_1.c
+new file mode 100644
+index 000000000..8017abc5f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movhi_1.c
+@@ -0,0 +1,61 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++void
++fpr_to_fpr (void)
++{
++  register uint16_t q0 asm ("q0");
++  register uint16_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++void
++gpr_to_fpr (uint16_t w0)
++{
++  register uint16_t q0 asm ("q0");
++  q0 = w0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++void
++zero_to_fpr ()
++{
++  register uint16_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++uint16_t
++fpr_to_gpr ()
++{
++  register uint16_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movqi_1.c b/gcc/testsuite/gcc.target/aarch64/movqi_1.c
+new file mode 100644
+index 000000000..401a79630
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movqi_1.c
+@@ -0,0 +1,61 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++void
++fpr_to_fpr (void)
++{
++  register uint8_t q0 asm ("q0");
++  register uint8_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++void
++gpr_to_fpr (uint8_t w0)
++{
++  register uint8_t q0 asm ("q0");
++  q0 = w0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++void
++zero_to_fpr ()
++{
++  register uint8_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++uint8_t
++fpr_to_gpr ()
++{
++  register uint8_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movsf_1.c b/gcc/testsuite/gcc.target/aarch64/movsf_1.c
+new file mode 100644
+index 000000000..09715aa4f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movsf_1.c
+@@ -0,0 +1,53 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++float
++fpr_to_fpr (float q0, float q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++float
++gpr_to_fpr ()
++{
++  register float w0 asm ("w0");
++  asm volatile ("" : "=r" (w0));
++  return w0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++float
++zero_to_fpr ()
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++void
++fpr_to_gpr (float q0)
++{
++  register float w0 asm ("w0");
++  w0 = q0;
++  asm volatile ("" :: "r" (w0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movsi_1.c b/gcc/testsuite/gcc.target/aarch64/movsi_1.c
+new file mode 100644
+index 000000000..5314139aa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movsi_1.c
+@@ -0,0 +1,61 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++void
++fpr_to_fpr (void)
++{
++  register uint32_t q0 asm ("q0");
++  register uint32_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++void
++gpr_to_fpr (uint32_t w0)
++{
++  register uint32_t q0 asm ("q0");
++  q0 = w0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++void
++zero_to_fpr ()
++{
++  register uint32_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++uint32_t
++fpr_to_gpr ()
++{
++  register uint32_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movtf_2.c b/gcc/testsuite/gcc.target/aarch64/movtf_2.c
+new file mode 100644
+index 000000000..38b16358d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movtf_2.c
+@@ -0,0 +1,81 @@
++/* { dg-do assemble } */
++/* { dg-require-effective-target large_long_double } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++long double
++fpr_to_fpr (long double q0, long double q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++long double
++gpr_to_fpr ()
++{
++  register long double x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++long double
++zero_to_fpr ()
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++void
++fpr_to_gpr (long double q0)
++{
++  register long double x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movti_2.c b/gcc/testsuite/gcc.target/aarch64/movti_2.c
+new file mode 100644
+index 000000000..c393b1220
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movti_2.c
+@@ -0,0 +1,86 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++void
++fpr_to_fpr (void)
++{
++  register __int128_t q0 asm ("q0");
++  register __int128_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++void
++gpr_to_fpr (__int128_t x0)
++{
++  register __int128_t q0 asm ("q0");
++  q0 = x0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++void
++zero_to_fpr ()
++{
++  register __int128_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++__int128_t
++fpr_to_gpr ()
++{
++  register __int128_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c
+new file mode 100644
+index 000000000..8a6afb13b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c
+@@ -0,0 +1,82 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++typedef unsigned char v16qi __attribute__((vector_size(16)));
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++v16qi
++fpr_to_fpr (v16qi q0, v16qi q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++v16qi
++gpr_to_fpr ()
++{
++  register v16qi x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++v16qi
++zero_to_fpr ()
++{
++  return (v16qi) {};
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++void
++fpr_to_gpr (v16qi q0)
++{
++  register v16qi x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c
+new file mode 100644
+index 000000000..4c97e6fbc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c
+@@ -0,0 +1,55 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++typedef unsigned char v8qi __attribute__((vector_size(8)));
++
++/*
++** fpr_to_fpr:
++**	fmov	d0, d1
++**	ret
++*/
++v8qi
++fpr_to_fpr (v8qi q0, v8qi q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	d0, x0
++**	ret
++*/
++v8qi
++gpr_to_fpr ()
++{
++  register v8qi x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++v8qi
++zero_to_fpr ()
++{
++  return (v8qi) {};
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	x0, d0
++**	ret
++*/
++void
++fpr_to_gpr (v8qi q0)
++{
++  register v8qi x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+-- 
+2.33.0
+
diff --git a/0129-Backport-SME-aarch64-Commonise-some-folding-code.patch b/0129-Backport-SME-aarch64-Commonise-some-folding-code.patch
new file mode 100644
index 0000000..01fb18d
--- /dev/null
+++ b/0129-Backport-SME-aarch64-Commonise-some-folding-code.patch
@@ -0,0 +1,83 @@
+From 805a7aec3ddab49b92bf2d5c1a3e288860cc14bf Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 20 Oct 2022 10:37:35 +0100
+Subject: [PATCH 030/157] [Backport][SME] aarch64: Commonise some folding code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=df99e9e42094dee0833ac38f53e7fae09b4d133c
+
+Add an aarch64_sve::gimple_folder helper for folding calls
+to integer constants.  SME will make more use of this.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h
+	(gimple_folder::fold_to_cstu): New member function.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(gimple_folder::fold_to_cstu): Define.
+	* config/aarch64/aarch64-sve-builtins-base.cc
+	(svcnt_bhwd_impl::fold): Use it.
+---
+ gcc/config/aarch64/aarch64-sve-builtins-base.cc | 9 ++-------
+ gcc/config/aarch64/aarch64-sve-builtins.cc      | 7 +++++++
+ gcc/config/aarch64/aarch64-sve-builtins.h       | 1 +
+ 3 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+index c24c05487..56c9d75e7 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+@@ -516,9 +516,7 @@ public:
+   gimple *
+   fold (gimple_folder &f) const OVERRIDE
+   {
+-    tree count = build_int_cstu (TREE_TYPE (f.lhs),
+-				 GET_MODE_NUNITS (m_ref_mode));
+-    return gimple_build_assign (f.lhs, count);
++    return f.fold_to_cstu (GET_MODE_NUNITS (m_ref_mode));
+   }
+ 
+   rtx
+@@ -553,10 +551,7 @@ public:
+     unsigned int elements_per_vq = 128 / GET_MODE_UNIT_BITSIZE (m_ref_mode);
+     HOST_WIDE_INT value = aarch64_fold_sve_cnt_pat (pattern, elements_per_vq);
+     if (value >= 0)
+-      {
+-	tree count = build_int_cstu (TREE_TYPE (f.lhs), value);
+-	return gimple_build_assign (f.lhs, count);
+-      }
++      return f.fold_to_cstu (value);
+ 
+     return NULL;
+   }
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index a70e3a6b4..e168c8334 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -2615,6 +2615,13 @@ gimple_folder::redirect_call (const function_instance &instance)
+   return call;
+ }
+ 
++/* Fold the call to constant VAL.  */
++gimple *
++gimple_folder::fold_to_cstu (poly_uint64 val)
++{
++  return gimple_build_assign (lhs, build_int_cstu (TREE_TYPE (lhs), val));
++}
++
+ /* Fold the call to a PTRUE, taking the element size from type suffix 0.  */
+ gimple *
+ gimple_folder::fold_to_ptrue ()
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 63d1db776..0d130b871 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -500,6 +500,7 @@ public:
+   tree load_store_cookie (tree);
+ 
+   gimple *redirect_call (const function_instance &);
++  gimple *fold_to_cstu (poly_uint64);
+   gimple *fold_to_pfalse ();
+   gimple *fold_to_ptrue ();
+   gimple *fold_to_vl_pred (unsigned int);
+-- 
+2.33.0
+
diff --git a/0130-Backport-SME-aarch64-Add-a-Z-operand-modifier-for-SV.patch b/0130-Backport-SME-aarch64-Add-a-Z-operand-modifier-for-SV.patch
new file mode 100644
index 0000000..bea41d9
--- /dev/null
+++ b/0130-Backport-SME-aarch64-Add-a-Z-operand-modifier-for-SV.patch
@@ -0,0 +1,49 @@
+From 8dc1eee26c61bea8aab62080bd961825142685f9 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 7 Nov 2023 15:22:57 +0000
+Subject: [PATCH 031/157] [Backport][SME] aarch64: Add a %Z operand modifier
+ for SVE registers
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f40eac535bd55192cf93daca16235efbcd91157a
+
+This patch adds a %Z operand modifier that prints registers as SVE z
+registers.  The SME patches need this, but so do Tamar's patches.
+I'm separating this out to unblock those.
+
+We should probably document the [wxbhsdqZ] modifiers as
+user-facing, but doing that for all of them is a separate patch.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_print_operand): Add a %Z
+	modifier for SVE registers.
+---
+ gcc/config/aarch64/aarch64.cc | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 3e83e48ec..fd1114b52 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -11901,6 +11901,10 @@ sizetochar (int size)
+      'N':		Take the duplicated element in a vector constant
+ 			and print the negative of it in decimal.
+      'b/h/s/d/q':	Print a scalar FP/SIMD register name.
++     'Z':		Same for SVE registers.  ('z' was already taken.)
++			Note that it is not necessary to use %Z for operands
++			that have SVE modes.  The convention is to use %Z
++			only for non-SVE (or potentially non-SVE) modes.
+      'S/T/U/V':		Print a FP/SIMD register name for a register list.
+ 			The register printed is the FP/SIMD register name
+ 			of X + 0/1/2/3 for S/T/U/V.
+@@ -12073,6 +12077,8 @@ aarch64_print_operand (FILE *f, rtx x, int code)
+     case 's':
+     case 'd':
+     case 'q':
++    case 'Z':
++      code = TOLOWER (code);
+       if (!REG_P (x) || !FP_REGNUM_P (REGNO (x)))
+ 	{
+ 	  output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code);
+-- 
+2.33.0
+
diff --git a/0131-Backport-SME-mode-switching-Remove-unused-bbnum-fiel.patch b/0131-Backport-SME-mode-switching-Remove-unused-bbnum-fiel.patch
new file mode 100644
index 0000000..15c8418
--- /dev/null
+++ b/0131-Backport-SME-mode-switching-Remove-unused-bbnum-fiel.patch
@@ -0,0 +1,104 @@
+From 8a43bd7885ce479cadb0643fbb0fc22d2b0ffced Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sun, 5 Nov 2023 18:28:46 +0000
+Subject: [PATCH 032/157] [Backport][SME] mode-switching: Remove unused bbnum
+ field
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2d55ed2b8a754d7279cd002941f7cb481f0fd133
+
+seginfo had an unused bbnum field, presumably dating from before
+BB information was attached directly to insns.
+
+gcc/
+	* mode-switching.cc: Remove unused forward references.
+	(seginfo): Remove bbnum.
+	(new_seginfo): Remove associated argument.
+	(optimize_mode_switching): Update calls accordingly.
+---
+ gcc/mode-switching.cc | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 6e3f1dc65..4cf8f03a0 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -65,13 +65,11 @@ along with GCC; see the file COPYING3.  If not see
+    MODE is the mode this insn must be executed in.
+    INSN_PTR is the insn to be executed (may be the note that marks the
+    beginning of a basic block).
+-   BBNUM is the flow graph basic block this insn occurs in.
+    NEXT is the next insn in the same basic block.  */
+ struct seginfo
+ {
+   int mode;
+   rtx_insn *insn_ptr;
+-  int bbnum;
+   struct seginfo *next;
+   HARD_REG_SET regs_live;
+ };
+@@ -84,11 +82,6 @@ struct bb_info
+   int mode_in;
+ };
+ 
+-static struct seginfo * new_seginfo (int, rtx_insn *, int, HARD_REG_SET);
+-static void add_seginfo (struct bb_info *, struct seginfo *);
+-static void reg_dies (rtx, HARD_REG_SET *);
+-static void reg_becomes_live (rtx, const_rtx, void *);
+-
+ /* Clear ode I from entity J in bitmap B.  */
+ #define clear_mode_bit(b, j, i) \
+        bitmap_clear_bit (b, (j * max_num_modes) + i)
+@@ -148,13 +141,13 @@ commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
+ }
+ 
+ /* Allocate a new BBINFO structure, initialized with the MODE, INSN,
+-   and basic block BB parameters.
++   and REGS_LIVE parameters.
+    INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty
+    basic block; that allows us later to insert instructions in a FIFO-like
+    manner.  */
+ 
+ static struct seginfo *
+-new_seginfo (int mode, rtx_insn *insn, int bb, HARD_REG_SET regs_live)
++new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET ®s_live)
+ {
+   struct seginfo *ptr;
+ 
+@@ -163,7 +156,6 @@ new_seginfo (int mode, rtx_insn *insn, int bb, HARD_REG_SET regs_live)
+   ptr = XNEW (struct seginfo);
+   ptr->mode = mode;
+   ptr->insn_ptr = insn;
+-  ptr->bbnum = bb;
+   ptr->next = NULL;
+   ptr->regs_live = regs_live;
+   return ptr;
+@@ -604,7 +596,7 @@ optimize_mode_switching (void)
+ 		gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos));
+ 		if (ins_pos != BB_END (bb))
+ 		  ins_pos = NEXT_INSN (ins_pos);
+-		ptr = new_seginfo (no_mode, ins_pos, bb->index, live_now);
++		ptr = new_seginfo (no_mode, ins_pos, live_now);
+ 		add_seginfo (info + bb->index, ptr);
+ 		for (i = 0; i < no_mode; i++)
+ 		  clear_mode_bit (transp[bb->index], j, i);
+@@ -622,7 +614,7 @@ optimize_mode_switching (void)
+ 		    {
+ 		      any_set_required = true;
+ 		      last_mode = mode;
+-		      ptr = new_seginfo (mode, insn, bb->index, live_now);
++		      ptr = new_seginfo (mode, insn, live_now);
+ 		      add_seginfo (info + bb->index, ptr);
+ 		      for (i = 0; i < no_mode; i++)
+ 			clear_mode_bit (transp[bb->index], j, i);
+@@ -651,7 +643,7 @@ optimize_mode_switching (void)
+ 	     mark the block as nontransparent.  */
+ 	  if (!any_set_required)
+ 	    {
+-	      ptr = new_seginfo (no_mode, BB_END (bb), bb->index, live_now);
++	      ptr = new_seginfo (no_mode, BB_END (bb), live_now);
+ 	      add_seginfo (info + bb->index, ptr);
+ 	      if (last_mode != no_mode)
+ 		for (i = 0; i < no_mode; i++)
+-- 
+2.33.0
+
diff --git a/0132-Backport-SME-mode-switching-Tweak-the-macro-hook-doc.patch b/0132-Backport-SME-mode-switching-Tweak-the-macro-hook-doc.patch
new file mode 100644
index 0000000..e3c0ff7
--- /dev/null
+++ b/0132-Backport-SME-mode-switching-Tweak-the-macro-hook-doc.patch
@@ -0,0 +1,311 @@
+From c980e40d2c27ac3ee33c9b6aea6d2b0d4080852e Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:54 +0000
+Subject: [PATCH 033/157] [Backport][SME] mode-switching: Tweak the macro/hook
+ documentation
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=8479a3759025961f80cf0cd6bb3f127e09d0510d
+
+I found the documentation for the mode-switching macros/hooks
+a bit hard to follow at first.  This patch tries to add the
+information that I think would have made it easier to understand.
+
+Of course, documentation preferences are personal, and so I could
+be changing something that others understood to something that
+seems impenetrable.
+
+Some notes on specific changes:
+
+- "in an optimizing compilation" didn't seem accurate; the pass
+  is run even at -O0, and often needs to be for correctness.
+
+- "at run time" meant when the compiler was run, rather than when
+  the compiled code was run.
+
+- Removing the list of optional macros isn't a clarification,
+  but it means that upcoming patches don't create an absurdly
+  long list.
+
+- I don't really understand the purpose of TARGET_MODE_PRIORITY,
+  so I mostly left that alone.
+
+gcc/
+	* target.def: Tweak documentation of mode-switching hooks.
+	* doc/tm.texi.in (OPTIMIZE_MODE_SWITCHING): Tweak documentation.
+	(NUM_MODES_FOR_MODE_SWITCHING): Likewise.
+	* doc/tm.texi: Regenerate.
+---
+ gcc/doc/tm.texi    | 69 ++++++++++++++++++++++++++++------------------
+ gcc/doc/tm.texi.in | 26 +++++++++--------
+ gcc/target.def     | 43 ++++++++++++++++++-----------
+ 3 files changed, 84 insertions(+), 54 deletions(-)
+
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 851d31c18..553aa4cf2 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10234,7 +10234,7 @@ The following macros control mode switching optimizations:
+ 
+ @defmac OPTIMIZE_MODE_SWITCHING (@var{entity})
+ Define this macro if the port needs extra instructions inserted for mode
+-switching in an optimizing compilation.
++switching.
+ 
+ For an example, the SH4 can perform both single and double precision
+ floating point operations, but to perform a single precision operation,
+@@ -10244,73 +10244,88 @@ purpose register as a scratch register, hence these FPSCR sets have to
+ be inserted before reload, i.e.@: you cannot put this into instruction emitting
+ or @code{TARGET_MACHINE_DEPENDENT_REORG}.
+ 
+-You can have multiple entities that are mode-switched, and select at run time
+-which entities actually need it.  @code{OPTIMIZE_MODE_SWITCHING} should
+-return nonzero for any @var{entity} that needs mode-switching.
++You can have multiple entities that are mode-switched, some of which might
++only be needed conditionally.  The entities are identified by their index
++into the @code{NUM_MODES_FOR_MODE_SWITCHING} initializer, with the length
++of the initializer determining the number of entities.
++
++@code{OPTIMIZE_MODE_SWITCHING} should return nonzero for any @var{entity}
++that needs mode-switching.
++
+ If you define this macro, you also have to define
+ @code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED},
+ @code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}.
+-@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT}
+-are optional.
++The other macros in this section are optional.
+ @end defmac
+ 
+ @defmac NUM_MODES_FOR_MODE_SWITCHING
+ If you define @code{OPTIMIZE_MODE_SWITCHING}, you have to define this as
+ initializer for an array of integers.  Each initializer element
+ N refers to an entity that needs mode switching, and specifies the number
+-of different modes that might need to be set for this entity.
+-The position of the initializer in the initializer---starting counting at
++of different modes that are defined for that entity.
++The position of the element in the initializer---starting counting at
+ zero---determines the integer that is used to refer to the mode-switched
+ entity in question.
+-In macros that take mode arguments / yield a mode result, modes are
+-represented as numbers 0 @dots{} N @minus{} 1.  N is used to specify that no mode
+-switch is needed / supplied.
++Modes are represented as numbers 0 @dots{} N @minus{} 1.
++In mode arguments and return values, N either represents an unknown
++mode or ``no mode'', depending on context.
+ @end defmac
+ 
+ @deftypefn {Target Hook} void TARGET_MODE_EMIT (int @var{entity}, int @var{mode}, int @var{prev_mode}, HARD_REG_SET @var{regs_live})
+ Generate one or more insns to set @var{entity} to @var{mode}.
+ @var{hard_reg_live} is the set of hard registers live at the point where
+ the insn(s) are to be inserted. @var{prev_moxde} indicates the mode
+-to switch from. Sets of a lower numbered entity will be emitted before
++to switch from, or is the number of modes if the previous mode is not
++known.  Sets of a lower numbered entity will be emitted before
+ sets of a higher numbered entity to a mode of the same or lower priority.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn})
+ @var{entity} is an integer specifying a mode-switched entity.
+-If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro
+-to return an integer value not larger than the corresponding element
+-in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity}
+-must be switched into prior to the execution of @var{insn}.
++If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook
++to return the mode that @var{entity} must be switched into prior to the
++execution of @var{insn}, or the number of modes if @var{insn} has no
++such requirement.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn})
+ @var{entity} is an integer specifying a mode-switched entity.
+-If this macro is defined, it is evaluated for every @var{insn} during mode
+-switching.  It determines the mode that an insn results
+-in (if different from the incoming mode).
++If this hook is defined, it is evaluated for every @var{insn} during mode
++switching.  It returns the mode that @var{entity} is in after @var{insn}
++has been executed.  @var{mode} is the mode that @var{entity} was in
++before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}.
++
++@var{mode} is equal to the number of modes defined for @var{entity}
++if the mode before @var{insn} is unknown.  The hook should likewise return
++the number of modes if it does not know what mode @var{entity} has after
++@var{insn}.
++
++Not defining the hook is equivalent to returning @var{mode}.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity})
+-If this macro is defined, it is evaluated for every @var{entity} that
+-needs mode switching.  It should evaluate to an integer, which is a mode
+-that @var{entity} is assumed to be switched to at function entry.
++If this hook is defined, it is evaluated for every @var{entity} that
++needs mode switching.  It should return the mode that @var{entity} is
++guaranteed to be in on entry to the function, or the number of modes
++if there is no such guarantee.
+ If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT}
+ must be defined.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} int TARGET_MODE_EXIT (int @var{entity})
+-If this macro is defined, it is evaluated for every @var{entity} that
+-needs mode switching.  It should evaluate to an integer, which is a mode
+-that @var{entity} is assumed to be switched to at function exit.
++If this hook is defined, it is evaluated for every @var{entity} that
++needs mode switching.  It should return the mode that @var{entity} must
++be in on return from the function, or the number of modes if there is no
++such requirement.
+ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}
+ must be defined.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} int TARGET_MODE_PRIORITY (int @var{entity}, int @var{n})
+-This macro specifies the order in which modes for @var{entity}
++This hook specifies the order in which modes for @var{entity}
+ are processed. 0 is the highest priority,
+ @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest.
+-The value of the macro should be an integer designating a mode
++The hook returns an integer designating a mode
+ for @var{entity}.  For any fixed @var{entity}, @code{mode_priority}
+ (@var{entity}, @var{n}) shall be a bijection in 0 @dots{}
+ @code{num_modes_for_mode_switching[@var{entity}] - 1}.
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index ac95cdf7a..9ec11b15c 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -6879,7 +6879,7 @@ The following macros control mode switching optimizations:
+ 
+ @defmac OPTIMIZE_MODE_SWITCHING (@var{entity})
+ Define this macro if the port needs extra instructions inserted for mode
+-switching in an optimizing compilation.
++switching.
+ 
+ For an example, the SH4 can perform both single and double precision
+ floating point operations, but to perform a single precision operation,
+@@ -6889,27 +6889,31 @@ purpose register as a scratch register, hence these FPSCR sets have to
+ be inserted before reload, i.e.@: you cannot put this into instruction emitting
+ or @code{TARGET_MACHINE_DEPENDENT_REORG}.
+ 
+-You can have multiple entities that are mode-switched, and select at run time
+-which entities actually need it.  @code{OPTIMIZE_MODE_SWITCHING} should
+-return nonzero for any @var{entity} that needs mode-switching.
++You can have multiple entities that are mode-switched, some of which might
++only be needed conditionally.  The entities are identified by their index
++into the @code{NUM_MODES_FOR_MODE_SWITCHING} initializer, with the length
++of the initializer determining the number of entities.
++
++@code{OPTIMIZE_MODE_SWITCHING} should return nonzero for any @var{entity}
++that needs mode-switching.
++
+ If you define this macro, you also have to define
+ @code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED},
+ @code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}.
+-@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT}
+-are optional.
++The other macros in this section are optional.
+ @end defmac
+ 
+ @defmac NUM_MODES_FOR_MODE_SWITCHING
+ If you define @code{OPTIMIZE_MODE_SWITCHING}, you have to define this as
+ initializer for an array of integers.  Each initializer element
+ N refers to an entity that needs mode switching, and specifies the number
+-of different modes that might need to be set for this entity.
+-The position of the initializer in the initializer---starting counting at
++of different modes that are defined for that entity.
++The position of the element in the initializer---starting counting at
+ zero---determines the integer that is used to refer to the mode-switched
+ entity in question.
+-In macros that take mode arguments / yield a mode result, modes are
+-represented as numbers 0 @dots{} N @minus{} 1.  N is used to specify that no mode
+-switch is needed / supplied.
++Modes are represented as numbers 0 @dots{} N @minus{} 1.
++In mode arguments and return values, N either represents an unknown
++mode or ``no mode'', depending on context.
+ @end defmac
+ 
+ @hook TARGET_MODE_EMIT
+diff --git a/gcc/target.def b/gcc/target.def
+index c9bb2b4c2..b87b0f927 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -6992,51 +6992,62 @@ DEFHOOK
+  "Generate one or more insns to set @var{entity} to @var{mode}.\n\
+ @var{hard_reg_live} is the set of hard registers live at the point where\n\
+ the insn(s) are to be inserted. @var{prev_moxde} indicates the mode\n\
+-to switch from. Sets of a lower numbered entity will be emitted before\n\
++to switch from, or is the number of modes if the previous mode is not\n\
++known.  Sets of a lower numbered entity will be emitted before\n\
+ sets of a higher numbered entity to a mode of the same or lower priority.",
+  void, (int entity, int mode, int prev_mode, HARD_REG_SET regs_live), NULL)
+ 
+ DEFHOOK
+ (needed,
+  "@var{entity} is an integer specifying a mode-switched entity.\n\
+-If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro\n\
+-to return an integer value not larger than the corresponding element\n\
+-in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity}\n\
+-must be switched into prior to the execution of @var{insn}.",
++If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook\n\
++to return the mode that @var{entity} must be switched into prior to the\n\
++execution of @var{insn}, or the number of modes if @var{insn} has no\n\
++such requirement.",
+  int, (int entity, rtx_insn *insn), NULL)
+ 
+ DEFHOOK
+ (after,
+  "@var{entity} is an integer specifying a mode-switched entity.\n\
+-If this macro is defined, it is evaluated for every @var{insn} during mode\n\
+-switching.  It determines the mode that an insn results\n\
+-in (if different from the incoming mode).",
++If this hook is defined, it is evaluated for every @var{insn} during mode\n\
++switching.  It returns the mode that @var{entity} is in after @var{insn}\n\
++has been executed.  @var{mode} is the mode that @var{entity} was in\n\
++before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}.\n\
++\n\
++@var{mode} is equal to the number of modes defined for @var{entity}\n\
++if the mode before @var{insn} is unknown.  The hook should likewise return\n\
++the number of modes if it does not know what mode @var{entity} has after\n\
++@var{insn}.\n\
++\n\
++Not defining the hook is equivalent to returning @var{mode}.",
+  int, (int entity, int mode, rtx_insn *insn), NULL)
+ 
+ DEFHOOK
+ (entry,
+- "If this macro is defined, it is evaluated for every @var{entity} that\n\
+-needs mode switching.  It should evaluate to an integer, which is a mode\n\
+-that @var{entity} is assumed to be switched to at function entry.\n\
++ "If this hook is defined, it is evaluated for every @var{entity} that\n\
++needs mode switching.  It should return the mode that @var{entity} is\n\
++guaranteed to be in on entry to the function, or the number of modes\n\
++if there is no such guarantee.\n\
+ If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT}\n\
+ must be defined.",
+  int, (int entity), NULL)
+ 
+ DEFHOOK
+ (exit,
+- "If this macro is defined, it is evaluated for every @var{entity} that\n\
+-needs mode switching.  It should evaluate to an integer, which is a mode\n\
+-that @var{entity} is assumed to be switched to at function exit.\n\
++ "If this hook is defined, it is evaluated for every @var{entity} that\n\
++needs mode switching.  It should return the mode that @var{entity} must\n\
++be in on return from the function, or the number of modes if there is no\n\
++such requirement.\n\
+ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}\n\
+ must be defined.",
+  int, (int entity), NULL)
+ 
+ DEFHOOK
+ (priority,
+- "This macro specifies the order in which modes for @var{entity}\n\
++ "This hook specifies the order in which modes for @var{entity}\n\
+ are processed. 0 is the highest priority,\n\
+ @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest.\n\
+-The value of the macro should be an integer designating a mode\n\
++The hook returns an integer designating a mode\n\
+ for @var{entity}.  For any fixed @var{entity}, @code{mode_priority}\n\
+ (@var{entity}, @var{n}) shall be a bijection in 0 @dots{}\n\
+ @code{num_modes_for_mode_switching[@var{entity}] - 1}.",
+-- 
+2.33.0
+
diff --git a/0133-Backport-SME-mode-switching-Add-note-problem.patch b/0133-Backport-SME-mode-switching-Add-note-problem.patch
new file mode 100644
index 0000000..21508da
--- /dev/null
+++ b/0133-Backport-SME-mode-switching-Add-note-problem.patch
@@ -0,0 +1,35 @@
+From 7ab54a765239bdd2ce548cffdd5b83f9c20f69da Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:55 +0000
+Subject: [PATCH 034/157] [Backport][SME] mode-switching: Add note problem
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=3cd3a09b3f91a1d023cb180763d40598d6bb274b
+
+optimize_mode_switching uses REG_DEAD notes to track register
+liveness, but it failed to tell DF to calculate up-to-date notes.
+
+Noticed by inspection.  I don't have a testcase that fails
+because of this.
+
+gcc/
+	* mode-switching.cc (optimize_mode_switching): Call
+	df_note_add_problem.
+---
+ gcc/mode-switching.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 4cf8f03a0..2a9f98793 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -540,6 +540,7 @@ optimize_mode_switching (void)
+       pre_exit = create_pre_exit (n_entities, entity_map, num_modes);
+     }
+ 
++  df_note_add_problem ();
+   df_analyze ();
+ 
+   /* Create the bitmap vectors.  */
+-- 
+2.33.0
+
diff --git a/0134-Backport-SME-mode-switching-Avoid-quadractic-list-op.patch b/0134-Backport-SME-mode-switching-Avoid-quadractic-list-op.patch
new file mode 100644
index 0000000..e74c104
--- /dev/null
+++ b/0134-Backport-SME-mode-switching-Avoid-quadractic-list-op.patch
@@ -0,0 +1,90 @@
+From a2a8b560c1749293d3b6d027e20753a7ea042c80 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:55 +0000
+Subject: [PATCH 035/157] [Backport][SME] mode-switching: Avoid quadractic list
+ operation
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=174ee5115a3004d3664165e9d619535b579111d4
+
+add_seginfo chained insn information to the end of a list
+by starting at the head of the list.  This patch avoids the
+quadraticness by keeping track of the tail pointer.
+
+gcc/
+	* mode-switching.cc (add_seginfo): Replace head pointer with
+	a pointer to the tail pointer.
+	(optimize_mode_switching): Update calls accordingly.
+---
+ gcc/mode-switching.cc | 24 ++++++++----------------
+ 1 file changed, 8 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 2a9f98793..6a13951c9 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -162,23 +162,14 @@ new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET ®s_live)
+ }
+ 
+ /* Add a seginfo element to the end of a list.
+-   HEAD is a pointer to the list beginning.
++   TAIL is a pointer to the list's null terminator.
+    INFO is the structure to be linked in.  */
+ 
+ static void
+-add_seginfo (struct bb_info *head, struct seginfo *info)
++add_seginfo (struct seginfo ***tail_ptr, struct seginfo *info)
+ {
+-  struct seginfo *ptr;
+-
+-  if (head->seginfo == NULL)
+-    head->seginfo = info;
+-  else
+-    {
+-      ptr = head->seginfo;
+-      while (ptr->next != NULL)
+-	ptr = ptr->next;
+-      ptr->next = info;
+-    }
++  **tail_ptr = info;
++  *tail_ptr = &info->next;
+ }
+ 
+ /* Record in LIVE that register REG died.  */
+@@ -573,6 +564,7 @@ optimize_mode_switching (void)
+ 	 Also compute the initial transparency settings.  */
+       FOR_EACH_BB_FN (bb, cfun)
+ 	{
++	  struct seginfo **tail_ptr = &info[bb->index].seginfo;
+ 	  struct seginfo *ptr;
+ 	  int last_mode = no_mode;
+ 	  bool any_set_required = false;
+@@ -598,7 +590,7 @@ optimize_mode_switching (void)
+ 		if (ins_pos != BB_END (bb))
+ 		  ins_pos = NEXT_INSN (ins_pos);
+ 		ptr = new_seginfo (no_mode, ins_pos, live_now);
+-		add_seginfo (info + bb->index, ptr);
++		add_seginfo (&tail_ptr, ptr);
+ 		for (i = 0; i < no_mode; i++)
+ 		  clear_mode_bit (transp[bb->index], j, i);
+ 	      }
+@@ -616,7 +608,7 @@ optimize_mode_switching (void)
+ 		      any_set_required = true;
+ 		      last_mode = mode;
+ 		      ptr = new_seginfo (mode, insn, live_now);
+-		      add_seginfo (info + bb->index, ptr);
++		      add_seginfo (&tail_ptr, ptr);
+ 		      for (i = 0; i < no_mode; i++)
+ 			clear_mode_bit (transp[bb->index], j, i);
+ 		    }
+@@ -645,7 +637,7 @@ optimize_mode_switching (void)
+ 	  if (!any_set_required)
+ 	    {
+ 	      ptr = new_seginfo (no_mode, BB_END (bb), live_now);
+-	      add_seginfo (info + bb->index, ptr);
++	      add_seginfo (&tail_ptr, ptr);
+ 	      if (last_mode != no_mode)
+ 		for (i = 0; i < no_mode; i++)
+ 		  clear_mode_bit (transp[bb->index], j, i);
+-- 
+2.33.0
+
diff --git a/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch b/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch
new file mode 100644
index 0000000..c1b4036
--- /dev/null
+++ b/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch
@@ -0,0 +1,136 @@
+From 194700063ed04b56d84912f7ace1b8370af6c696 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:56 +0000
+Subject: [PATCH 036/157] [Backport][SME] mode-switching: Fix the mode passed
+ to the emit hook
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5afd208beaef50bcc43b556d4c41d41656b06436
+
+optimize_mode_switching passes an entity's current mode (if known)
+to the emit hook.  However, the mode that it passed ignored the
+effect of the after hook.  Instead, the mode for the first emit
+call in a block was taken from the incoming mode, whereas the
+mode for each subsequent emit call was taken from the result
+of the previous call.
+
+The previous pass through the insns already calculated the
+correct mode, so this patch records it in the seginfo structure.
+(There was a 32-bit hole on 64-bit hosts, so this doesn't increase
+the size of the structure for them.)
+
+gcc/
+	* mode-switching.cc (seginfo): Add a prev_mode field.
+	(new_seginfo): Take and initialize the prev_mode.
+	(optimize_mode_switching): Update calls accordingly.
+	Use the recorded modes during the emit phase, rather than
+	computing one on the fly.
+---
+ gcc/mode-switching.cc | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 6a13951c9..584cd4f67 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3.  If not see
+    NEXT is the next insn in the same basic block.  */
+ struct seginfo
+ {
++  int prev_mode;
+   int mode;
+   rtx_insn *insn_ptr;
+   struct seginfo *next;
+@@ -140,20 +141,22 @@ commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
+   return need_commit;
+ }
+ 
+-/* Allocate a new BBINFO structure, initialized with the MODE, INSN,
+-   and REGS_LIVE parameters.
++/* Allocate a new BBINFO structure, initialized with the PREV_MODE, MODE,
++   INSN, and REGS_LIVE parameters.
+    INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty
+    basic block; that allows us later to insert instructions in a FIFO-like
+    manner.  */
+ 
+ static struct seginfo *
+-new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET ®s_live)
++new_seginfo (int prev_mode, int mode, rtx_insn *insn,
++	     const HARD_REG_SET ®s_live)
+ {
+   struct seginfo *ptr;
+ 
+   gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn)
+ 	      || insn == BB_END (NOTE_BASIC_BLOCK (insn)));
+   ptr = XNEW (struct seginfo);
++  ptr->prev_mode = prev_mode;
+   ptr->mode = mode;
+   ptr->insn_ptr = insn;
+   ptr->next = NULL;
+@@ -589,7 +592,7 @@ optimize_mode_switching (void)
+ 		gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos));
+ 		if (ins_pos != BB_END (bb))
+ 		  ins_pos = NEXT_INSN (ins_pos);
+-		ptr = new_seginfo (no_mode, ins_pos, live_now);
++		ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now);
+ 		add_seginfo (&tail_ptr, ptr);
+ 		for (i = 0; i < no_mode; i++)
+ 		  clear_mode_bit (transp[bb->index], j, i);
+@@ -605,12 +608,12 @@ optimize_mode_switching (void)
+ 
+ 		  if (mode != no_mode && mode != last_mode)
+ 		    {
+-		      any_set_required = true;
+-		      last_mode = mode;
+-		      ptr = new_seginfo (mode, insn, live_now);
++		      ptr = new_seginfo (last_mode, mode, insn, live_now);
+ 		      add_seginfo (&tail_ptr, ptr);
+ 		      for (i = 0; i < no_mode; i++)
+ 			clear_mode_bit (transp[bb->index], j, i);
++		      any_set_required = true;
++		      last_mode = mode;
+ 		    }
+ 
+ 		  if (targetm.mode_switching.after)
+@@ -636,7 +639,7 @@ optimize_mode_switching (void)
+ 	     mark the block as nontransparent.  */
+ 	  if (!any_set_required)
+ 	    {
+-	      ptr = new_seginfo (no_mode, BB_END (bb), live_now);
++	      ptr = new_seginfo (last_mode, no_mode, BB_END (bb), live_now);
+ 	      add_seginfo (&tail_ptr, ptr);
+ 	      if (last_mode != no_mode)
+ 		for (i = 0; i < no_mode; i++)
+@@ -777,9 +780,9 @@ optimize_mode_switching (void)
+       FOR_EACH_BB_FN (bb, cfun)
+ 	{
+ 	  struct seginfo *ptr, *next;
+-	  int cur_mode = bb_info[j][bb->index].mode_in;
++	  struct seginfo *first = bb_info[j][bb->index].seginfo;
+ 
+-	  for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
++	  for (ptr = first; ptr; ptr = next)
+ 	    {
+ 	      next = ptr->next;
+ 	      if (ptr->mode != no_mode)
+@@ -789,14 +792,15 @@ optimize_mode_switching (void)
+ 		  rtl_profile_for_bb (bb);
+ 		  start_sequence ();
+ 
++		  int cur_mode = (ptr == first && ptr->prev_mode == no_mode
++				  ? bb_info[j][bb->index].mode_in
++				  : ptr->prev_mode);
++
+ 		  targetm.mode_switching.emit (entity_map[j], ptr->mode,
+ 					       cur_mode, ptr->regs_live);
+ 		  mode_set = get_insns ();
+ 		  end_sequence ();
+ 
+-		  /* modes kill each other inside a basic block.  */
+-		  cur_mode = ptr->mode;
+-
+ 		  /* Insert MODE_SET only if it is nonempty.  */
+ 		  if (mode_set != NULL_RTX)
+ 		    {
+-- 
+2.33.0
+
diff --git a/0136-Backport-SME-mode-switching-Simplify-recording-of-tr.patch b/0136-Backport-SME-mode-switching-Simplify-recording-of-tr.patch
new file mode 100644
index 0000000..1b99d67
--- /dev/null
+++ b/0136-Backport-SME-mode-switching-Simplify-recording-of-tr.patch
@@ -0,0 +1,103 @@
+From ac51d446ee605e942b0831d3ff617980d94bf502 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:56 +0000
+Subject: [PATCH 037/157] [Backport][SME] mode-switching: Simplify recording of
+ transparency
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=335b55f4146c5ef9e3bf4bcb7e58e887c3150b02
+
+For a given block, an entity is either transparent for
+all modes or for none.  Each update to the transparency set
+therefore used a loop like:
+
+		for (i = 0; i < no_mode; i++)
+		  clear_mode_bit (transp[bb->index], j, i);
+
+This patch instead starts out with a bit-per-block bitmap
+and updates the main bitmap at the end.
+
+This isn't much of a simplification on its own.  The main
+purpose is to simplify later patches.
+
+gcc/
+	* mode-switching.cc (optimize_mode_switching): Initially
+	compute transparency in a bit-per-block bitmap.
+---
+ gcc/mode-switching.cc | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 584cd4f67..4d2b9e284 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -555,6 +555,8 @@ optimize_mode_switching (void)
+   bitmap_vector_clear (antic, last_basic_block_for_fn (cfun));
+   bitmap_vector_clear (comp, last_basic_block_for_fn (cfun));
+ 
++  auto_sbitmap transp_all (last_basic_block_for_fn (cfun));
++
+   for (j = n_entities - 1; j >= 0; j--)
+     {
+       int e = entity_map[j];
+@@ -562,6 +564,8 @@ optimize_mode_switching (void)
+       struct bb_info *info = bb_info[j];
+       rtx_insn *insn;
+ 
++      bitmap_ones (transp_all);
++
+       /* Determine what the first use (if any) need for a mode of entity E is.
+ 	 This will be the mode that is anticipatable for this block.
+ 	 Also compute the initial transparency settings.  */
+@@ -594,8 +598,7 @@ optimize_mode_switching (void)
+ 		  ins_pos = NEXT_INSN (ins_pos);
+ 		ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now);
+ 		add_seginfo (&tail_ptr, ptr);
+-		for (i = 0; i < no_mode; i++)
+-		  clear_mode_bit (transp[bb->index], j, i);
++		bitmap_clear_bit (transp_all, bb->index);
+ 	      }
+ 	  }
+ 
+@@ -610,8 +613,7 @@ optimize_mode_switching (void)
+ 		    {
+ 		      ptr = new_seginfo (last_mode, mode, insn, live_now);
+ 		      add_seginfo (&tail_ptr, ptr);
+-		      for (i = 0; i < no_mode; i++)
+-			clear_mode_bit (transp[bb->index], j, i);
++		      bitmap_clear_bit (transp_all, bb->index);
+ 		      any_set_required = true;
+ 		      last_mode = mode;
+ 		    }
+@@ -642,8 +644,7 @@ optimize_mode_switching (void)
+ 	      ptr = new_seginfo (last_mode, no_mode, BB_END (bb), live_now);
+ 	      add_seginfo (&tail_ptr, ptr);
+ 	      if (last_mode != no_mode)
+-		for (i = 0; i < no_mode; i++)
+-		  clear_mode_bit (transp[bb->index], j, i);
++		bitmap_clear_bit (transp_all, bb->index);
+ 	    }
+ 	}
+       if (targetm.mode_switching.entry && targetm.mode_switching.exit)
+@@ -666,8 +667,7 @@ optimize_mode_switching (void)
+ 		 an extra check in make_preds_opaque.  We also
+ 		 need this to avoid confusing pre_edge_lcm when
+ 		 antic is cleared but transp and comp are set.  */
+-	      for (i = 0; i < no_mode; i++)
+-		clear_mode_bit (transp[bb->index], j, i);
++	      bitmap_clear_bit (transp_all, bb->index);
+ 
+ 	      /* Insert a fake computing definition of MODE into entry
+ 		 blocks which compute no mode. This represents the mode on
+@@ -687,6 +687,9 @@ optimize_mode_switching (void)
+ 
+ 	  FOR_EACH_BB_FN (bb, cfun)
+ 	    {
++	      if (!bitmap_bit_p (transp_all, bb->index))
++		clear_mode_bit (transp[bb->index], j, m);
++
+ 	      if (info[bb->index].seginfo->mode == m)
+ 		set_mode_bit (antic[bb->index], j, m);
+ 
+-- 
+2.33.0
+
diff --git a/0137-Backport-SME-mode-switching-Tweak-entry-exit-handlin.patch b/0137-Backport-SME-mode-switching-Tweak-entry-exit-handlin.patch
new file mode 100644
index 0000000..8444847
--- /dev/null
+++ b/0137-Backport-SME-mode-switching-Tweak-entry-exit-handlin.patch
@@ -0,0 +1,92 @@
+From c0aaf329d9c547b249ac120a8d1995d8546a1edb Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:57 +0000
+Subject: [PATCH 038/157] [Backport][SME] mode-switching: Tweak entry/exit
+ handling
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=e59ec35276599805cdc6c3979d8a167b027d286e
+
+An entity isn't transparent in a block that requires a specific mode.
+optimize_mode_switching took that into account for normal insns,
+but didn't for the exit block.  Later patches misbehaved because
+of this.
+
+In contrast, an entity was correctly marked as non-transparent
+in the entry block, but the reasoning seemed a bit convoluted.
+It also referred to a function that no longer exists.
+Since KILL = ~TRANSP, the entity is by definition not transparent
+in a block that defines the entity, so I think we can make it so
+without comment.
+
+Finally, the exit handling was nested in the entry handling,
+but that doesn't seem necessary.  A target could say that an
+entity is undefined on entry but must be defined on return,
+on a "be liberal in what you accept, be conservative in what
+you do" principle.
+
+gcc/
+	* mode-switching.cc (optimize_mode_switching): Mark the exit
+	block as nontransparent if it requires a specific mode.
+	Handle the entry and exit mode as sibling rather than nested
+	concepts.  Remove outdated comment.
+---
+ gcc/mode-switching.cc | 34 +++++++++++++++-------------------
+ 1 file changed, 15 insertions(+), 19 deletions(-)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 4d2b9e284..4761c2ff0 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -649,34 +649,30 @@ optimize_mode_switching (void)
+ 	}
+       if (targetm.mode_switching.entry && targetm.mode_switching.exit)
+ 	{
+-	  int mode = targetm.mode_switching.entry (e);
+-
+ 	  info[post_entry->index].mode_out =
+ 	    info[post_entry->index].mode_in = no_mode;
+-	  if (pre_exit)
+-	    {
+-	      info[pre_exit->index].mode_out =
+-		info[pre_exit->index].mode_in = no_mode;
+-	    }
+ 
++	  int mode = targetm.mode_switching.entry (e);
+ 	  if (mode != no_mode)
+ 	    {
+-	      bb = post_entry;
+-
+-	      /* By always making this nontransparent, we save
+-		 an extra check in make_preds_opaque.  We also
+-		 need this to avoid confusing pre_edge_lcm when
+-		 antic is cleared but transp and comp are set.  */
+-	      bitmap_clear_bit (transp_all, bb->index);
+-
+ 	      /* Insert a fake computing definition of MODE into entry
+ 		 blocks which compute no mode. This represents the mode on
+ 		 entry.  */
+-	      info[bb->index].computing = mode;
++	      info[post_entry->index].computing = mode;
++	      bitmap_clear_bit (transp_all, post_entry->index);
++	    }
+ 
+-	      if (pre_exit)
+-		info[pre_exit->index].seginfo->mode =
+-		  targetm.mode_switching.exit (e);
++	  if (pre_exit)
++	    {
++	      info[pre_exit->index].mode_out =
++		info[pre_exit->index].mode_in = no_mode;
++
++	      int mode = targetm.mode_switching.exit (e);
++	      if (mode != no_mode)
++		{
++		  info[pre_exit->index].seginfo->mode = mode;
++		  bitmap_clear_bit (transp_all, pre_exit->index);
++		}
+ 	    }
+ 	}
+ 
+-- 
+2.33.0
+
diff --git a/0138-Backport-SME-mode-switching-Allow-targets-to-set-the.patch b/0138-Backport-SME-mode-switching-Allow-targets-to-set-the.patch
new file mode 100644
index 0000000..8d066b2
--- /dev/null
+++ b/0138-Backport-SME-mode-switching-Allow-targets-to-set-the.patch
@@ -0,0 +1,93 @@
+From 9505464aec8f95125293c64e2eea9577e9be4700 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:57 +0000
+Subject: [PATCH 039/157] [Backport][SME] mode-switching: Allow targets to set
+ the mode for EH handlers
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=4b803fbf839439b1deca660e32d5ced211111dfa
+
+The mode-switching pass already had hooks to say what mode
+an entity is in on entry to a function and what mode it must
+be in on return.  For SME, we also want to say what mode an
+entity is guaranteed to be in on entry to an exception handler.
+
+gcc/
+	* target.def (mode_switching.eh_handler): New hook.
+	* doc/tm.texi.in (TARGET_MODE_EH_HANDLER): New @hook.
+	* doc/tm.texi: Regenerate.
+	* mode-switching.cc (optimize_mode_switching): Use eh_handler
+	to get the mode on entry to an exception handler.
+---
+ gcc/doc/tm.texi       | 6 ++++++
+ gcc/doc/tm.texi.in    | 2 ++
+ gcc/mode-switching.cc | 5 ++++-
+ gcc/target.def        | 7 +++++++
+ 4 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 553aa4cf2..4788b3f7a 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10321,6 +10321,12 @@ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}
+ must be defined.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} int TARGET_MODE_EH_HANDLER (int @var{entity})
++If this hook is defined, it should return the mode that @var{entity} is
++guaranteed to be in on entry to an exception handler, or the number of modes
++if there is no such guarantee.
++@end deftypefn
++
+ @deftypefn {Target Hook} int TARGET_MODE_PRIORITY (int @var{entity}, int @var{n})
+ This hook specifies the order in which modes for @var{entity}
+ are processed. 0 is the highest priority,
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 9ec11b15c..ad343504f 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -6926,6 +6926,8 @@ mode or ``no mode'', depending on context.
+ 
+ @hook TARGET_MODE_EXIT
+ 
++@hook TARGET_MODE_EH_HANDLER
++
+ @hook TARGET_MODE_PRIORITY
+ 
+ @node Target Attributes
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 4761c2ff0..9a6ba6cca 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -596,7 +596,10 @@ optimize_mode_switching (void)
+ 		gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos));
+ 		if (ins_pos != BB_END (bb))
+ 		  ins_pos = NEXT_INSN (ins_pos);
+-		ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now);
++		if (bb_has_eh_pred (bb)
++		    && targetm.mode_switching.eh_handler)
++		  last_mode = targetm.mode_switching.eh_handler (e);
++		ptr = new_seginfo (no_mode, last_mode, ins_pos, live_now);
+ 		add_seginfo (&tail_ptr, ptr);
+ 		bitmap_clear_bit (transp_all, bb->index);
+ 	      }
+diff --git a/gcc/target.def b/gcc/target.def
+index b87b0f927..bbb482de6 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -7042,6 +7042,13 @@ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}\n\
+ must be defined.",
+  int, (int entity), NULL)
+ 
++DEFHOOK
++(eh_handler,
++ "If this hook is defined, it should return the mode that @var{entity} is\n\
++guaranteed to be in on entry to an exception handler, or the number of modes\n\
++if there is no such guarantee.",
++ int, (int entity), NULL)
++
+ DEFHOOK
+ (priority,
+  "This hook specifies the order in which modes for @var{entity}\n\
+-- 
+2.33.0
+
diff --git a/0139-Backport-SME-mode-switching-Pass-set-of-live-registe.patch b/0139-Backport-SME-mode-switching-Pass-set-of-live-registe.patch
new file mode 100644
index 0000000..037a4f7
--- /dev/null
+++ b/0139-Backport-SME-mode-switching-Pass-set-of-live-registe.patch
@@ -0,0 +1,211 @@
+From a6964e11c7f624cdaed2c9608565a5968292b70f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:58 +0000
+Subject: [PATCH 040/157] [Backport][SME] mode-switching: Pass set of live
+ registers to the needed hook
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=29d3e1892ebec8abce784077d1f1a3e21d763218
+
+The emit hook already takes the set of live hard registers as input.
+This patch passes it to the needed hook too.  SME uses this to
+optimise the mode choice based on whether state is live or dead.
+
+The main caller already had access to the required info, but the
+special handling of return values did not.
+
+gcc/
+	* target.def (mode_switching.needed): Add a regs_live parameter.
+	* doc/tm.texi: Regenerate.
+	* config/epiphany/epiphany-protos.h (epiphany_mode_needed): Update
+	accordingly.
+	* config/epiphany/epiphany.cc (epiphany_mode_needed): Likewise.
+	* config/epiphany/mode-switch-use.cc (insert_uses): Likewise.
+	* config/i386/i386.cc (ix86_mode_needed): Likewise.
+	* config/riscv/riscv.cc (riscv_mode_needed): Likewise.
+	* config/sh/sh.cc (sh_mode_needed): Likewise.
+	* mode-switching.cc (optimize_mode_switching): Likewise.
+	(create_pre_exit): Likewise, using the DF simulate functions
+	to calculate the required information.
+---
+ gcc/config/epiphany/epiphany-protos.h  |  4 +++-
+ gcc/config/epiphany/epiphany.cc        |  2 +-
+ gcc/config/epiphany/mode-switch-use.cc |  2 +-
+ gcc/config/i386/i386.cc                |  2 +-
+ gcc/config/sh/sh.cc                    |  4 ++--
+ gcc/doc/tm.texi                        |  5 +++--
+ gcc/mode-switching.cc                  | 14 ++++++++++++--
+ gcc/target.def                         |  5 +++--
+ 8 files changed, 26 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h
+index 61b63234e..d463e5483 100644
+--- a/gcc/config/epiphany/epiphany-protos.h
++++ b/gcc/config/epiphany/epiphany-protos.h
+@@ -44,7 +44,9 @@ extern void emit_set_fp_mode (int entity, int mode, int prev_mode,
+ #endif
+ extern void epiphany_insert_mode_switch_use (rtx_insn *insn, int, int);
+ extern void epiphany_expand_set_fp_mode (rtx *operands);
+-extern int epiphany_mode_needed (int entity, rtx_insn *insn);
++#ifdef HARD_CONST
++extern int epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET);
++#endif
+ extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn);
+ extern bool epiphany_epilogue_uses (int regno);
+ extern bool epiphany_optimize_mode_switching (int entity);
+diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
+index f8c049340..be0fbc68c 100644
+--- a/gcc/config/epiphany/epiphany.cc
++++ b/gcc/config/epiphany/epiphany.cc
+@@ -2400,7 +2400,7 @@ epiphany_mode_priority (int entity, int priority)
+ }
+ 
+ int
+-epiphany_mode_needed (int entity, rtx_insn *insn)
++epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
+ {
+   enum attr_fp_mode mode;
+ 
+diff --git a/gcc/config/epiphany/mode-switch-use.cc b/gcc/config/epiphany/mode-switch-use.cc
+index 887550a33..cacb1ce5a 100644
+--- a/gcc/config/epiphany/mode-switch-use.cc
++++ b/gcc/config/epiphany/mode-switch-use.cc
+@@ -58,7 +58,7 @@ insert_uses (void)
+ 	{
+ 	  if (!INSN_P (insn))
+ 	    continue;
+-	  mode = epiphany_mode_needed (e, insn);
++	  mode = epiphany_mode_needed (e, insn, {});
+ 	  if (mode == no_mode)
+ 	    continue;
+ 	  if (target_insert_mode_switch_use)
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index 60f3296b0..4d591d217 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -14522,7 +14522,7 @@ ix86_i387_mode_needed (int entity, rtx_insn *insn)
+    prior to the execution of insn.  */
+ 
+ static int
+-ix86_mode_needed (int entity, rtx_insn *insn)
++ix86_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
+ {
+   switch (entity)
+     {
+diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
+index 03e1c04ec..85e83e12e 100644
+--- a/gcc/config/sh/sh.cc
++++ b/gcc/config/sh/sh.cc
+@@ -195,7 +195,7 @@ static int calc_live_regs (HARD_REG_SET *);
+ static HOST_WIDE_INT rounded_frame_size (int);
+ static bool sh_frame_pointer_required (void);
+ static void sh_emit_mode_set (int, int, int, HARD_REG_SET);
+-static int sh_mode_needed (int, rtx_insn *);
++static int sh_mode_needed (int, rtx_insn *, HARD_REG_SET);
+ static int sh_mode_after (int, int, rtx_insn *);
+ static int sh_mode_entry (int);
+ static int sh_mode_exit (int);
+@@ -12529,7 +12529,7 @@ sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
+ }
+ 
+ static int
+-sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn)
++sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn, HARD_REG_SET)
+ {
+   return recog_memoized (insn) >= 0  ? get_attr_fp_mode (insn) : FP_MODE_NONE;
+ }
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 4788b3f7a..d8ac6c4d6 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10280,12 +10280,13 @@ known.  Sets of a lower numbered entity will be emitted before
+ sets of a higher numbered entity to a mode of the same or lower priority.
+ @end deftypefn
+ 
+-@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn})
++@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn}, HARD_REG_SET @var{regs_live})
+ @var{entity} is an integer specifying a mode-switched entity.
+ If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook
+ to return the mode that @var{entity} must be switched into prior to the
+ execution of @var{insn}, or the number of modes if @var{insn} has no
+-such requirement.
++such requirement.  @var{regs_live} contains the set of hard registers
++that are live before @var{insn}.
+ @end deftypefn
+ 
+ @deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn})
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 9a6ba6cca..6bbda5058 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -254,6 +254,9 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
+ 	    && GET_CODE (PATTERN (last_insn)) == USE
+ 	    && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
+ 	  {
++	    auto_bitmap live;
++	    df_simulate_initialize_backwards (src_bb, live);
++
+ 	    int ret_start = REGNO (ret_reg);
+ 	    int nregs = REG_NREGS (ret_reg);
+ 	    int ret_end = ret_start + nregs;
+@@ -262,6 +265,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
+ 	    bool forced_late_switch = false;
+ 	    rtx_insn *before_return_copy;
+ 
++	    df_simulate_one_insn_backwards (src_bb, last_insn, live);
++
+ 	    do
+ 	      {
+ 		rtx_insn *return_copy = PREV_INSN (last_insn);
+@@ -269,6 +274,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
+ 		int copy_start, copy_num;
+ 		int j;
+ 
++		df_simulate_one_insn_backwards (src_bb, return_copy, live);
++
+ 		if (NONDEBUG_INSN_P (return_copy))
+ 		  {
+ 		    /* When using SJLJ exceptions, the call to the
+@@ -368,11 +375,14 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
+ 		       the case for floating point on SH4 - then it might
+ 		       be set by an arithmetic operation that needs a
+ 		       different mode than the exit block.  */
++		    HARD_REG_SET hard_regs_live;
++		    REG_SET_TO_HARD_REG_SET (hard_regs_live, live);
+ 		    for (j = n_entities - 1; j >= 0; j--)
+ 		      {
+ 			int e = entity_map[j];
+ 			int mode =
+-			  targetm.mode_switching.needed (e, return_copy);
++			  targetm.mode_switching.needed (e, return_copy,
++							 hard_regs_live);
+ 
+ 			if (mode != num_modes[e]
+ 			    && mode != targetm.mode_switching.exit (e))
+@@ -609,7 +619,7 @@ optimize_mode_switching (void)
+ 	    {
+ 	      if (INSN_P (insn))
+ 		{
+-		  int mode = targetm.mode_switching.needed (e, insn);
++		  int mode = targetm.mode_switching.needed (e, insn, live_now);
+ 		  rtx link;
+ 
+ 		  if (mode != no_mode && mode != last_mode)
+diff --git a/gcc/target.def b/gcc/target.def
+index bbb482de6..06a52bdaf 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -7003,8 +7003,9 @@ DEFHOOK
+ If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook\n\
+ to return the mode that @var{entity} must be switched into prior to the\n\
+ execution of @var{insn}, or the number of modes if @var{insn} has no\n\
+-such requirement.",
+- int, (int entity, rtx_insn *insn), NULL)
++such requirement.  @var{regs_live} contains the set of hard registers\n\
++that are live before @var{insn}.",
++ int, (int entity, rtx_insn *insn, HARD_REG_SET regs_live), NULL)
+ 
+ DEFHOOK
+ (after,
+-- 
+2.33.0
+
diff --git a/0140-Backport-SME-mode-switching-Pass-the-set-of-live-reg.patch b/0140-Backport-SME-mode-switching-Pass-the-set-of-live-reg.patch
new file mode 100644
index 0000000..da76e1b
--- /dev/null
+++ b/0140-Backport-SME-mode-switching-Pass-the-set-of-live-reg.patch
@@ -0,0 +1,177 @@
+From 4457604c11c0a32f3736d73429d1e5fb7baae3a5 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:58 +0000
+Subject: [PATCH 041/157] [Backport][SME] mode-switching: Pass the set of live
+ registers to the after hook
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=93d65f39bc5c3dc318deb6da0e3633f3a4c6c34d
+
+This patch passes the set of live hard registers to the after hook,
+like the previous one did for the needed hook.
+
+gcc/
+	* target.def (mode_switching.after): Add a regs_live parameter.
+	* doc/tm.texi: Regenerate.
+	* config/epiphany/epiphany-protos.h (epiphany_mode_after): Update
+	accordingly.
+	* config/epiphany/epiphany.cc (epiphany_mode_needed): Likewise.
+	(epiphany_mode_after): Likewise.
+	* config/i386/i386.cc (ix86_mode_after): Likewise.
+	* config/riscv/riscv.cc (riscv_mode_after): Likewise.
+	* config/sh/sh.cc (sh_mode_after): Likewise.
+	* mode-switching.cc (optimize_mode_switching): Likewise.
+---
+ gcc/config/epiphany/epiphany-protos.h | 3 ++-
+ gcc/config/epiphany/epiphany.cc       | 5 +++--
+ gcc/config/i386/i386.cc               | 2 +-
+ gcc/config/sh/sh.cc                   | 5 +++--
+ gcc/doc/tm.texi                       | 4 +++-
+ gcc/mode-switching.cc                 | 8 ++++----
+ gcc/target.def                        | 4 +++-
+ 7 files changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h
+index d463e5483..6326b7e80 100644
+--- a/gcc/config/epiphany/epiphany-protos.h
++++ b/gcc/config/epiphany/epiphany-protos.h
+@@ -46,8 +46,9 @@ extern void epiphany_insert_mode_switch_use (rtx_insn *insn, int, int);
+ extern void epiphany_expand_set_fp_mode (rtx *operands);
+ #ifdef HARD_CONST
+ extern int epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET);
++extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn,
++				HARD_REG_SET);
+ #endif
+-extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn);
+ extern bool epiphany_epilogue_uses (int regno);
+ extern bool epiphany_optimize_mode_switching (int entity);
+ extern bool epiphany_is_interrupt_p (tree);
+diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
+index be0fbc68c..62636b1ec 100644
+--- a/gcc/config/epiphany/epiphany.cc
++++ b/gcc/config/epiphany/epiphany.cc
+@@ -2437,7 +2437,7 @@ epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
+     return 2;
+   case EPIPHANY_MSW_ENTITY_ROUND_KNOWN:
+     if (recog_memoized (insn) == CODE_FOR_set_fp_mode)
+-      mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn);
++      mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn, {});
+     /* Fall through.  */
+   case EPIPHANY_MSW_ENTITY_NEAREST:
+   case EPIPHANY_MSW_ENTITY_TRUNC:
+@@ -2498,7 +2498,8 @@ epiphany_mode_entry_exit (int entity, bool exit)
+ }
+ 
+ int
+-epiphany_mode_after (int entity, int last_mode, rtx_insn *insn)
++epiphany_mode_after (int entity, int last_mode, rtx_insn *insn,
++		     HARD_REG_SET)
+ {
+   /* We have too few call-saved registers to hope to keep the masks across
+      calls.  */
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index 4d591d217..593185fa6 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -14583,7 +14583,7 @@ ix86_avx_u128_mode_after (int mode, rtx_insn *insn)
+ /* Return the mode that an insn results in.  */
+ 
+ static int
+-ix86_mode_after (int entity, int mode, rtx_insn *insn)
++ix86_mode_after (int entity, int mode, rtx_insn *insn, HARD_REG_SET)
+ {
+   switch (entity)
+     {
+diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
+index 85e83e12e..74d61c43b 100644
+--- a/gcc/config/sh/sh.cc
++++ b/gcc/config/sh/sh.cc
+@@ -196,7 +196,7 @@ static HOST_WIDE_INT rounded_frame_size (int);
+ static bool sh_frame_pointer_required (void);
+ static void sh_emit_mode_set (int, int, int, HARD_REG_SET);
+ static int sh_mode_needed (int, rtx_insn *, HARD_REG_SET);
+-static int sh_mode_after (int, int, rtx_insn *);
++static int sh_mode_after (int, int, rtx_insn *, HARD_REG_SET);
+ static int sh_mode_entry (int);
+ static int sh_mode_exit (int);
+ static int sh_mode_priority (int entity, int n);
+@@ -12535,7 +12535,8 @@ sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn, HARD_REG_SET)
+ }
+ 
+ static int
+-sh_mode_after (int entity ATTRIBUTE_UNUSED, int mode, rtx_insn *insn)
++sh_mode_after (int entity ATTRIBUTE_UNUSED, int mode, rtx_insn *insn,
++	       HARD_REG_SET)
+ {
+   if (TARGET_HITACHI && recog_memoized (insn) >= 0 &&
+       get_attr_fp_set (insn) != FP_SET_NONE)
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index d8ac6c4d6..7fce485b2 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10289,12 +10289,14 @@ such requirement.  @var{regs_live} contains the set of hard registers
+ that are live before @var{insn}.
+ @end deftypefn
+ 
+-@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn})
++@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn}, HARD_REG_SET @var{regs_live})
+ @var{entity} is an integer specifying a mode-switched entity.
+ If this hook is defined, it is evaluated for every @var{insn} during mode
+ switching.  It returns the mode that @var{entity} is in after @var{insn}
+ has been executed.  @var{mode} is the mode that @var{entity} was in
+ before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}.
++@var{regs_live} is the set of hard registers that are live after @var{insn}
++has been executed.
+ 
+ @var{mode} is equal to the number of modes defined for @var{entity}
+ if the mode before @var{insn} is unknown.  The hook should likewise return
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 6bbda5058..4f0445894 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -631,10 +631,6 @@ optimize_mode_switching (void)
+ 		      last_mode = mode;
+ 		    }
+ 
+-		  if (targetm.mode_switching.after)
+-		    last_mode = targetm.mode_switching.after (e, last_mode,
+-							      insn);
+-
+ 		  /* Update LIVE_NOW.  */
+ 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ 		    if (REG_NOTE_KIND (link) == REG_DEAD)
+@@ -644,6 +640,10 @@ optimize_mode_switching (void)
+ 		  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ 		    if (REG_NOTE_KIND (link) == REG_UNUSED)
+ 		      reg_dies (XEXP (link, 0), &live_now);
++
++		  if (targetm.mode_switching.after)
++		    last_mode = targetm.mode_switching.after (e, last_mode,
++							      insn, live_now);
+ 		}
+ 	    }
+ 
+diff --git a/gcc/target.def b/gcc/target.def
+index 06a52bdaf..67c20bbb0 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -7014,6 +7014,8 @@ If this hook is defined, it is evaluated for every @var{insn} during mode\n\
+ switching.  It returns the mode that @var{entity} is in after @var{insn}\n\
+ has been executed.  @var{mode} is the mode that @var{entity} was in\n\
+ before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}.\n\
++@var{regs_live} is the set of hard registers that are live after @var{insn}\n\
++has been executed.\n\
+ \n\
+ @var{mode} is equal to the number of modes defined for @var{entity}\n\
+ if the mode before @var{insn} is unknown.  The hook should likewise return\n\
+@@ -7021,7 +7023,7 @@ the number of modes if it does not know what mode @var{entity} has after\n\
+ @var{insn}.\n\
+ \n\
+ Not defining the hook is equivalent to returning @var{mode}.",
+- int, (int entity, int mode, rtx_insn *insn), NULL)
++ int, (int entity, int mode, rtx_insn *insn, HARD_REG_SET regs_live), NULL)
+ 
+ DEFHOOK
+ (entry,
+-- 
+2.33.0
+
diff --git a/0141-Backport-SME-mode-switching-Use-1-based-edge-aux-fie.patch b/0141-Backport-SME-mode-switching-Use-1-based-edge-aux-fie.patch
new file mode 100644
index 0000000..0cb257e
--- /dev/null
+++ b/0141-Backport-SME-mode-switching-Use-1-based-edge-aux-fie.patch
@@ -0,0 +1,56 @@
+From b0d3536b2a28d3a7084e3bbb9532e719aaf2016b Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:59 +0000
+Subject: [PATCH 042/157] [Backport][SME] mode-switching: Use 1-based edge aux
+ fields
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=718228a6f479fe252e0e6f71933c2465b7b480a9
+
+The pass used the edge aux field to record which mode change
+should happen on the edge, with -1 meaning "none".  It's more
+convenient for later patches to leave aux zero for "none",
+and use numbers based at 1 to record a change.
+
+gcc/
+	* mode-switching.cc (commit_mode_sets): Use 1-based edge aux values.
+---
+ gcc/mode-switching.cc | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 4f0445894..89a8494c6 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -106,10 +106,10 @@ commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info)
+   for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--)
+     {
+       edge eg = INDEX_EDGE (edge_list, ed);
+-      int mode;
+ 
+-      if ((mode = (int)(intptr_t)(eg->aux)) != -1)
++      if (eg->aux)
+ 	{
++	  int mode = (int) (intptr_t) eg->aux - 1;
+ 	  HARD_REG_SET live_at_edge;
+ 	  basic_block src_bb = eg->src;
+ 	  int cur_mode = info[src_bb->index].mode_out;
+@@ -727,14 +727,14 @@ optimize_mode_switching (void)
+ 	{
+ 	  edge eg = INDEX_EDGE (edge_list, ed);
+ 
+-	  eg->aux = (void *)(intptr_t)-1;
++	  eg->aux = (void *) (intptr_t) 0;
+ 
+ 	  for (i = 0; i < no_mode; i++)
+ 	    {
+ 	      int m = targetm.mode_switching.priority (entity_map[j], i);
+ 	      if (mode_bit_p (insert[ed], j, m))
+ 		{
+-		  eg->aux = (void *)(intptr_t)m;
++		  eg->aux = (void *) (intptr_t) (m + 1);
+ 		  break;
+ 		}
+ 	    }
+-- 
+2.33.0
+
diff --git a/0142-Backport-SME-mode-switching-Add-a-target-configurabl.patch b/0142-Backport-SME-mode-switching-Add-a-target-configurabl.patch
new file mode 100644
index 0000000..9123e40
--- /dev/null
+++ b/0142-Backport-SME-mode-switching-Add-a-target-configurabl.patch
@@ -0,0 +1,337 @@
+From 88d76baa38bb29d5cc732b3c0188b74ef9783713 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:28:59 +0000
+Subject: [PATCH 043/157] [Backport][SME] mode-switching: Add a
+ target-configurable confluence operator
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=493b0038d7d04986c7de977074d095e4eb7d9a27
+
+The mode-switching pass assumed that all of an entity's modes
+were mutually exclusive.  However, the upcoming SME changes
+have an entity with some overlapping modes, so that there is
+sometimes a "superunion" mode that contains two given modes.
+We can use this relationship to pass something more helpful than
+"don't know" to the emit hook.
+
+This patch adds a new hook that targets can use to specify
+a mode confluence operator.
+
+With mutually exclusive modes, it's possible to compute a block's
+incoming and outgoing modes by looking at its availability sets.
+With the confluence operator, we instead need to solve a full
+dataflow problem.
+
+However, when emitting a mode transition, the upcoming SME use of
+mode-switching benefits from having as much information as possible
+about the starting mode.  Calculating this information is definitely
+worth the compile time.
+
+The dataflow problem is written to work before and after the LCM
+problem has been solved.  A later patch makes use of this.
+
+While there (since git blame would ping me for the reindented code),
+I used a lambda to avoid the cut-&-pasted loops.
+
+gcc/
+	* target.def (mode_switching.confluence): New hook.
+	* doc/tm.texi (TARGET_MODE_CONFLUENCE): New @hook.
+	* doc/tm.texi.in: Regenerate.
+	* mode-switching.cc (confluence_info): New variable.
+	(mode_confluence, forward_confluence_n, forward_transfer): New
+	functions.
+	(optimize_mode_switching): Use them to calculate mode_in when
+	TARGET_MODE_CONFLUENCE is defined.
+---
+ gcc/doc/tm.texi       |  16 ++++
+ gcc/doc/tm.texi.in    |   2 +
+ gcc/mode-switching.cc | 179 +++++++++++++++++++++++++++++++++++-------
+ gcc/target.def        |  17 ++++
+ 4 files changed, 186 insertions(+), 28 deletions(-)
+
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 7fce485b2..d7053ec9e 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10306,6 +10306,22 @@ the number of modes if it does not know what mode @var{entity} has after
+ Not defining the hook is equivalent to returning @var{mode}.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} int TARGET_MODE_CONFLUENCE (int @var{entity}, int @var{mode1}, int @var{mode2})
++By default, the mode-switching pass assumes that a given entity's modes
++are mutually exclusive.  This means that the pass can only tell
++@code{TARGET_MODE_EMIT} about an entity's previous mode if all
++incoming paths of execution leave the entity in the same state.
++
++However, some entities might have overlapping, non-exclusive modes,
++so that it is sometimes possible to represent ``mode @var{mode1} or mode
++@var{mode2}'' with something more specific than ``mode not known''.
++If this is true for at least one entity, you should define this hook
++and make it return a mode that includes @var{mode1} and @var{mode2}
++as possibilities.  (The mode can include other possibilities too.)
++The hook should return the number of modes if no suitable mode exists
++for the given arguments.
++@end deftypefn
++
+ @deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity})
+ If this hook is defined, it is evaluated for every @var{entity} that
+ needs mode switching.  It should return the mode that @var{entity} is
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index ad343504f..d420e62fd 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -6922,6 +6922,8 @@ mode or ``no mode'', depending on context.
+ 
+ @hook TARGET_MODE_AFTER
+ 
++@hook TARGET_MODE_CONFLUENCE
++
+ @hook TARGET_MODE_ENTRY
+ 
+ @hook TARGET_MODE_EXIT
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 89a8494c6..065767902 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -484,6 +484,101 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
+   return pre_exit;
+ }
+ 
++/* Return the confluence of modes MODE1 and MODE2 for entity ENTITY,
++   using NO_MODE to represent an unknown mode if nothing more precise
++   is available.  */
++
++int
++mode_confluence (int entity, int mode1, int mode2, int no_mode)
++{
++  if (mode1 == mode2)
++    return mode1;
++
++  if (mode1 != no_mode
++      && mode2 != no_mode
++      && targetm.mode_switching.confluence)
++    return targetm.mode_switching.confluence (entity, mode1, mode2);
++
++  return no_mode;
++}
++
++/* Information for the dataflow problems below.  */
++struct
++{
++  /* Information about each basic block, indexed by block id.  */
++  struct bb_info *bb_info;
++
++  /* The entity that we're processing.  */
++  int entity;
++
++  /* The number of modes defined for the entity, and thus the identifier
++     of the "don't know" mode.  */
++  int no_mode;
++} confluence_info;
++
++/* Propagate information about any mode change on edge E to the
++   destination block's mode_in.  Return true if something changed.
++
++   The mode_in and mode_out fields use no_mode + 1 to mean "not yet set".  */
++
++static bool
++forward_confluence_n (edge e)
++{
++  /* The entry and exit blocks have no useful mode information.  */
++  if (e->src->index == ENTRY_BLOCK || e->dest->index == EXIT_BLOCK)
++    return false;
++
++  /* We don't control mode changes across abnormal edges.  */
++  if (e->flags & EDGE_ABNORMAL)
++    return false;
++
++  /* E->aux is nonzero if we have computed the LCM problem and scheduled
++     E to change the mode to E->aux - 1.  Otherwise model the change
++     from the source to the destination.  */
++  struct bb_info *bb_info = confluence_info.bb_info;
++  int no_mode = confluence_info.no_mode;
++  int src_mode = bb_info[e->src->index].mode_out;
++  if (e->aux)
++    src_mode = (int) (intptr_t) e->aux - 1;
++  if (src_mode == no_mode + 1)
++    return false;
++
++  int dest_mode = bb_info[e->dest->index].mode_in;
++  if (dest_mode == no_mode + 1)
++    {
++      bb_info[e->dest->index].mode_in = src_mode;
++      return true;
++    }
++
++  int entity = confluence_info.entity;
++  int new_mode = mode_confluence (entity, src_mode, dest_mode, no_mode);
++  if (dest_mode == new_mode)
++    return false;
++
++  bb_info[e->dest->index].mode_in = new_mode;
++  return true;
++}
++
++/* Update block BB_INDEX's mode_out based on its mode_in.  Return true if
++   something changed.  */
++
++static bool
++forward_transfer (int bb_index)
++{
++  /* The entry and exit blocks have no useful mode information.  */
++  if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK)
++    return false;
++
++  /* Only propagate through a block if the entity is transparent.  */
++  struct bb_info *bb_info = confluence_info.bb_info;
++  if (bb_info[bb_index].computing != confluence_info.no_mode
++      || bb_info[bb_index].mode_out == bb_info[bb_index].mode_in)
++    return false;
++
++  bb_info[bb_index].mode_out = bb_info[bb_index].mode_in;
++  return true;
++}
++
+ /* Find all insns that need a particular mode setting, and insert the
+    necessary mode switches.  Return true if we did work.  */
+ 
+@@ -567,6 +662,39 @@ optimize_mode_switching (void)
+ 
+   auto_sbitmap transp_all (last_basic_block_for_fn (cfun));
+ 
++  auto_bitmap blocks;
++
++  /* Forward-propagate mode information through blocks where the entity
++     is transparent, so that mode_in describes the mode on entry to each
++     block and mode_out describes the mode on exit from each block.  */
++  auto forwprop_mode_info = [&](struct bb_info *info,
++				int entity, int no_mode)
++    {
++      /* Use no_mode + 1 to mean "not yet set".  */
++      FOR_EACH_BB_FN (bb, cfun)
++	{
++	  if (bb_has_abnormal_pred (bb))
++	    info[bb->index].mode_in = info[bb->index].seginfo->mode;
++	  else
++	    info[bb->index].mode_in = no_mode + 1;
++	  if (info[bb->index].computing != no_mode)
++	    info[bb->index].mode_out = info[bb->index].computing;
++	  else
++	    info[bb->index].mode_out = no_mode + 1;
++	}
++
++      confluence_info.bb_info = info;
++      confluence_info.entity = entity;
++      confluence_info.no_mode = no_mode;
++
++      bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun));
++      df_simple_dataflow (DF_FORWARD, NULL, NULL, forward_confluence_n,
++			  forward_transfer, blocks,
++			  df_get_postorder (DF_FORWARD),
++			  df_get_n_blocks (DF_FORWARD));
++
++    };
++
+   for (j = n_entities - 1; j >= 0; j--)
+     {
+       int e = entity_map[j];
+@@ -720,6 +848,7 @@ optimize_mode_switching (void)
+   for (j = n_entities - 1; j >= 0; j--)
+     {
+       int no_mode = num_modes[entity_map[j]];
++      struct bb_info *info = bb_info[j];
+ 
+       /* Insert all mode sets that have been inserted by lcm.  */
+ 
+@@ -740,39 +869,33 @@ optimize_mode_switching (void)
+ 	    }
+ 	}
+ 
++      /* mode_in and mode_out can be calculated directly from avin and
++	 avout if all the modes are mutually exclusive.  Use the target-
++	 provided confluence function otherwise.  */
++      if (targetm.mode_switching.confluence)
++	forwprop_mode_info (info, entity_map[j], no_mode);
++
+       FOR_EACH_BB_FN (bb, cfun)
+ 	{
+-	  struct bb_info *info = bb_info[j];
+-	  int last_mode = no_mode;
+-
+-	  /* intialize mode in availability for bb.  */
+-	  for (i = 0; i < no_mode; i++)
+-	    if (mode_bit_p (avout[bb->index], j, i))
+-	      {
+-		if (last_mode == no_mode)
+-		  last_mode = i;
+-		if (last_mode != i)
++	  auto modes_confluence = [&](sbitmap *av)
++	    {
++	      for (int i = 0; i < no_mode; ++i)
++		if (mode_bit_p (av[bb->index], j, i))
+ 		  {
+-		    last_mode = no_mode;
+-		    break;
++		    for (int i2 = i + 1; i2 < no_mode; ++i2)
++		      if (mode_bit_p (av[bb->index], j, i2))
++			return no_mode;
++		    return i;
+ 		  }
+-	      }
+-	  info[bb->index].mode_out = last_mode;
++	      return no_mode;
++	    };
+ 
+-	  /* intialize mode out availability for bb.  */
+-	  last_mode = no_mode;
+-	  for (i = 0; i < no_mode; i++)
+-	    if (mode_bit_p (avin[bb->index], j, i))
+-	      {
+-		if (last_mode == no_mode)
+-		  last_mode = i;
+-		if (last_mode != i)
+-		  {
+-		    last_mode = no_mode;
+-		    break;
+-		  }
+-	      }
+-	  info[bb->index].mode_in = last_mode;
++	  /* intialize mode in/out availability for bb.  */
++	  if (!targetm.mode_switching.confluence)
++	    {
++	      info[bb->index].mode_out = modes_confluence (avout);
++	      info[bb->index].mode_in = modes_confluence (avin);
++	    }
+ 
+ 	  for (i = 0; i < no_mode; i++)
+ 	    if (mode_bit_p (del[bb->index], j, i))
+diff --git a/gcc/target.def b/gcc/target.def
+index 67c20bbb0..1e2091ed3 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -7025,6 +7025,23 @@ the number of modes if it does not know what mode @var{entity} has after\n\
+ Not defining the hook is equivalent to returning @var{mode}.",
+  int, (int entity, int mode, rtx_insn *insn, HARD_REG_SET regs_live), NULL)
+ 
++DEFHOOK
++(confluence,
++ "By default, the mode-switching pass assumes that a given entity's modes\n\
++are mutually exclusive.  This means that the pass can only tell\n\
++@code{TARGET_MODE_EMIT} about an entity's previous mode if all\n\
++incoming paths of execution leave the entity in the same state.\n\
++\n\
++However, some entities might have overlapping, non-exclusive modes,\n\
++so that it is sometimes possible to represent ``mode @var{mode1} or mode\n\
++@var{mode2}'' with something more specific than ``mode not known''.\n\
++If this is true for at least one entity, you should define this hook\n\
++and make it return a mode that includes @var{mode1} and @var{mode2}\n\
++as possibilities.  (The mode can include other possibilities too.)\n\
++The hook should return the number of modes if no suitable mode exists\n\
++for the given arguments.",
++ int, (int entity, int mode1, int mode2), NULL)
++
+ DEFHOOK
+ (entry,
+  "If this hook is defined, it is evaluated for every @var{entity} that\n\
+-- 
+2.33.0
+
diff --git a/0143-Backport-SME-mode-switching-Add-a-backprop-hook.patch b/0143-Backport-SME-mode-switching-Add-a-backprop-hook.patch
new file mode 100644
index 0000000..8fb51ae
--- /dev/null
+++ b/0143-Backport-SME-mode-switching-Add-a-backprop-hook.patch
@@ -0,0 +1,483 @@
+From cb4189b45a3a411958ab6aa85108f6dc7516acf5 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 11 Nov 2023 17:29:00 +0000
+Subject: [PATCH 044/157] [Backport][SME] mode-switching: Add a backprop hook
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=fc8458e20a524d053f576d64a606e21f8bd03b84
+
+This patch adds a way for targets to ask that selected mode changes
+be brought forward, through a combination of:
+
+(1) requiring a mode in blocks where the entity was previously
+    transparent
+
+(2) pushing the transition at the head of a block onto incomging edges
+
+SME has two uses for this:
+
+- A "one-shot" entity that, for any given path of execution,
+  either stays off or makes exactly one transition from off to on.
+  This relies only on (1) above; see the hook description for more info.
+
+  The main purpose of using mode-switching for this entity is to
+  shrink-wrap the code that requires it.
+
+- A second entity for which all transitions must be from known
+  modes, which is enforced using a combination of (1) and (2).
+  More specifically, (1) looks for edges B1->B2 for which:
+
+  - B2 requires a specific mode and
+  - B1 does not guarantee a specific starting mode
+
+  In this system, such an edge is only possible if the entity is
+  transparent in B1.  (1) then forces B1 to require some safe common
+  mode.  Applying this inductively means that all incoming edges are
+  from known modes.  If different edges give different starting modes,
+  (2) pushes the transitions onto the edges themselves; this only
+  happens if the entity is not transparent in some predecessor block.
+
+The patch also uses the back-propagation as an excuse to do a simple
+on-the-fly optimisation.
+
+Hopefully the comments in the patch explain things a bit better.
+
+gcc/
+	* target.def (mode_switching.backprop): New hook.
+	* doc/tm.texi.in (TARGET_MODE_BACKPROP): New @hook.
+	* doc/tm.texi: Regenerate.
+	* mode-switching.cc (struct bb_info): Add single_succ.
+	(confluence_info): Add transp field.
+	(single_succ_confluence_n, single_succ_transfer): New functions.
+	(backprop_confluence_n, backprop_transfer): Likewise.
+	(optimize_mode_switching): Use them.  Push mode transitions onto
+	a block's incoming edges, if the backprop hook requires it.
+---
+ gcc/doc/tm.texi       |  28 +++++
+ gcc/doc/tm.texi.in    |   2 +
+ gcc/mode-switching.cc | 275 ++++++++++++++++++++++++++++++++++++++++++
+ gcc/target.def        |  29 +++++
+ 4 files changed, 334 insertions(+)
+
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index d7053ec9e..5f0972356 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10322,6 +10322,34 @@ The hook should return the number of modes if no suitable mode exists
+ for the given arguments.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} int TARGET_MODE_BACKPROP (int @var{entity}, int @var{mode1}, int @var{mode2})
++If defined, the mode-switching pass uses this hook to back-propagate mode
++requirements through blocks that have no mode requirements of their own.
++Specifically, @var{mode1} is the mode that @var{entity} has on exit
++from a block B1 (say) and @var{mode2} is the mode that the next block
++requires @var{entity} to have.  B1 does not have any mode requirements
++of its own.
++
++The hook should return the mode that it prefers or requires @var{entity}
++to have in B1, or the number of modes if there is no such requirement.
++If the hook returns a required mode for more than one of B1's outgoing
++edges, those modes are combined as for @code{TARGET_MODE_CONFLUENCE}.
++
++For example, suppose there is a ``one-shot'' entity that,
++for a given execution of a function, either stays off or makes exactly
++one transition from off to on.  It is safe to make the transition at any
++time, but it is better not to do so unnecessarily.  This hook allows the
++function to manage such an entity without having to track its state at
++runtime.  Specifically. the entity would have two modes, 0 for off and
++1 for on, with 2 representing ``don't know''.  The system is forbidden from
++transitioning from 2 to 1, since 2 represents the possibility that the
++entity is already on (and the aim is to avoid having to emit code to
++check for that case).  This hook would therefore return 1 when @var{mode1}
++is 2 and @var{mode2} is 1, which would force the entity to be on in the
++source block.  Applying this inductively would remove all transitions
++in which the previous state is unknown.
++@end deftypefn
++
+ @deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity})
+ If this hook is defined, it is evaluated for every @var{entity} that
+ needs mode switching.  It should return the mode that @var{entity} is
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index d420e62fd..fcab21744 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -6924,6 +6924,8 @@ mode or ``no mode'', depending on context.
+ 
+ @hook TARGET_MODE_CONFLUENCE
+ 
++@hook TARGET_MODE_BACKPROP
++
+ @hook TARGET_MODE_ENTRY
+ 
+ @hook TARGET_MODE_EXIT
+diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
+index 065767902..c2a0f0294 100644
+--- a/gcc/mode-switching.cc
++++ b/gcc/mode-switching.cc
+@@ -81,6 +81,7 @@ struct bb_info
+   int computing;
+   int mode_out;
+   int mode_in;
++  int single_succ;
+ };
+ 
+ /* Clear ode I from entity J in bitmap B.  */
+@@ -508,6 +509,9 @@ struct
+   /* Information about each basic block, indexed by block id.  */
+   struct bb_info *bb_info;
+ 
++  /* A bitmap of blocks for which the current entity is transparent.  */
++  sbitmap transp;
++
+   /* The entity that we're processing.  */
+   int entity;
+ 
+@@ -579,6 +583,210 @@ forward_transfer (int bb_index)
+   return true;
+ }
+ 
++/* A backwards confluence function.  Update the the bb_info single_succ
++   field for E's source block, based on changes to E's destination block.
++   At the end of the dataflow problem, single_succ is the single mode
++   that all successors require (directly or indirectly), or no_mode
++   if there are conflicting requirements.
++
++   Initially, a value of no_mode + 1 means "don't know".  */
++
++static bool
++single_succ_confluence_n (edge e)
++{
++  /* The entry block has no associated mode information.  */
++  if (e->src->index == ENTRY_BLOCK)
++    return false;
++
++  /* We don't control mode changes across abnormal edges.  */
++  if (e->flags & EDGE_ABNORMAL)
++    return false;
++
++  /* Do nothing if we've already found a conflict.  */
++  struct bb_info *bb_info = confluence_info.bb_info;
++  int no_mode = confluence_info.no_mode;
++  int src_mode = bb_info[e->src->index].single_succ;
++  if (src_mode == no_mode)
++    return false;
++
++  /* Work out what mode the destination block (or its successors) require.  */
++  int dest_mode;
++  if (e->dest->index == EXIT_BLOCK)
++    dest_mode = no_mode;
++  else if (bitmap_bit_p (confluence_info.transp, e->dest->index))
++    dest_mode = bb_info[e->dest->index].single_succ;
++  else
++    dest_mode = bb_info[e->dest->index].seginfo->mode;
++
++  /* Do nothing if the destination block has no new information.  */
++  if (dest_mode == no_mode + 1 || dest_mode == src_mode)
++    return false;
++
++  /* Detect conflicting modes.  */
++  if (src_mode != no_mode + 1)
++    dest_mode = no_mode;
++
++  bb_info[e->src->index].single_succ = dest_mode;
++  return true;
++}
++
++/* A backward transfer function for computing the bb_info single_succ
++   fields, as described above single_succ_confluence.  */
++
++static bool
++single_succ_transfer (int bb_index)
++{
++  /* We don't have any field to transfer to.  Assume that, after the
++     first iteration, we are only called if single_succ has changed.
++     We should then process incoming edges if the entity is transparent.  */
++  return bitmap_bit_p (confluence_info.transp, bb_index);
++}
++
++/* Check whether the target wants to back-propagate a mode change across
++   edge E, and update the source block's computed mode if so.  Return true
++   if something changed.  */
++
++static bool
++backprop_confluence_n (edge e)
++{
++  /* The entry and exit blocks have no useful mode information.  */
++  if (e->src->index == ENTRY_BLOCK || e->dest->index == EXIT_BLOCK)
++    return false;
++
++  /* We don't control mode changes across abnormal edges.  */
++  if (e->flags & EDGE_ABNORMAL)
++    return false;
++
++  /* We can only require a new mode in the source block if the entity
++     was originally transparent there.  */
++  if (!bitmap_bit_p (confluence_info.transp, e->src->index))
++    return false;
++
++  /* Exit now if there is no required mode, or if all paths into the
++     source block leave the entity in the required mode.  */
++  struct bb_info *bb_info = confluence_info.bb_info;
++  int no_mode = confluence_info.no_mode;
++  int src_mode = bb_info[e->src->index].mode_out;
++  int dest_mode = bb_info[e->dest->index].mode_in;
++  if (dest_mode == no_mode || src_mode == dest_mode)
++    return false;
++
++  /* See what the target thinks about this transition.  */
++  int entity = confluence_info.entity;
++  int new_mode = targetm.mode_switching.backprop (entity, src_mode,
++						  dest_mode);
++  if (new_mode == no_mode)
++    return false;
++
++  /* The target doesn't like the current transition, but would be happy
++     with a transition from NEW_MODE.
++
++     If we force the source block to use NEW_MODE, we might introduce a
++     double transition on at least one path through the function (one to
++     NEW_MODE and then one to DEST_MODE).  Therefore, if all destination
++     blocks require the same mode, it is usually better to bring that
++     mode requirement forward.
++
++     If that isn't possible, merge the preference for this edge with
++     the preferences for other edges.  no_mode + 1 indicates that there
++     was no previous preference.  */
++  int old_mode = bb_info[e->src->index].computing;
++  if (bb_info[e->src->index].single_succ != no_mode)
++    new_mode = bb_info[e->src->index].single_succ;
++  else if (old_mode != no_mode + 1)
++    new_mode = mode_confluence (entity, old_mode, new_mode, no_mode);
++
++  if (old_mode == new_mode)
++    return false;
++
++  bb_info[e->src->index].computing = new_mode;
++  return true;
++}
++
++/* If the current entity was originally transparent in block BB_INDEX,
++   update the incoming mode to match the outgoing mode.  Register a mode
++   change if the entity is no longer transparent.
++
++   Also, as an on-the-fly optimization, check whether the entity was
++   originally transparent in BB_INDEX and if all successor blocks require
++   the same mode.  If so, anticipate the mode change in BB_INDEX if
++   doing it on the incoming edges would require no more mode changes than
++   doing it on the outgoing edges.  The aim is to reduce the total number
++   of mode changes emitted for the function (and thus reduce code size and
++   cfg complexity) without increasing the number of mode changes on any
++   given path through the function.  A typical case where it helps is:
++
++	  T
++	 / \
++	T   M
++	 \ /
++	  M
++
++   where the entity is transparent in the T blocks and is required to have
++   mode M in the M blocks.  If there are no redundancies leading up to this,
++   there will be two mutually-exclusive changes to mode M, one on each of
++   the T->M edges.  The optimization instead converts it to:
++
++	  T            T            M
++	 / \          / \          / \
++	T   M   ->   M   M   ->   M   M
++	 \ /          \ /          \ /
++	  M            M            M
++
++   which creates a single transition to M for both paths through the diamond.
++
++   Return true if something changed.  */
++
++static bool
++backprop_transfer (int bb_index)
++{
++  /* The entry and exit blocks have no useful mode information.  */
++  if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK)
++    return false;
++
++  /* We can only require a new mode if the entity was previously
++     transparent.  */
++  if (!bitmap_bit_p (confluence_info.transp, bb_index))
++    return false;
++
++  struct bb_info *bb_info = confluence_info.bb_info;
++  basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
++  int no_mode = confluence_info.no_mode;
++  int mode_in = bb_info[bb_index].mode_in;
++  int mode_out = bb_info[bb_index].computing;
++  if (mode_out == no_mode + 1)
++    {
++      /* The entity is still transparent for this block.  See whether
++	 all successor blocks need the same mode, either directly or
++	 indirectly.  */
++      mode_out = bb_info[bb_index].single_succ;
++      if (mode_out == no_mode)
++	return false;
++
++      /* Get a minimum bound on the number of transitions that would be
++	 removed if BB itself required MODE_OUT.  */
++      unsigned int moved = 0;
++      for (edge e : bb->succs)
++	if (e->dest->index != EXIT_BLOCK
++	    && mode_out == bb_info[e->dest->index].seginfo->mode)
++	  moved += 1;
++
++      /* See whether making the mode change on all incoming edges would
++	 be no worse than making it on MOVED outgoing edges.  */
++      if (moved < EDGE_COUNT (bb->preds))
++	return false;
++
++      bb_info[bb_index].mode_out = mode_out;
++      bb_info[bb_index].computing = mode_out;
++    }
++  else if (mode_out == mode_in)
++    return false;
++
++  bb_info[bb_index].mode_in = mode_out;
++  bb_info[bb_index].seginfo->mode = mode_out;
++  return true;
++}
++
+ /* Find all insns that need a particular mode setting, and insert the
+    necessary mode switches.  Return true if we did work.  */
+ 
+@@ -684,6 +892,7 @@ optimize_mode_switching (void)
+ 	}
+ 
+       confluence_info.bb_info = info;
++      confluence_info.transp = nullptr;
+       confluence_info.entity = entity;
+       confluence_info.no_mode = no_mode;
+ 
+@@ -695,6 +904,9 @@ optimize_mode_switching (void)
+ 
+     };
+ 
++  if (targetm.mode_switching.backprop)
++    clear_aux_for_edges ();
++
+   for (j = n_entities - 1; j >= 0; j--)
+     {
+       int e = entity_map[j];
+@@ -817,6 +1029,53 @@ optimize_mode_switching (void)
+ 	    }
+ 	}
+ 
++      /* If the target requests it, back-propagate selected mode requirements
++	 through transparent blocks.  */
++      if (targetm.mode_switching.backprop)
++	{
++	  /* First work out the mode on entry to and exit from each block.  */
++	  forwprop_mode_info (info, e, no_mode);
++
++	  /* Compute the single_succ fields, as described above
++	     single_succ_confluence.  */
++	  FOR_EACH_BB_FN (bb, cfun)
++	    info[bb->index].single_succ = no_mode + 1;
++
++	  confluence_info.transp = transp_all;
++	  bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun));
++	  df_simple_dataflow (DF_BACKWARD, NULL, NULL,
++			      single_succ_confluence_n,
++			      single_succ_transfer, blocks,
++			      df_get_postorder (DF_BACKWARD),
++			      df_get_n_blocks (DF_BACKWARD));
++
++	  FOR_EACH_BB_FN (bb, cfun)
++	    {
++	      /* Repurpose mode_in as the first mode required by the block,
++		 or the output mode if none.  */
++	      if (info[bb->index].seginfo->mode != no_mode)
++		info[bb->index].mode_in = info[bb->index].seginfo->mode;
++
++	      /* In transparent blocks, use computing == no_mode + 1
++		 to indicate that no propagation has taken place.  */
++	      if (info[bb->index].computing == no_mode)
++		info[bb->index].computing = no_mode + 1;
++	    }
++
++	  bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun));
++	  df_simple_dataflow (DF_BACKWARD, NULL, NULL, backprop_confluence_n,
++			      backprop_transfer, blocks,
++			      df_get_postorder (DF_BACKWARD),
++			      df_get_n_blocks (DF_BACKWARD));
++
++	  /* Any block that now computes a mode is no longer transparent.  */
++	  FOR_EACH_BB_FN (bb, cfun)
++	    if (info[bb->index].computing == no_mode + 1)
++	      info[bb->index].computing = no_mode;
++	    else if (info[bb->index].computing != no_mode)
++	      bitmap_clear_bit (transp_all, bb->index);
++	}
++
+       /* Set the anticipatable and computing arrays.  */
+       for (i = 0; i < no_mode; i++)
+ 	{
+@@ -900,6 +1159,22 @@ optimize_mode_switching (void)
+ 	  for (i = 0; i < no_mode; i++)
+ 	    if (mode_bit_p (del[bb->index], j, i))
+ 	      info[bb->index].seginfo->mode = no_mode;
++
++	  /* See whether the target can perform the first transition.
++	     If not, push it onto the incoming edges.  The earlier backprop
++	     pass should ensure that the resulting transitions are valid.  */
++	  if (targetm.mode_switching.backprop)
++	    {
++	      int from_mode = info[bb->index].mode_in;
++	      int to_mode = info[bb->index].seginfo->mode;
++	      if (targetm.mode_switching.backprop (entity_map[j], from_mode,
++						   to_mode) != no_mode)
++		{
++		  for (edge e : bb->preds)
++		    e->aux = (void *) (intptr_t) (to_mode + 1);
++		  info[bb->index].mode_in = to_mode;
++		}
++	    }
+ 	}
+ 
+       /* Now output the remaining mode sets in all the segments.  */
+diff --git a/gcc/target.def b/gcc/target.def
+index 1e2091ed3..4d77c1523 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -7042,6 +7042,35 @@ The hook should return the number of modes if no suitable mode exists\n\
+ for the given arguments.",
+  int, (int entity, int mode1, int mode2), NULL)
+ 
++DEFHOOK
++(backprop,
++ "If defined, the mode-switching pass uses this hook to back-propagate mode\n\
++requirements through blocks that have no mode requirements of their own.\n\
++Specifically, @var{mode1} is the mode that @var{entity} has on exit\n\
++from a block B1 (say) and @var{mode2} is the mode that the next block\n\
++requires @var{entity} to have.  B1 does not have any mode requirements\n\
++of its own.\n\
++\n\
++The hook should return the mode that it prefers or requires @var{entity}\n\
++to have in B1, or the number of modes if there is no such requirement.\n\
++If the hook returns a required mode for more than one of B1's outgoing\n\
++edges, those modes are combined as for @code{TARGET_MODE_CONFLUENCE}.\n\
++\n\
++For example, suppose there is a ``one-shot'' entity that,\n\
++for a given execution of a function, either stays off or makes exactly\n\
++one transition from off to on.  It is safe to make the transition at any\n\
++time, but it is better not to do so unnecessarily.  This hook allows the\n\
++function to manage such an entity without having to track its state at\n\
++runtime.  Specifically. the entity would have two modes, 0 for off and\n\
++1 for on, with 2 representing ``don't know''.  The system is forbidden from\n\
++transitioning from 2 to 1, since 2 represents the possibility that the\n\
++entity is already on (and the aim is to avoid having to emit code to\n\
++check for that case).  This hook would therefore return 1 when @var{mode1}\n\
++is 2 and @var{mode2} is 1, which would force the entity to be on in the\n\
++source block.  Applying this inductively would remove all transitions\n\
++in which the previous state is unknown.",
++ int, (int entity, int mode1, int mode2), NULL)
++
+ DEFHOOK
+ (entry,
+  "If this hook is defined, it is evaluated for every @var{entity} that\n\
+-- 
+2.33.0
+
diff --git a/0144-Backport-SME-aarch64-Add-a-result_mode-helper-functi.patch b/0144-Backport-SME-aarch64-Add-a-result_mode-helper-functi.patch
new file mode 100644
index 0000000..ad6da47
--- /dev/null
+++ b/0144-Backport-SME-aarch64-Add-a-result_mode-helper-functi.patch
@@ -0,0 +1,81 @@
+From 4553f252c10968037edceba4abe3984dc9bbad2a Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Fri, 1 Dec 2023 08:36:15 +0000
+Subject: [PATCH 045/157] [Backport][SME] aarch64: Add a result_mode helper
+ function
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a1bc121c00e30bd1bdaa62d87cbe64eb88e74f45
+
+SME will add more intrinsics whose expansion code requires
+the mode of the function return value.  This patch adds an
+associated helper routine.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h
+	(function_expander::result_mode): New member function.
+	* config/aarch64/aarch64-sve-builtins-base.cc
+	(svld234_impl::expand): Use it.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(function_expander::get_reg_target): Likewise.
+---
+ gcc/config/aarch64/aarch64-sve-builtins-base.cc | 2 +-
+ gcc/config/aarch64/aarch64-sve-builtins.cc      | 2 +-
+ gcc/config/aarch64/aarch64-sve-builtins.h       | 9 +++++++++
+ 3 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+index 56c9d75e7..c9bf13792 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+@@ -1272,7 +1272,7 @@ public:
+   rtx
+   expand (function_expander &e) const OVERRIDE
+   {
+-    machine_mode tuple_mode = TYPE_MODE (TREE_TYPE (e.call_expr));
++    machine_mode tuple_mode = e.result_mode ();
+     insn_code icode = convert_optab_handler (vec_mask_load_lanes_optab,
+ 					     tuple_mode, e.vector_mode (0));
+     return e.use_contiguous_load_insn (icode);
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index e168c8334..91af96687 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -2796,7 +2796,7 @@ function_expander::get_fallback_value (machine_mode mode, unsigned int nops,
+ rtx
+ function_expander::get_reg_target ()
+ {
+-  machine_mode target_mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
++  machine_mode target_mode = result_mode ();
+   if (!possible_target || GET_MODE (possible_target) != target_mode)
+     possible_target = gen_reg_rtx (target_mode);
+   return possible_target;
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 0d130b871..52994cde0 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -528,6 +528,8 @@ public:
+   insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
+ 					   machine_mode = E_VOIDmode);
+ 
++  machine_mode result_mode () const;
++
+   bool overlaps_input_p (rtx);
+ 
+   rtx convert_to_pmode (rtx);
+@@ -877,6 +879,13 @@ function_base::call_properties (const function_instance &instance) const
+   return flags;
+ }
+ 
++/* Return the mode of the result of a call.  */
++inline machine_mode
++function_expander::result_mode () const
++{
++  return TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
++}
++
+ }
+ 
+ #endif
+-- 
+2.33.0
+
diff --git a/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch b/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch
new file mode 100644
index 0000000..cdaf6ee
--- /dev/null
+++ b/0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch
@@ -0,0 +1,232 @@
+From 60612cbd9cdd9b5079c0505b9d53c9cd98fba4b1 Mon Sep 17 00:00:00 2001
+From: Kewen Lin 
+Date: Tue, 15 Nov 2022 20:26:07 -0600
+Subject: [PATCH 046/157] [Backport][SME] rtl: Try to remove EH edges after
+ {pro,epi}logue generation [PR90259]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=63e1b2e767a3f4695373c2406ff719c0a60c1858
+
+After prologue and epilogue generation, the judgement on whether
+one memory access onto stack frame may trap or not could change,
+since we get more exact stack information by now.
+
+As PR90259 shows, some memory access becomes impossible to trap
+any more after prologue and epilogue generation, it can make
+subsequent optimization be able to remove it if safe, but it
+results in unexpected control flow status due to REG_EH_REGION
+note missing.
+
+This patch proposes to try to remove EH edges with function
+purge_all_dead_edges after prologue and epilogue generation,
+it simplifies CFG as early as we can and don't need any fixup
+in downstream passes.
+
+CFG simplification result with PR90259's case as example:
+
+*before*
+
+   18: %1:TF=call [`__gcc_qdiv'] argc:0
+      REG_EH_REGION 0x2
+   77: NOTE_INSN_BASIC_BLOCK 3
+   19: NOTE_INSN_DELETED
+   20: NOTE_INSN_DELETED
+  110: [%31:SI+0x20]=%1:DF
+      REG_EH_REGION 0x2
+  116: NOTE_INSN_BASIC_BLOCK 4
+  111: [%31:SI+0x28]=%2:DF
+      REG_EH_REGION 0x2
+   22: NOTE_INSN_BASIC_BLOCK 5
+  108: %0:DF=[%31:SI+0x20]
+      REG_EH_REGION 0x2
+  117: NOTE_INSN_BASIC_BLOCK 6
+  109: %1:DF=[%31:SI+0x28]
+      REG_EH_REGION 0x2
+   79: NOTE_INSN_BASIC_BLOCK 7
+   26: [%31:SI+0x18]=%0:DF
+  104: pc=L69
+  105: barrier
+
+*after*
+
+   18: %1:TF=call [`__gcc_qdiv'] argc:0
+      REG_EH_REGION 0x2
+   77: NOTE_INSN_BASIC_BLOCK 3
+   19: NOTE_INSN_DELETED
+   20: NOTE_INSN_DELETED
+  110: [%31:SI+0x20]=%1:DF
+  111: [%31:SI+0x28]=%2:DF
+  108: %0:DF=[%31:SI+0x20]
+  109: %1:DF=[%31:SI+0x28]
+   26: [%31:SI+0x18]=%0:DF
+  104: pc=L69
+  105: barrier
+
+	PR rtl-optimization/90259
+
+gcc/ChangeLog:
+
+	* function.cc (rest_of_handle_thread_prologue_and_epilogue): Add
+	parameter fun, and call function purge_all_dead_edges.
+	(pass_thread_prologue_and_epilogue::execute): Name unamed parameter
+	as fun, and use it for rest_of_handle_thread_prologue_and_epilogue.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.target/powerpc/pr90259.C: New.
+---
+ gcc/function.cc                            |  13 ++-
+ gcc/testsuite/g++.target/powerpc/pr90259.C | 103 +++++++++++++++++++++
+ 2 files changed, 113 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/g++.target/powerpc/pr90259.C
+
+diff --git a/gcc/function.cc b/gcc/function.cc
+index 49c7ccf4b..28de39dd6 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -6529,7 +6529,7 @@ make_pass_leaf_regs (gcc::context *ctxt)
+ }
+ 
+ static unsigned int
+-rest_of_handle_thread_prologue_and_epilogue (void)
++rest_of_handle_thread_prologue_and_epilogue (function *fun)
+ {
+   /* prepare_shrink_wrap is sensitive to the block structure of the control
+      flow graph, so clean it up first.  */
+@@ -6546,6 +6546,13 @@ rest_of_handle_thread_prologue_and_epilogue (void)
+      Fix that up.  */
+   fixup_partitions ();
+ 
++  /* After prologue and epilogue generation, the judgement on whether
++     one memory access onto stack frame may trap or not could change,
++     since we get more exact stack information by now.  So try to
++     remove any EH edges here, see PR90259.  */
++  if (fun->can_throw_non_call_exceptions)
++    purge_all_dead_edges ();
++
+   /* Shrink-wrapping can result in unreachable edges in the epilogue,
+      see PR57320.  */
+   cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
+@@ -6614,9 +6621,9 @@ public:
+   {}
+ 
+   /* opt_pass methods: */
+-  virtual unsigned int execute (function *)
++  unsigned int execute (function * fun) final override
+     {
+-      return rest_of_handle_thread_prologue_and_epilogue ();
++      return rest_of_handle_thread_prologue_and_epilogue (fun);
+     }
+ 
+ }; // class pass_thread_prologue_and_epilogue
+diff --git a/gcc/testsuite/g++.target/powerpc/pr90259.C b/gcc/testsuite/g++.target/powerpc/pr90259.C
+new file mode 100644
+index 000000000..db75ac7fe
+--- /dev/null
++++ b/gcc/testsuite/g++.target/powerpc/pr90259.C
+@@ -0,0 +1,103 @@
++/* { dg-require-effective-target long_double_ibm128 } */
++/* { dg-options "-O2 -ffloat-store -fgcse -fnon-call-exceptions -fno-forward-propagate -fno-omit-frame-pointer -fstack-protector-all" } */
++/* { dg-add-options long_double_ibm128 } */
++
++/* Verify there is no ICE.  */
++
++template  struct b
++{
++  static constexpr int c = a;
++};
++template  using d = b;
++struct e
++{
++  int f;
++  int
++  g ()
++  {
++    return __builtin_ceil (f / (long double) h);
++  }
++  float h;
++};
++template  using k = d;
++template  class n
++{
++public:
++  e ae;
++  void af ();
++};
++template 
++void
++n::af ()
++{
++  ae.g ();
++}
++template  using m = int;
++template ::c>>
++using aj = n;
++struct o
++{
++  void
++  af ()
++  {
++    al.af ();
++  }
++  aj al;
++};
++template  class am;
++template  class ao
++{
++protected:
++  static i *ap (int);
++};
++template  class p;
++template  class p : ao
++{
++public:
++  static ar
++  as (const int &p1, j...)
++  {
++    (*ao::ap (p1)) (j ()...);
++  }
++};
++template  class am
++{
++  template  using av = int;
++
++public:
++  template , void>,
++	    typename = av>
++  am (i);
++  using aw = ar (*) (const int &, j...);
++  aw ax;
++};
++template 
++template 
++am::am (i)
++{
++  ax = p::as;
++}
++struct G
++{
++  void ba (am);
++};
++struct q
++{
++  q ()
++  {
++    G a;
++    a.ba (r ());
++  }
++  struct r
++  {
++    void
++    operator() (o p1)
++    try
++      {
++	p1.af ();
++      }
++    catch (int)
++      {
++      }
++  };
++} s;
+-- 
+2.33.0
+
diff --git a/0146-Backport-SME-Fix-PR-middle-end-107705-ICE-after-recl.patch b/0146-Backport-SME-Fix-PR-middle-end-107705-ICE-after-recl.patch
new file mode 100644
index 0000000..4d3168b
--- /dev/null
+++ b/0146-Backport-SME-Fix-PR-middle-end-107705-ICE-after-recl.patch
@@ -0,0 +1,71 @@
+From beb962ec516f152cef482b229c9adf0390dc3b2c Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Thu, 17 Nov 2022 22:03:08 +0000
+Subject: [PATCH 047/157] [Backport][SME] Fix PR middle-end/107705: ICE after
+ reclaration error
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ceba66ee230bb96b0889fc8ec7333c7ffae96d6e
+
+The problem here is after we created a call expression
+in the C front-end, we replace the decl type with
+an error mark node. We then end up calling
+aggregate_value_p with the call expression
+with the decl with the error mark as the type
+and we ICE.
+
+The fix is to check the function type
+after we process the call expression inside
+aggregate_value_p to get it.
+
+OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
+
+Thanks,
+Andrew Pinski
+
+gcc/ChangeLog:
+
+	PR middle-end/107705
+	* function.cc (aggregate_value_p): Return 0 if
+	the function type was an error operand.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.dg/redecl-22.c: New test.
+---
+ gcc/function.cc                  | 3 +++
+ gcc/testsuite/gcc.dg/redecl-22.c | 9 +++++++++
+ 2 files changed, 12 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/redecl-22.c
+
+diff --git a/gcc/function.cc b/gcc/function.cc
+index 28de39dd6..99aa738eb 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -2090,6 +2090,9 @@ aggregate_value_p (const_tree exp, const_tree fntype)
+   if (VOID_TYPE_P (type))
+     return 0;
+ 
++  if (error_operand_p (fntype))
++    return 0;
++
+   /* If a record should be passed the same as its first (and only) member
+      don't pass it as an aggregate.  */
+   if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
+diff --git a/gcc/testsuite/gcc.dg/redecl-22.c b/gcc/testsuite/gcc.dg/redecl-22.c
+new file mode 100644
+index 000000000..7758570fa
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/redecl-22.c
+@@ -0,0 +1,9 @@
++/* We used to ICE in the gimplifier, PR 107705 */
++/* { dg-do compile } */
++/* { dg-options "-w" } */
++int f (void)
++{
++  int (*p) (void) = 0; // { dg-note "" }
++  return p ();
++  int p = 1; // { dg-error "" }
++}
+-- 
+2.33.0
+
diff --git a/0147-Backport-SME-function-Change-return-type-of-predicat.patch b/0147-Backport-SME-function-Change-return-type-of-predicat.patch
new file mode 100644
index 0000000..809a73b
--- /dev/null
+++ b/0147-Backport-SME-function-Change-return-type-of-predicat.patch
@@ -0,0 +1,351 @@
+From c074871572ef22cbcca8f0f4bc493d60caeddd78 Mon Sep 17 00:00:00 2001
+From: Uros Bizjak 
+Date: Wed, 21 Jun 2023 21:55:30 +0200
+Subject: [PATCH 048/157] [Backport][SME] function: Change return type of
+ predicate function from int to bool
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ce47d3c2cf59bb2cc94afc4bbef88b0e4950f086
+
+Also change some internal variables to bool and some functions to void.
+
+gcc/ChangeLog:
+
+	* function.h (emit_initial_value_sets):
+	Change return type from int to void.
+	(aggregate_value_p): Change return type from int to bool.
+	(prologue_contains): Ditto.
+	(epilogue_contains): Ditto.
+	(prologue_epilogue_contains): Ditto.
+	* function.cc (temp_slot): Make "in_use" variable bool.
+	(make_slot_available): Update for changed "in_use" variable.
+	(assign_stack_temp_for_type): Ditto.
+	(emit_initial_value_sets): Change return type from int to void
+	and update function body accordingly.
+	(instantiate_virtual_regs): Ditto.
+	(rest_of_handle_thread_prologue_and_epilogue): Ditto.
+	(safe_insn_predicate): Change return type from int to bool.
+	(aggregate_value_p): Change return type from int to bool
+	and update function body accordingly.
+	(prologue_contains): Change return type from int to bool.
+	(prologue_epilogue_contains): Ditto.
+---
+ gcc/function.cc | 77 ++++++++++++++++++++++++-------------------------
+ gcc/function.h  | 10 +++----
+ 2 files changed, 42 insertions(+), 45 deletions(-)
+
+diff --git a/gcc/function.cc b/gcc/function.cc
+index 99aa738eb..fc8eb5812 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -578,8 +578,8 @@ public:
+   tree type;
+   /* The alignment (in bits) of the slot.  */
+   unsigned int align;
+-  /* Nonzero if this temporary is currently in use.  */
+-  char in_use;
++  /* True if this temporary is currently in use.  */
++  bool in_use;
+   /* Nesting level at which this slot is being used.  */
+   int level;
+   /* The offset of the slot from the frame_pointer, including extra space
+@@ -674,7 +674,7 @@ make_slot_available (class temp_slot *temp)
+ {
+   cut_slot_from_list (temp, temp_slots_at_level (temp->level));
+   insert_slot_to_list (temp, &avail_temp_slots);
+-  temp->in_use = 0;
++  temp->in_use = false;
+   temp->level = -1;
+   n_temp_slots_in_use--;
+ }
+@@ -848,7 +848,7 @@ assign_stack_temp_for_type (machine_mode mode, poly_int64 size, tree type)
+ 	  if (known_ge (best_p->size - rounded_size, alignment))
+ 	    {
+ 	      p = ggc_alloc ();
+-	      p->in_use = 0;
++	      p->in_use = false;
+ 	      p->size = best_p->size - rounded_size;
+ 	      p->base_offset = best_p->base_offset + rounded_size;
+ 	      p->full_size = best_p->full_size - rounded_size;
+@@ -918,7 +918,7 @@ assign_stack_temp_for_type (machine_mode mode, poly_int64 size, tree type)
+     }
+ 
+   p = selected;
+-  p->in_use = 1;
++  p->in_use = true;
+   p->type = type;
+   p->level = temp_slot_level;
+   n_temp_slots_in_use++;
+@@ -1340,7 +1340,7 @@ has_hard_reg_initial_val (machine_mode mode, unsigned int regno)
+   return NULL_RTX;
+ }
+ 
+-unsigned int
++void
+ emit_initial_value_sets (void)
+ {
+   struct initial_value_struct *ivs = crtl->hard_reg_initial_vals;
+@@ -1348,7 +1348,7 @@ emit_initial_value_sets (void)
+   rtx_insn *seq;
+ 
+   if (ivs == 0)
+-    return 0;
++    return;
+ 
+   start_sequence ();
+   for (i = 0; i < ivs->num_entries; i++)
+@@ -1357,7 +1357,6 @@ emit_initial_value_sets (void)
+   end_sequence ();
+ 
+   emit_insn_at_entry (seq);
+-  return 0;
+ }
+ 
+ /* Return the hardreg-pseudoreg initial values pair entry I and
+@@ -1535,7 +1534,7 @@ instantiate_virtual_regs_in_rtx (rtx *loc)
+ /* A subroutine of instantiate_virtual_regs_in_insn.  Return true if X
+    matches the predicate for insn CODE operand OPERAND.  */
+ 
+-static int
++static bool
+ safe_insn_predicate (int code, int operand, rtx x)
+ {
+   return code < 0 || insn_operand_matches ((enum insn_code) code, operand, x);
+@@ -1948,7 +1947,7 @@ instantiate_decls (tree fndecl)
+ /* Pass through the INSNS of function FNDECL and convert virtual register
+    references to hard register references.  */
+ 
+-static unsigned int
++static void
+ instantiate_virtual_regs (void)
+ {
+   rtx_insn *insn;
+@@ -2002,8 +2001,6 @@ instantiate_virtual_regs (void)
+   /* Indicate that, from now on, assign_stack_local should use
+      frame_pointer_rtx.  */
+   virtuals_instantiated = 1;
+-
+-  return 0;
+ }
+ 
+ namespace {
+@@ -2031,7 +2028,8 @@ public:
+   /* opt_pass methods: */
+   virtual unsigned int execute (function *)
+     {
+-      return instantiate_virtual_regs ();
++      instantiate_virtual_regs ();
++      return 0;
+     }
+ 
+ }; // class pass_instantiate_virtual_regs
+@@ -2045,12 +2043,12 @@ make_pass_instantiate_virtual_regs (gcc::context *ctxt)
+ }
+ 
+ 
+-/* Return 1 if EXP is an aggregate type (or a value with aggregate type).
++/* Return true if EXP is an aggregate type (or a value with aggregate type).
+    This means a type for which function calls must pass an address to the
+    function or get an address back from the function.
+    EXP may be a type node or an expression (whose type is tested).  */
+ 
+-int
++bool
+ aggregate_value_p (const_tree exp, const_tree fntype)
+ {
+   const_tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
+@@ -2070,7 +2068,7 @@ aggregate_value_p (const_tree exp, const_tree fntype)
+ 	  else
+ 	    /* For internal functions, assume nothing needs to be
+ 	       returned in memory.  */
+-	    return 0;
++	    return false;
+ 	}
+ 	break;
+       case FUNCTION_DECL:
+@@ -2088,10 +2086,10 @@ aggregate_value_p (const_tree exp, const_tree fntype)
+       }
+ 
+   if (VOID_TYPE_P (type))
+-    return 0;
++    return false;
+ 
+   if (error_operand_p (fntype))
+-    return 0;
++    return false;
+ 
+   /* If a record should be passed the same as its first (and only) member
+      don't pass it as an aggregate.  */
+@@ -2102,25 +2100,25 @@ aggregate_value_p (const_tree exp, const_tree fntype)
+      reference, do so.  */
+   if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL)
+       && DECL_BY_REFERENCE (exp))
+-    return 1;
++    return true;
+ 
+   /* Function types that are TREE_ADDRESSABLE force return in memory.  */
+   if (fntype && TREE_ADDRESSABLE (fntype))
+-    return 1;
++    return true;
+ 
+   /* Types that are TREE_ADDRESSABLE must be constructed in memory,
+      and thus can't be returned in registers.  */
+   if (TREE_ADDRESSABLE (type))
+-    return 1;
++    return true;
+ 
+   if (TYPE_EMPTY_P (type))
+-    return 0;
++    return false;
+ 
+   if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
+-    return 1;
++    return true;
+ 
+   if (targetm.calls.return_in_memory (type, fntype))
+-    return 1;
++    return true;
+ 
+   /* Make sure we have suitable call-clobbered regs to return
+      the value in; if not, we must return it in memory.  */
+@@ -2129,7 +2127,7 @@ aggregate_value_p (const_tree exp, const_tree fntype)
+   /* If we have something other than a REG (e.g. a PARALLEL), then assume
+      it is OK.  */
+   if (!REG_P (reg))
+-    return 0;
++    return false;
+ 
+   /* Use the default ABI if the type of the function isn't known.
+      The scheme for handling interoperability between different ABIs
+@@ -2142,9 +2140,9 @@ aggregate_value_p (const_tree exp, const_tree fntype)
+   nregs = hard_regno_nregs (regno, TYPE_MODE (type));
+   for (i = 0; i < nregs; i++)
+     if (!fixed_regs[regno + i] && !abi.clobbers_full_reg_p (regno + i))
+-      return 1;
++      return true;
+ 
+-  return 0;
++  return false;
+ }
+ 
+ /* Return true if we should assign DECL a pseudo register; false if it
+@@ -5741,26 +5739,26 @@ contains (const rtx_insn *insn, hash_table *hash)
+   return hash->find (const_cast (insn)) != NULL;
+ }
+ 
+-int
++bool
+ prologue_contains (const rtx_insn *insn)
+ {
+   return contains (insn, prologue_insn_hash);
+ }
+ 
+-int
++bool
+ epilogue_contains (const rtx_insn *insn)
+ {
+   return contains (insn, epilogue_insn_hash);
+ }
+ 
+-int
++bool
+ prologue_epilogue_contains (const rtx_insn *insn)
+ {
+   if (contains (insn, prologue_insn_hash))
+-    return 1;
++    return true;
+   if (contains (insn, epilogue_insn_hash))
+-    return 1;
+-  return 0;
++    return true;
++  return false;
+ }
+ 
+ void
+@@ -6386,14 +6384,13 @@ current_function_name (void)
+ }
+ 
+ 
+-static unsigned int
++static void
+ rest_of_handle_check_leaf_regs (void)
+ {
+ #ifdef LEAF_REGISTERS
+   crtl->uses_only_leaf_regs
+     = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
+ #endif
+-  return 0;
+ }
+ 
+ /* Insert a TYPE into the used types hash table of CFUN.  */
+@@ -6518,7 +6515,8 @@ public:
+   /* opt_pass methods: */
+   virtual unsigned int execute (function *)
+     {
+-      return rest_of_handle_check_leaf_regs ();
++      rest_of_handle_check_leaf_regs ();
++      return 0;
+     }
+ 
+ }; // class pass_leaf_regs
+@@ -6531,7 +6529,7 @@ make_pass_leaf_regs (gcc::context *ctxt)
+   return new pass_leaf_regs (ctxt);
+ }
+ 
+-static unsigned int
++static void
+ rest_of_handle_thread_prologue_and_epilogue (function *fun)
+ {
+   /* prepare_shrink_wrap is sensitive to the block structure of the control
+@@ -6563,8 +6561,6 @@ rest_of_handle_thread_prologue_and_epilogue (function *fun)
+   /* The stack usage info is finalized during prologue expansion.  */
+   if (flag_stack_usage_info || flag_callgraph_info)
+     output_stack_usage ();
+-
+-  return 0;
+ }
+ 
+ /* Record a final call to CALLEE at LOCATION.  */
+@@ -6626,7 +6622,8 @@ public:
+   /* opt_pass methods: */
+   unsigned int execute (function * fun) final override
+     {
+-      return rest_of_handle_thread_prologue_and_epilogue (fun);
++      rest_of_handle_thread_prologue_and_epilogue (fun);
++      return 0;
+     }
+ 
+ }; // class pass_thread_prologue_and_epilogue
+diff --git a/gcc/function.h b/gcc/function.h
+index a53fb24d2..4e8131706 100644
+--- a/gcc/function.h
++++ b/gcc/function.h
+@@ -653,11 +653,11 @@ extern rtx get_hard_reg_initial_val (machine_mode, unsigned int);
+ extern rtx has_hard_reg_initial_val (machine_mode, unsigned int);
+ 
+ /* Called from gimple_expand_cfg.  */
+-extern unsigned int emit_initial_value_sets (void);
++extern void emit_initial_value_sets (void);
+ 
+ extern bool initial_value_entry (int i, rtx *, rtx *);
+ extern void instantiate_decl_rtl (rtx x);
+-extern int aggregate_value_p (const_tree, const_tree);
++extern bool aggregate_value_p (const_tree, const_tree);
+ extern bool use_register_for_decl (const_tree);
+ extern gimple_seq gimplify_parameters (gimple_seq *);
+ extern void locate_and_pad_parm (machine_mode, tree, int, int, int,
+@@ -698,9 +698,9 @@ extern void clobber_return_register (void);
+ extern void expand_function_end (void);
+ extern rtx get_arg_pointer_save_area (void);
+ extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
+-extern int prologue_contains (const rtx_insn *);
+-extern int epilogue_contains (const rtx_insn *);
+-extern int prologue_epilogue_contains (const rtx_insn *);
++extern bool prologue_contains (const rtx_insn *);
++extern bool epilogue_contains (const rtx_insn *);
++extern bool prologue_epilogue_contains (const rtx_insn *);
+ extern void record_prologue_seq (rtx_insn *);
+ extern void record_epilogue_seq (rtx_insn *);
+ extern void emit_return_into_block (bool simple_p, basic_block bb);
+-- 
+2.33.0
+
diff --git a/0148-Backport-SME-Allow-prologues-and-epilogues-to-be-ins.patch b/0148-Backport-SME-Allow-prologues-and-epilogues-to-be-ins.patch
new file mode 100644
index 0000000..13dc0e3
--- /dev/null
+++ b/0148-Backport-SME-Allow-prologues-and-epilogues-to-be-ins.patch
@@ -0,0 +1,233 @@
+From 417d51e1ecf41b3ba3ddf24eaf1e07db5c1ded9e Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 09:28:46 +0000
+Subject: [PATCH 049/157] [Backport][SME] Allow prologues and epilogues to be
+ inserted later
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=e9d2ae6b9816e61a6148040149c63faa83f54702
+
+Arm's SME adds a new processor mode called streaming mode.
+This mode enables some new (matrix-oriented) instructions and
+disables several existing groups of instructions, such as most
+Advanced SIMD vector instructions and a much smaller set of SVE
+instructions.  It can also change the current vector length.
+
+There are instructions to switch in and out of streaming mode.
+However, their effect on the ISA and vector length can't be represented
+directly in RTL, so they need to be emitted late in the pass pipeline,
+close to md_reorg.
+
+It's sometimes the responsibility of the prologue and epilogue to
+switch modes, which means we need to emit the prologue and epilogue
+sequences late as well.  (This loses shrink-wrapping and scheduling
+opportunities, but that's a price worth paying.)
+
+This patch therefore adds a target hook for forcing prologue
+and epilogue insertion to happen later in the pipeline.
+
+gcc/
+	* target.def (use_late_prologue_epilogue): New hook.
+	* doc/tm.texi.in: Add TARGET_USE_LATE_PROLOGUE_EPILOGUE.
+	* doc/tm.texi: Regenerate.
+	* passes.def (pass_late_thread_prologue_and_epilogue): New pass.
+	* tree-pass.h (make_pass_late_thread_prologue_and_epilogue): Declare.
+	* function.cc (pass_thread_prologue_and_epilogue::gate): New function.
+	(pass_data_late_thread_prologue_and_epilogue): New pass variable.
+	(pass_late_thread_prologue_and_epilogue): New pass class.
+	(make_pass_late_thread_prologue_and_epilogue): New function.
+---
+ gcc/doc/tm.texi    | 19 ++++++++++++++++++
+ gcc/doc/tm.texi.in |  2 ++
+ gcc/function.cc    | 50 ++++++++++++++++++++++++++++++++++++++++++++++
+ gcc/passes.def     |  3 +++
+ gcc/target.def     | 21 +++++++++++++++++++
+ gcc/tree-pass.h    |  2 ++
+ 6 files changed, 97 insertions(+)
+
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 5f0972356..d930d233d 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -11684,6 +11684,25 @@ of the if-block in the @code{struct ce_if_block} structure that is pointed
+ to by @var{ce_info}.
+ @end defmac
+ 
++@deftypefn {Target Hook} bool TARGET_USE_LATE_PROLOGUE_EPILOGUE ()
++Return true if the current function's prologue and epilogue should
++be emitted late in the pass pipeline, instead of at the usual point.
++
++Normally, the prologue and epilogue sequences are introduced soon after
++register allocation is complete.  The advantage of this approach is that
++it allows the prologue and epilogue instructions to be optimized and
++scheduled with other code in the function.  However, some targets
++require the prologue and epilogue to be the first and last sequences
++executed by the function, with no variation allowed.  This hook should
++return true on such targets.
++
++The default implementation returns false, which is correct for most
++targets.  The hook should only return true if there is a specific
++target limitation that cannot be described in RTL.  For example,
++the hook might return true if the prologue and epilogue need to switch
++between instruction sets.
++@end deftypefn
++
+ @deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_REORG (void)
+ If non-null, this hook performs a target-specific pass over the
+ instruction stream.  The compiler will run it at all optimization levels,
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index fcab21744..19eabec48 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -7708,6 +7708,8 @@ of the if-block in the @code{struct ce_if_block} structure that is pointed
+ to by @var{ce_info}.
+ @end defmac
+ 
++@hook TARGET_USE_LATE_PROLOGUE_EPILOGUE
++
+ @hook TARGET_MACHINE_DEPENDENT_REORG
+ 
+ @hook TARGET_INIT_BUILTINS
+diff --git a/gcc/function.cc b/gcc/function.cc
+index fc8eb5812..7c90b5f23 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -84,6 +84,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "function-abi.h"
+ #include "value-range.h"
+ #include "gimple-range.h"
++#include "insn-attr.h"
+ 
+ /* So we can assign to cfun in this file.  */
+ #undef cfun
+@@ -6620,6 +6621,11 @@ public:
+   {}
+ 
+   /* opt_pass methods: */
++  bool gate (function *) final override
++    {
++      return !targetm.use_late_prologue_epilogue ();
++    }
++
+   unsigned int execute (function * fun) final override
+     {
+       rest_of_handle_thread_prologue_and_epilogue (fun);
+@@ -6628,6 +6634,44 @@ public:
+ 
+ }; // class pass_thread_prologue_and_epilogue
+ 
++const pass_data pass_data_late_thread_prologue_and_epilogue =
++{
++  RTL_PASS, /* type */
++  "late_pro_and_epilogue", /* name */
++  OPTGROUP_NONE, /* optinfo_flags */
++  TV_THREAD_PROLOGUE_AND_EPILOGUE, /* tv_id */
++  0, /* properties_required */
++  0, /* properties_provided */
++  0, /* properties_destroyed */
++  0, /* todo_flags_start */
++  ( TODO_df_verify | TODO_df_finish ), /* todo_flags_finish */
++};
++
++class pass_late_thread_prologue_and_epilogue : public rtl_opt_pass
++{
++public:
++  pass_late_thread_prologue_and_epilogue (gcc::context *ctxt)
++    : rtl_opt_pass (pass_data_late_thread_prologue_and_epilogue, ctxt)
++  {}
++
++  /* opt_pass methods: */
++  bool gate (function *) final override
++    {
++      return targetm.use_late_prologue_epilogue ();
++    }
++
++  unsigned int execute (function *fn) final override
++    {
++      /* It's not currently possible to have both delay slots and
++	 late prologue/epilogue, since the latter has to run before
++	 the former, and the former won't honor whatever restrictions
++	 the latter is trying to enforce.  */
++      gcc_assert (!DELAY_SLOTS);
++      rest_of_handle_thread_prologue_and_epilogue (fn);
++      return 0;
++    }
++}; // class pass_late_thread_prologue_and_epilogue
++
+ } // anon namespace
+ 
+ rtl_opt_pass *
+@@ -6636,6 +6680,12 @@ make_pass_thread_prologue_and_epilogue (gcc::context *ctxt)
+   return new pass_thread_prologue_and_epilogue (ctxt);
+ }
+ 
++rtl_opt_pass *
++make_pass_late_thread_prologue_and_epilogue (gcc::context *ctxt)
++{
++  return new pass_late_thread_prologue_and_epilogue (ctxt);
++}
++
+ namespace {
+ 
+ const pass_data pass_data_zero_call_used_regs =
+diff --git a/gcc/passes.def b/gcc/passes.def
+index cdc600298..8797f166f 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -523,6 +523,9 @@ along with GCC; see the file COPYING3.  If not see
+ 	      NEXT_PASS (pass_stack_regs_run);
+ 	  POP_INSERT_PASSES ()
+       POP_INSERT_PASSES ()
++      NEXT_PASS (pass_late_thread_prologue_and_epilogue);
++      /* No target-independent code motion is allowed beyond this point,
++         excepting the legacy delayed-branch pass.  */
+       NEXT_PASS (pass_late_compilation);
+       PUSH_INSERT_PASSES_WITHIN (pass_late_compilation)
+ 	  NEXT_PASS (pass_zero_call_used_regs);
+diff --git a/gcc/target.def b/gcc/target.def
+index 4d77c1523..fd4899612 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -4120,6 +4120,27 @@ returns @code{VOIDmode}.",
+  machine_mode, (machine_mode m1, machine_mode m2),
+  default_cc_modes_compatible)
+ 
++DEFHOOK
++(use_late_prologue_epilogue,
++ "Return true if the current function's prologue and epilogue should\n\
++be emitted late in the pass pipeline, instead of at the usual point.\n\
++\n\
++Normally, the prologue and epilogue sequences are introduced soon after\n\
++register allocation is complete.  The advantage of this approach is that\n\
++it allows the prologue and epilogue instructions to be optimized and\n\
++scheduled with other code in the function.  However, some targets\n\
++require the prologue and epilogue to be the first and last sequences\n\
++executed by the function, with no variation allowed.  This hook should\n\
++return true on such targets.\n\
++\n\
++The default implementation returns false, which is correct for most\n\
++targets.  The hook should only return true if there is a specific\n\
++target limitation that cannot be described in RTL.  For example,\n\
++the hook might return true if the prologue and epilogue need to switch\n\
++between instruction sets.",
++ bool, (),
++ hook_bool_void_false)
++
+ /* Do machine-dependent code transformations.  Called just before
+      delayed-branch scheduling.  */
+ DEFHOOK
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 34e60bc38..1c983ef71 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -612,6 +612,8 @@ extern rtl_opt_pass *make_pass_gcse2 (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_split_after_reload (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_thread_prologue_and_epilogue (gcc::context
+ 							     *ctxt);
++extern rtl_opt_pass *make_pass_late_thread_prologue_and_epilogue (gcc::context
++								  *ctxt);
+ extern rtl_opt_pass *make_pass_zero_call_used_regs (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_split_complex_instructions (gcc::context *ctxt);
+ extern rtl_opt_pass *make_pass_stack_adjustments (gcc::context *ctxt);
+-- 
+2.33.0
+
diff --git a/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch b/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
new file mode 100644
index 0000000..d892432
--- /dev/null
+++ b/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
@@ -0,0 +1,239 @@
+From e906213086639df81085a0101bf88fb66c1dbc2b Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 09:35:57 +0000
+Subject: [PATCH 050/157] [Backport][SME] Add a target hook for sibcall
+ epilogues
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2e0aefa77157396acb48833407637303edba450a
+
+Epilogues for sibling calls are generated using the
+sibcall_epilogue pattern.  One disadvantage of this approach
+is that the target doesn't know which call the epilogue is for,
+even though the code that generates the pattern has the call
+to hand.
+
+Although call instructions are currently rtxes, and so could be
+passed as an operand to the pattern, the main point of introducing
+rtx_insn was to move towards separating the rtx and insn types
+(a good thing IMO).  There also isn't an existing practice of
+passing genuine instructions (as opposed to labels) to
+instruction patterns.
+
+This patch therefore adds a hook that can be defined as an
+alternative to sibcall_epilogue.  The advantage is that it
+can be passed the call; the disadvantage is that it can't
+use .md conveniences like generating instructions from
+textual patterns (although most epilogues are too complex
+to benefit much from that anyway).
+
+gcc/
+	* doc/tm.texi.in: Add TARGET_EMIT_EPILOGUE_FOR_SIBCALL.
+	* doc/tm.texi: Regenerate.
+	* target.def (emit_epilogue_for_sibcall): New hook.
+	* calls.cc (can_implement_as_sibling_call_p): Use it.
+	* function.cc (thread_prologue_and_epilogue_insns): Likewise.
+	(reposition_prologue_and_epilogue_notes): Likewise.
+	* config/aarch64/aarch64-protos.h (aarch64_expand_epilogue): Take
+	an rtx_call_insn * rather than a bool.
+	* config/aarch64/aarch64.cc (aarch64_expand_epilogue): Likewise.
+	(TARGET_EMIT_EPILOGUE_FOR_SIBCALL): Define.
+	* config/aarch64/aarch64.md (epilogue): Update call.
+	(sibcall_epilogue): Delete.
+---
+ gcc/calls.cc                        |  3 ++-
+ gcc/config/aarch64/aarch64-protos.h |  2 +-
+ gcc/config/aarch64/aarch64.cc       | 11 +++++++----
+ gcc/config/aarch64/aarch64.md       | 11 +----------
+ gcc/doc/tm.texi                     |  8 ++++++++
+ gcc/doc/tm.texi.in                  |  2 ++
+ gcc/function.cc                     | 15 +++++++++++++--
+ gcc/target.def                      |  9 +++++++++
+ 8 files changed, 43 insertions(+), 18 deletions(-)
+
+diff --git a/gcc/calls.cc b/gcc/calls.cc
+index 4d0bc45be..c1db66883 100644
+--- a/gcc/calls.cc
++++ b/gcc/calls.cc
+@@ -2461,7 +2461,8 @@ can_implement_as_sibling_call_p (tree exp,
+ 				 tree addr,
+ 				 const args_size &args_size)
+ {
+-  if (!targetm.have_sibcall_epilogue ())
++  if (!targetm.have_sibcall_epilogue ()
++      && !targetm.emit_epilogue_for_sibcall)
+     {
+       maybe_complain_about_tail_call
+ 	(exp,
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 86e444a60..97984f3ab 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -887,7 +887,7 @@ const char * aarch64_gen_far_branch (rtx *, int, const char *, const char *);
+ const char * aarch64_output_probe_stack_range (rtx, rtx);
+ const char * aarch64_output_probe_sve_stack_clash (rtx, rtx, rtx, rtx);
+ void aarch64_err_no_fpadvsimd (machine_mode);
+-void aarch64_expand_epilogue (bool);
++void aarch64_expand_epilogue (rtx_call_insn *);
+ rtx aarch64_ptrue_all (unsigned int);
+ opt_machine_mode aarch64_ptrue_all_mode (rtx);
+ rtx aarch64_convert_sve_data_to_pred (rtx, machine_mode, rtx);
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index fd1114b52..055b436b1 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -10046,7 +10046,7 @@ aarch64_use_return_insn_p (void)
+    from a deallocated stack, and we optimize the unwind records by
+    emitting them all together if possible.  */
+ void
+-aarch64_expand_epilogue (bool for_sibcall)
++aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ {
+   poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
+   HOST_WIDE_INT callee_adjust = cfun->machine->frame.callee_adjust;
+@@ -10194,7 +10194,7 @@ aarch64_expand_epilogue (bool for_sibcall)
+ 	   explicitly authenticate.
+     */
+   if (aarch64_return_address_signing_enabled ()
+-      && (for_sibcall || !TARGET_ARMV8_3))
++      && (sibcall || !TARGET_ARMV8_3))
+     {
+       switch (aarch64_ra_sign_key)
+ 	{
+@@ -10212,7 +10212,7 @@ aarch64_expand_epilogue (bool for_sibcall)
+     }
+ 
+   /* Stack adjustment for exception handler.  */
+-  if (crtl->calls_eh_return && !for_sibcall)
++  if (crtl->calls_eh_return && !sibcall)
+     {
+       /* We need to unwind the stack by the offset computed by
+ 	 EH_RETURN_STACKADJ_RTX.  We have already reset the CFA
+@@ -10223,7 +10223,7 @@ aarch64_expand_epilogue (bool for_sibcall)
+     }
+ 
+   emit_use (gen_rtx_REG (DImode, LR_REGNUM));
+-  if (!for_sibcall)
++  if (!sibcall)
+     emit_jump_insn (ret_rtx);
+ }
+ 
+@@ -28246,6 +28246,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_HAVE_SHADOW_CALL_STACK
+ #define TARGET_HAVE_SHADOW_CALL_STACK true
+ 
++#undef TARGET_EMIT_EPILOGUE_FOR_SIBCALL
++#define TARGET_EMIT_EPILOGUE_FOR_SIBCALL aarch64_expand_epilogue
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ 
+ #include "gt-aarch64.h"
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 7267a74d6..a78476c8a 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -871,16 +871,7 @@
+   [(clobber (const_int 0))]
+   ""
+   "
+-  aarch64_expand_epilogue (false);
+-  DONE;
+-  "
+-)
+-
+-(define_expand "sibcall_epilogue"
+-  [(clobber (const_int 0))]
+-  ""
+-  "
+-  aarch64_expand_epilogue (true);
++  aarch64_expand_epilogue (nullptr);
+   DONE;
+   "
+ )
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index d930d233d..369f4b8da 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -11703,6 +11703,14 @@ the hook might return true if the prologue and epilogue need to switch
+ between instruction sets.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} void TARGET_EMIT_EPILOGUE_FOR_SIBCALL (rtx_call_insn *@var{call})
++If defined, this hook emits an epilogue sequence for sibling (tail)
++call instruction @var{call}.  Another way of providing epilogues
++for sibling calls is to define the @code{sibcall_epilogue} instruction
++pattern; the main advantage of this hook over the pattern is that it
++has access to the call instruction.
++@end deftypefn
++
+ @deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_REORG (void)
+ If non-null, this hook performs a target-specific pass over the
+ instruction stream.  The compiler will run it at all optimization levels,
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 19eabec48..748b0777a 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -7710,6 +7710,8 @@ to by @var{ce_info}.
+ 
+ @hook TARGET_USE_LATE_PROLOGUE_EPILOGUE
+ 
++@hook TARGET_EMIT_EPILOGUE_FOR_SIBCALL
++
+ @hook TARGET_MACHINE_DEPENDENT_REORG
+ 
+ @hook TARGET_INIT_BUILTINS
+diff --git a/gcc/function.cc b/gcc/function.cc
+index 7c90b5f23..ddab43ca4 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -6209,7 +6209,17 @@ thread_prologue_and_epilogue_insns (void)
+       if (!(CALL_P (insn) && SIBLING_CALL_P (insn)))
+ 	continue;
+ 
+-      if (rtx_insn *ep_seq = targetm.gen_sibcall_epilogue ())
++      rtx_insn *ep_seq;
++      if (targetm.emit_epilogue_for_sibcall)
++	{
++	  start_sequence ();
++	  targetm.emit_epilogue_for_sibcall (as_a (insn));
++	  ep_seq = get_insns ();
++	  end_sequence ();
++	}
++      else
++	ep_seq = targetm.gen_sibcall_epilogue ();
++      if (ep_seq)
+ 	{
+ 	  start_sequence ();
+ 	  emit_note (NOTE_INSN_EPILOGUE_BEG);
+@@ -6259,7 +6269,8 @@ reposition_prologue_and_epilogue_notes (void)
+ {
+   if (!targetm.have_prologue ()
+       && !targetm.have_epilogue ()
+-      && !targetm.have_sibcall_epilogue ())
++      && !targetm.have_sibcall_epilogue ()
++      && !targetm.emit_epilogue_for_sibcall)
+     return;
+ 
+   /* Since the hash table is created on demand, the fact that it is
+diff --git a/gcc/target.def b/gcc/target.def
+index fd4899612..cf9f96eba 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -4141,6 +4141,15 @@ between instruction sets.",
+  bool, (),
+  hook_bool_void_false)
+ 
++DEFHOOK
++(emit_epilogue_for_sibcall,
++ "If defined, this hook emits an epilogue sequence for sibling (tail)\n\
++call instruction @var{call}.  Another way of providing epilogues\n\
++for sibling calls is to define the @code{sibcall_epilogue} instruction\n\
++pattern; the main advantage of this hook over the pattern is that it\n\
++has access to the call instruction.",
++ void, (rtx_call_insn *call), NULL)
++
+ /* Do machine-dependent code transformations.  Called just before
+      delayed-branch scheduling.  */
+ DEFHOOK
+-- 
+2.33.0
+
diff --git a/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch b/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch
new file mode 100644
index 0000000..4c71f2a
--- /dev/null
+++ b/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch
@@ -0,0 +1,461 @@
+From 58adede22d9ff2368b5c24ec3fc0e53bd3ddc8bd Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 09:44:52 +0000
+Subject: [PATCH 051/157] [Backport][SME] Add a new target hook:
+ TARGET_START_CALL_ARGS
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=672fad57c1f99ff893019e2da4620e26b9b31dd2
+
+We have the following two hooks into the call expansion code:
+
+- TARGET_CALL_ARGS is called for each argument before arguments
+  are moved into hard registers.
+
+- TARGET_END_CALL_ARGS is called after the end of the call
+  sequence (specifically, after any return value has been
+  moved to a pseudo).
+
+This patch adds a TARGET_START_CALL_ARGS hook that is called before
+the TARGET_CALL_ARGS sequence.  This means that TARGET_START_CALL_REGS
+and TARGET_END_CALL_REGS bracket the region in which argument registers
+might be live.  They also bracket a region in which the only call
+emiitted by target-independent code is the call to the target function
+itself.  (For example, TARGET_START_CALL_ARGS happens after any use of
+memcpy to copy arguments, and TARGET_END_CALL_ARGS happens before any
+use of memcpy to copy the result.)
+
+Also, the patch adds the cumulative argument structure as an argument
+to the hooks, so that the target can use it to record and retrieve
+information about the call as a whole.
+
+The TARGET_CALL_ARGS docs said:
+
+   While generating RTL for a function call, this target hook is invoked once
+   for each argument passed to the function, either a register returned by
+   ``TARGET_FUNCTION_ARG`` or a memory location.  It is called just
+-  before the point where argument registers are stored.
+
+The last bit was true for normal calls, but for libcalls the hook was
+invoked earlier, before stack arguments have been copied.  I don't think
+this caused a practical difference for nvptx (the only port to use the
+hooks) since I wouldn't expect any libcalls to take stack parameters.
+
+gcc/
+	* doc/tm.texi.in: Add TARGET_START_CALL_ARGS.
+	* doc/tm.texi: Regenerate.
+	* target.def (start_call_args): New hook.
+	(call_args, end_call_args): Add a parameter for the cumulative
+	argument information.
+	* hooks.h (hook_void_rtx_tree): Delete.
+	* hooks.cc (hook_void_rtx_tree): Likewise.
+	* targhooks.h (hook_void_CUMULATIVE_ARGS): Declare.
+	(hook_void_CUMULATIVE_ARGS_rtx_tree): Likewise.
+	* targhooks.cc (hook_void_CUMULATIVE_ARGS): New function.
+	(hook_void_CUMULATIVE_ARGS_rtx_tree): Likewise.
+	* calls.cc (expand_call): Call start_call_args before computing
+	and storing stack parameters.  Pass the cumulative argument
+	information to call_args and end_call_args.
+	(emit_library_call_value_1): Likewise.
+	* config/nvptx/nvptx.cc (nvptx_call_args): Add a cumulative
+	argument parameter.
+	(nvptx_end_call_args): Likewise.
+---
+ gcc/calls.cc              | 61 +++++++++++++++++++++------------------
+ gcc/config/nvptx/nvptx.cc |  4 +--
+ gcc/doc/tm.texi           | 53 +++++++++++++++++++++++++++-------
+ gcc/doc/tm.texi.in        |  2 ++
+ gcc/hooks.cc              |  5 ----
+ gcc/hooks.h               |  1 -
+ gcc/target.def            | 59 +++++++++++++++++++++++++++++--------
+ gcc/targhooks.cc          | 10 +++++++
+ gcc/targhooks.h           |  5 ++--
+ 9 files changed, 140 insertions(+), 60 deletions(-)
+
+diff --git a/gcc/calls.cc b/gcc/calls.cc
+index c1db66883..4a8535cc6 100644
+--- a/gcc/calls.cc
++++ b/gcc/calls.cc
+@@ -3507,15 +3507,26 @@ expand_call (tree exp, rtx target, int ignore)
+ 		sibcall_failure = 1;
+ 	    }
+ 
++      /* Set up the next argument register.  For sibling calls on machines
++	 with register windows this should be the incoming register.  */
++      if (pass == 0)
++	next_arg_reg = targetm.calls.function_incoming_arg
++	  (args_so_far, function_arg_info::end_marker ());
++      else
++	next_arg_reg = targetm.calls.function_arg
++	  (args_so_far, function_arg_info::end_marker ());
++
++      targetm.calls.start_call_args (args_so_far);
++
+       bool any_regs = false;
+       for (i = 0; i < num_actuals; i++)
+ 	if (args[i].reg != NULL_RTX)
+ 	  {
+ 	    any_regs = true;
+-	    targetm.calls.call_args (args[i].reg, funtype);
++	    targetm.calls.call_args (args_so_far, args[i].reg, funtype);
+ 	  }
+       if (!any_regs)
+-	targetm.calls.call_args (pc_rtx, funtype);
++	targetm.calls.call_args (args_so_far, pc_rtx, funtype);
+ 
+       /* Figure out the register where the value, if any, will come back.  */
+       valreg = 0;
+@@ -3578,15 +3589,6 @@ expand_call (tree exp, rtx target, int ignore)
+ 	 later safely search backwards to find the CALL_INSN.  */
+       before_call = get_last_insn ();
+ 
+-      /* Set up next argument register.  For sibling calls on machines
+-	 with register windows this should be the incoming register.  */
+-      if (pass == 0)
+-	next_arg_reg = targetm.calls.function_incoming_arg
+-	  (args_so_far, function_arg_info::end_marker ());
+-      else
+-	next_arg_reg = targetm.calls.function_arg
+-	  (args_so_far, function_arg_info::end_marker ());
+-
+       if (pass == 1 && (return_flags & ERF_RETURNS_ARG))
+ 	{
+ 	  int arg_nr = return_flags & ERF_RETURN_ARG_MASK;
+@@ -3879,7 +3881,7 @@ expand_call (tree exp, rtx target, int ignore)
+       for (i = 0; i < num_actuals; ++i)
+ 	free (args[i].aligned_regs);
+ 
+-      targetm.calls.end_call_args ();
++      targetm.calls.end_call_args (args_so_far);
+ 
+       insns = get_insns ();
+       end_sequence ();
+@@ -4437,17 +4439,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
+     }
+ #endif
+ 
+-  /* When expanding a normal call, args are stored in push order,
+-     which is the reverse of what we have here.  */
+-  bool any_regs = false;
+-  for (int i = nargs; i-- > 0; )
+-    if (argvec[i].reg != NULL_RTX)
+-      {
+-	targetm.calls.call_args (argvec[i].reg, NULL_TREE);
+-	any_regs = true;
+-      }
+-  if (!any_regs)
+-    targetm.calls.call_args (pc_rtx, NULL_TREE);
++  rtx call_cookie
++    = targetm.calls.function_arg (args_so_far,
++				  function_arg_info::end_marker ());
+ 
+   /* Push the args that need to be pushed.  */
+ 
+@@ -4565,6 +4559,20 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
+ 
+   fun = prepare_call_address (NULL, fun, NULL, &call_fusage, 0, 0);
+ 
++  targetm.calls.start_call_args (args_so_far);
++
++  /* When expanding a normal call, args are stored in push order,
++     which is the reverse of what we have here.  */
++  bool any_regs = false;
++  for (int i = nargs; i-- > 0; )
++    if (argvec[i].reg != NULL_RTX)
++      {
++	targetm.calls.call_args (args_so_far, argvec[i].reg, NULL_TREE);
++	any_regs = true;
++      }
++  if (!any_regs)
++    targetm.calls.call_args (args_so_far, pc_rtx, NULL_TREE);
++
+   /* Now load any reg parms into their regs.  */
+ 
+   /* ARGNUM indexes the ARGVEC array in the order in which the arguments
+@@ -4671,10 +4679,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
+ 	       get_identifier (XSTR (orgfun, 0)),
+ 	       build_function_type (tfom, NULL_TREE),
+ 	       original_args_size.constant, args_size.constant,
+-	       struct_value_size,
+-	       targetm.calls.function_arg (args_so_far,
+-					   function_arg_info::end_marker ()),
+-	       valreg,
++	       struct_value_size, call_cookie, valreg,
+ 	       old_inhibit_defer_pop + 1, call_fusage, flags, args_so_far);
+ 
+   if (flag_ipa_ra)
+@@ -4694,7 +4699,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
+       valreg = gen_rtx_REG (TYPE_MODE (tfom), REGNO (valreg));
+     }
+ 
+-  targetm.calls.end_call_args ();
++  targetm.calls.end_call_args (args_so_far);
+ 
+   /* For calls to `setjmp', etc., inform function.cc:setjmp_warnings
+      that it should complain if nonvolatile values are live.  For
+diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
+index 3634a49de..7f2103ba6 100644
+--- a/gcc/config/nvptx/nvptx.cc
++++ b/gcc/config/nvptx/nvptx.cc
+@@ -1780,7 +1780,7 @@ nvptx_get_drap_rtx (void)
+    argument to the next call.  */
+ 
+ static void
+-nvptx_call_args (rtx arg, tree fntype)
++nvptx_call_args (cumulative_args_t, rtx arg, tree fntype)
+ {
+   if (!cfun->machine->doing_call)
+     {
+@@ -1808,7 +1808,7 @@ nvptx_call_args (rtx arg, tree fntype)
+    information we recorded.  */
+ 
+ static void
+-nvptx_end_call_args (void)
++nvptx_end_call_args (cumulative_args_t)
+ {
+   cfun->machine->doing_call = false;
+   free_EXPR_LIST_list (&cfun->machine->call_args);
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 369f4b8da..357c29a4d 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -5392,26 +5392,59 @@ except the last are treated as named.
+ You need not define this hook if it always returns @code{false}.
+ @end deftypefn
+ 
+-@deftypefn {Target Hook} void TARGET_CALL_ARGS (rtx, @var{tree})
++@deftypefn {Target Hook} void TARGET_START_CALL_ARGS (cumulative_args_t @var{complete_args})
++This target hook is invoked while generating RTL for a function call,
++after the argument values have been computed, and after stack arguments
++have been initialized, but before register arguments have been moved into
++their ABI-defined hard register locations.  It precedes calls to the related
++hooks @code{TARGET_CALL_ARGS} and @code{TARGET_END_CALL_ARGS}.
++The significance of this position in the call expansion is that:
++
++@itemize @bullet
++@item
++No argument registers are live.
++@item
++Although a call sequence can in general involve subcalls (such as using
++@code{memcpy} to copy large arguments), no such subcall will occur between
++the call to this hook and the generation of the main call instruction.
++@end itemize
++
++The single argument @var{complete_args} is the state of the target
++function's cumulative argument information after the final call to
++@code{TARGET_FUNCTION_ARG}.
++
++The hook can be used for things like switching processor mode, in cases
++where different calls need different processor modes.  Most ports do not
++need to implement anything for this hook.
++@end deftypefn
++
++@deftypefn {Target Hook} void TARGET_CALL_ARGS (cumulative_args_t @var{complete_args}, rtx @var{loc}, tree @var{type})
+ While generating RTL for a function call, this target hook is invoked once
+ for each argument passed to the function, either a register returned by
+ @code{TARGET_FUNCTION_ARG} or a memory location.  It is called just
+-before the point where argument registers are stored.  The type of the
+-function to be called is also passed as the second argument; it is
+-@code{NULL_TREE} for libcalls.  The @code{TARGET_END_CALL_ARGS} hook is
+-invoked just after the code to copy the return reg has been emitted.
+-This functionality can be used to perform special setup of call argument
+-registers if a target needs it.
++before the point where argument registers are stored.
++
++@var{complete_args} is the state of the target function's cumulative
++argument information after the final call to @code{TARGET_FUNCTION_ARG}.
++@var{loc} is the location of the argument.  @var{type} is the type of
++the function being called, or @code{NULL_TREE} for libcalls.
++
+ For functions without arguments, the hook is called once with @code{pc_rtx}
+ passed instead of an argument register.
+-Most ports do not need to implement anything for this hook.
++
++This functionality can be used to perform special setup of call argument
++registers, if a target needs it.  Most ports do not need to implement
++anything for this hook.
+ @end deftypefn
+ 
+-@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (void)
++@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (cumulative_args_t @var{complete_args})
+ This target hook is invoked while generating RTL for a function call,
+ just after the point where the return reg is copied into a pseudo.  It
+ signals that all the call argument and return registers for the just
+-emitted call are now no longer in use.
++emitted call are now no longer in use.  @var{complete_args} is the
++state of the target function's cumulative argument information after
++the final call to @code{TARGET_FUNCTION_ARG}.
++
+ Most ports do not need to implement anything for this hook.
+ @end deftypefn
+ 
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 748b0777a..4ebc9afbf 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -3774,6 +3774,8 @@ These machine description macros help implement varargs:
+ 
+ @hook TARGET_STRICT_ARGUMENT_NAMING
+ 
++@hook TARGET_START_CALL_ARGS
++
+ @hook TARGET_CALL_ARGS
+ 
+ @hook TARGET_END_CALL_ARGS
+diff --git a/gcc/hooks.cc b/gcc/hooks.cc
+index b29233f4f..0f4e7ce10 100644
+--- a/gcc/hooks.cc
++++ b/gcc/hooks.cc
+@@ -280,11 +280,6 @@ hook_void_FILEptr_tree (FILE *, tree)
+ {
+ }
+ 
+-void
+-hook_void_rtx_tree (rtx, tree)
+-{
+-}
+-
+ void
+ hook_void_constcharptr (const char *)
+ {
+diff --git a/gcc/hooks.h b/gcc/hooks.h
+index 1056e1e9e..e2a742f43 100644
+--- a/gcc/hooks.h
++++ b/gcc/hooks.h
+@@ -83,7 +83,6 @@ extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
+ extern void hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *,
+ 						       const_tree);
+ extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx);
+-extern void hook_void_rtx_tree (rtx, tree);
+ extern void hook_void_FILEptr_tree (FILE *, tree);
+ extern void hook_void_tree (tree);
+ extern void hook_void_tree_treeptr (tree, tree *);
+diff --git a/gcc/target.def b/gcc/target.def
+index cf9f96eba..a57e51b0d 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -4784,32 +4784,67 @@ not generate any instructions in this case.",
+ 	int *pretend_args_size, int second_time),
+  default_setup_incoming_varargs)
+ 
++DEFHOOK
++(start_call_args,
++ "This target hook is invoked while generating RTL for a function call,\n\
++after the argument values have been computed, and after stack arguments\n\
++have been initialized, but before register arguments have been moved into\n\
++their ABI-defined hard register locations.  It precedes calls to the related\n\
++hooks @code{TARGET_CALL_ARGS} and @code{TARGET_END_CALL_ARGS}.\n\
++The significance of this position in the call expansion is that:\n\
++\n\
++@itemize @bullet\n\
++@item\n\
++No argument registers are live.\n\
++@item\n\
++Although a call sequence can in general involve subcalls (such as using\n\
++@code{memcpy} to copy large arguments), no such subcall will occur between\n\
++the call to this hook and the generation of the main call instruction.\n\
++@end itemize\n\
++\n\
++The single argument @var{complete_args} is the state of the target\n\
++function's cumulative argument information after the final call to\n\
++@code{TARGET_FUNCTION_ARG}.\n\
++\n\
++The hook can be used for things like switching processor mode, in cases\n\
++where different calls need different processor modes.  Most ports do not\n\
++need to implement anything for this hook.",
++ void, (cumulative_args_t complete_args),
++ hook_void_CUMULATIVE_ARGS)
++
+ DEFHOOK
+ (call_args,
+  "While generating RTL for a function call, this target hook is invoked once\n\
+ for each argument passed to the function, either a register returned by\n\
+ @code{TARGET_FUNCTION_ARG} or a memory location.  It is called just\n\
+-before the point where argument registers are stored.  The type of the\n\
+-function to be called is also passed as the second argument; it is\n\
+-@code{NULL_TREE} for libcalls.  The @code{TARGET_END_CALL_ARGS} hook is\n\
+-invoked just after the code to copy the return reg has been emitted.\n\
+-This functionality can be used to perform special setup of call argument\n\
+-registers if a target needs it.\n\
++before the point where argument registers are stored.\n\
++\n\
++@var{complete_args} is the state of the target function's cumulative\n\
++argument information after the final call to @code{TARGET_FUNCTION_ARG}.\n\
++@var{loc} is the location of the argument.  @var{type} is the type of\n\
++the function being called, or @code{NULL_TREE} for libcalls.\n\
++\n\
+ For functions without arguments, the hook is called once with @code{pc_rtx}\n\
+ passed instead of an argument register.\n\
+-Most ports do not need to implement anything for this hook.",
+- void, (rtx, tree),
+- hook_void_rtx_tree)
++\n\
++This functionality can be used to perform special setup of call argument\n\
++registers, if a target needs it.  Most ports do not need to implement\n\
++anything for this hook.",
++ void, (cumulative_args_t complete_args, rtx loc, tree type),
++ hook_void_CUMULATIVE_ARGS_rtx_tree)
+ 
+ DEFHOOK
+ (end_call_args,
+  "This target hook is invoked while generating RTL for a function call,\n\
+ just after the point where the return reg is copied into a pseudo.  It\n\
+ signals that all the call argument and return registers for the just\n\
+-emitted call are now no longer in use.\n\
++emitted call are now no longer in use.  @var{complete_args} is the\n\
++state of the target function's cumulative argument information after\n\
++the final call to @code{TARGET_FUNCTION_ARG}.\n\
++\n\
+ Most ports do not need to implement anything for this hook.",
+- void, (void),
+- hook_void_void)
++ void, (cumulative_args_t complete_args),
++ hook_void_CUMULATIVE_ARGS)
+ 
+ DEFHOOK
+ (push_argument,
+diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
+index 399d6f874..c88afa5db 100644
+--- a/gcc/targhooks.cc
++++ b/gcc/targhooks.cc
+@@ -772,12 +772,22 @@ hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t,
+   return 0;
+ }
+ 
++void
++hook_void_CUMULATIVE_ARGS (cumulative_args_t)
++{
++}
++
+ void
+ hook_void_CUMULATIVE_ARGS_tree (cumulative_args_t ca ATTRIBUTE_UNUSED,
+ 				tree ATTRIBUTE_UNUSED)
+ {
+ }
+ 
++void
++hook_void_CUMULATIVE_ARGS_rtx_tree (cumulative_args_t, rtx, tree)
++{
++}
++
+ /* Default implementation of TARGET_PUSH_ARGUMENT.  */
+ 
+ bool
+diff --git a/gcc/targhooks.h b/gcc/targhooks.h
+index ecce55ebe..c6e12fc2e 100644
+--- a/gcc/targhooks.h
++++ b/gcc/targhooks.h
+@@ -138,8 +138,9 @@ extern bool hook_bool_CUMULATIVE_ARGS_arg_info_true
+   (cumulative_args_t, const function_arg_info &);
+ extern int hook_int_CUMULATIVE_ARGS_arg_info_0
+   (cumulative_args_t, const function_arg_info &);
+-extern void hook_void_CUMULATIVE_ARGS_tree
+-  (cumulative_args_t, tree);
++extern void hook_void_CUMULATIVE_ARGS (cumulative_args_t);
++extern void hook_void_CUMULATIVE_ARGS_tree (cumulative_args_t, tree);
++extern void hook_void_CUMULATIVE_ARGS_rtx_tree (cumulative_args_t, rtx, tree);
+ extern const char *hook_invalid_arg_for_unprototyped_fn
+   (const_tree, const_tree, const_tree);
+ extern void default_function_arg_advance
+-- 
+2.33.0
+
diff --git a/0151-Backport-SME-Allow-targets-to-add-USEs-to-asms.patch b/0151-Backport-SME-Allow-targets-to-add-USEs-to-asms.patch
new file mode 100644
index 0000000..cb06751
--- /dev/null
+++ b/0151-Backport-SME-Allow-targets-to-add-USEs-to-asms.patch
@@ -0,0 +1,490 @@
+From 8684458c3faf358e5a15dfb73b4ef632341ddf0a Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 09:52:41 +0000
+Subject: [PATCH 052/157] [Backport][SME] Allow targets to add USEs to asms
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=414d795d8a365b6e72a84257caa36cb3bed7e0ba
+
+Arm's SME has an array called ZA that for inline asm purposes
+is effectively a form of special-purpose memory.  It doesn't
+have an associated storage type and so can't be passed and
+returned in normal C/C++ objects.
+
+We'd therefore like "za" in a clobber list to mean that an inline
+asm can read from and write to ZA.  (Just reading or writing
+individually is unlikely to be useful, but we could add syntax
+for that too if necessary.)
+
+There is currently a TARGET_MD_ASM_ADJUST target hook that allows
+targets to add clobbers to an asm instruction.  This patch
+extends that to allow targets to add USEs as well.
+
+gcc/
+	* target.def (md_asm_adjust): Add a uses parameter.
+	* doc/tm.texi: Regenerate.
+	* cfgexpand.cc (expand_asm_loc): Update call to md_asm_adjust.
+	Handle any USEs created by the target.
+	(expand_asm_stmt): Likewise.
+	* recog.cc (asm_noperands): Handle asms with USEs.
+	(decode_asm_operands): Likewise.
+	* config/arm/aarch-common-protos.h (arm_md_asm_adjust): Add uses
+	parameter.
+	* config/arm/aarch-common.cc (arm_md_asm_adjust): Likewise.
+	* config/arm/arm.cc (thumb1_md_asm_adjust): Likewise.
+	* config/avr/avr.cc (avr_md_asm_adjust): Likewise.
+	* config/cris/cris.cc (cris_md_asm_adjust): Likewise.
+	* config/i386/i386.cc (ix86_md_asm_adjust): Likewise.
+	* config/mn10300/mn10300.cc (mn10300_md_asm_adjust): Likewise.
+	* config/nds32/nds32.cc (nds32_md_asm_adjust): Likewise.
+	* config/pdp11/pdp11.cc (pdp11_md_asm_adjust): Likewise.
+	* config/rs6000/rs6000.cc (rs6000_md_asm_adjust): Likewise.
+	* config/s390/s390.cc (s390_md_asm_adjust): Likewise.
+	* config/vax/vax.cc (vax_md_asm_adjust): Likewise.
+	* config/visium/visium.cc (visium_md_asm_adjust): Likewise.
+---
+ gcc/cfgexpand.cc                     | 37 +++++++++++++++++++---------
+ gcc/config/arm/aarch-common-protos.h |  2 +-
+ gcc/config/arm/aarch-common.cc       |  3 ++-
+ gcc/config/arm/arm.cc                |  5 ++--
+ gcc/config/avr/avr.cc                |  1 +
+ gcc/config/cris/cris.cc              |  6 +++--
+ gcc/config/i386/i386.cc              |  5 ++--
+ gcc/config/mn10300/mn10300.cc        |  3 ++-
+ gcc/config/nds32/nds32.cc            |  4 +--
+ gcc/config/pdp11/pdp11.cc            |  6 +++--
+ gcc/config/rs6000/rs6000.cc          |  3 ++-
+ gcc/config/s390/s390.cc              |  3 ++-
+ gcc/config/vax/vax.cc                |  4 ++-
+ gcc/config/visium/visium.cc          |  5 ++--
+ gcc/doc/tm.texi                      |  5 ++--
+ gcc/recog.cc                         | 20 ++++++++++-----
+ gcc/target.def                       |  5 ++--
+ 17 files changed, 77 insertions(+), 40 deletions(-)
+
+diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
+index 4691355aa..5401a4ebd 100644
+--- a/gcc/cfgexpand.cc
++++ b/gcc/cfgexpand.cc
+@@ -2873,6 +2873,7 @@ expand_asm_loc (tree string, int vol, location_t locus)
+       auto_vec input_rvec, output_rvec;
+       auto_vec input_mode;
+       auto_vec constraints;
++      auto_vec use_rvec;
+       auto_vec clobber_rvec;
+       HARD_REG_SET clobbered_regs;
+       CLEAR_HARD_REG_SET (clobbered_regs);
+@@ -2882,16 +2883,20 @@ expand_asm_loc (tree string, int vol, location_t locus)
+ 
+       if (targetm.md_asm_adjust)
+ 	targetm.md_asm_adjust (output_rvec, input_rvec, input_mode,
+-			       constraints, clobber_rvec, clobbered_regs,
+-			       locus);
++			       constraints, use_rvec, clobber_rvec,
++			       clobbered_regs, locus);
+ 
+       asm_op = body;
+       nclobbers = clobber_rvec.length ();
+-      body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (1 + nclobbers));
++      auto nuses = use_rvec.length ();
++      body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (1 + nuses + nclobbers));
+ 
+-      XVECEXP (body, 0, 0) = asm_op;
+-      for (i = 0; i < nclobbers; i++)
+-	XVECEXP (body, 0, i + 1) = gen_rtx_CLOBBER (VOIDmode, clobber_rvec[i]);
++      i = 0;
++      XVECEXP (body, 0, i++) = asm_op;
++      for (rtx use : use_rvec)
++	XVECEXP (body, 0, i++) = gen_rtx_USE (VOIDmode, use);
++      for (rtx clobber : clobber_rvec)
++	XVECEXP (body, 0, i++) = gen_rtx_CLOBBER (VOIDmode, clobber);
+     }
+ 
+   emit_insn (body);
+@@ -3443,11 +3448,12 @@ expand_asm_stmt (gasm *stmt)
+      maintaining source-level compatibility means automatically clobbering
+      the flags register.  */
+   rtx_insn *after_md_seq = NULL;
++  auto_vec use_rvec;
+   if (targetm.md_asm_adjust)
+     after_md_seq
+ 	= targetm.md_asm_adjust (output_rvec, input_rvec, input_mode,
+-				 constraints, clobber_rvec, clobbered_regs,
+-				 locus);
++				 constraints, use_rvec, clobber_rvec,
++				 clobbered_regs, locus);
+ 
+   /* Do not allow the hook to change the output and input count,
+      lest it mess up the operand numbering.  */
+@@ -3455,7 +3461,8 @@ expand_asm_stmt (gasm *stmt)
+   gcc_assert (input_rvec.length() == ninputs);
+   gcc_assert (constraints.length() == noutputs + ninputs);
+ 
+-  /* But it certainly can adjust the clobbers.  */
++  /* But it certainly can adjust the uses and clobbers.  */
++  unsigned nuses = use_rvec.length ();
+   unsigned nclobbers = clobber_rvec.length ();
+ 
+   /* Third pass checks for easy conflicts.  */
+@@ -3527,7 +3534,7 @@ expand_asm_stmt (gasm *stmt)
+ 			       ARGVEC CONSTRAINTS OPNAMES))
+      If there is more than one, put them inside a PARALLEL.  */
+ 
+-  if (noutputs == 0 && nclobbers == 0)
++  if (noutputs == 0 && nuses == 0 && nclobbers == 0)
+     {
+       /* No output operands: put in a raw ASM_OPERANDS rtx.  */
+       if (nlabels > 0)
+@@ -3535,7 +3542,7 @@ expand_asm_stmt (gasm *stmt)
+       else
+ 	emit_insn (body);
+     }
+-  else if (noutputs == 1 && nclobbers == 0)
++  else if (noutputs == 1 && nuses == 0 && nclobbers == 0)
+     {
+       ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0];
+       if (nlabels > 0)
+@@ -3551,7 +3558,8 @@ expand_asm_stmt (gasm *stmt)
+       if (num == 0)
+ 	num = 1;
+ 
+-      body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers));
++      body = gen_rtx_PARALLEL (VOIDmode,
++			       rtvec_alloc (num + nuses + nclobbers));
+ 
+       /* For each output operand, store a SET.  */
+       for (i = 0; i < noutputs; ++i)
+@@ -3578,6 +3586,11 @@ expand_asm_stmt (gasm *stmt)
+       if (i == 0)
+ 	XVECEXP (body, 0, i++) = obody;
+ 
++      /* Add the uses specified by the target hook.  No checking should
++	 be needed since this doesn't come directly from user code.  */
++      for (rtx use : use_rvec)
++	XVECEXP (body, 0, i++) = gen_rtx_USE (VOIDmode, use);
++
+       /* Store (clobber REG) for each clobbered register specified.  */
+       for (unsigned j = 0; j < nclobbers; ++j)
+ 	{
+diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h
+index ae0465159..3b525c174 100644
+--- a/gcc/config/arm/aarch-common-protos.h
++++ b/gcc/config/arm/aarch-common-protos.h
+@@ -149,7 +149,7 @@ struct cpu_cost_table
+ 
+ rtx_insn *arm_md_asm_adjust (vec &outputs, vec & /*inputs*/,
+ 			     vec & /*input_modes*/,
+-			     vec &constraints,
++			     vec &constraints, vec &,
+ 			     vec &clobbers, HARD_REG_SET &clobbered_regs,
+ 			     location_t loc);
+ 
+diff --git a/gcc/config/arm/aarch-common.cc b/gcc/config/arm/aarch-common.cc
+index 04a53d750..365cfc140 100644
+--- a/gcc/config/arm/aarch-common.cc
++++ b/gcc/config/arm/aarch-common.cc
+@@ -533,7 +533,8 @@ arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer)
+ rtx_insn *
+ arm_md_asm_adjust (vec &outputs, vec & /*inputs*/,
+ 		   vec & /*input_modes*/,
+-		   vec &constraints, vec & /*clobbers*/,
++		   vec &constraints,
++		   vec & /*uses*/, vec & /*clobbers*/,
+ 		   HARD_REG_SET & /*clobbered_regs*/, location_t loc)
+ {
+   bool saw_asm_flag = false;
+diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
+index b700c23b8..c72e9c0b0 100644
+--- a/gcc/config/arm/arm.cc
++++ b/gcc/config/arm/arm.cc
+@@ -325,7 +325,7 @@ static HOST_WIDE_INT arm_constant_alignment (const_tree, HOST_WIDE_INT);
+ static rtx_insn *thumb1_md_asm_adjust (vec &, vec &,
+ 				       vec &,
+ 				       vec &, vec &,
+-				       HARD_REG_SET &, location_t);
++				       vec &, HARD_REG_SET &, location_t);
+ static const char *arm_identify_fpu_from_isa (sbitmap);
+ 
+ /* Table of machine attributes.  */
+@@ -34209,7 +34209,8 @@ arm_stack_protect_guard (void)
+ rtx_insn *
+ thumb1_md_asm_adjust (vec &outputs, vec & /*inputs*/,
+ 		      vec & /*input_modes*/,
+-		      vec &constraints, vec & /*clobbers*/,
++		      vec &constraints,
++		      vec &, vec & /*clobbers*/,
+ 		      HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/)
+ {
+   for (unsigned i = 0, n = outputs.length (); i < n; ++i)
+diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
+index 4ed390e4c..1b5a95410 100644
+--- a/gcc/config/avr/avr.cc
++++ b/gcc/config/avr/avr.cc
+@@ -14497,6 +14497,7 @@ static rtx_insn *
+ avr_md_asm_adjust (vec &/*outputs*/, vec &/*inputs*/,
+                    vec & /*input_modes*/,
+                    vec &/*constraints*/,
++		   vec &/*uses*/,
+                    vec &clobbers, HARD_REG_SET &clobbered_regs,
+ 		   location_t /*loc*/)
+ {
+diff --git a/gcc/config/cris/cris.cc b/gcc/config/cris/cris.cc
+index f0017d630..3a1c85481 100644
+--- a/gcc/config/cris/cris.cc
++++ b/gcc/config/cris/cris.cc
+@@ -151,7 +151,8 @@ static void cris_function_arg_advance (cumulative_args_t,
+ 				       const function_arg_info &);
+ static rtx_insn *cris_md_asm_adjust (vec &, vec &,
+ 				     vec &, vec &,
+-				     vec &, HARD_REG_SET &, location_t);
++				     vec &, vec &,
++				     HARD_REG_SET &, location_t);
+ 
+ static void cris_option_override (void);
+ 
+@@ -3506,7 +3507,8 @@ cris_function_arg_advance (cumulative_args_t ca_v,
+ static rtx_insn *
+ cris_md_asm_adjust (vec &outputs, vec &inputs,
+ 		    vec & /*input_modes*/,
+-		    vec &constraints, vec &clobbers,
++		    vec &constraints,
++		    vec &/*uses*/, vec &clobbers,
+ 		    HARD_REG_SET &clobbered_regs, location_t /*loc*/)
+ {
+   /* For the time being, all asms clobber condition codes.
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index 593185fa6..83a0d8abb 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -22252,8 +22252,9 @@ ix86_c_mode_for_suffix (char suffix)
+ static rtx_insn *
+ ix86_md_asm_adjust (vec &outputs, vec & /*inputs*/,
+ 		    vec & /*input_modes*/,
+-		    vec &constraints, vec &clobbers,
+-		    HARD_REG_SET &clobbered_regs, location_t loc)
++		    vec &constraints, vec &/*uses*/,
++		    vec &clobbers, HARD_REG_SET &clobbered_regs,
++		    location_t loc)
+ {
+   bool saw_asm_flag = false;
+ 
+diff --git a/gcc/config/mn10300/mn10300.cc b/gcc/config/mn10300/mn10300.cc
+index 2a58dd925..2ca2c769c 100644
+--- a/gcc/config/mn10300/mn10300.cc
++++ b/gcc/config/mn10300/mn10300.cc
+@@ -2849,7 +2849,8 @@ mn10300_conditional_register_usage (void)
+ static rtx_insn *
+ mn10300_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/,
+ 		       vec & /*input_modes*/,
+-		       vec & /*constraints*/, vec &clobbers,
++		       vec & /*constraints*/,
++		       vec &/*uses*/, vec &clobbers,
+ 		       HARD_REG_SET &clobbered_regs, location_t /*loc*/)
+ {
+   clobbers.safe_push (gen_rtx_REG (CCmode, CC_REG));
+diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
+index 71fe9e8bc..27530495f 100644
+--- a/gcc/config/nds32/nds32.cc
++++ b/gcc/config/nds32/nds32.cc
+@@ -4199,8 +4199,8 @@ nds32_md_asm_adjust (vec &outputs ATTRIBUTE_UNUSED,
+ 		     vec &inputs ATTRIBUTE_UNUSED,
+ 		     vec &input_modes ATTRIBUTE_UNUSED,
+ 		     vec &constraints ATTRIBUTE_UNUSED,
+-		     vec &clobbers, HARD_REG_SET &clobbered_regs,
+-		     location_t /*loc*/)
++		     vec &/*uses*/, vec &clobbers,
++		     HARD_REG_SET &clobbered_regs, location_t /*loc*/)
+ {
+   if (!flag_inline_asm_r15)
+     {
+diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc
+index 380223439..25cf62cbc 100644
+--- a/gcc/config/pdp11/pdp11.cc
++++ b/gcc/config/pdp11/pdp11.cc
+@@ -155,7 +155,8 @@ static int pdp11_addr_cost (rtx, machine_mode, addr_space_t, bool);
+ static int pdp11_insn_cost (rtx_insn *insn, bool speed);
+ static rtx_insn *pdp11_md_asm_adjust (vec &, vec &,
+ 				      vec &, vec &,
+-				      vec &, HARD_REG_SET &, location_t);
++				      vec &, vec &,
++				      HARD_REG_SET &, location_t);
+ static bool pdp11_return_in_memory (const_tree, const_tree);
+ static rtx pdp11_function_value (const_tree, const_tree, bool);
+ static rtx pdp11_libcall_value (machine_mode, const_rtx);
+@@ -2137,7 +2138,8 @@ pdp11_cmp_length (rtx *operands, int words)
+ static rtx_insn *
+ pdp11_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/,
+ 		     vec & /*input_modes*/,
+-		     vec & /*constraints*/, vec &clobbers,
++		     vec & /*constraints*/,
++		     vec &/*uses*/, vec &clobbers,
+ 		     HARD_REG_SET &clobbered_regs, location_t /*loc*/)
+ {
+   clobbers.safe_push (gen_rtx_REG (CCmode, CC_REGNUM));
+diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
+index 0b75861bb..55d4ce751 100644
+--- a/gcc/config/rs6000/rs6000.cc
++++ b/gcc/config/rs6000/rs6000.cc
+@@ -3443,7 +3443,8 @@ rs6000_builtin_mask_calculate (void)
+ static rtx_insn *
+ rs6000_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/,
+ 		      vec & /*input_modes*/,
+-		      vec & /*constraints*/, vec &clobbers,
++		      vec & /*constraints*/,
++		      vec &/*uses*/, vec &clobbers,
+ 		      HARD_REG_SET &clobbered_regs, location_t /*loc*/)
+ {
+   clobbers.safe_push (gen_rtx_REG (SImode, CA_REGNO));
+diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
+index ae0cf9ef5..f1599a5c5 100644
+--- a/gcc/config/s390/s390.cc
++++ b/gcc/config/s390/s390.cc
+@@ -16994,7 +16994,8 @@ s390_hard_fp_reg_p (rtx x)
+ static rtx_insn *
+ s390_md_asm_adjust (vec &outputs, vec &inputs,
+ 		    vec &input_modes,
+-		    vec &constraints, vec & /*clobbers*/,
++		    vec &constraints,
++		    vec &/*uses*/, vec &/*clobbers*/,
+ 		    HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/)
+ {
+   if (!TARGET_VXE)
+diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc
+index 28c1af59a..7673a1428 100644
+--- a/gcc/config/vax/vax.cc
++++ b/gcc/config/vax/vax.cc
+@@ -57,7 +57,8 @@ static bool vax_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+ static machine_mode vax_cc_modes_compatible (machine_mode, machine_mode);
+ static rtx_insn *vax_md_asm_adjust (vec &, vec &,
+ 				    vec &, vec &,
+-				    vec &, HARD_REG_SET &, location_t);
++				    vec &, vec &, HARD_REG_SET &,
++				    location_t);
+ static rtx vax_function_arg (cumulative_args_t, const function_arg_info &);
+ static void vax_function_arg_advance (cumulative_args_t,
+ 				      const function_arg_info &);
+@@ -1179,6 +1180,7 @@ vax_md_asm_adjust (vec &outputs ATTRIBUTE_UNUSED,
+ 		   vec &inputs ATTRIBUTE_UNUSED,
+ 		   vec &input_modes ATTRIBUTE_UNUSED,
+ 		   vec &constraints ATTRIBUTE_UNUSED,
++		   vec &/*uses*/,
+ 		   vec &clobbers, HARD_REG_SET &clobbered_regs,
+ 		   location_t /*loc*/)
+ {
+diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
+index 03c1a33e1..35b46ced9 100644
+--- a/gcc/config/visium/visium.cc
++++ b/gcc/config/visium/visium.cc
+@@ -190,7 +190,7 @@ static tree visium_build_builtin_va_list (void);
+ static rtx_insn *visium_md_asm_adjust (vec &, vec &,
+ 				       vec &,
+ 				       vec &, vec &,
+-				       HARD_REG_SET &, location_t);
++				       vec &, HARD_REG_SET &, location_t);
+ 
+ static bool visium_legitimate_constant_p (machine_mode, rtx);
+ 
+@@ -794,7 +794,8 @@ visium_conditional_register_usage (void)
+ static rtx_insn *
+ visium_md_asm_adjust (vec & /*outputs*/, vec & /*inputs*/,
+ 		      vec & /*input_modes*/,
+-		      vec & /*constraints*/, vec &clobbers,
++		      vec & /*constraints*/,
++		      vec &/*uses*/, vec &clobbers,
+ 		      HARD_REG_SET &clobbered_regs, location_t /*loc*/)
+ {
+   clobbers.safe_push (gen_rtx_REG (CCmode, FLAGS_REGNUM));
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 357c29a4d..4f93facf7 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -11626,10 +11626,11 @@ from shared libraries (DLLs).
+ You need not define this macro if it would always evaluate to zero.
+ @end defmac
+ 
+-@deftypefn {Target Hook} {rtx_insn *} TARGET_MD_ASM_ADJUST (vec& @var{outputs}, vec& @var{inputs}, vec& @var{input_modes}, vec& @var{constraints}, vec& @var{clobbers}, HARD_REG_SET& @var{clobbered_regs}, location_t @var{loc})
++@deftypefn {Target Hook} {rtx_insn *} TARGET_MD_ASM_ADJUST (vec& @var{outputs}, vec& @var{inputs}, vec& @var{input_modes}, vec& @var{constraints}, vec& @var{usess}, vec& @var{clobbers}, HARD_REG_SET& @var{clobbered_regs}, location_t @var{loc})
+ This target hook may add @dfn{clobbers} to @var{clobbers} and
+ @var{clobbered_regs} for any hard regs the port wishes to automatically
+-clobber for an asm.  The @var{outputs} and @var{inputs} may be inspected
++clobber for an asm.  It can also add hard registers that are used by the
++asm to @var{uses}.  The @var{outputs} and @var{inputs} may be inspected
+ to avoid clobbering a register that is already used by the asm.  @var{loc}
+ is the source location of the asm.
+ 
+diff --git a/gcc/recog.cc b/gcc/recog.cc
+index cd2410ab2..5b81d5e21 100644
+--- a/gcc/recog.cc
++++ b/gcc/recog.cc
+@@ -1977,13 +1977,17 @@ asm_noperands (const_rtx body)
+ 	{
+ 	  /* Multiple output operands, or 1 output plus some clobbers:
+ 	     body is
+-	     [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...].  */
+-	  /* Count backwards through CLOBBERs to determine number of SETs.  */
++	     [(set OUTPUT (asm_operands ...))...
++	      (use (reg ...))...
++	      (clobber (reg ...))...].  */
++	  /* Count backwards through USEs and CLOBBERs to determine
++	     number of SETs.  */
+ 	  for (i = XVECLEN (body, 0); i > 0; i--)
+ 	    {
+ 	      if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
+ 		break;
+-	      if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
++	      if (GET_CODE (XVECEXP (body, 0, i - 1)) != USE
++		  && GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
+ 		return -1;
+ 	    }
+ 
+@@ -2010,10 +2014,13 @@ asm_noperands (const_rtx body)
+       else
+ 	{
+ 	  /* 0 outputs, but some clobbers:
+-	     body is [(asm_operands ...) (clobber (reg ...))...].  */
++	     body is [(asm_operands ...)
++		      (use (reg ...))...
++		      (clobber (reg ...))...].  */
+ 	  /* Make sure all the other parallel things really are clobbers.  */
+ 	  for (i = XVECLEN (body, 0) - 1; i > 0; i--)
+-	    if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
++	    if (GET_CODE (XVECEXP (body, 0, i)) != USE
++		&& GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
+ 	      return -1;
+ 	}
+     }
+@@ -2080,7 +2087,8 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
+ 	       the SETs.  Their constraints are in the ASM_OPERANDS itself.  */
+ 	    for (i = 0; i < nparallel; i++)
+ 	      {
+-		if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
++		if (GET_CODE (XVECEXP (body, 0, i)) == USE
++		    || GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
+ 		  break;		/* Past last SET */
+ 		gcc_assert (GET_CODE (XVECEXP (body, 0, i)) == SET);
+ 		if (operands)
+diff --git a/gcc/target.def b/gcc/target.def
+index a57e51b0d..60096c60c 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -4309,7 +4309,8 @@ DEFHOOK
+ (md_asm_adjust,
+  "This target hook may add @dfn{clobbers} to @var{clobbers} and\n\
+ @var{clobbered_regs} for any hard regs the port wishes to automatically\n\
+-clobber for an asm.  The @var{outputs} and @var{inputs} may be inspected\n\
++clobber for an asm.  It can also add hard registers that are used by the\n\
++asm to @var{uses}.  The @var{outputs} and @var{inputs} may be inspected\n\
+ to avoid clobbering a register that is already used by the asm.  @var{loc}\n\
+ is the source location of the asm.\n\
+ \n\
+@@ -4320,7 +4321,7 @@ changes to @var{inputs} must be accompanied by the corresponding changes\n\
+ to @var{input_modes}.",
+  rtx_insn *,
+  (vec& outputs, vec& inputs, vec& input_modes,
+-  vec& constraints, vec& clobbers,
++  vec& constraints, vec& usess, vec& clobbers,
+   HARD_REG_SET& clobbered_regs, location_t loc),
+  NULL)
+ 
+-- 
+2.33.0
+
diff --git a/0152-Backport-SME-New-compact-syntax-for-insn-and-insn_sp.patch b/0152-Backport-SME-New-compact-syntax-for-insn-and-insn_sp.patch
new file mode 100644
index 0000000..edf0b1e
--- /dev/null
+++ b/0152-Backport-SME-New-compact-syntax-for-insn-and-insn_sp.patch
@@ -0,0 +1,998 @@
+From 763db5ed42e18cdddf979dda82056345e3af15ed Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Mon, 19 Jun 2023 15:47:46 +0100
+Subject: [PATCH 053/157] [Backport][SME] New compact syntax for insn and
+ insn_split in Machine Descriptions.
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=957ae90406591739b68e95ad49a0232faeb74217
+
+This patch adds support for a compact syntax for specifying constraints in
+instruction patterns. Credit for the idea goes to Richard Earnshaw.
+
+With this new syntax we want a clean break from the current limitations to make
+something that is hopefully easier to use and maintain.
+
+The idea behind this compact syntax is that often times it's quite hard to
+correlate the entries in the constrains list, attributes and instruction lists.
+
+One has to count and this often is tedious.  Additionally when changing a single
+line in the insn multiple lines in a diff change, making it harder to see what's
+going on.
+
+This new syntax takes into account many of the common things that are done in MD
+files.   It's also worth saying that this version is intended to deal with the
+common case of a string based alternatives.   For C chunks we have some ideas
+but those are not intended to be addressed here.
+
+It's easiest to explain with an example:
+
+normal syntax:
+
+(define_insn_and_split "*movsi_aarch64"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m,  r,  r,  r, w,r,w, w")
+	(match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Ds"))]
+  "(register_operand (operands[0], SImode)
+    || aarch64_reg_or_zero (operands[1], SImode))"
+  "@
+   mov\\t%w0, %w1
+   mov\\t%w0, %w1
+   mov\\t%w0, %w1
+   mov\\t%w0, %1
+   #
+   * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+   ldr\\t%w0, %1
+   ldr\\t%s0, %1
+   str\\t%w1, %0
+   str\\t%s1, %0
+   adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]
+   adr\\t%x0, %c1
+   adrp\\t%x0, %A1
+   fmov\\t%s0, %w1
+   fmov\\t%w0, %s1
+   fmov\\t%s0, %s1
+   * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
+  "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
+    && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
+   [(const_int 0)]
+   "{
+       aarch64_expand_mov_immediate (operands[0], operands[1]);
+       DONE;
+    }"
+  ;; The "mov_imm" type for CNT is just a placeholder.
+  [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
+		    load_4,store_4,store_4,load_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
+   (set_attr "arch"   "*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
+   (set_attr "length" "4,4,4,4,*,  4,4, 4,4, 4,8,4,4, 4, 4, 4,   4")
+]
+)
+
+New syntax:
+
+(define_insn_and_split "*movsi_aarch64"
+  [(set (match_operand:SI 0 "nonimmediate_operand")
+	(match_operand:SI 1 "aarch64_mov_operand"))]
+  "(register_operand (operands[0], SImode)
+    || aarch64_reg_or_zero (operands[1], SImode))"
+  {@ [cons: =0, 1; attrs: type, arch, length]
+     [r , r  ; mov_reg  , *   , 4] mov\t%w0, %w1
+     [k , r  ; mov_reg  , *   , 4] ^
+     [r , k  ; mov_reg  , *   , 4] ^
+     [r , M  ; mov_imm  , *   , 4] mov\t%w0, %1
+     [r , n  ; mov_imm  , *   ,16] #
+     /* The "mov_imm" type for CNT is just a placeholder.  */
+     [r , Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
+     [r , m  ; load_4   , *   , 4] ldr\t%w0, %1
+     [w , m  ; load_4   , fp  , 4] ldr\t%s0, %1
+     [m , rZ ; store_4  , *   , 4] str\t%w1, %0
+     [m , w  ; store_4  , fp  , 4] str\t%s1, %0
+     [r , Usw; load_4   , *   , 8] adrp\t%x0, %A1;ldr\t%w0, [%x0, %L1]
+     [r , Usa; adr      , *   , 4] adr\t%x0, %c1
+     [r , Ush; adr      , *   , 4] adrp\t%x0, %A1
+     [w , rZ ; f_mcr    , fp  , 4] fmov\t%s0, %w1
+     [r , w  ; f_mrc    , fp  , 4] fmov\t%w0, %s1
+     [w , w  ; fmov     , fp  , 4] fmov\t%s0, %s1
+     [w , Ds ; neon_move, simd, 4] << aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
+  }
+  "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
+    && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
+  [(const_int 0)]
+  {
+    aarch64_expand_mov_immediate (operands[0], operands[1]);
+    DONE;
+  }
+)
+
+The main syntax rules are as follows (See docs for full rules):
+  - Template must start with "{@" and end with "}" to use the new syntax.
+  - "{@" is followed by a layout in parentheses which is "cons:" followed by
+    a list of match_operand/match_scratch IDs, then a semicolon, then the
+    same for attributes ("attrs:"). Both sections are optional (so you can
+    use only cons, or only attrs, or both), and cons must come before attrs
+    if present.
+  - Each alternative begins with any amount of whitespace.
+  - Following the whitespace is a comma-separated list of constraints and/or
+    attributes within brackets [], with sections separated by a semicolon.
+  - Following the closing ']' is any amount of whitespace, and then the actual
+    asm output.
+  - Spaces are allowed in the list (they will simply be removed).
+  - All alternatives should be specified: a blank list should be
+    "[,,]", "[,,;,]" etc., not "[]" or "" (however genattr may segfault if
+    you leave certain attributes empty, I have found).
+  - The actual constraint string in the match_operand or match_scratch, and
+    the attribute string in the set_attr, must be blank or an empty string
+    (you can't combine the old and new syntaxes).
+  - The common idion * return can be shortened by using <<.
+  - Any unexpanded iterators left during processing will result in an error at
+    compile time.   If for some reason <> is needed in the output then these
+    must be escaped using \.
+  - Within an {@ block both multiline and singleline C comments are allowed, but
+    when used outside of a C block they must be the only non-whitespace blocks on
+    the line
+  - Inside an {@ block any unexpanded iterators will result in a compile time
+    fault instead of incorrect assembly being generated at runtime.  If the
+    literal <> is needed in the output this needs to be escaped with \<\>.
+  - This check is not performed inside C blocks (lines starting with *).
+  - Instead of copying the previous instruction again in the next pattern, one
+    can use ^ to refer to the previous asm string.
+
+This patch works by blindly transforming the new syntax into the old syntax,
+so it doesn't do extensive checking. However, it does verify that:
+	- The correct number of constraints/attributes are specified.
+	- You haven't mixed old and new syntax.
+	- The specified operand IDs/attribute names actually exist.
+	- You don't have duplicate cons
+
+If something goes wrong, it may write invalid constraints/attributes/template
+back into the rtx. But this shouldn't matter because error_at will cause the
+program to fail on exit anyway.
+
+Because this transformation occurs as early as possible (before patterns are
+queued), the rest of the compiler can completely ignore the new syntax and
+assume that the old syntax will always be used.
+
+This doesn't seem to have any measurable effect on the runtime of gen*
+programs.
+
+gcc/ChangeLog:
+
+	* gensupport.cc (class conlist, add_constraints, add_attributes,
+	skip_spaces, expect_char, preprocess_compact_syntax,
+	parse_section_layout, parse_section, convert_syntax): New.
+	(process_rtx): Check for conversion.
+	* genoutput.cc (process_template): Check for unresolved iterators.
+	(class data): Add compact_syntax_p.
+	(gen_insn): Use it.
+	* gensupport.h (compact_syntax): New.
+	(hash-set.h): Include.
+	* doc/md.texi: Document it.
+
+Co-Authored-By: Omar Tahir 
+---
+ gcc/doc/md.texi   | 163 +++++++++++++++
+ gcc/genoutput.cc  |  48 ++++-
+ gcc/gensupport.cc | 498 ++++++++++++++++++++++++++++++++++++++++++++++
+ gcc/gensupport.h  |   3 +
+ 4 files changed, 709 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
+index 3b544358b..04ace8f7f 100644
+--- a/gcc/doc/md.texi
++++ b/gcc/doc/md.texi
+@@ -27,6 +27,7 @@ See the next chapter for information on the C header file.
+                         from such an insn.
+ * Output Statement::    For more generality, write C code to output
+                         the assembler code.
++* Compact Syntax::      Compact syntax for writing machine descriptors.
+ * Predicates::          Controlling what kinds of operands can be used
+                         for an insn.
+ * Constraints::         Fine-tuning operand selection.
+@@ -713,6 +714,168 @@ you can use @samp{*} inside of a @samp{@@} multi-alternative template:
+ @end group
+ @end smallexample
+ 
++@node Compact Syntax
++@section Compact Syntax
++@cindex compact syntax
++
++When a @code{define_insn} or @code{define_insn_and_split} has multiple
++alternatives it may be beneficial to use the compact syntax when specifying
++alternatives.
++
++This syntax puts the constraints and attributes on the same horizontal line as
++the instruction assembly template.
++
++As an example
++
++@smallexample
++@group
++(define_insn_and_split ""
++  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r")
++	(match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,Usv"))]
++  ""
++  "@@
++   mov\\t%w0, %w1
++   mov\\t%w0, %w1
++   mov\\t%w0, %w1
++   mov\\t%w0, %1
++   #
++   * return aarch64_output_sve_cnt_immediate ('cnt', '%x0', operands[1]);"
++  "&& true"
++   [(const_int 0)]
++  @{
++     aarch64_expand_mov_immediate (operands[0], operands[1]);
++     DONE;
++  @}
++  [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm")
++   (set_attr "arch"   "*,*,*,*,*,sve")
++   (set_attr "length" "4,4,4,4,*,  4")
++]
++)
++@end group
++@end smallexample
++
++can be better expressed as:
++
++@smallexample
++@group
++(define_insn_and_split ""
++  [(set (match_operand:SI 0 "nonimmediate_operand")
++	(match_operand:SI 1 "aarch64_mov_operand"))]
++  ""
++  @{@@ [cons: =0, 1; attrs: type, arch, length]
++     [r , r  ; mov_reg  , *   , 4] mov\t%w0, %w1
++     [k , r  ; mov_reg  , *   , 4] ^
++     [r , k  ; mov_reg  , *   , 4] ^
++     [r , M  ; mov_imm  , *   , 4] mov\t%w0, %1
++     [r , n  ; mov_imm  , *   , *] #
++     [r , Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++  @}
++  "&& true"
++  [(const_int 0)]
++  @{
++    aarch64_expand_mov_immediate (operands[0], operands[1]);
++    DONE;
++  @}
++)
++@end group
++@end smallexample
++
++The syntax rules are as follows:
++@itemize @bullet
++@item
++Templates must start with @samp{@{@@} to use the new syntax.
++
++@item
++@samp{@{@@} is followed by a layout in square brackets which is @samp{cons:}
++followed by a comma-separated list of @code{match_operand}/@code{match_scratch}
++operand numbers, then a semicolon, followed by the same for attributes
++(@samp{attrs:}).  Operand modifiers like @code{=} and @code{+} can be placed
++before an operand number.
++Both sections are optional (so you can use only @samp{cons}, or only
++@samp{attrs}, or both), and @samp{cons} must come before @samp{attrs} if
++present.
++
++@item
++Each alternative begins with any amount of whitespace.
++
++@item
++Following the whitespace is a comma-separated list of "constraints" and/or
++"attributes" within brackets @code{[]}, with sections separated by a semicolon.
++
++@item
++Should you want to copy the previous asm line, the symbol @code{^} can be used.
++This allows less copy pasting between alternative and reduces the number of
++lines to update on changes.
++
++@item
++When using C functions for output, the idiom @samp{* return @var{function};}
++can be replaced with the shorthand @samp{<< @var{function};}.
++
++@item
++Following the closing @samp{]} is any amount of whitespace, and then the actual
++asm output.
++
++@item
++Spaces are allowed in the list (they will simply be removed).
++
++@item
++All constraint alternatives should be specified.  For example, a list of
++of three blank alternatives should be written @samp{[,,]} rather than
++@samp{[]}.
++
++@item
++All attribute alternatives should be non-empty, with @samp{*}
++representing the default attribute value.  For example, a list of three
++default attribute values should be written @samp{[*,*,*]} rather than
++@samp{[]}.
++
++@item
++Within an @samp{@{@@} block both multiline and singleline C comments are
++allowed, but when used outside of a C block they must be the only non-whitespace
++blocks on the line.
++
++@item
++Within an @samp{@{@@} block, any iterators that do not get expanded will result
++in an error.  If for some reason it is required to have @code{<} or @code{>} in
++the output then these must be escaped using @backslashchar{}.
++
++@item
++It is possible to use the @samp{attrs} list to specify some attributes and to
++use the normal @code{set_attr} syntax to specify other attributes.  There must
++not be any overlap between the two lists.
++
++In other words, the following is valid:
++@smallexample
++@group
++(define_insn_and_split ""
++  [(set (match_operand:SI 0 "nonimmediate_operand")
++	(match_operand:SI 1 "aarch64_mov_operand"))]
++  ""
++  @{@@ [cons: 0, 1; attrs: type, arch, length]@}
++  @dots{} 
++  [(set_attr "foo" "mov_imm")]
++)
++@end group
++@end smallexample
++
++but this is not valid:
++@smallexample
++@group
++(define_insn_and_split ""
++  [(set (match_operand:SI 0 "nonimmediate_operand")
++	(match_operand:SI 1 "aarch64_mov_operand"))]
++  ""
++  @{@@ [cons: 0, 1; attrs: type, arch, length]@}
++  @dots{} 
++  [(set_attr "arch" "bar")
++   (set_attr "foo" "mov_imm")]
++)
++@end group
++@end smallexample
++
++because it specifies @code{arch} twice.
++@end itemize
++
+ @node Predicates
+ @section Predicates
+ @cindex predicates
+diff --git a/gcc/genoutput.cc b/gcc/genoutput.cc
+index 6bb03e286..de5dafdbf 100644
+--- a/gcc/genoutput.cc
++++ b/gcc/genoutput.cc
+@@ -157,6 +157,7 @@ public:
+   int n_alternatives;		/* Number of alternatives in each constraint */
+   int operand_number;		/* Operand index in the big array.  */
+   int output_format;		/* INSN_OUTPUT_FORMAT_*.  */
++  bool compact_syntax_p;
+   struct operand_data operand[MAX_MAX_OPERANDS];
+ };
+ 
+@@ -700,12 +701,51 @@ process_template (class data *d, const char *template_code)
+ 	  if (sp != ep)
+ 	    message_at (d->loc, "trailing whitespace in output template");
+ 
+-	  while (cp < sp)
++	  /* Check for any unexpanded iterators.  */
++	  if (bp[0] != '*' && d->compact_syntax_p)
+ 	    {
+-	      putchar (*cp);
+-	      cp++;
++	      const char *p = cp;
++	      const char *last_bracket = nullptr;
++	      while (p < sp)
++		{
++		  if (*p == '\\' && p + 1 < sp)
++		    {
++		      putchar (*p);
++		      putchar (*(p+1));
++		      p += 2;
++		      continue;
++		    }
++
++		  if (*p == '>' && last_bracket && *last_bracket == '<')
++		    {
++		      int len = p - last_bracket;
++		      fatal_at (d->loc, "unresolved iterator '%.*s' in '%s'",
++				len - 1, last_bracket + 1, cp);
++		    }
++		  else if (*p == '<' || *p == '>')
++		    last_bracket = p;
++
++		  putchar (*p);
++		  p += 1;
++		}
++
++	      if (last_bracket)
++		{
++		  char *nl = strchr (const_cast (cp), '\n');
++		  if (nl)
++		    *nl = '\0';
++		  fatal_at (d->loc, "unmatched angle brackets, likely an "
++			    "error in iterator syntax in %s", cp);
++		}
++	    }
++	  else
++	    {
++	      while (cp < sp)
++		putchar (*(cp++));
+ 	    }
+ 
++	  cp = sp;
++
+ 	  if (!found_star)
+ 	    puts ("\",");
+ 	  else if (*bp != '*')
+@@ -881,6 +921,8 @@ gen_insn (md_rtx_info *info)
+   else
+     d->name = 0;
+ 
++  d->compact_syntax_p = compact_syntax.contains (insn);
++
+   /* Build up the list in the same order as the insns are seen
+      in the machine description.  */
+   d->next = 0;
+diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc
+index 42680499d..23c61dcdd 100644
+--- a/gcc/gensupport.cc
++++ b/gcc/gensupport.cc
+@@ -18,6 +18,8 @@
+    .  */
+ 
+ #include "bconfig.h"
++#define INCLUDE_STRING
++#define INCLUDE_VECTOR
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+@@ -33,6 +35,8 @@
+ static rtx operand_data[MAX_OPERANDS];
+ static rtx match_operand_entries_in_pattern[MAX_OPERANDS];
+ static char used_operands_numbers[MAX_OPERANDS];
++/* List of entries which are part of the new syntax.  */
++hash_set compact_syntax;
+ 
+ 
+ /* In case some macros used by files we include need it, define this here.  */
+@@ -545,6 +549,497 @@ gen_rewrite_sequence (rtvec vec)
+   return new_vec;
+ }
+ 
++/* The following is for handling the compact syntax for constraints and
++   attributes.
++
++   The normal syntax looks like this:
++
++       ...
++       (match_operand: 0 "s_register_operand" "r,I,k")
++       (match_operand: 2 "s_register_operand" "r,k,I")
++       ...
++       "@
++	
++	
++	"
++       ...
++       (set_attr "length" "4,8,8")
++
++   The compact syntax looks like this:
++
++       ...
++       (match_operand: 0 "s_register_operand")
++       (match_operand: 2 "s_register_operand")
++       ...
++       {@ [cons: 0, 2; attrs: length]
++	[r,r; 4] 
++	[I,k; 8] 
++	[k,I; 8] 
++       }
++       ...
++       []
++
++   This is the only place where this syntax needs to be handled.  Relevant
++   patterns are transformed from compact to the normal syntax before they are
++   queued, so none of the gen* programs need to know about this syntax at all.
++
++   Conversion process (convert_syntax):
++
++   0) Check that pattern actually uses new syntax (check for {@ ... }).
++
++   1) Get the "layout", i.e. the "[cons: 0 2; attrs: length]" from the above
++      example.  cons must come first; both are optional. Set up two vecs,
++      convec and attrvec, for holding the results of the transformation.
++
++   2) For each alternative: parse the list of constraints and/or attributes,
++      and enqueue them in the relevant lists in convec and attrvec.  By the end
++      of this process, convec[N].con and attrvec[N].con should contain regular
++      syntax constraint/attribute lists like "r,I,k".  Copy the asm to a string
++      as we go.
++
++   3) Search the rtx and write the constraint and attribute lists into the
++      correct places. Write the asm back into the template.  */
++
++/* Helper class for shuffling constraints/attributes in convert_syntax and
++   add_constraints/add_attributes.  This includes commas but not whitespace.  */
++
++class conlist {
++private:
++  std::string con;
++
++public:
++  std::string name;
++  int idx = -1;
++
++  conlist () = default;
++
++  /* [ns..ns + len) should be a string with the id of the rtx to match
++     i.e. if rtx is the relevant match_operand or match_scratch then
++     [ns..ns + len) should equal itoa (XINT (rtx, 0)), and if set_attr then
++     [ns..ns + len) should equal XSTR (rtx, 0).  */
++  conlist (const char *ns, unsigned int len, bool numeric)
++  {
++    /* Trim leading whitespaces.  */
++    while (ISBLANK (*ns))
++      {
++	ns++;
++	len--;
++      }
++
++    /* Trim trailing whitespace.  */
++    for (int i = len - 1; i >= 0; i--, len--)
++      if (!ISBLANK (ns[i]))
++	break;
++
++    /* Parse off any modifiers.  */
++    while (!ISALNUM (*ns))
++      {
++	con += *(ns++);
++	len--;
++      }
++
++    name.assign (ns, len);
++    if (numeric)
++      idx = std::stoi (name);
++  }
++
++  /* Adds a character to the end of the string.  */
++  void add (char c)
++  {
++    con += c;
++  }
++
++  /* Output the string in the form of a brand-new char *, then effectively
++     clear the internal string by resetting len to 0.  */
++  char *out ()
++  {
++    /* Final character is always a trailing comma, so strip it out.  */
++    char *q = xstrndup (con.c_str (), con.size () - 1);
++    con.clear ();
++    return q;
++  }
++};
++
++typedef std::vector vec_conlist;
++
++/* Add constraints to an rtx.  This function is similar to remove_constraints.
++   Errors if adding the constraints would overwrite existing constraints.  */
++
++static void
++add_constraints (rtx part, file_location loc, vec_conlist &cons)
++{
++  const char *format_ptr;
++
++  if (part == NULL_RTX)
++    return;
++
++  /* If match_op or match_scr, check if we have the right one, and if so, copy
++     over the constraint list.  */
++  if (GET_CODE (part) == MATCH_OPERAND || GET_CODE (part) == MATCH_SCRATCH)
++    {
++      int field = GET_CODE (part) == MATCH_OPERAND ? 2 : 1;
++      unsigned id = XINT (part, 0);
++
++      if (id >= cons.size () || cons[id].idx == -1)
++	return;
++
++      if (XSTR (part, field)[0] != '\0')
++	{
++	  error_at (loc, "can't mix normal and compact constraint syntax");
++	  return;
++	}
++      XSTR (part, field) = cons[id].out ();
++      cons[id].idx = -1;
++    }
++
++  format_ptr = GET_RTX_FORMAT (GET_CODE (part));
++
++  /* Recursively search the rtx.  */
++  for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
++    switch (*format_ptr++)
++      {
++      case 'e':
++      case 'u':
++	add_constraints (XEXP (part, i), loc, cons);
++	break;
++      case 'E':
++	if (XVEC (part, i) != NULL)
++	  for (int j = 0; j < XVECLEN (part, i); j++)
++	    add_constraints (XVECEXP (part, i, j), loc, cons);
++	break;
++      default:
++	continue;
++      }
++}
++
++/* Add ATTRS to definition X's attribute list.  */
++
++static void
++add_attributes (rtx x, vec_conlist &attrs)
++{
++  unsigned int attr_index = GET_CODE (x) == DEFINE_INSN ? 4 : 3;
++  rtvec orig = XVEC (x, attr_index);
++  if (orig)
++    {
++      size_t n_curr = XVECLEN (x, attr_index);
++      rtvec copy = rtvec_alloc (n_curr + attrs.size ());
++
++      /* Create a shallow copy of existing entries.  */
++      memcpy (©->elem[attrs.size ()], &orig->elem[0],
++	      sizeof (rtx) * n_curr);
++      XVEC (x, attr_index) = copy;
++    }
++   else
++    XVEC (x, attr_index) = rtvec_alloc (attrs.size ());
++
++  /* Create the new elements.  */
++  for (unsigned i = 0; i < attrs.size (); i++)
++    {
++      rtx attr = rtx_alloc (SET_ATTR);
++      XSTR (attr, 0) = xstrdup (attrs[i].name.c_str ());
++      XSTR (attr, 1) = attrs[i].out ();
++      XVECEXP (x, attr_index, i) = attr;
++    }
++}
++
++/* Consumes spaces and tabs.  */
++
++static inline void
++skip_spaces (const char **str)
++{
++  while (ISBLANK (**str))
++    (*str)++;
++}
++
++/* Consumes the given character, if it's there.  */
++
++static inline bool
++expect_char (const char **str, char c)
++{
++  if (**str != c)
++    return false;
++  (*str)++;
++  return true;
++}
++
++/* Parses the section layout that follows a "{@" if using new syntax. Builds
++   a vector for a single section. E.g. if we have "attrs: length, arch]..."
++   then list will have two elements, the first for "length" and the second
++   for "arch".  */
++
++static void
++parse_section_layout (file_location loc, const char **templ, const char *label,
++		      vec_conlist &list, bool numeric)
++{
++  const char *name_start;
++  size_t label_len = strlen (label);
++  if (strncmp (label, *templ, label_len) == 0)
++    {
++      *templ += label_len;
++
++      /* Gather the names.  */
++      while (**templ != ';' && **templ != ']')
++	{
++	  skip_spaces (templ);
++	  name_start = *templ;
++	  int len = 0;
++	  char val = (*templ)[len];
++	  while (val != ',' && val != ';' && val != ']')
++	    {
++	      if (val == 0 || val == '\n')
++	        fatal_at (loc, "missing ']'");
++	      val = (*templ)[++len];
++	    }
++	  *templ += len;
++	  if (val == ',')
++	    (*templ)++;
++	  list.push_back (conlist (name_start, len, numeric));
++	}
++    }
++}
++
++/* Parse a section, a section is defined as a named space separated list, e.g.
++
++   foo: a, b, c
++
++   is a section named "foo" with entries a, b and c.  */
++
++static void
++parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no,
++	       vec_conlist &list, file_location loc, const char *name)
++{
++  unsigned int i;
++
++  /* Go through the list, one character at a time, adding said character
++     to the correct string.  */
++  for (i = 0; **templ != ']' && **templ != ';'; (*templ)++)
++    if (!ISBLANK (**templ))
++      {
++	if (**templ == 0 || **templ == '\n')
++	  fatal_at (loc, "missing ']'");
++	list[i].add (**templ);
++	if (**templ == ',')
++	  {
++	    ++i;
++	    if (i == n_elems)
++	      fatal_at (loc, "too many %ss in alternative %d: expected %d",
++			name, alt_no, n_elems);
++	  }
++      }
++
++  if (i + 1 < n_elems)
++    fatal_at (loc, "too few %ss in alternative %d: expected %d, got %d",
++	      name, alt_no, n_elems, i);
++
++  list[i].add (',');
++}
++
++/* The compact syntax has more convience syntaxes.  As such we post process
++   the lines to get them back to something the normal syntax understands.  */
++
++static void
++preprocess_compact_syntax (file_location loc, int alt_no, std::string &line,
++			   std::string &last_line)
++{
++  /* Check if we're copying the last statement.  */
++  if (line.find ("^") == 0 && line.size () == 1)
++    {
++      if (last_line.empty ())
++	fatal_at (loc, "found instruction to copy previous line (^) in"
++		       "alternative %d but no previous line to copy", alt_no);
++      line = last_line;
++      return;
++    }
++
++  std::string result;
++  std::string buffer;
++  /* Check if we have << which means return c statement.  */
++  if (line.find ("<<") == 0)
++    {
++      result.append ("* return ");
++      const char *chunk = line.c_str () + 2;
++      skip_spaces (&chunk);
++      result.append (chunk);
++    }
++  else
++    result.append (line);
++
++  line = result;
++  return;
++}
++
++/* Converts an rtx from compact syntax to normal syntax if possible.  */
++
++static void
++convert_syntax (rtx x, file_location loc)
++{
++  int alt_no;
++  unsigned int templ_index;
++  const char *templ;
++  vec_conlist tconvec, convec, attrvec;
++
++  templ_index = GET_CODE (x) == DEFINE_INSN ? 3 : 2;
++
++  templ = XTMPL (x, templ_index);
++
++  /* Templates with constraints start with "{@".  */
++  if (strncmp ("*{@", templ, 3))
++    return;
++
++  /* Get the layout for the template.  */
++  templ += 3;
++  skip_spaces (&templ);
++
++  if (!expect_char (&templ, '['))
++    fatal_at (loc, "expecing `[' to begin section list");
++
++  parse_section_layout (loc, &templ, "cons:", tconvec, true);
++
++  /* Check for any duplicate cons entries and sort based on i.  */
++  for (auto e : tconvec)
++    {
++      unsigned idx = e.idx;
++      if (idx >= convec.size ())
++	convec.resize (idx + 1);
++
++      if (convec[idx].idx >= 0)
++	fatal_at (loc, "duplicate cons number found: %d", idx);
++      convec[idx] = e;
++    }
++  tconvec.clear ();
++
++  if (*templ != ']')
++    {
++      if (*templ == ';')
++	skip_spaces (&(++templ));
++      parse_section_layout (loc, &templ, "attrs:", attrvec, false);
++    }
++
++  if (!expect_char (&templ, ']'))
++    fatal_at (loc, "expecting `]` to end section list - section list must have "
++		   "cons first, attrs second");
++
++  /* We will write the un-constrainified template into new_templ.  */
++  std::string new_templ;
++  new_templ.append ("@");
++
++  /* Skip to the first proper line.  */
++  skip_spaces (&templ);
++  if (*templ == 0)
++    fatal_at (loc, "'{@...}' blocks must have at least one alternative");
++  if (*templ != '\n')
++    fatal_at (loc, "unexpected character '%c' after ']'", *templ);
++  templ++;
++
++  alt_no = 0;
++  std::string last_line;
++
++  /* Process the alternatives.  */
++  while (*(templ - 1) != '\0')
++    {
++      /* Skip leading whitespace.  */
++      std::string buffer;
++      skip_spaces (&templ);
++
++      /* Check if we're at the end.  */
++      if (templ[0] == '}' && templ[1] == '\0')
++	break;
++
++      if (expect_char (&templ, '['))
++	{
++	  new_templ += '\n';
++	  new_templ.append (buffer);
++	  /* Parse the constraint list, then the attribute list.  */
++	  if (convec.size () > 0)
++	    parse_section (&templ, convec.size (), alt_no, convec, loc,
++			   "constraint");
++
++	  if (attrvec.size () > 0)
++	    {
++	      if (convec.size () > 0 && !expect_char (&templ, ';'))
++		fatal_at (loc, "expected `;' to separate constraints "
++			       "and attributes in alternative %d", alt_no);
++
++	      parse_section (&templ, attrvec.size (), alt_no,
++			     attrvec, loc, "attribute");
++	    }
++
++	  if (!expect_char (&templ, ']'))
++	    fatal_at (loc, "expected end of constraint/attribute list but "
++			   "missing an ending `]' in alternative %d", alt_no);
++	}
++      else if (templ[0] == '/' && templ[1] == '/')
++	{
++	  templ += 2;
++	  /* Glob till newline or end of string.  */
++	  while (*templ != '\n' || *templ != '\0')
++	    templ++;
++
++	  /* Skip any newlines or whitespaces needed.  */
++	  while (ISSPACE(*templ))
++	    templ++;
++	  continue;
++	}
++      else if (templ[0] == '/' && templ[1] == '*')
++	{
++	  templ += 2;
++	  /* Glob till newline or end of multiline comment.  */
++	  while (templ[0] != 0 && templ[0] != '*' && templ[1] != '/')
++	    templ++;
++
++	while (templ[0] != '*' || templ[1] != '/')
++	  {
++	    if (templ[0] == 0)
++	      fatal_at (loc, "unterminated '/*'");
++	    templ++;
++	  }
++	templ += 2;
++
++	  /* Skip any newlines or whitespaces needed.  */
++	  while (ISSPACE(*templ))
++	    templ++;
++	  continue;
++	}
++      else
++	fatal_at (loc, "expected constraint/attribute list at beginning of "
++		       "alternative %d but missing a starting `['", alt_no);
++
++      /* Skip whitespace between list and asm.  */
++      skip_spaces (&templ);
++
++      /* Copy asm to new template.  */
++      std::string line;
++      while (*templ != '\n' && *templ != '\0')
++	line += *templ++;
++
++      /* Apply any pre-processing needed to the line.  */
++      preprocess_compact_syntax (loc, alt_no, line, last_line);
++      new_templ.append (line);
++      last_line = line;
++
++      /* Normal "*..." syntax expects the closing quote to be on the final
++	 line of asm, whereas we allow the closing "}" to be on its own line.
++	 Postpone copying the '\n' until we know that there is another
++	 alternative in the list.  */
++      while (ISSPACE (*templ))
++	templ++;
++      ++alt_no;
++    }
++
++  /* Write the constraints and attributes into their proper places.  */
++  if (convec.size () > 0)
++    add_constraints (x, loc, convec);
++
++  if (attrvec.size () > 0)
++    add_attributes (x, attrvec);
++
++  /* Copy over the new un-constrainified template.  */
++  XTMPL (x, templ_index) = xstrdup (new_templ.c_str ());
++
++  /* Register for later checks during iterator expansions.  */
++  compact_syntax.add (x);
++}
++
+ /* Process a top level rtx in some way, queuing as appropriate.  */
+ 
+ static void
+@@ -553,10 +1048,12 @@ process_rtx (rtx desc, file_location loc)
+   switch (GET_CODE (desc))
+     {
+     case DEFINE_INSN:
++      convert_syntax (desc, loc);
+       queue_pattern (desc, &define_insn_tail, loc);
+       break;
+ 
+     case DEFINE_COND_EXEC:
++      convert_syntax (desc, loc);
+       queue_pattern (desc, &define_cond_exec_tail, loc);
+       break;
+ 
+@@ -631,6 +1128,7 @@ process_rtx (rtx desc, file_location loc)
+ 	attr = XVEC (desc, split_code + 1);
+ 	PUT_CODE (desc, DEFINE_INSN);
+ 	XVEC (desc, 4) = attr;
++	convert_syntax (desc, loc);
+ 
+ 	/* Queue them.  */
+ 	insn_elem = queue_pattern (desc, &define_insn_tail, loc);
+diff --git a/gcc/gensupport.h b/gcc/gensupport.h
+index 9a0fd7393..a19fc1319 100644
+--- a/gcc/gensupport.h
++++ b/gcc/gensupport.h
+@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
+ #ifndef GCC_GENSUPPORT_H
+ #define GCC_GENSUPPORT_H
+ 
++#include "hash-set.h"
+ #include "read-md.h"
+ 
+ struct obstack;
+@@ -218,6 +219,8 @@ struct pattern_stats
+   int num_operand_vars;
+ };
+ 
++extern hash_set compact_syntax;
++
+ extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec);
+ extern void compute_test_codes (rtx, file_location, char *);
+ extern file_location get_file_location (rtx);
+-- 
+2.33.0
+
diff --git a/0153-Backport-SME-recog-Improve-parser-for-pattern-new-co.patch b/0153-Backport-SME-recog-Improve-parser-for-pattern-new-co.patch
new file mode 100644
index 0000000..1302ea1
--- /dev/null
+++ b/0153-Backport-SME-recog-Improve-parser-for-pattern-new-co.patch
@@ -0,0 +1,104 @@
+From 35b64175c6fd622212d0bf936e7e98c635e1c618 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Wed, 13 Sep 2023 14:50:30 +0100
+Subject: [PATCH 054/157] [Backport][SME] recog: Improve parser for pattern new
+ compact syntax
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=dd1091fe455c1ede5993b4cdf10d0f7c461b86d7
+
+Hi all,
+
+this is to add support to the new compact pattern syntax for the case
+where the constraints do appear unsorted like:
+
+(define_insn "*si3_insn_uxtw"
+  [(set (match_operand:DI 0 "register_operand")
+        (zero_extend:DI (SHIFT_no_rotate:SI
+         (match_operand:SI 1 "register_operand")
+         (match_operand:QI 2 "aarch64_reg_or_shift_imm_si"))))]
+  ""
+  {@ [cons: =0, 2,   1]
+     [      r,  Uss, r] \\t%w0, %w1, %2
+     [      r,  r,   r] \\t%w0, %w1, %w2
+  }
+  [(set_attr "type" "bfx,shift_reg")]
+)
+
+Best Regards
+
+  Andrea
+
+gcc/Changelog
+
+2023-09-20  Richard Sandiford  
+
+	* gensupport.cc (convert_syntax): Updated to support unordered
+	constraints in compact syntax.
+---
+ gcc/gensupport.cc | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc
+index 23c61dcdd..97c614850 100644
+--- a/gcc/gensupport.cc
++++ b/gcc/gensupport.cc
+@@ -895,19 +895,6 @@ convert_syntax (rtx x, file_location loc)
+ 
+   parse_section_layout (loc, &templ, "cons:", tconvec, true);
+ 
+-  /* Check for any duplicate cons entries and sort based on i.  */
+-  for (auto e : tconvec)
+-    {
+-      unsigned idx = e.idx;
+-      if (idx >= convec.size ())
+-	convec.resize (idx + 1);
+-
+-      if (convec[idx].idx >= 0)
+-	fatal_at (loc, "duplicate cons number found: %d", idx);
+-      convec[idx] = e;
+-    }
+-  tconvec.clear ();
+-
+   if (*templ != ']')
+     {
+       if (*templ == ';')
+@@ -950,13 +937,13 @@ convert_syntax (rtx x, file_location loc)
+ 	  new_templ += '\n';
+ 	  new_templ.append (buffer);
+ 	  /* Parse the constraint list, then the attribute list.  */
+-	  if (convec.size () > 0)
+-	    parse_section (&templ, convec.size (), alt_no, convec, loc,
++	  if (tconvec.size () > 0)
++	    parse_section (&templ, tconvec.size (), alt_no, tconvec, loc,
+ 			   "constraint");
+ 
+ 	  if (attrvec.size () > 0)
+ 	    {
+-	      if (convec.size () > 0 && !expect_char (&templ, ';'))
++	      if (tconvec.size () > 0 && !expect_char (&templ, ';'))
+ 		fatal_at (loc, "expected `;' to separate constraints "
+ 			       "and attributes in alternative %d", alt_no);
+ 
+@@ -1026,6 +1013,19 @@ convert_syntax (rtx x, file_location loc)
+       ++alt_no;
+     }
+ 
++  /* Check for any duplicate cons entries and sort based on i.  */
++  for (auto e : tconvec)
++    {
++      unsigned idx = e.idx;
++      if (idx >= convec.size ())
++	convec.resize (idx + 1);
++
++      if (convec[idx].idx >= 0)
++	fatal_at (loc, "duplicate cons number found: %d", idx);
++      convec[idx] = e;
++    }
++  tconvec.clear ();
++
+   /* Write the constraints and attributes into their proper places.  */
+   if (convec.size () > 0)
+     add_constraints (x, loc, convec);
+-- 
+2.33.0
+
diff --git a/0154-Backport-SME-recog-Support-space-in-cons.patch b/0154-Backport-SME-recog-Support-space-in-cons.patch
new file mode 100644
index 0000000..f11eb41
--- /dev/null
+++ b/0154-Backport-SME-recog-Support-space-in-cons.patch
@@ -0,0 +1,49 @@
+From e593ad216bd1f4f75d9875898f352e0e5f978159 Mon Sep 17 00:00:00 2001
+From: Andrea Corallo 
+Date: Fri, 15 Sep 2023 10:23:02 +0200
+Subject: [PATCH 055/157] [Backport][SME] recog: Support space in "[ cons"
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=9d31045b21324166c3997d603961d99e3c4c357d
+
+Hi all,
+
+this is to allow for spaces before "cons:" in the definitions of
+patterns using the new compact syntax, ex:
+
+(define_insn "aarch64_simd_dup"
+  [(set (match_operand:VDQ_I 0 "register_operand")
+        (vec_duplicate:VDQ_I
+          (match_operand: 1 "register_operand")))]
+  "TARGET_SIMD"
+  {@ [ cons: =0 , 1  ; attrs: type      ]
+     [ w        , w  ; neon_dup      ] dup\t%0., %1.[0]
+     [ w        , ?r ; neon_from_gp  ] dup\t%0., %1
+  }
+)
+
+gcc/Changelog
+
+2023-09-20  Andrea Corallo  
+
+	* gensupport.cc (convert_syntax): Skip spaces before "cons:"
+	in new compact pattern syntax.
+---
+ gcc/gensupport.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc
+index 97c614850..3d7a6d4fd 100644
+--- a/gcc/gensupport.cc
++++ b/gcc/gensupport.cc
+@@ -893,6 +893,8 @@ convert_syntax (rtx x, file_location loc)
+   if (!expect_char (&templ, '['))
+     fatal_at (loc, "expecing `[' to begin section list");
+ 
++  skip_spaces (&templ);
++
+   parse_section_layout (loc, &templ, "cons:", tconvec, true);
+ 
+   if (*templ != ']')
+-- 
+2.33.0
+
diff --git a/0155-Backport-SME-aarch64-Generalise-require_immediate_la.patch b/0155-Backport-SME-aarch64-Generalise-require_immediate_la.patch
new file mode 100644
index 0000000..3a47094
--- /dev/null
+++ b/0155-Backport-SME-aarch64-Generalise-require_immediate_la.patch
@@ -0,0 +1,164 @@
+From cb6d55f6bc7c490f72a43dd87543ab7a7ea582a8 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:18 +0000
+Subject: [PATCH 056/157] [Backport][SME] aarch64: Generalise
+ require_immediate_lane_index
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c0cf2c893d54420b0c19fee7bd41ae40017d0106
+
+require_immediate_lane_index previously hard-coded the assumption
+that the group size is determined by the argument immediately before
+the index.  However, for SME, there are cases where it should be
+determined by an earlier argument instead.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h:
+	(function_checker::require_immediate_lane_index): Add an argument
+	for the index of the indexed vector argument.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(function_checker::require_immediate_lane_index): Likewise.
+	* config/aarch64/aarch64-sve-builtins-shapes.cc
+	(ternary_bfloat_lane_base::check): Update accordingly.
+	(ternary_qq_lane_base::check): Likewise.
+	(binary_lane_def::check): Likewise.
+	(binary_long_lane_def::check): Likewise.
+	(ternary_lane_def::check): Likewise.
+	(ternary_lane_rotate_def::check): Likewise.
+	(ternary_long_lane_def::check): Likewise.
+	(ternary_qq_lane_rotate_def::check): Likewise.
+---
+ .../aarch64/aarch64-sve-builtins-shapes.cc     | 16 ++++++++--------
+ gcc/config/aarch64/aarch64-sve-builtins.cc     | 18 ++++++++++++------
+ gcc/config/aarch64/aarch64-sve-builtins.h      |  3 ++-
+ 3 files changed, 22 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index f57f92698..4fa4181b9 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -941,7 +941,7 @@ struct ternary_bfloat_lane_base
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return c.require_immediate_lane_index (3, N);
++    return c.require_immediate_lane_index (3, 2, N);
+   }
+ };
+ 
+@@ -956,7 +956,7 @@ struct ternary_qq_lane_base
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return c.require_immediate_lane_index (3, 4);
++    return c.require_immediate_lane_index (3, 0);
+   }
+ };
+ 
+@@ -1123,7 +1123,7 @@ struct binary_lane_def : public overloaded_base<0>
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return c.require_immediate_lane_index (2);
++    return c.require_immediate_lane_index (2, 1);
+   }
+ };
+ SHAPE (binary_lane)
+@@ -1162,7 +1162,7 @@ struct binary_long_lane_def : public overloaded_base<0>
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return c.require_immediate_lane_index (2);
++    return c.require_immediate_lane_index (2, 1);
+   }
+ };
+ SHAPE (binary_long_lane)
+@@ -2817,7 +2817,7 @@ struct ternary_lane_def : public overloaded_base<0>
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return c.require_immediate_lane_index (3);
++    return c.require_immediate_lane_index (3, 2);
+   }
+ };
+ SHAPE (ternary_lane)
+@@ -2845,7 +2845,7 @@ struct ternary_lane_rotate_def : public overloaded_base<0>
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return (c.require_immediate_lane_index (3, 2)
++    return (c.require_immediate_lane_index (3, 2, 2)
+ 	    && c.require_immediate_one_of (4, 0, 90, 180, 270));
+   }
+ };
+@@ -2868,7 +2868,7 @@ struct ternary_long_lane_def
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return c.require_immediate_lane_index (3);
++    return c.require_immediate_lane_index (3, 2);
+   }
+ };
+ SHAPE (ternary_long_lane)
+@@ -2965,7 +2965,7 @@ struct ternary_qq_lane_rotate_def : public overloaded_base<0>
+   bool
+   check (function_checker &c) const OVERRIDE
+   {
+-    return (c.require_immediate_lane_index (3, 4)
++    return (c.require_immediate_lane_index (3, 0)
+ 	    && c.require_immediate_one_of (4, 0, 90, 180, 270));
+   }
+ };
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 91af96687..7924cdf0f 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -2440,20 +2440,26 @@ function_checker::require_immediate_enum (unsigned int rel_argno, tree type)
+   return false;
+ }
+ 
+-/* Check that argument REL_ARGNO is suitable for indexing argument
+-   REL_ARGNO - 1, in groups of GROUP_SIZE elements.  REL_ARGNO counts
+-   from the end of the predication arguments.  */
++/* The intrinsic conceptually divides vector argument REL_VEC_ARGNO into
++   groups of GROUP_SIZE elements.  Return true if argument REL_ARGNO is
++   a suitable constant index for selecting one of these groups.  The
++   selection happens within a 128-bit quadword, rather than the whole vector.
++
++   REL_ARGNO and REL_VEC_ARGNO count from the end of the predication
++   arguments.  */
+ bool
+ function_checker::require_immediate_lane_index (unsigned int rel_argno,
++						unsigned int rel_vec_argno,
+ 						unsigned int group_size)
+ {
+   unsigned int argno = m_base_arg + rel_argno;
+   if (!argument_exists_p (argno))
+     return true;
+ 
+-  /* Get the type of the previous argument.  tree_argument_type wants a
+-     1-based number, whereas ARGNO is 0-based.  */
+-  machine_mode mode = TYPE_MODE (type_argument_type (m_fntype, argno));
++  /* Get the type of the vector argument.  tree_argument_type wants a
++     1-based number, whereas VEC_ARGNO is 0-based.  */
++  unsigned int vec_argno = m_base_arg + rel_vec_argno;
++  machine_mode mode = TYPE_MODE (type_argument_type (m_fntype, vec_argno + 1));
+   gcc_assert (VECTOR_MODE_P (mode));
+   unsigned int nlanes = 128 / (group_size * GET_MODE_UNIT_BITSIZE (mode));
+   return require_immediate_range (rel_argno, 0, nlanes - 1);
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 52994cde0..824c31cd7 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -463,7 +463,8 @@ public:
+   bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
+ 				    HOST_WIDE_INT);
+   bool require_immediate_enum (unsigned int, tree);
+-  bool require_immediate_lane_index (unsigned int, unsigned int = 1);
++  bool require_immediate_lane_index (unsigned int, unsigned int,
++				     unsigned int = 1);
+   bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
+ 				 HOST_WIDE_INT, HOST_WIDE_INT);
+   bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
+-- 
+2.33.0
+
diff --git a/0156-Backport-SME-aarch64-Add-backend-support-for-DFP.patch b/0156-Backport-SME-aarch64-Add-backend-support-for-DFP.patch
new file mode 100644
index 0000000..607c83c
--- /dev/null
+++ b/0156-Backport-SME-aarch64-Add-backend-support-for-DFP.patch
@@ -0,0 +1,469 @@
+From 8394394bd26c7be6129b9a4e673d2a3530d9efde Mon Sep 17 00:00:00 2001
+From: Christophe Lyon 
+Date: Fri, 11 Mar 2022 16:21:02 +0000
+Subject: [PATCH 057/157] [Backport][SME] aarch64: Add backend support for DFP
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0dc8e1e7026d9b8ec8b669c051786d426a52cd22
+
+This patch updates the aarch64 backend as needed to support DFP modes
+(SD, DD and TD).
+
+Changes	v1->v2:
+
+* Drop	support	for DFP	modes in
+  aarch64_gen_{load||store}[wb]_pair as these are only used in
+  prologue/epilogue where DFP modes are not used.  Drop	the
+  changes to the corresponding patterns in aarch64.md, and
+  useless GPF_PAIR iterator.
+
+* In aarch64_reinterpret_float_as_int, handle DDmode the same way
+  as DFmode (needed in case the representation of the
+  floating-point value can be loaded using mov/movk.
+
+* In aarch64_float_const_zero_rtx_p, reject constants with DFP
+  mode: when X is zero, the callers want to emit either '0' or
+  'zr' depending on the context, which is not the way 0.0 is
+  represented in DFP mode (in particular fmov d0, #0 is not right
+  for DFP).
+
+* In aarch64_legitimate_constant_p, accept DFP
+
+2022-03-31  Christophe Lyon  
+
+	gcc/
+	* config/aarch64/aarch64.cc
+	(aarch64_split_128bit_move): Handle DFP modes.
+	(aarch64_mode_valid_for_sched_fusion_p): Likewise.
+	(aarch64_classify_address): Likewise.
+	(aarch64_legitimize_address_displacement): Likewise.
+	(aarch64_reinterpret_float_as_int): Likewise.
+	(aarch64_float_const_zero_rtx_p): Likewise.
+	(aarch64_can_const_movi_rtx_p): Likewise.
+	(aarch64_anchor_offset): Likewise.
+	(aarch64_secondary_reload): Likewise.
+	(aarch64_rtx_costs): Likewise.
+	(aarch64_legitimate_constant_p): Likewise.
+	(aarch64_gimplify_va_arg_expr): Likewise.
+	(aapcs_vfp_sub_candidate): Likewise.
+	(aarch64_vfp_is_call_or_return_candidate): Likewise.
+	(aarch64_output_scalar_simd_mov_immediate): Likewise.
+	(aarch64_gen_adjusted_ldpstp): Likewise.
+	(aarch64_scalar_mode_supported_p): Accept DFP modes if enabled.
+	* config/aarch64/aarch64.md
+	(movsf_aarch64): Use SFD iterator and rename into
+	mov_aarch64.
+	(movdf_aarch64): Use DFD iterator and rename into
+	mov_aarch64.
+	(movtf_aarch64): Use TFD iterator and rename into
+	mov_aarch64.
+	(split pattern for move TF mode): Use TFD iterator.
+	* config/aarch64/iterators.md
+	(GPF_TF_F16_MOV): Add DFP modes.
+	(SFD, DFD, TFD): New iterators.
+	(GPF_TF): Add DFP modes.
+	(TX, DX, DX2): Likewise.
+---
+ gcc/config/aarch64/aarch64.cc   | 82 ++++++++++++++++++++++-----------
+ gcc/config/aarch64/aarch64.md   | 34 +++++++-------
+ gcc/config/aarch64/iterators.md | 24 +++++++---
+ 3 files changed, 89 insertions(+), 51 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 055b436b1..02210ed13 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -5068,7 +5068,7 @@ aarch64_split_128bit_move (rtx dst, rtx src)
+ 
+   machine_mode mode = GET_MODE (dst);
+ 
+-  gcc_assert (mode == TImode || mode == TFmode);
++  gcc_assert (mode == TImode || mode == TFmode || mode == TDmode);
+   gcc_assert (!(side_effects_p (src) || side_effects_p (dst)));
+   gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode);
+ 
+@@ -10834,6 +10834,7 @@ aarch64_mode_valid_for_sched_fusion_p (machine_mode mode)
+ {
+   return mode == SImode || mode == DImode
+ 	 || mode == SFmode || mode == DFmode
++	 || mode == SDmode || mode == DDmode
+ 	 || (aarch64_vector_mode_supported_p (mode)
+ 	     && (known_eq (GET_MODE_SIZE (mode), 8)
+ 		 || (known_eq (GET_MODE_SIZE (mode), 16)
+@@ -10876,12 +10877,13 @@ aarch64_classify_address (struct aarch64_address_info *info,
+   vec_flags &= ~VEC_PARTIAL;
+ 
+   /* On BE, we use load/store pair for all large int mode load/stores.
+-     TI/TFmode may also use a load/store pair.  */
++     TI/TF/TDmode may also use a load/store pair.  */
+   bool advsimd_struct_p = (vec_flags == (VEC_ADVSIMD | VEC_STRUCT));
+   bool load_store_pair_p = (type == ADDR_QUERY_LDP_STP
+ 			    || type == ADDR_QUERY_LDP_STP_N
+ 			    || mode == TImode
+ 			    || mode == TFmode
++			    || mode == TDmode
+ 			    || (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
+@@ -10955,7 +10957,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	  info->offset = op1;
+ 	  info->const_offset = offset;
+ 
+-	  /* TImode and TFmode values are allowed in both pairs of X
++	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
+ 	     registers and individual Q registers.  The available
+ 	     address modes are:
+ 	     X,X: 7-bit signed scaled offset
+@@ -10964,7 +10966,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	     When performing the check for pairs of X registers i.e.  LDP/STP
+ 	     pass down DImode since that is the natural size of the LDP/STP
+ 	     instruction memory accesses.  */
+-	  if (mode == TImode || mode == TFmode)
++	  if (mode == TImode || mode == TFmode || mode == TDmode)
+ 	    return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
+ 		    && (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
+ 			|| offset_12bit_unsigned_scaled_p (mode, offset)));
+@@ -11087,14 +11089,14 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	  info->offset = XEXP (XEXP (x, 1), 1);
+ 	  info->const_offset = offset;
+ 
+-	  /* TImode and TFmode values are allowed in both pairs of X
++	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
+ 	     registers and individual Q registers.  The available
+ 	     address modes are:
+ 	     X,X: 7-bit signed scaled offset
+ 	     Q:   9-bit signed offset
+ 	     We conservatively require an offset representable in either mode.
+ 	   */
+-	  if (mode == TImode || mode == TFmode)
++	  if (mode == TImode || mode == TFmode || mode == TDmode)
+ 	    return (aarch64_offset_7bit_signed_scaled_p (mode, offset)
+ 		    && aarch64_offset_9bit_signed_unscaled_p (mode, offset));
+ 
+@@ -11256,9 +11258,9 @@ aarch64_legitimize_address_displacement (rtx *offset1, rtx *offset2,
+ 	 offset.  Use 4KB range for 1- and 2-byte accesses and a 16KB
+ 	 range otherwise to increase opportunities for sharing the base
+ 	 address of different sizes.  Unaligned accesses use the signed
+-	 9-bit range, TImode/TFmode use the intersection of signed
++	 9-bit range, TImode/TFmode/TDmode use the intersection of signed
+ 	 scaled 7-bit and signed 9-bit offset.  */
+-      if (mode == TImode || mode == TFmode)
++      if (mode == TImode || mode == TFmode || mode == TDmode)
+ 	second_offset = ((const_offset + 0x100) & 0x1f8) - 0x100;
+       else if ((const_offset & (size - 1)) != 0)
+ 	second_offset = ((const_offset + 0x100) & 0x1ff) - 0x100;
+@@ -11339,7 +11341,7 @@ aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval)
+ 		  CONST_DOUBLE_REAL_VALUE (value),
+ 		  REAL_MODE_FORMAT (mode));
+ 
+-  if (mode == DFmode)
++  if (mode == DFmode || mode == DDmode)
+     {
+       int order = BYTES_BIG_ENDIAN ? 1 : 0;
+       ival = zext_hwi (res[order], 32);
+@@ -11380,11 +11382,15 @@ aarch64_float_const_rtx_p (rtx x)
+   return false;
+ }
+ 
+-/* Return TRUE if rtx X is immediate constant 0.0 */
++/* Return TRUE if rtx X is immediate constant 0.0 (but not in Decimal
++   Floating Point).  */
+ bool
+ aarch64_float_const_zero_rtx_p (rtx x)
+ {
+-  if (GET_MODE (x) == VOIDmode)
++  /* 0.0 in Decimal Floating Point cannot be represented by #0 or
++     zr as our callers expect, so no need to check the actual
++     value if X is of Decimal Floating Point type.  */
++  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_DECIMAL_FLOAT)
+     return false;
+ 
+   if (REAL_VALUE_MINUS_ZERO (*CONST_DOUBLE_REAL_VALUE (x)))
+@@ -11422,7 +11428,7 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
+   else
+     return false;
+ 
+-   /* use a 64 bit mode for everything except for DI/DF mode, where we use
++   /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
+      a 128 bit vector mode.  */
+   int width = GET_MODE_BITSIZE (imode) == 64 ? 128 : 64;
+ 
+@@ -12628,7 +12634,7 @@ aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size,
+   if (IN_RANGE (offset, -256, 0))
+     return 0;
+ 
+-  if (mode == TImode || mode == TFmode)
++  if (mode == TImode || mode == TFmode || mode == TDmode)
+     return (offset + 0x100) & ~0x1ff;
+ 
+   /* Use 12-bit offset by access size.  */
+@@ -12737,7 +12743,9 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+ 
+   /* Without the TARGET_SIMD instructions we cannot move a Q register
+      to a Q register directly.  We need a scratch.  */
+-  if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
++  if (REG_P (x)
++      && (mode == TFmode || mode == TImode || mode == TDmode)
++      && mode == GET_MODE (x)
+       && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
+       && reg_class_subset_p (rclass, FP_REGS))
+     {
+@@ -12745,14 +12753,16 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+       return NO_REGS;
+     }
+ 
+-  /* A TFmode or TImode memory access should be handled via an FP_REGS
++  /* A TFmode, TImode or TDmode memory access should be handled via an FP_REGS
+      because AArch64 has richer addressing modes for LDR/STR instructions
+      than LDP/STP instructions.  */
+   if (TARGET_FLOAT && rclass == GENERAL_REGS
+       && known_eq (GET_MODE_SIZE (mode), 16) && MEM_P (x))
+     return FP_REGS;
+ 
+-  if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x))
++  if (rclass == FP_REGS
++      && (mode == TImode || mode == TFmode || mode == TDmode)
++      && CONSTANT_P(x))
+       return GENERAL_REGS;
+ 
+   return NO_REGS;
+@@ -13883,9 +13893,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
+ 		*cost += extra_cost->ldst.storev;
+ 	      else if (GET_MODE_CLASS (mode) == MODE_INT)
+ 		*cost += extra_cost->ldst.store;
+-	      else if (mode == SFmode)
++	      else if (mode == SFmode || mode == SDmode)
+ 		*cost += extra_cost->ldst.storef;
+-	      else if (mode == DFmode)
++	      else if (mode == DFmode || mode == DDmode)
+ 		*cost += extra_cost->ldst.stored;
+ 
+ 	      *cost +=
+@@ -14009,11 +14019,11 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
+ 	  /* mov[df,sf]_aarch64.  */
+ 	  if (aarch64_float_const_representable_p (x))
+ 	    /* FMOV (scalar immediate).  */
+-	    *cost += extra_cost->fp[mode == DFmode].fpconst;
++	    *cost += extra_cost->fp[mode == DFmode || mode == DDmode].fpconst;
+ 	  else if (!aarch64_float_const_zero_rtx_p (x))
+ 	    {
+ 	      /* This will be a load from memory.  */
+-	      if (mode == DFmode)
++	      if (mode == DFmode || mode == DDmode)
+ 		*cost += extra_cost->ldst.loadd;
+ 	      else
+ 		*cost += extra_cost->ldst.loadf;
+@@ -14039,9 +14049,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
+ 	    *cost += extra_cost->ldst.loadv;
+ 	  else if (GET_MODE_CLASS (mode) == MODE_INT)
+ 	    *cost += extra_cost->ldst.load;
+-	  else if (mode == SFmode)
++	  else if (mode == SFmode || mode == SDmode)
+ 	    *cost += extra_cost->ldst.loadf;
+-	  else if (mode == DFmode)
++	  else if (mode == DFmode || mode == DDmode)
+ 	    *cost += extra_cost->ldst.loadd;
+ 
+ 	  *cost +=
+@@ -19623,7 +19633,7 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
+ {
+   /* Support CSE and rematerialization of common constants.  */
+   if (CONST_INT_P (x)
+-      || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
++      || CONST_DOUBLE_P (x))
+     return true;
+ 
+   /* Only accept variable-length vector constants if they can be
+@@ -20064,6 +20074,18 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
+ 	  field_t = long_double_type_node;
+ 	  field_ptr_t = long_double_ptr_type_node;
+ 	  break;
++	case SDmode:
++	  field_t = dfloat32_type_node;
++	  field_ptr_t = build_pointer_type (dfloat32_type_node);
++	  break;
++	case DDmode:
++	  field_t = dfloat64_type_node;
++	  field_ptr_t = build_pointer_type (dfloat64_type_node);
++	  break;
++	case TDmode:
++	  field_t = dfloat128_type_node;
++	  field_ptr_t = build_pointer_type (dfloat128_type_node);
++	  break;
+ 	case E_HFmode:
+ 	  field_t = aarch64_fp16_type_node;
+ 	  field_ptr_t = aarch64_fp16_ptr_type_node;
+@@ -20315,7 +20337,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
+     case REAL_TYPE:
+       mode = TYPE_MODE (type);
+       if (mode != DFmode && mode != SFmode
+-	  && mode != TFmode && mode != HFmode)
++	  && mode != TFmode && mode != HFmode
++	  && mode != SDmode && mode != DDmode && mode != TDmode)
+ 	return -1;
+ 
+       if (*modep == VOIDmode)
+@@ -20631,7 +20654,9 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
+   machine_mode new_mode = VOIDmode;
+   bool composite_p = aarch64_composite_type_p (type, mode);
+ 
+-  if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT)
++  if ((!composite_p
++       && (GET_MODE_CLASS (mode) == MODE_FLOAT
++	   || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT))
+       || aarch64_short_vector_p (type, mode))
+     {
+       *count = 1;
+@@ -23565,7 +23590,7 @@ aarch64_output_scalar_simd_mov_immediate (rtx immediate, scalar_int_mode mode)
+     }
+ 
+   machine_mode vmode;
+-  /* use a 64 bit mode for everything except for DI/DF mode, where we use
++  /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
+      a 128 bit vector mode.  */
+   int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;
+ 
+@@ -26417,7 +26442,7 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
+     base_off = (off_val_1 + off_val_3) / 2;
+   else
+     /* However, due to issues with negative LDP/STP offset generation for
+-       larger modes, for DF, DI and vector modes. we must not use negative
++       larger modes, for DF, DD, DI and vector modes. we must not use negative
+        addresses smaller than 9 signed unadjusted bits can store.  This
+        provides the most range in this case.  */
+     base_off = off_val_1;
+@@ -26695,6 +26720,9 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
+ static bool
+ aarch64_scalar_mode_supported_p (scalar_mode mode)
+ {
++  if (DECIMAL_FLOAT_MODE_P (mode))
++    return default_decimal_float_supported_p ();
++
+   return (mode == HFmode
+ 	  ? true
+ 	  : default_scalar_mode_supported_p (mode));
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index a78476c8a..8757a962f 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1476,11 +1476,11 @@
+    (set_attr "arch" "simd,fp16,simd,*,simd,*,simd,*,fp16,simd,*,*,*,*,*")]
+ )
+ 
+-(define_insn "*movsf_aarch64"
+-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+-	(match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
+-  "TARGET_FLOAT && (register_operand (operands[0], SFmode)
+-    || aarch64_reg_or_fp_zero (operands[1], SFmode))"
++(define_insn "*mov_aarch64"
++  [(set (match_operand:SFD 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
++	(match_operand:SFD 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
++  "TARGET_FLOAT && (register_operand (operands[0], mode)
++    || aarch64_reg_or_fp_zero (operands[1], mode))"
+   "@
+    movi\\t%0.2s, #0
+    fmov\\t%s0, %w1
+@@ -1500,11 +1500,11 @@
+    (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
+ )
+ 
+-(define_insn "*movdf_aarch64"
+-  [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+-	(match_operand:DF 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
+-  "TARGET_FLOAT && (register_operand (operands[0], DFmode)
+-    || aarch64_reg_or_fp_zero (operands[1], DFmode))"
++(define_insn "*mov_aarch64"
++  [(set (match_operand:DFD 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
++	(match_operand:DFD 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
++  "TARGET_FLOAT && (register_operand (operands[0], mode)
++    || aarch64_reg_or_fp_zero (operands[1], mode))"
+   "@
+    movi\\t%d0, #0
+    fmov\\t%d0, %x1
+@@ -1545,13 +1545,13 @@
+   }
+ )
+ 
+-(define_insn "*movtf_aarch64"
+-  [(set (match_operand:TF 0
++(define_insn "*mov_aarch64"
++  [(set (match_operand:TFD 0
+ 	 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
+-	(match_operand:TF 1
++	(match_operand:TFD 1
+ 	 "general_operand"      " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
+-  "TARGET_FLOAT && (register_operand (operands[0], TFmode)
+-    || aarch64_reg_or_fp_zero (operands[1], TFmode))"
++  "TARGET_FLOAT && (register_operand (operands[0], mode)
++    || aarch64_reg_or_fp_zero (operands[1], mode))"
+   "@
+    mov\\t%0.16b, %1.16b
+    #
+@@ -1571,8 +1571,8 @@
+ )
+ 
+ (define_split
+-   [(set (match_operand:TF 0 "register_operand" "")
+-	 (match_operand:TF 1 "nonmemory_operand" ""))]
++   [(set (match_operand:TFD 0 "register_operand" "")
++	 (match_operand:TFD 1 "nonmemory_operand" ""))]
+   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
+   [(const_int 0)]
+   {
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index 967e6b0b1..d0cd1b788 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -67,14 +67,24 @@
+ (define_mode_iterator GPF_TF_F16 [HF SF DF TF])
+ 
+ ;; Iterator for all scalar floating point modes suitable for moving, including
+-;; special BF type (HF, SF, DF, TF and BF)
+-(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF])
++;; special BF type and decimal floating point types (HF, SF, DF, TF, BF,
++;; SD, DD and TD)
++(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF SD DD TD])
++
++;; Iterator for scalar 32bit fp modes (SF, SD)
++(define_mode_iterator SFD [SD SF])
++
++;; Iterator for scalar 64bit fp modes (DF, DD)
++(define_mode_iterator DFD [DD DF])
++
++;; Iterator for scalar 128bit fp modes (TF, TD)
++(define_mode_iterator TFD [TD TF])
+ 
+ ;; Double vector modes.
+ (define_mode_iterator VDF [V2SF V4HF])
+ 
+-;; Iterator for all scalar floating point modes (SF, DF and TF)
+-(define_mode_iterator GPF_TF [SF DF TF])
++;; Iterator for all scalar floating point modes (SF, DF, TF, SD, DD, and TD)
++(define_mode_iterator GPF_TF [SF DF TF SD DD TD])
+ 
+ ;; Integer Advanced SIMD modes.
+ (define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
+@@ -301,7 +311,7 @@
+ ;; 2 and 4 lane SI modes.
+ (define_mode_iterator VS [V2SI V4SI])
+ 
+-(define_mode_iterator TX [TI TF])
++(define_mode_iterator TX [TI TF TD])
+ 
+ ;; Advanced SIMD opaque structure modes.
+ (define_mode_iterator VSTRUCT [OI CI XI])
+@@ -403,10 +413,10 @@
+ 				  V4x8HF V4x4SF V4x2DF V4x8BF])
+ 
+ ;; Double scalar modes
+-(define_mode_iterator DX [DI DF])
++(define_mode_iterator DX [DI DF DD])
+ 
+ ;; Duplicate of the above
+-(define_mode_iterator DX2 [DI DF])
++(define_mode_iterator DX2 [DI DF DD])
+ 
+ ;; Single scalar modes
+ (define_mode_iterator SX [SI SF])
+-- 
+2.33.0
+
diff --git a/0157-Backport-SME-aarch64-Vector-move-fixes-for-nosimd.patch b/0157-Backport-SME-aarch64-Vector-move-fixes-for-nosimd.patch
new file mode 100644
index 0000000..b2257ea
--- /dev/null
+++ b/0157-Backport-SME-aarch64-Vector-move-fixes-for-nosimd.patch
@@ -0,0 +1,1824 @@
+From 737d2a5f1c5e725b7e5a20075270016ebf56b44c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 13 Sep 2022 09:28:49 +0100
+Subject: [PATCH 058/157] [Backport][SME] aarch64: Vector move fixes for
+ +nosimd
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=721c0fb3aca31d3bf8ad6e929eab32e29a427e60
+
+This patch fixes various issues around the handling of vectors
+and (particularly) vector structures with +nosimd.  Previously,
+passing and returning structures would trigger an ICE, since:
+
+* we didn't allow the structure modes to be stored in FPRs
+
+* we didn't provide +nosimd move patterns
+
+* splitting the moves into word-sized pieces (the default
+  strategy without move patterns) doesn't work because the
+  registers are doubleword sized.
+
+The patch is a bit of a hodge-podge since a lot of the handling of
+moves, register costs, and register legitimacy is so interconnected.
+It didn't seem feasible to split things further.
+
+Some notes:
+
+* The patch recognises vector and tuple modes based on TARGET_FLOAT
+  rather than TARGET_SIMD, and instead adds TARGET_SIMD to places
+  that really do need the vector ISA.  This is necessary for the
+  modes to be handled correctly in register arguments and returns.
+
+* The 64-bit (DREG) STP peephole required TARGET_SIMD but the
+  LDP peephole didn't.  I think the LDP one is right, since
+  DREG moves could involve GPRs as well as FPRs.
+
+* The patch keeps the existing choices of instructions for
+  TARGET_SIMD, just in case they happen to be better than FMOV
+  on some uarches.
+
+* Before the patch, +nosimd Q<->Q moves of 128-bit scalars went via
+  a GPR, thanks to a secondary reload pattern.  This approach might
+  not be ideal, but there's no reason that 128-bit vectors should
+  behave differently from 128-bit scalars.  The patch therefore
+  extends the current scalar approach to vectors.
+
+* Multi-vector LD1 and ST1 require TARGET_SIMD, so the TARGET_FLOAT
+  structure moves need to use LDP/STP and LDR/STR combinations
+  instead.  That's also what we do for big-endian even with
+  TARGET_SIMD, so most of the code was already there.  The patterns
+  for structures of 64-bit vectors are identical, but the patterns
+  for structures of 128-bit vectors need to cope with the lack of
+  128-bit Q<->Q moves.
+
+  It isn't feasible to move multi-vector tuples via GPRs, so the
+  patch moves them via memory instead.  This contaminates the port
+  with its first secondary memory reload.
+
+gcc/
+
+	* config/aarch64/aarch64.cc (aarch64_classify_vector_mode): Use
+	TARGET_FLOAT instead of TARGET_SIMD.
+	(aarch64_vectorize_related_mode): Restrict ADVSIMD handling to
+	TARGET_SIMD.
+	(aarch64_hard_regno_mode_ok): Don't allow tuples of 2 64-bit vectors
+	in GPRs.
+	(aarch64_classify_address): Treat little-endian structure moves
+	like big-endian for TARGET_FLOAT && !TARGET_SIMD.
+	(aarch64_secondary_memory_needed): New function.
+	(aarch64_secondary_reload): Handle 128-bit Advanced SIMD vectors
+	in the same way as TF, TI and TD.
+	(aarch64_rtx_mult_cost): Restrict ADVSIMD handling to TARGET_SIMD.
+	(aarch64_rtx_costs): Likewise.
+	(aarch64_register_move_cost): Treat a pair of 64-bit vectors
+	separately from a single 128-bit vector.  Handle the cost implied
+	by aarch64_secondary_memory_needed.
+	(aarch64_simd_valid_immediate): Restrict ADVSIMD handling to
+	TARGET_SIMD.
+	(aarch64_expand_vec_perm_const_1): Likewise.
+	(TARGET_SECONDARY_MEMORY_NEEDED): New macro.
+	* config/aarch64/iterators.md (VTX): New iterator.
+	* config/aarch64/aarch64.md (arches): Add fp_q as a synonym of simd.
+	(arch_enabled): Adjust accordingly.
+	(@aarch64_reload_mov): Extend to...
+	(@aarch64_reload_mov): ...this.
+	* config/aarch64/aarch64-simd.md (mov): Require TARGET_FLOAT
+	rather than TARGET_SIMD.
+	(movmisalign): Likewise.
+	(load_pair): Likewise.
+	(vec_store_pair): Likewise.
+	(load_pair): Likewise.
+	(vec_store_pair): Likewise.
+	(@aarch64_split_simd_mov): Likewise.
+	(aarch64_get_low): Likewise.
+	(aarch64_get_high): Likewise.
+	(aarch64_get_half): Likewise.  Canonicalize to a move for
+	lowpart extracts.
+	(*aarch64_simd_mov): Require TARGET_FLOAT rather than
+	TARGET_SIMD.  Use different w<-w and r<-w instructions for
+	!TARGET_SIMD.  Disable immediate moves for !TARGET_SIMD but
+	add an alternative specifically for w<-Z.
+	(*aarch64_simd_mov): Require TARGET_FLOAT rather than
+	TARGET_SIMD.  Likewise for the associated define_splits.  Disable
+	FPR moves and immediate moves for !TARGET_SIMD but add an alternative
+	specifically for w<-Z.
+	(aarch64_simd_mov_from_high): Require TARGET_FLOAT rather than
+	TARGET_SIMD.  Restrict the existing alternatives to TARGET_SIMD
+	but add a new r<-w one for !TARGET_SIMD.
+	(*aarch64_get_high): New pattern.
+	(load_pair_lanes): Require TARGET_FLOAT rather than TARGET_SIMD.
+	(store_pair_lanes): Likewise.
+	(*aarch64_combine_internal): Likewise.  Restrict existing
+	w<-w, w<-r and w<-m alternatives to TARGET_SIMD but add a new w<-r
+	alternative for !TARGET_SIMD.
+	(*aarch64_combine_internal_be): Likewise.
+	(aarch64_combinez): Require TARGET_FLOAT rather than TARGET_SIMD.
+	Remove bogus arch attribute.
+	(*aarch64_combinez_be): Likewise.
+	(@aarch64_vec_concat): Require TARGET_FLOAT rather than
+	TARGET_SIMD.
+	(aarch64_combine): Likewise.
+	(aarch64_rev_reglist): Likewise.
+	(mov): Likewise.
+	(*aarch64_be_mov): Extend to TARGET_FLOAT &&
+	!TARGET_SIMD, regardless of endianness.  Extend associated
+	define_splits in the same way, both for this pattern and the
+	ones below.
+	(*aarch64_be_mov): Likewise.  Restrict w<-w
+	alternative to TARGET_SIMD.
+	(*aarch64_be_movoi): Likewise.
+	(*aarch64_be_movci): Likewise.
+	(*aarch64_be_movxi): Likewise.
+	(*aarch64_be_mov): Extend to TARGET_FLOAT
+	&& !TARGET_SIMD, regardless of endianness.  Restrict w<-w alternative
+	to TARGET_SIMD for tuples of 128-bit vectors.
+	(*aarch64_be_mov): Likewise.
+	* config/aarch64/aarch64-ldpstp.md: Remove TARGET_SIMD condition
+	from DREG STP peephole.  Change TARGET_SIMD to TARGET_FLOAT in
+	the VQ and VP_2E LDP and STP peepholes.
+
+gcc/testsuite/
+	* gcc.target/aarch64/ldp_stp_20.c: New test.
+	* gcc.target/aarch64/ldp_stp_21.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_22.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_23.c: Likewise.
+	* gcc.target/aarch64/ldp_stp_24.c: Likewise.
+	* gcc.target/aarch64/movv16qi_1.c (gpr_to_gpr): New function.
+	* gcc.target/aarch64/movv8qi_1.c (gpr_to_gpr): Likewise.
+	* gcc.target/aarch64/movv16qi_2.c: New test.
+	* gcc.target/aarch64/movv16qi_3.c: Likewise.
+	* gcc.target/aarch64/movv2di_1.c: Likewise.
+	* gcc.target/aarch64/movv2x16qi_1.c: Likewise.
+	* gcc.target/aarch64/movv2x8qi_1.c: Likewise.
+	* gcc.target/aarch64/movv3x16qi_1.c: Likewise.
+	* gcc.target/aarch64/movv3x8qi_1.c: Likewise.
+	* gcc.target/aarch64/movv4x16qi_1.c: Likewise.
+	* gcc.target/aarch64/movv4x8qi_1.c: Likewise.
+	* gcc.target/aarch64/movv8qi_2.c: Likewise.
+	* gcc.target/aarch64/movv8qi_3.c: Likewise.
+	* gcc.target/aarch64/vect_unary_2.c: Likewise.
+---
+ gcc/config/aarch64/aarch64-ldpstp.md          |  11 +-
+ gcc/config/aarch64/aarch64-simd.md            | 199 +++++++++++-------
+ gcc/config/aarch64/aarch64.cc                 |  94 ++++++---
+ gcc/config/aarch64/aarch64.md                 |  11 +-
+ gcc/config/aarch64/iterators.md               |   2 +
+ gcc/testsuite/gcc.target/aarch64/ldp_stp_20.c |   7 +
+ gcc/testsuite/gcc.target/aarch64/ldp_stp_21.c |   7 +
+ gcc/testsuite/gcc.target/aarch64/ldp_stp_22.c |  13 ++
+ gcc/testsuite/gcc.target/aarch64/ldp_stp_23.c |  16 ++
+ gcc/testsuite/gcc.target/aarch64/ldp_stp_24.c |  16 ++
+ gcc/testsuite/gcc.target/aarch64/movv16qi_1.c |  21 ++
+ gcc/testsuite/gcc.target/aarch64/movv16qi_2.c |  27 +++
+ gcc/testsuite/gcc.target/aarch64/movv16qi_3.c |  30 +++
+ gcc/testsuite/gcc.target/aarch64/movv2di_1.c  | 103 +++++++++
+ .../gcc.target/aarch64/movv2x16qi_1.c         |  40 ++++
+ .../gcc.target/aarch64/movv2x8qi_1.c          |  38 ++++
+ .../gcc.target/aarch64/movv3x16qi_1.c         |  44 ++++
+ .../gcc.target/aarch64/movv3x8qi_1.c          |  41 ++++
+ .../gcc.target/aarch64/movv4x16qi_1.c         |  44 ++++
+ .../gcc.target/aarch64/movv4x8qi_1.c          |  42 ++++
+ gcc/testsuite/gcc.target/aarch64/movv8qi_1.c  |  15 ++
+ gcc/testsuite/gcc.target/aarch64/movv8qi_2.c  |  27 +++
+ gcc/testsuite/gcc.target/aarch64/movv8qi_3.c  |  30 +++
+ .../gcc.target/aarch64/vect_unary_2.c         |   5 +
+ 24 files changed, 774 insertions(+), 109 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/ldp_stp_20.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/ldp_stp_21.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/ldp_stp_22.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/ldp_stp_23.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/ldp_stp_24.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv16qi_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv16qi_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv2di_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv2x16qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv2x8qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv3x16qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv3x8qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv4x16qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv4x8qi_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv8qi_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv8qi_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/vect_unary_2.c
+
+diff --git a/gcc/config/aarch64/aarch64-ldpstp.md b/gcc/config/aarch64/aarch64-ldpstp.md
+index ba76a1b78..f8446e212 100644
+--- a/gcc/config/aarch64/aarch64-ldpstp.md
++++ b/gcc/config/aarch64/aarch64-ldpstp.md
+@@ -83,8 +83,7 @@
+ 	(match_operand:DREG 1 "register_operand" ""))
+    (set (match_operand:DREG2 2 "memory_operand" "")
+ 	(match_operand:DREG2 3 "register_operand" ""))]
+-  "TARGET_SIMD
+-   && aarch64_operands_ok_for_ldpstp (operands, false, mode)"
++  "aarch64_operands_ok_for_ldpstp (operands, false, mode)"
+   [(parallel [(set (match_dup 0) (match_dup 1))
+ 	      (set (match_dup 2) (match_dup 3))])]
+ {
+@@ -96,7 +95,7 @@
+ 	(match_operand:VQ 1 "memory_operand" ""))
+    (set (match_operand:VQ2 2 "register_operand" "")
+ 	(match_operand:VQ2 3 "memory_operand" ""))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && aarch64_operands_ok_for_ldpstp (operands, true, mode)
+    && (aarch64_tune_params.extra_tuning_flags
+ 	& AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS) == 0"
+@@ -111,7 +110,7 @@
+ 	(match_operand:VQ 1 "register_operand" ""))
+    (set (match_operand:VQ2 2 "memory_operand" "")
+ 	(match_operand:VQ2 3 "register_operand" ""))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && aarch64_operands_ok_for_ldpstp (operands, false, mode)
+    && (aarch64_tune_params.extra_tuning_flags
+ 	& AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS) == 0"
+@@ -306,7 +305,7 @@
+    (set (match_operand:VP_2E 6 "memory_operand" "")
+         (match_operand:VP_2E 7 "aarch64_reg_or_zero" ""))
+    (match_dup 8)]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && aarch64_operands_adjust_ok_for_ldpstp (operands, false, mode)"
+   [(const_int 0)]
+ {
+@@ -327,7 +326,7 @@
+    (set (match_operand:VP_2E 6 "register_operand" "")
+         (match_operand:VP_2E 7 "memory_operand" ""))
+    (match_dup 8)]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && aarch64_operands_adjust_ok_for_ldpstp (operands, true, mode)"
+   [(const_int 0)]
+ {
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index a47b39281..ef7fc4ecb 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -21,7 +21,7 @@
+ (define_expand "mov"
+   [(set (match_operand:VALL_F16 0 "nonimmediate_operand")
+ 	(match_operand:VALL_F16 1 "general_operand"))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   "
+   /* Force the operand into a register if it is not an
+      immediate whose use can be replaced with xzr.
+@@ -52,7 +52,7 @@
+ (define_expand "movmisalign"
+   [(set (match_operand:VALL_F16 0 "nonimmediate_operand")
+         (match_operand:VALL_F16 1 "general_operand"))]
+-  "TARGET_SIMD && !STRICT_ALIGNMENT"
++  "TARGET_FLOAT && !STRICT_ALIGNMENT"
+ {
+   /* This pattern is not permitted to fail during expansion: if both arguments
+      are non-registers (e.g. memory := constant, which can be created by the
+@@ -116,10 +116,10 @@
+ 
+ (define_insn "*aarch64_simd_mov"
+   [(set (match_operand:VDMOV 0 "nonimmediate_operand"
+-		"=w, m,  m,  w, ?r, ?w, ?r, w")
++		"=w, m,  m,  w, ?r, ?w, ?r,  w,  w")
+ 	(match_operand:VDMOV 1 "general_operand"
+-		"m,  Dz, w,  w,  w,  r,  r, Dn"))]
+-  "TARGET_SIMD
++		"m,  Dz, w,  w,  w,  r,  r, Dn, Dz"))]
++  "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+ {
+@@ -128,26 +128,34 @@
+      case 0: return "ldr\t%d0, %1";
+      case 1: return "str\txzr, %0";
+      case 2: return "str\t%d1, %0";
+-     case 3: return "mov\t%0., %1.";
+-     case 4: return "umov\t%0, %1.d[0]";
++     case 3:
++       if (TARGET_SIMD)
++	 return "mov\t%0., %1.";
++       return "fmov\t%d0, %d1";
++     case 4:
++       if (TARGET_SIMD)
++	 return "umov\t%0, %1.d[0]";
++       return "fmov\t%x0, %d1";
+      case 5: return "fmov\t%d0, %1";
+      case 6: return "mov\t%0, %1";
+      case 7:
+ 	return aarch64_output_simd_mov_immediate (operands[1], 64);
++     case 8: return "fmov\t%d0, xzr";
+      default: gcc_unreachable ();
+      }
+ }
+   [(set_attr "type" "neon_load1_1reg, store_8, neon_store1_1reg,\
+ 		     neon_logic, neon_to_gp, f_mcr,\
+-		     mov_reg, neon_move")]
++		     mov_reg, neon_move, f_mcr")
++   (set_attr "arch" "*,*,*,*,*,*,*,simd,*")]
+ )
+ 
+ (define_insn "*aarch64_simd_mov"
+   [(set (match_operand:VQMOV 0 "nonimmediate_operand"
+-		"=w, Umn,  m,  w, ?r, ?w, ?r, w")
++		"=w, Umn,  m,  w, ?r, ?w, ?r, w,  w")
+ 	(match_operand:VQMOV 1 "general_operand"
+-		"m,  Dz, w,  w,  w,  r,  r, Dn"))]
+-  "TARGET_SIMD
++		"m,  Dz, w,  w,  w,  r,  r, Dn, Dz"))]
++  "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+ {
+@@ -167,14 +175,17 @@
+ 	return "#";
+     case 7:
+ 	return aarch64_output_simd_mov_immediate (operands[1], 128);
++    case 8:
++	return "fmov\t%d0, xzr";
+     default:
+ 	gcc_unreachable ();
+     }
+ }
+   [(set_attr "type" "neon_load1_1reg, store_16, neon_store1_1reg,\
+ 		     neon_logic, multiple, multiple,\
+-		     multiple, neon_move")
+-   (set_attr "length" "4,4,4,4,8,8,8,4")]
++		     multiple, neon_move, fmov")
++   (set_attr "length" "4,4,4,4,8,8,8,4,4")
++   (set_attr "arch" "*,*,*,simd,*,*,*,simd,*")]
+ )
+ 
+ ;; When storing lane zero we can use the normal STR and its more permissive
+@@ -195,7 +206,7 @@
+ 	(match_operand:DREG 1 "aarch64_mem_pair_operand" "Ump"))
+    (set (match_operand:DREG2 2 "register_operand" "=w")
+ 	(match_operand:DREG2 3 "memory_operand" "m"))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && rtx_equal_p (XEXP (operands[3], 0),
+ 		   plus_constant (Pmode,
+ 				  XEXP (operands[1], 0),
+@@ -209,7 +220,7 @@
+ 	(match_operand:DREG 1 "register_operand" "w"))
+    (set (match_operand:DREG2 2 "memory_operand" "=m")
+ 	(match_operand:DREG2 3 "register_operand" "w"))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && rtx_equal_p (XEXP (operands[2], 0),
+ 		   plus_constant (Pmode,
+ 				  XEXP (operands[0], 0),
+@@ -223,7 +234,7 @@
+ 	(match_operand:VQ 1 "aarch64_mem_pair_operand" "Ump"))
+    (set (match_operand:VQ2 2 "register_operand" "=w")
+ 	(match_operand:VQ2 3 "memory_operand" "m"))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+     && rtx_equal_p (XEXP (operands[3], 0),
+ 		    plus_constant (Pmode,
+ 			       XEXP (operands[1], 0),
+@@ -237,10 +248,11 @@
+ 	(match_operand:VQ 1 "register_operand" "w"))
+    (set (match_operand:VQ2 2 "memory_operand" "=m")
+ 	(match_operand:VQ2 3 "register_operand" "w"))]
+-  "TARGET_SIMD && rtx_equal_p (XEXP (operands[2], 0),
+-		plus_constant (Pmode,
+-			       XEXP (operands[0], 0),
+-			       GET_MODE_SIZE (mode)))"
++  "TARGET_FLOAT
++   && rtx_equal_p (XEXP (operands[2], 0),
++		   plus_constant (Pmode,
++				  XEXP (operands[0], 0),
++				  GET_MODE_SIZE (mode)))"
+   "stp\\t%q1, %q3, %z0"
+   [(set_attr "type" "neon_stp_q")]
+ )
+@@ -248,8 +260,9 @@
+ 
+ (define_split
+   [(set (match_operand:VQMOV 0 "register_operand" "")
+-      (match_operand:VQMOV 1 "register_operand" ""))]
+-  "TARGET_SIMD && reload_completed
++	(match_operand:VQMOV 1 "register_operand" ""))]
++  "TARGET_FLOAT
++   && reload_completed
+    && GP_REGNUM_P (REGNO (operands[0]))
+    && GP_REGNUM_P (REGNO (operands[1]))"
+   [(const_int 0)]
+@@ -261,7 +274,8 @@
+ (define_split
+   [(set (match_operand:VQMOV 0 "register_operand" "")
+         (match_operand:VQMOV 1 "register_operand" ""))]
+-  "TARGET_SIMD && reload_completed
++  "TARGET_FLOAT
++   && reload_completed
+    && ((FP_REGNUM_P (REGNO (operands[0])) && GP_REGNUM_P (REGNO (operands[1])))
+        || (GP_REGNUM_P (REGNO (operands[0])) && FP_REGNUM_P (REGNO (operands[1]))))"
+   [(const_int 0)]
+@@ -273,7 +287,7 @@
+ (define_expand "@aarch64_split_simd_mov"
+   [(set (match_operand:VQMOV 0)
+ 	(match_operand:VQMOV 1))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   {
+     rtx dst = operands[0];
+     rtx src = operands[1];
+@@ -306,13 +320,20 @@
+         (vec_select:
+           (match_operand:VQMOV 1 "register_operand")
+           (match_operand 2 "ascending_int_parallel")))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
++  {
++    if (vect_par_cnst_lo_half (operands[2], mode))
++      {
++	emit_move_insn (operands[0], gen_lowpart (mode, operands[1]));
++	DONE;
++      }
++  }
+ )
+ 
+ (define_expand "aarch64_get_low"
+   [(match_operand: 0 "register_operand")
+    (match_operand:VQMOV 1 "register_operand")]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   {
+     rtx lo = aarch64_simd_vect_par_cnst_half (mode, , false);
+     emit_insn (gen_aarch64_get_half (operands[0], operands[1], lo));
+@@ -323,7 +344,7 @@
+ (define_expand "aarch64_get_high"
+   [(match_operand: 0 "register_operand")
+    (match_operand:VQMOV 1 "register_operand")]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   {
+     rtx hi = aarch64_simd_vect_par_cnst_half (mode, , true);
+     emit_insn (gen_aarch64_get_half (operands[0], operands[1], hi));
+@@ -350,15 +371,17 @@
+ )
+ 
+ (define_insn "aarch64_simd_mov_from_high"
+-  [(set (match_operand: 0 "register_operand" "=w,?r")
++  [(set (match_operand: 0 "register_operand" "=w,?r,?r")
+         (vec_select:
+-          (match_operand:VQMOV_NO2E 1 "register_operand" "w,w")
++          (match_operand:VQMOV_NO2E 1 "register_operand" "w,w,w")
+           (match_operand:VQMOV_NO2E 2 "vect_par_cnst_hi_half" "")))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   "@
+-   dup\\t%d0, %1.d[1]
+-   umov\t%0, %1.d[1]"
+-  [(set_attr "type" "neon_dup,neon_to_gp")
++   dup\t%d0, %1.d[1]
++   umov\t%0, %1.d[1]
++   fmov\t%0, %1.d[1]"
++  [(set_attr "type" "neon_dup,neon_to_gp,f_mrc")
++   (set_attr "arch" "simd,simd,*")
+    (set_attr "length" "4")]
+ )
+ 
+@@ -4322,12 +4345,22 @@
+   [(set_attr "type" "neon_to_gp, neon_dup, neon_store1_one_lane")]
+ )
+ 
++(define_insn "*aarch64_get_high"
++  [(set (match_operand: 0 "aarch64_simd_nonimmediate_operand" "=r")
++	(vec_select:
++	  (match_operand:VQ_2E 1 "register_operand" "w")
++	  (parallel [(match_operand:SI 2 "immediate_operand")])))]
++  "TARGET_FLOAT && ENDIAN_LANE_N (, INTVAL (operands[2])) == 1"
++  "fmov\t%0, %1.d[1]"
++  [(set_attr "type" "f_mrc")]
++)
++
+ (define_insn "load_pair_lanes"
+   [(set (match_operand: 0 "register_operand" "=w")
+ 	(vec_concat:
+ 	   (match_operand:VDCSIF 1 "memory_operand" "Utq")
+ 	   (match_operand:VDCSIF 2 "memory_operand" "m")))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && aarch64_mergeable_load_pair_p (mode, operands[1], operands[2])"
+   "ldr\\t%0, %1"
+   [(set_attr "type" "neon_load1_1reg")]
+@@ -4357,7 +4390,7 @@
+ 	(vec_concat:
+ 	   (match_operand:VDCSIF 1 "register_operand" "w, r")
+ 	   (match_operand:VDCSIF 2 "register_operand" "w, r")))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   "@
+    stp\t%1, %2, %y0
+    stp\t%1, %2, %y0"
+@@ -4372,39 +4405,44 @@
+ ;; the register alternatives either don't accept or themselves disparage.
+ 
+ (define_insn "*aarch64_combine_internal"
+-  [(set (match_operand: 0 "aarch64_reg_or_mem_pair_operand" "=w, w, w, Umn, Umn")
++  [(set (match_operand: 0 "aarch64_reg_or_mem_pair_operand" "=w, w, w, w, Umn, Umn")
+ 	(vec_concat:
+-	  (match_operand:VDCSIF 1 "register_operand" "0, 0, 0, ?w, ?r")
+-	  (match_operand:VDCSIF 2 "aarch64_simd_nonimmediate_operand" "w, ?r, Utv, w, ?r")))]
+-  "TARGET_SIMD
++	  (match_operand:VDCSIF 1 "register_operand" "0, 0, 0, 0, ?w, ?r")
++	  (match_operand:VDCSIF 2 "aarch64_simd_nonimmediate_operand" "w, ?r, ?r, Utv, w, ?r")))]
++  "TARGET_FLOAT
+    && !BYTES_BIG_ENDIAN
+    && (register_operand (operands[0], mode)
+        || register_operand (operands[2], mode))"
+   "@
+    ins\t%0.[1], %2.[0]
+    ins\t%0.[1], %2
++   fmov\t%0.d[1], %2
+    ld1\t{%0.}[1], %2
+    stp\t%1, %2, %y0
+    stp\t%1, %2, %y0"
+-  [(set_attr "type" "neon_ins, neon_from_gp, neon_load1_one_lane, neon_stp, store_16")]
++  [(set_attr "type" "neon_ins, neon_from_gp, f_mcr,
++		     neon_load1_one_lane, neon_stp, store_16")
++   (set_attr "arch" "simd,simd,*,simd,*,*")]
+ )
+ 
+ (define_insn "*aarch64_combine_internal_be"
+-  [(set (match_operand: 0 "aarch64_reg_or_mem_pair_operand" "=w, w, w, Umn, Umn")
++  [(set (match_operand: 0 "aarch64_reg_or_mem_pair_operand" "=w, w, w, w, Umn, Umn")
+ 	(vec_concat:
+-	  (match_operand:VDCSIF 2 "aarch64_simd_nonimmediate_operand" "w, ?r, Utv, ?w, ?r")
+-	  (match_operand:VDCSIF 1 "register_operand" "0, 0, 0, ?w, ?r")))]
+-  "TARGET_SIMD
++	  (match_operand:VDCSIF 2 "aarch64_simd_nonimmediate_operand" "w, ?r, ?r, Utv, ?w, ?r")
++	  (match_operand:VDCSIF 1 "register_operand" "0, 0, 0, 0, ?w, ?r")))]
++  "TARGET_FLOAT
+    && BYTES_BIG_ENDIAN
+    && (register_operand (operands[0], mode)
+        || register_operand (operands[2], mode))"
+   "@
+    ins\t%0.[1], %2.[0]
+    ins\t%0.[1], %2
++   fmov\t%0.d[1], %2
+    ld1\t{%0.}[1], %2
+    stp\t%2, %1, %y0
+    stp\t%2, %1, %y0"
+-  [(set_attr "type" "neon_ins, neon_from_gp, neon_load1_one_lane, neon_stp, store_16")]
++  [(set_attr "type" "neon_ins, neon_from_gp, f_mcr, neon_load1_one_lane, neon_stp, store_16")
++   (set_attr "arch" "simd,simd,*,simd,*,*")]
+ )
+ 
+ ;; In this insn, operand 1 should be low, and operand 2 the high part of the
+@@ -4415,13 +4453,12 @@
+ 	(vec_concat:
+ 	  (match_operand:VDCSIF 1 "nonimmediate_operand" "w,?r,m")
+ 	  (match_operand:VDCSIF 2 "aarch64_simd_or_scalar_imm_zero")))]
+-  "TARGET_SIMD && !BYTES_BIG_ENDIAN"
++  "TARGET_FLOAT && !BYTES_BIG_ENDIAN"
+   "@
+    fmov\\t%0, %1
+    fmov\t%0, %1
+    ldr\\t%0, %1"
+-  [(set_attr "type" "neon_move, neon_from_gp, neon_load1_1reg")
+-   (set_attr "arch" "simd,fp,simd")]
++  [(set_attr "type" "neon_move, neon_from_gp, neon_load1_1reg")]
+ )
+ 
+ (define_insn "*aarch64_combinez_be"
+@@ -4429,13 +4466,12 @@
+         (vec_concat:
+ 	  (match_operand:VDCSIF 2 "aarch64_simd_or_scalar_imm_zero")
+ 	  (match_operand:VDCSIF 1 "nonimmediate_operand" "w,?r,m")))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN"
++  "TARGET_FLOAT && BYTES_BIG_ENDIAN"
+   "@
+    fmov\\t%0, %1
+    fmov\t%0, %1
+    ldr\\t%0, %1"
+-  [(set_attr "type" "neon_move, neon_from_gp, neon_load1_1reg")
+-   (set_attr "arch" "simd,fp,simd")]
++  [(set_attr "type" "neon_move, neon_from_gp, neon_load1_1reg")]
+ )
+ 
+ ;; Form a vector whose first half (in array order) comes from operand 1
+@@ -4446,7 +4482,7 @@
+ 	(vec_concat:
+ 	  (match_operand:VDCSIF 1 "general_operand")
+ 	  (match_operand:VDCSIF 2 "general_operand")))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+ {
+   int lo = BYTES_BIG_ENDIAN ? 2 : 1;
+   int hi = BYTES_BIG_ENDIAN ? 1 : 2;
+@@ -4464,7 +4500,7 @@
+     }
+   else
+     {
+-      /* Use *aarch64_combine_general.  */
++      /* Use *aarch64_combine_internal.  */
+       operands[lo] = force_reg (mode, operands[lo]);
+       if (!aarch64_simd_nonimmediate_operand (operands[hi], mode))
+ 	{
+@@ -4486,7 +4522,7 @@
+   [(match_operand: 0 "register_operand")
+    (match_operand:VDC 1 "general_operand")
+    (match_operand:VDC 2 "general_operand")]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+ {
+   if (BYTES_BIG_ENDIAN)
+     std::swap (operands[1], operands[2]);
+@@ -7367,7 +7403,7 @@
+ (define_expand "mov"
+   [(set (match_operand:VSTRUCT_QD 0 "nonimmediate_operand")
+ 	(match_operand:VSTRUCT_QD 1 "general_operand"))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+ {
+   if (can_create_pseudo_p ())
+     {
+@@ -7379,7 +7415,7 @@
+ (define_expand "mov"
+   [(set (match_operand:VSTRUCT 0 "nonimmediate_operand")
+ 	(match_operand:VSTRUCT 1 "general_operand"))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+ {
+   if (can_create_pseudo_p ())
+     {
+@@ -7559,7 +7595,8 @@
+ (define_insn "*aarch64_be_mov"
+   [(set (match_operand:VSTRUCT_2D 0 "nonimmediate_operand" "=w,m,w")
+ 	(match_operand:VSTRUCT_2D 1 "general_operand"      " w,w,m"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], mode)
+        || register_operand (operands[1], mode))"
+   "@
+@@ -7573,7 +7610,8 @@
+ (define_insn "*aarch64_be_mov"
+   [(set (match_operand:VSTRUCT_2Q 0 "nonimmediate_operand" "=w,m,w")
+ 	(match_operand:VSTRUCT_2Q 1 "general_operand"      " w,w,m"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], mode)
+        || register_operand (operands[1], mode))"
+   "@
+@@ -7581,13 +7619,15 @@
+    stp\\t%q1, %R1, %0
+    ldp\\t%q0, %R0, %1"
+   [(set_attr "type" "multiple,neon_stp_q,neon_ldp_q")
++   (set_attr "arch" "simd,*,*")
+    (set_attr "length" "8,4,4")]
+ )
+ 
+ (define_insn "*aarch64_be_movoi"
+   [(set (match_operand:OI 0 "nonimmediate_operand" "=w,m,w")
+ 	(match_operand:OI 1 "general_operand"      " w,w,m"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], OImode)
+        || register_operand (operands[1], OImode))"
+   "@
+@@ -7595,57 +7635,66 @@
+    stp\\t%q1, %R1, %0
+    ldp\\t%q0, %R0, %1"
+   [(set_attr "type" "multiple,neon_stp_q,neon_ldp_q")
++   (set_attr "arch" "simd,*,*")
+    (set_attr "length" "8,4,4")]
+ )
+ 
+ (define_insn "*aarch64_be_mov"
+   [(set (match_operand:VSTRUCT_3QD 0 "nonimmediate_operand" "=w,o,w")
+ 	(match_operand:VSTRUCT_3QD 1 "general_operand"      " w,w,o"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], mode)
+        || register_operand (operands[1], mode))"
+   "#"
+   [(set_attr "type" "multiple")
++   (set_attr "arch" "fp,*,*")
+    (set_attr "length" "12,8,8")]
+ )
+ 
+ (define_insn "*aarch64_be_movci"
+   [(set (match_operand:CI 0 "nonimmediate_operand" "=w,o,w")
+ 	(match_operand:CI 1 "general_operand"      " w,w,o"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], CImode)
+        || register_operand (operands[1], CImode))"
+   "#"
+   [(set_attr "type" "multiple")
+-   (set_attr "length" "12,4,4")]
++   (set_attr "arch" "simd,*,*")
++   (set_attr "length" "12,8,8")]
+ )
+ 
+ (define_insn "*aarch64_be_mov"
+   [(set (match_operand:VSTRUCT_4QD 0 "nonimmediate_operand" "=w,o,w")
+ 	(match_operand:VSTRUCT_4QD 1 "general_operand"      " w,w,o"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], mode)
+        || register_operand (operands[1], mode))"
+   "#"
+   [(set_attr "type" "multiple")
++   (set_attr "arch" "fp,*,*")
+    (set_attr "length" "16,8,8")]
+ )
+ 
+ (define_insn "*aarch64_be_movxi"
+   [(set (match_operand:XI 0 "nonimmediate_operand" "=w,o,w")
+ 	(match_operand:XI 1 "general_operand"      " w,w,o"))]
+-  "TARGET_SIMD && BYTES_BIG_ENDIAN
++  "TARGET_FLOAT
++   && (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+    && (register_operand (operands[0], XImode)
+        || register_operand (operands[1], XImode))"
+   "#"
+   [(set_attr "type" "multiple")
+-   (set_attr "length" "16,4,4")]
++   (set_attr "arch" "simd,*,*")
++   (set_attr "length" "16,8,8")]
+ )
+ 
+ (define_split
+   [(set (match_operand:VSTRUCT_2QD 0 "register_operand")
+ 	(match_operand:VSTRUCT_2QD 1 "register_operand"))]
+-  "TARGET_SIMD && reload_completed"
++  "TARGET_FLOAT && reload_completed"
+   [(const_int 0)]
+ {
+   aarch64_simd_emit_reg_reg_move (operands, mode, 2);
+@@ -7655,7 +7704,7 @@
+ (define_split
+   [(set (match_operand:OI 0 "register_operand")
+ 	(match_operand:OI 1 "register_operand"))]
+-  "TARGET_SIMD && reload_completed"
++  "TARGET_FLOAT && reload_completed"
+   [(const_int 0)]
+ {
+   aarch64_simd_emit_reg_reg_move (operands, TImode, 2);
+@@ -7665,7 +7714,7 @@
+ (define_split
+   [(set (match_operand:VSTRUCT_3QD 0 "nonimmediate_operand")
+ 	(match_operand:VSTRUCT_3QD 1 "general_operand"))]
+-  "TARGET_SIMD && reload_completed"
++  "TARGET_FLOAT && reload_completed"
+   [(const_int 0)]
+ {
+   if (register_operand (operands[0], mode)
+@@ -7674,7 +7723,7 @@
+       aarch64_simd_emit_reg_reg_move (operands, mode, 3);
+       DONE;
+     }
+-  else if (BYTES_BIG_ENDIAN)
++  else if (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+     {
+       int elt_size = GET_MODE_SIZE (mode).to_constant () / ;
+       machine_mode pair_mode = elt_size == 16 ? V2x16QImode : V2x8QImode;
+@@ -7701,7 +7750,7 @@
+ (define_split
+   [(set (match_operand:CI 0 "nonimmediate_operand")
+ 	(match_operand:CI 1 "general_operand"))]
+-  "TARGET_SIMD && reload_completed"
++  "TARGET_FLOAT && reload_completed"
+   [(const_int 0)]
+ {
+   if (register_operand (operands[0], CImode)
+@@ -7710,7 +7759,7 @@
+       aarch64_simd_emit_reg_reg_move (operands, TImode, 3);
+       DONE;
+     }
+-  else if (BYTES_BIG_ENDIAN)
++  else if (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+     {
+       emit_move_insn (simplify_gen_subreg (OImode, operands[0], CImode, 0),
+ 		      simplify_gen_subreg (OImode, operands[1], CImode, 0));
+@@ -7729,7 +7778,7 @@
+ (define_split
+   [(set (match_operand:VSTRUCT_4QD 0 "nonimmediate_operand")
+ 	(match_operand:VSTRUCT_4QD 1 "general_operand"))]
+-  "TARGET_SIMD && reload_completed"
++  "TARGET_FLOAT && reload_completed"
+   [(const_int 0)]
+ {
+   if (register_operand (operands[0], mode)
+@@ -7738,7 +7787,7 @@
+       aarch64_simd_emit_reg_reg_move (operands, mode, 4);
+       DONE;
+     }
+-  else if (BYTES_BIG_ENDIAN)
++  else if (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+     {
+       int elt_size = GET_MODE_SIZE (mode).to_constant () / ;
+       machine_mode pair_mode = elt_size == 16 ? V2x16QImode : V2x8QImode;
+@@ -7759,7 +7808,7 @@
+ (define_split
+   [(set (match_operand:XI 0 "nonimmediate_operand")
+ 	(match_operand:XI 1 "general_operand"))]
+-  "TARGET_SIMD && reload_completed"
++  "TARGET_FLOAT && reload_completed"
+   [(const_int 0)]
+ {
+   if (register_operand (operands[0], XImode)
+@@ -7768,7 +7817,7 @@
+       aarch64_simd_emit_reg_reg_move (operands, TImode, 4);
+       DONE;
+     }
+-  else if (BYTES_BIG_ENDIAN)
++  else if (!TARGET_SIMD || BYTES_BIG_ENDIAN)
+     {
+       emit_move_insn (simplify_gen_subreg (OImode, operands[0], XImode, 0),
+ 		      simplify_gen_subreg (OImode, operands[1], XImode, 0));
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 02210ed13..b4b646fa0 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -3748,7 +3748,7 @@ aarch64_classify_vector_mode (machine_mode mode)
+     case E_OImode:
+     case E_CImode:
+     case E_XImode:
+-      return TARGET_SIMD ? VEC_ADVSIMD | VEC_STRUCT : 0;
++      return TARGET_FLOAT ? VEC_ADVSIMD | VEC_STRUCT : 0;
+ 
+     /* Structures of 64-bit Advanced SIMD vectors.  */
+     case E_V2x8QImode:
+@@ -3775,7 +3775,7 @@ aarch64_classify_vector_mode (machine_mode mode)
+     case E_V4x4HFmode:
+     case E_V4x2SFmode:
+     case E_V4x1DFmode:
+-      return TARGET_SIMD ? VEC_ADVSIMD | VEC_STRUCT | VEC_PARTIAL : 0;
++      return TARGET_FLOAT ? VEC_ADVSIMD | VEC_STRUCT | VEC_PARTIAL : 0;
+ 
+     /* Structures of 128-bit Advanced SIMD vectors.  */
+     case E_V2x16QImode:
+@@ -3802,7 +3802,7 @@ aarch64_classify_vector_mode (machine_mode mode)
+     case E_V4x8HFmode:
+     case E_V4x4SFmode:
+     case E_V4x2DFmode:
+-      return TARGET_SIMD ? VEC_ADVSIMD | VEC_STRUCT : 0;
++      return TARGET_FLOAT ? VEC_ADVSIMD | VEC_STRUCT : 0;
+ 
+     /* 64-bit Advanced SIMD vectors.  */
+     case E_V8QImode:
+@@ -3822,7 +3822,7 @@ aarch64_classify_vector_mode (machine_mode mode)
+     case E_V8BFmode:
+     case E_V4SFmode:
+     case E_V2DFmode:
+-      return TARGET_SIMD ? VEC_ADVSIMD : 0;
++      return TARGET_FLOAT ? VEC_ADVSIMD : 0;
+ 
+     default:
+       return 0;
+@@ -4110,7 +4110,8 @@ aarch64_vectorize_related_mode (machine_mode vector_mode,
+     }
+ 
+   /* Prefer to use 1 128-bit vector instead of 2 64-bit vectors.  */
+-  if ((vec_flags & VEC_ADVSIMD)
++  if (TARGET_SIMD
++      && (vec_flags & VEC_ADVSIMD)
+       && known_eq (nunits, 0U)
+       && known_eq (GET_MODE_BITSIZE (vector_mode), 64U)
+       && maybe_ge (GET_MODE_BITSIZE (element_mode)
+@@ -4208,7 +4209,7 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode)
+ 
+   if (GP_REGNUM_P (regno))
+     {
+-      if (vec_flags & VEC_ANY_SVE)
++      if (vec_flags & (VEC_ANY_SVE | VEC_STRUCT))
+ 	return false;
+       if (known_le (GET_MODE_SIZE (mode), 8))
+ 	return true;
+@@ -10884,7 +10885,8 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 			    || mode == TImode
+ 			    || mode == TFmode
+ 			    || mode == TDmode
+-			    || (BYTES_BIG_ENDIAN && advsimd_struct_p));
++			    || ((!TARGET_SIMD || 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.  */
+@@ -10914,6 +10916,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
+   /* On LE, for AdvSIMD, don't support anything other than POST_INC or
+      REG addressing.  */
+   if (advsimd_struct_p
++      && TARGET_SIMD
+       && !BYTES_BIG_ENDIAN
+       && (code != POST_INC && code != REG))
+     return false;
+@@ -10976,7 +10979,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	            && aarch64_offset_7bit_signed_scaled_p (DImode, offset + 48));
+ 
+ 	  /* A 7bit offset check because OImode will emit a ldp/stp
+-	     instruction (only big endian will get here).
++	     instruction (only !TARGET_SIMD or big endian will get here).
+ 	     For ldp/stp instructions, the offset is scaled for the size of a
+ 	     single element of the pair.  */
+ 	  if (aarch64_advsimd_partial_struct_mode_p (mode)
+@@ -10987,7 +10990,8 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	    return aarch64_offset_7bit_signed_scaled_p (TImode, offset);
+ 
+ 	  /* Three 9/12 bit offsets checks because CImode will emit three
+-	     ldr/str instructions (only big endian will get here).  */
++	     ldr/str instructions (only !TARGET_SIMD or big endian will
++	     get here).  */
+ 	  if (aarch64_advsimd_partial_struct_mode_p (mode)
+ 	      && known_eq (GET_MODE_SIZE (mode), 24))
+ 	    return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
+@@ -12716,18 +12720,16 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+   /* Use aarch64_sve_reload_mem for SVE memory reloads that cannot use
+      LDR and STR.  See the comment at the head of aarch64-sve.md for
+      more details about the big-endian handling.  */
++  unsigned int vec_flags = aarch64_classify_vector_mode (mode);
+   if (reg_class_subset_p (rclass, FP_REGS)
+       && !((REG_P (x) && HARD_REGISTER_P (x))
+ 	   || aarch64_simd_valid_immediate (x, NULL))
+-      && mode != VNx16QImode)
++      && mode != VNx16QImode
++      && (vec_flags & VEC_SVE_DATA)
++      && ((vec_flags & VEC_PARTIAL) || BYTES_BIG_ENDIAN))
+     {
+-      unsigned int vec_flags = aarch64_classify_vector_mode (mode);
+-      if ((vec_flags & VEC_SVE_DATA)
+-	  && ((vec_flags & VEC_PARTIAL) || BYTES_BIG_ENDIAN))
+-	{
+-	  sri->icode = CODE_FOR_aarch64_sve_reload_mem;
+-	  return NO_REGS;
+-	}
++      sri->icode = CODE_FOR_aarch64_sve_reload_mem;
++      return NO_REGS;
+     }
+ 
+   /* If we have to disable direct literal pool loads and stores because the
+@@ -12744,9 +12746,13 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+   /* Without the TARGET_SIMD instructions we cannot move a Q register
+      to a Q register directly.  We need a scratch.  */
+   if (REG_P (x)
+-      && (mode == TFmode || mode == TImode || mode == TDmode)
++      && (mode == TFmode
++	  || mode == TImode
++	  || mode == TDmode
++	  || (vec_flags == VEC_ADVSIMD && known_eq (GET_MODE_SIZE (mode), 16)))
+       && mode == GET_MODE (x)
+-      && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
++      && !TARGET_SIMD
++      && FP_REGNUM_P (REGNO (x))
+       && reg_class_subset_p (rclass, FP_REGS))
+     {
+       sri->icode = code_for_aarch64_reload_mov (mode);
+@@ -12768,6 +12774,28 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+   return NO_REGS;
+ }
+ 
++/* Implement TARGET_SECONDARY_MEMORY_NEEDED.  */
++
++static bool
++aarch64_secondary_memory_needed (machine_mode mode, reg_class_t class1,
++				 reg_class_t class2)
++{
++  if (!TARGET_SIMD
++      && reg_classes_intersect_p (class1, FP_REGS)
++      && reg_classes_intersect_p (class2, FP_REGS))
++    {
++      /* We can't do a 128-bit FPR-to-FPR move without TARGET_SIMD,
++	 so we can't easily split a move involving tuples of 128-bit
++	 vectors.  Force the copy through memory instead.
++
++	 (Tuples of 64-bit vectors are fine.)  */
++      unsigned int vec_flags = aarch64_classify_vector_mode (mode);
++      if (vec_flags == (VEC_ADVSIMD | VEC_STRUCT))
++	return true;
++    }
++  return false;
++}
++
+ static bool
+ aarch64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+ {
+@@ -13311,7 +13339,7 @@ aarch64_rtx_mult_cost (rtx x, enum rtx_code code, int outer, bool speed)
+   if (VECTOR_MODE_P (mode))
+     {
+       unsigned int vec_flags = aarch64_classify_vector_mode (mode);
+-      if (vec_flags & VEC_ADVSIMD)
++      if (TARGET_SIMD && (vec_flags & VEC_ADVSIMD))
+ 	{
+ 	  /* The select-operand-high-half versions of the instruction have the
+ 	     same cost as the three vector version - don't add the costs of the
+@@ -14257,7 +14285,7 @@ cost_minus:
+ 	  {
+ 	    /* SUBL2 and SUBW2.  */
+ 	    unsigned int vec_flags = aarch64_classify_vector_mode (mode);
+-	    if (vec_flags & VEC_ADVSIMD)
++	    if (TARGET_SIMD && (vec_flags & VEC_ADVSIMD))
+ 	      {
+ 		/* The select-operand-high-half versions of the sub instruction
+ 		   have the same cost as the regular three vector version -
+@@ -14359,7 +14387,7 @@ cost_plus:
+ 	  {
+ 	    /* ADDL2 and ADDW2.  */
+ 	    unsigned int vec_flags = aarch64_classify_vector_mode (mode);
+-	    if (vec_flags & VEC_ADVSIMD)
++	    if (TARGET_SIMD && (vec_flags & VEC_ADVSIMD))
+ 	      {
+ 		/* The select-operand-high-half versions of the add instruction
+ 		   have the same cost as the regular three vector version -
+@@ -15284,7 +15312,9 @@ aarch64_register_move_cost (machine_mode mode,
+     return aarch64_register_move_cost (mode, from, GENERAL_REGS)
+             + aarch64_register_move_cost (mode, GENERAL_REGS, to);
+ 
+-  if (known_eq (GET_MODE_SIZE (mode), 16))
++  unsigned int vec_flags = aarch64_classify_vector_mode (mode);
++  if (vec_flags != (VEC_ADVSIMD | VEC_STRUCT | VEC_PARTIAL)
++      && known_eq (GET_MODE_SIZE (mode), 16))
+     {
+       /* 128-bit operations on general registers require 2 instructions.  */
+       if (from == GENERAL_REGS && to == GENERAL_REGS)
+@@ -15312,6 +15342,16 @@ aarch64_register_move_cost (machine_mode mode,
+   else if (to == GENERAL_REGS)
+     return regmove_cost->FP2GP;
+ 
++  if (!TARGET_SIMD && vec_flags == (VEC_ADVSIMD | VEC_STRUCT))
++    {
++      /* Needs a round-trip through memory, which can use LDP/STP for pairs.
++	 The cost must be greater than 2 units to indicate that direct
++	 moves aren't possible.  */
++      auto per_vector = (aarch64_tune_params.memmov_cost.load_fp
++			 + aarch64_tune_params.memmov_cost.store_fp);
++      return MIN (CEIL (per_vector, 2), 4);
++    }
++
+   return regmove_cost->FP2FP;
+ }
+ 
+@@ -21504,6 +21544,9 @@ aarch64_simd_valid_immediate (rtx op, simd_immediate_info *info,
+   if (vec_flags == 0 || vec_flags == (VEC_ADVSIMD | VEC_STRUCT))
+     return false;
+ 
++  if ((vec_flags & VEC_ADVSIMD) && !TARGET_SIMD)
++    return false;
++
+   if (vec_flags & VEC_SVE_PRED)
+     return aarch64_sve_pred_valid_immediate (op, info);
+ 
+@@ -24430,7 +24473,7 @@ aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
+       std::swap (d->op0, d->op1);
+     }
+ 
+-  if ((d->vec_flags == VEC_ADVSIMD
++  if (((d->vec_flags == VEC_ADVSIMD && TARGET_SIMD)
+        || d->vec_flags == VEC_SVE_DATA
+        || d->vec_flags == (VEC_SVE_DATA | VEC_PARTIAL)
+        || d->vec_flags == VEC_SVE_PRED)
+@@ -27977,6 +28020,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_SECONDARY_RELOAD
+ #define TARGET_SECONDARY_RELOAD aarch64_secondary_reload
+ 
++#undef TARGET_SECONDARY_MEMORY_NEEDED
++#define TARGET_SECONDARY_MEMORY_NEEDED aarch64_secondary_memory_needed
++
+ #undef TARGET_SHIFT_TRUNCATION_MASK
+ #define TARGET_SHIFT_TRUNCATION_MASK aarch64_shift_truncation_mask
+ 
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 8757a962f..c0cc91756 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -374,8 +374,11 @@
+ ;; Attributes of the architecture required to support the instruction (or
+ ;; alternative). This attribute is used to compute attribute "enabled", use type
+ ;; "any" to enable an alternative in all cases.
++;;
++;; As a convenience, "fp_q" means "fp" + the ability to move between
++;; Q registers and is equivalent to "simd".
+ 
+-(define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
++(define_enum "arches" [ any rcpc8_4 fp fp_q simd sve fp16])
+ 
+ (define_enum_attr "arch" "arches" (const_string "any"))
+ 
+@@ -403,7 +406,7 @@
+ 	(and (eq_attr "arch" "fp")
+ 	     (match_test "TARGET_FLOAT"))
+ 
+-	(and (eq_attr "arch" "simd")
++	(and (eq_attr "arch" "fp_q, simd")
+ 	     (match_test "TARGET_SIMD"))
+ 
+ 	(and (eq_attr "arch" "fp16")
+@@ -6768,8 +6771,8 @@
+ )
+ 
+ (define_expand "@aarch64_reload_mov"
+-  [(set (match_operand:TX 0 "register_operand" "=w")
+-        (match_operand:TX 1 "register_operand" "w"))
++  [(set (match_operand:VTX 0 "register_operand" "=w")
++        (match_operand:VTX 1 "register_operand" "w"))
+    (clobber (match_operand:DI 2 "register_operand" "=&r"))
+   ]
+   "TARGET_FLOAT"
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index d0cd1b788..a8a39b65a 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -313,6 +313,8 @@
+ 
+ (define_mode_iterator TX [TI TF TD])
+ 
++(define_mode_iterator VTX [TI TF TD V16QI V8HI V4SI V2DI V8HF V4SF V2DF V8BF])
++
+ ;; Advanced SIMD opaque structure modes.
+ (define_mode_iterator VSTRUCT [OI CI XI])
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_20.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_20.c
+new file mode 100644
+index 000000000..7e705e119
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_20.c
+@@ -0,0 +1,7 @@
++/* { dg-options "-O2" } */
++
++#pragma GCC target "+nosimd+fp"
++
++#include "ldp_stp_6.c"
++
++/* { dg-final { scan-assembler "stp\td\[0-9\]+, d\[0-9\]+, \\\[x\[0-9\]+\\\]" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_21.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_21.c
+new file mode 100644
+index 000000000..462e3c9aa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_21.c
+@@ -0,0 +1,7 @@
++/* { dg-options "-O2" } */
++
++#pragma GCC target "+nosimd+fp"
++
++#include "ldp_stp_8.c"
++
++/* { dg-final { scan-assembler-times "ldp\td\[0-9\], d\[0-9\]+, \\\[x\[0-9\]+\\\]" 2 } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_22.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_22.c
+new file mode 100644
+index 000000000..283c56dd2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_22.c
+@@ -0,0 +1,13 @@
++/* { dg-options "-O2" } */
++
++#pragma GCC target "+nosimd+fp"
++
++void
++foo (__Float32x4_t *ptr)
++{
++  ptr[0] = ptr[2];
++  ptr[1] = ptr[3];
++}
++
++/* { dg-final { scan-assembler {\tldp\tq[0-9]+, q[0-9]+} } } */
++/* { dg-final { scan-assembler {\tstp\tq[0-9]+, q[0-9]+} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_23.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_23.c
+new file mode 100644
+index 000000000..b14976cfe
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_23.c
+@@ -0,0 +1,16 @@
++/* { dg-options "-O2" } */
++
++#pragma GCC target "+nosimd+fp"
++
++void
++foo (char *char_ptr)
++{
++  __Float64x2_t *ptr = (__Float64x2_t *)(char_ptr + 1);
++  asm volatile ("" ::
++		"w" (ptr[1]),
++		"w" (ptr[2]),
++		"w" (ptr[3]),
++		"w" (ptr[4]));
++}
++
++/* { dg-final { scan-assembler-times {\tldp\tq[0-9]+, q[0-9]+} 2 } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_24.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_24.c
+new file mode 100644
+index 000000000..a99426eb2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_24.c
+@@ -0,0 +1,16 @@
++/* { dg-options "-O2" } */
++
++#pragma GCC target "+nosimd+fp"
++
++void
++foo (char *char_ptr)
++{
++  __Float64x2_t *ptr = (__Float64x2_t *)(char_ptr + 1);
++  asm volatile ("" :
++		"=w" (ptr[1]),
++		"=w" (ptr[2]),
++		"=w" (ptr[3]),
++		"=w" (ptr[4]));
++}
++
++/* { dg-final { scan-assembler-times {\tstp\tq[0-9]+, q[0-9]+} 2 } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c
+index 8a6afb13b..cac4241b0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/movv16qi_1.c
+@@ -80,3 +80,24 @@ fpr_to_gpr (v16qi q0)
+   x0 = q0;
+   asm volatile ("" :: "r" (x0));
+ }
++
++/*
++** gpr_to_gpr:
++** (
++**	mov	x0, x2
++**	mov	x1, x3
++** |
++**	mov	x1, x3
++**	mov	x0, x2
++** )
++**	ret
++*/
++void
++gpr_to_gpr ()
++{
++  register v16qi x0 asm ("x0");
++  register v16qi x2 asm ("x2");
++  asm volatile ("" : "=r" (x2));
++  x0 = x2;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv16qi_2.c b/gcc/testsuite/gcc.target/aarch64/movv16qi_2.c
+new file mode 100644
+index 000000000..08a0a19b5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv16qi_2.c
+@@ -0,0 +1,27 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_GENERAL(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE zero_##TYPE () { return (TYPE) {}; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_GENERAL (__Int8x16_t)
++TEST_GENERAL (__Int16x8_t)
++TEST_GENERAL (__Int32x4_t)
++TEST_GENERAL (__Int64x2_t)
++TEST_GENERAL (__Bfloat16x8_t)
++TEST_GENERAL (__Float16x8_t)
++TEST_GENERAL (__Float32x4_t)
++TEST_GENERAL (__Float64x2_t)
++
++__Int8x16_t const_s8x8 () { return (__Int8x16_t) { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; }
++__Int16x8_t const_s16x4 () { return (__Int16x8_t) { 1, 0, 1, 0, 1, 0, 1, 0 }; }
++__Int32x4_t const_s32x2 () { return (__Int32x4_t) { 1, 2, 3, 4 }; }
++__Int64x2_t const_s64x1 () { return (__Int64x2_t) { 100, 100 }; }
++__Float16x8_t const_f16x4 () { return (__Float16x8_t) { 2, 2, 2, 2, 2, 2, 2, 2 }; }
++__Float32x4_t const_f32x2 () { return (__Float32x4_t) { 1, 2, 1, 2 }; }
++__Float64x2_t const_f64x1 () { return (__Float64x2_t) { 32, 32 }; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv16qi_3.c b/gcc/testsuite/gcc.target/aarch64/movv16qi_3.c
+new file mode 100644
+index 000000000..d43b994c1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv16qi_3.c
+@@ -0,0 +1,30 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE \
++  test_##TYPE (void) \
++  { \
++    typedef TYPE v __attribute__((aligned(1))); \
++    register v *ptr asm ("x0"); \
++    asm volatile ("" : "=r" (ptr)); \
++    return *ptr; \
++  }
++
++TEST_VECTOR (__Int8x16_t)
++TEST_VECTOR (__Int16x8_t)
++TEST_VECTOR (__Int32x4_t)
++TEST_VECTOR (__Int64x2_t)
++TEST_VECTOR (__Bfloat16x8_t)
++TEST_VECTOR (__Float16x8_t)
++TEST_VECTOR (__Float32x4_t)
++TEST_VECTOR (__Float64x2_t)
++
++/*
++** test___Int8x16_t:
++**	ldr	q0, \[x0\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv2di_1.c b/gcc/testsuite/gcc.target/aarch64/movv2di_1.c
+new file mode 100644
+index 000000000..e3b55fd52
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv2di_1.c
+@@ -0,0 +1,103 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+nosimd+fp"
++
++typedef long long v2di __attribute__((vector_size(16)));
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++v2di
++fpr_to_fpr (v2di q0, v2di q1)
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++v2di
++gpr_to_fpr ()
++{
++  register v2di x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++v2di
++zero_to_fpr ()
++{
++  return (v2di) {};
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++void
++fpr_to_gpr (v2di q0)
++{
++  register v2di x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
++
++/*
++** gpr_to_gpr:
++** (
++**	mov	x0, x2
++**	mov	x1, x3
++** |
++**	mov	x1, x3
++**	mov	x0, x2
++** )
++**	ret
++*/
++void
++gpr_to_gpr ()
++{
++  register v2di x0 asm ("x0");
++  register v2di x2 asm ("x2");
++  asm volatile ("" : "=r" (x2));
++  x0 = x2;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv2x16qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv2x16qi_1.c
+new file mode 100644
+index 000000000..90e3b426d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv2x16qi_1.c
+@@ -0,0 +1,40 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC aarch64 "arm_neon.h"
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_VECTOR (int8x16x2_t)
++TEST_VECTOR (int16x8x2_t)
++TEST_VECTOR (int32x4x2_t)
++TEST_VECTOR (int64x2x2_t)
++TEST_VECTOR (float16x8x2_t)
++TEST_VECTOR (bfloat16x8x2_t)
++TEST_VECTOR (float32x4x2_t)
++TEST_VECTOR (float64x2x2_t)
++
++/*
++** mov_int8x16x2_t:
++**	sub	sp, sp, #32
++**	stp	q2, q3, \[sp\]
++**	ldp	q0, q1, \[sp\]
++**	add	sp, sp, #?32
++**	ret
++*/
++/*
++** load_int8x16x2_t:
++**	ldp	q0, q1, \[x0\]
++**	ret
++*/
++/*
++** store_int8x16x2_t: { xfail *-*-* }
++**	stp	q0, q1, \[x0\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv2x8qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv2x8qi_1.c
+new file mode 100644
+index 000000000..883a0ea71
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv2x8qi_1.c
+@@ -0,0 +1,38 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC aarch64 "arm_neon.h"
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_VECTOR (int8x8x2_t)
++TEST_VECTOR (int16x4x2_t)
++TEST_VECTOR (int32x2x2_t)
++TEST_VECTOR (int64x1x2_t)
++TEST_VECTOR (float16x4x2_t)
++TEST_VECTOR (bfloat16x4x2_t)
++TEST_VECTOR (float32x2x2_t)
++TEST_VECTOR (float64x1x2_t)
++
++/*
++** mov_int8x8x2_t:
++**	fmov	d0, d2
++**	fmov	d1, d3
++**	ret
++*/
++/*
++** load_int8x8x2_t:
++**	ldp	d0, d1, \[x0\]
++**	ret
++*/
++/*
++** store_int8x8x2_t:
++**	stp	d0, d1, \[x0\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv3x16qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv3x16qi_1.c
+new file mode 100644
+index 000000000..070a596bf
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv3x16qi_1.c
+@@ -0,0 +1,44 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC aarch64 "arm_neon.h"
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_VECTOR (int8x16x3_t)
++TEST_VECTOR (int16x8x3_t)
++TEST_VECTOR (int32x4x3_t)
++TEST_VECTOR (int64x2x3_t)
++TEST_VECTOR (float16x8x3_t)
++TEST_VECTOR (bfloat16x8x3_t)
++TEST_VECTOR (float32x4x3_t)
++TEST_VECTOR (float64x2x3_t)
++
++/*
++** mov_int8x16x3_t:
++**	sub	sp, sp, #48
++**	stp	q3, q4, \[sp\]
++**	str	q5, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\]
++**	ldr	q2, \[sp, #?32\]
++**	add	sp, sp, #?48
++**	ret
++*/
++/*
++** load_int8x16x3_t:
++**	ldp	q0, q1, \[x0\]
++**	ldr	q2, \[x0, #?32\]
++**	ret
++*/
++/*
++** store_int8x16x3_t: { xfail *-*-* }
++**	stp	q0, q1, \[x0\]
++**	stp	q2, \[x0, #?32\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv3x8qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv3x8qi_1.c
+new file mode 100644
+index 000000000..4b873d749
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv3x8qi_1.c
+@@ -0,0 +1,41 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC aarch64 "arm_neon.h"
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_VECTOR (int8x8x3_t)
++TEST_VECTOR (int16x4x3_t)
++TEST_VECTOR (int32x2x3_t)
++TEST_VECTOR (int64x1x3_t)
++TEST_VECTOR (float16x4x3_t)
++TEST_VECTOR (bfloat16x4x3_t)
++TEST_VECTOR (float32x2x3_t)
++TEST_VECTOR (float64x1x3_t)
++
++/*
++** mov_int8x8x3_t:
++**	fmov	d0, d3
++**	fmov	d1, d4
++**	fmov	d2, d5
++**	ret
++*/
++/*
++** load_int8x8x3_t:
++**	ldp	d0, d1, \[x0\]
++**	ldr	d2, \[x0, #?16\]
++**	ret
++*/
++/*
++** store_int8x8x3_t:
++**	stp	d0, d1, \[x0\]
++**	str	d2, \[x0, #?16\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv4x16qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv4x16qi_1.c
+new file mode 100644
+index 000000000..6a517b4fe
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv4x16qi_1.c
+@@ -0,0 +1,44 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC aarch64 "arm_neon.h"
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_VECTOR (int8x16x4_t)
++TEST_VECTOR (int16x8x4_t)
++TEST_VECTOR (int32x4x4_t)
++TEST_VECTOR (int64x2x4_t)
++TEST_VECTOR (float16x8x4_t)
++TEST_VECTOR (bfloat16x8x4_t)
++TEST_VECTOR (float32x4x4_t)
++TEST_VECTOR (float64x2x4_t)
++
++/*
++** mov_int8x16x4_t:
++**	sub	sp, sp, #64
++**	stp	q4, q5, \[sp\]
++**	stp	q6, q7, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\]
++**	ldp	q2, q3, \[sp, #?32\]
++**	add	sp, sp, #?64
++**	ret
++*/
++/*
++** load_int8x16x4_t:
++**	ldp	q0, q1, \[x0\]
++**	ldp	q2, q3, \[x0, #?32\]
++**	ret
++*/
++/*
++** store_int8x16x4_t: { xfail *-*-* }
++**	stp	q0, q1, \[x0\]
++**	stp	q2, q3, \[x0, #?32\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv4x8qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv4x8qi_1.c
+new file mode 100644
+index 000000000..f096be4a5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv4x8qi_1.c
+@@ -0,0 +1,42 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC aarch64 "arm_neon.h"
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_VECTOR (int8x8x4_t)
++TEST_VECTOR (int16x4x4_t)
++TEST_VECTOR (int32x2x4_t)
++TEST_VECTOR (int64x1x4_t)
++TEST_VECTOR (float16x4x4_t)
++TEST_VECTOR (bfloat16x4x4_t)
++TEST_VECTOR (float32x2x4_t)
++TEST_VECTOR (float64x1x4_t)
++
++/*
++** mov_int8x8x4_t:
++**	fmov	d0, d4
++**	fmov	d1, d5
++**	fmov	d2, d6
++**	fmov	d3, d7
++**	ret
++*/
++/*
++** load_int8x8x4_t:
++**	ldp	d0, d1, \[x0\]
++**	ldp	d2, d3, \[x0, #?16\]
++**	ret
++*/
++/*
++** store_int8x8x4_t:
++**	stp	d0, d1, \[x0\]
++**	stp	d2, d3, \[x0, #?16\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c b/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c
+index 4c97e6fbc..d2b5d8025 100644
+--- a/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/movv8qi_1.c
+@@ -53,3 +53,18 @@ fpr_to_gpr (v8qi q0)
+   x0 = q0;
+   asm volatile ("" :: "r" (x0));
+ }
++
++/*
++** gpr_to_gpr:
++**	mov	x0, x1
++**	ret
++*/
++void
++gpr_to_gpr ()
++{
++  register v8qi x0 asm ("x0");
++  register v8qi x1 asm ("x1");
++  asm volatile ("" : "=r" (x1));
++  x0 = x1;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv8qi_2.c b/gcc/testsuite/gcc.target/aarch64/movv8qi_2.c
+new file mode 100644
+index 000000000..0d8576ffe
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv8qi_2.c
+@@ -0,0 +1,27 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_GENERAL(TYPE) \
++  TYPE mov_##TYPE (TYPE a, TYPE b) { return b; } \
++  TYPE zero_##TYPE () { return (TYPE) {}; } \
++  TYPE load_##TYPE (TYPE *ptr) { return *ptr; } \
++  void store_##TYPE (TYPE *ptr, TYPE a) { *ptr = a; }
++
++TEST_GENERAL (__Int8x8_t)
++TEST_GENERAL (__Int16x4_t)
++TEST_GENERAL (__Int32x2_t)
++TEST_GENERAL (__Int64x1_t)
++TEST_GENERAL (__Bfloat16x4_t)
++TEST_GENERAL (__Float16x4_t)
++TEST_GENERAL (__Float32x2_t)
++TEST_GENERAL (__Float64x1_t)
++
++__Int8x8_t const_s8x8 () { return (__Int8x8_t) { 1, 1, 1, 1, 1, 1, 1, 1 }; }
++__Int16x4_t const_s16x4 () { return (__Int16x4_t) { 1, 0, 1, 0 }; }
++__Int32x2_t const_s32x2 () { return (__Int32x2_t) { 1, 2 }; }
++__Int64x1_t const_s64x1 () { return (__Int64x1_t) { 100 }; }
++__Float16x4_t const_f16x4 () { return (__Float16x4_t) { 2, 2, 2, 2 }; }
++__Float32x2_t const_f32x2 () { return (__Float32x2_t) { 1, 2 }; }
++__Float64x1_t const_f64x1 () { return (__Float64x1_t) { 32 }; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv8qi_3.c b/gcc/testsuite/gcc.target/aarch64/movv8qi_3.c
+new file mode 100644
+index 000000000..1caa1a788
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv8qi_3.c
+@@ -0,0 +1,30 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nosimd+fp"
++
++#define TEST_VECTOR(TYPE) \
++  TYPE \
++  test_##TYPE (void) \
++  { \
++    typedef TYPE v __attribute__((aligned(1))); \
++    register v *ptr asm ("x0"); \
++    asm volatile ("" : "=r" (ptr)); \
++    return *ptr; \
++  }
++
++TEST_VECTOR (__Int8x8_t)
++TEST_VECTOR (__Int16x4_t)
++TEST_VECTOR (__Int32x2_t)
++TEST_VECTOR (__Int64x1_t)
++TEST_VECTOR (__Bfloat16x4_t)
++TEST_VECTOR (__Float16x4_t)
++TEST_VECTOR (__Float32x2_t)
++TEST_VECTOR (__Float64x1_t)
++
++/*
++** test___Int8x8_t:
++**	ldr	d0, \[x0\]
++**	ret
++*/
+diff --git a/gcc/testsuite/gcc.target/aarch64/vect_unary_2.c b/gcc/testsuite/gcc.target/aarch64/vect_unary_2.c
+new file mode 100644
+index 000000000..454ac2771
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/vect_unary_2.c
+@@ -0,0 +1,5 @@
++/* { dg-options "-O3 -fno-math-errno --save-temps" } */
++
++#pragma GCC target "+nosimd+fp"
++
++#include "vect_unary_1.c"
+-- 
+2.33.0
+
diff --git a/0158-Backport-SME-aarch64-Simplify-output-template-emissi.patch b/0158-Backport-SME-aarch64-Simplify-output-template-emissi.patch
new file mode 100644
index 0000000..6d50608
--- /dev/null
+++ b/0158-Backport-SME-aarch64-Simplify-output-template-emissi.patch
@@ -0,0 +1,213 @@
+From b51d3b1af24758534e5a8f3a52a56106b935c485 Mon Sep 17 00:00:00 2001
+From: Kyrylo Tkachov 
+Date: Wed, 31 May 2023 11:23:23 +0100
+Subject: [PATCH 059/157] [Backport][SME] aarch64: Simplify output template
+ emission code for a few patterns
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=11bd9b1f8133fc07c267e6d1aee8b01e06c7a750
+
+If the output code for a define_insn just does a switch (which_alternative) with no other computation we can almost always
+replace it with more compact MD syntax for each alternative in a mult-alternative '@' block.
+This patch cleans up some such patterns in the aarch64 backend, making them shorter and more concise.
+No behavioural change intended.
+
+Bootstrapped and tested on aarch64-none-linux-gnu.
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64-simd.md (*aarch64_simd_mov): Rewrite
+	output template to avoid explicit switch on which_alternative.
+	(*aarch64_simd_mov): Likewise.
+	(and3): Likewise.
+	(ior3): Likewise.
+	* config/aarch64/aarch64.md (*mov_aarch64): Likewise.
+---
+ gcc/config/aarch64/aarch64-simd.md | 97 +++++++++---------------------
+ gcc/config/aarch64/aarch64.md      | 42 ++++---------
+ 2 files changed, 40 insertions(+), 99 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index ef7fc4ecb..2d688edf5 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -122,28 +122,16 @@
+   "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+-{
+-   switch (which_alternative)
+-     {
+-     case 0: return "ldr\t%d0, %1";
+-     case 1: return "str\txzr, %0";
+-     case 2: return "str\t%d1, %0";
+-     case 3:
+-       if (TARGET_SIMD)
+-	 return "mov\t%0., %1.";
+-       return "fmov\t%d0, %d1";
+-     case 4:
+-       if (TARGET_SIMD)
+-	 return "umov\t%0, %1.d[0]";
+-       return "fmov\t%x0, %d1";
+-     case 5: return "fmov\t%d0, %1";
+-     case 6: return "mov\t%0, %1";
+-     case 7:
+-	return aarch64_output_simd_mov_immediate (operands[1], 64);
+-     case 8: return "fmov\t%d0, xzr";
+-     default: gcc_unreachable ();
+-     }
+-}
++  "@
++   ldr\t%d0, %1
++   str\txzr, %0
++   str\t%d1, %0
++   * return TARGET_SIMD ? \"mov\t%0., %1.\" : \"fmov\t%d0, %d1\";
++   * return TARGET_SIMD ? \"umov\t%0, %1.d[0]\" : \"fmov\t%x0, %d1\";
++   fmov\t%d0, %1
++   mov\t%0, %1
++   * return aarch64_output_simd_mov_immediate (operands[1], 64);
++   fmov\t%d0, xzr"
+   [(set_attr "type" "neon_load1_1reg, store_8, neon_store1_1reg,\
+ 		     neon_logic, neon_to_gp, f_mcr,\
+ 		     mov_reg, neon_move, f_mcr")
+@@ -158,29 +146,16 @@
+   "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+-{
+-  switch (which_alternative)
+-    {
+-    case 0:
+-	return "ldr\t%q0, %1";
+-    case 1:
+-	return "stp\txzr, xzr, %0";
+-    case 2:
+-	return "str\t%q1, %0";
+-    case 3:
+-	return "mov\t%0., %1.";
+-    case 4:
+-    case 5:
+-    case 6:
+-	return "#";
+-    case 7:
+-	return aarch64_output_simd_mov_immediate (operands[1], 128);
+-    case 8:
+-	return "fmov\t%d0, xzr";
+-    default:
+-	gcc_unreachable ();
+-    }
+-}
++  "@
++   ldr\t%q0, %1
++   stp\txzr, xzr, %0
++   str\t%q1, %0
++   mov\t%0., %1.
++   #
++   #
++   #
++   * return aarch64_output_simd_mov_immediate (operands[1], 128);
++   fmov\t%d0, xzr"
+   [(set_attr "type" "neon_load1_1reg, store_16, neon_store1_1reg,\
+ 		     neon_logic, multiple, multiple,\
+ 		     multiple, neon_move, fmov")
+@@ -1004,18 +979,10 @@
+ 	(and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+ 		   (match_operand:VDQ_I 2 "aarch64_reg_or_bic_imm" "w,Db")))]
+   "TARGET_SIMD"
+-  {
+-    switch (which_alternative)
+-      {
+-      case 0:
+-	return "and\t%0., %1., %2.";
+-      case 1:
+-	return aarch64_output_simd_mov_immediate (operands[2], ,
+-						  AARCH64_CHECK_BIC);
+-      default:
+-	gcc_unreachable ();
+-      }
+-  }
++  "@
++   and\t%0., %1., %2.
++   * return aarch64_output_simd_mov_immediate (operands[2], ,\
++					       AARCH64_CHECK_BIC);"
+   [(set_attr "type" "neon_logic")]
+ )
+ 
+@@ -1025,18 +992,10 @@
+ 	(ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+ 		   (match_operand:VDQ_I 2 "aarch64_reg_or_orr_imm" "w,Do")))]
+   "TARGET_SIMD"
+-  {
+-    switch (which_alternative)
+-      {
+-      case 0:
+-	return "orr\t%0., %1., %2.";
+-      case 1:
+-	return aarch64_output_simd_mov_immediate (operands[2], ,
+-						  AARCH64_CHECK_ORR);
+-      default:
+-	gcc_unreachable ();
+-      }
+-  }
++  "@
++   orr\t%0., %1., %2.
++   * return aarch64_output_simd_mov_immediate (operands[2], ,\
++					       AARCH64_CHECK_ORR);"
+   [(set_attr "type" "neon_logic")]
+ )
+ 
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index c0cc91756..7454a5c77 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1198,36 +1198,18 @@
+ 	(match_operand:SHORT 1 "aarch64_mov_operand"  " r,M,D,Usv,m,m,rZ,w,w,rZ,w"))]
+   "(register_operand (operands[0], mode)
+     || aarch64_reg_or_zero (operands[1], mode))"
+-{
+-   switch (which_alternative)
+-     {
+-     case 0:
+-       return "mov\t%w0, %w1";
+-     case 1:
+-       return "mov\t%w0, %1";
+-     case 2:
+-       return aarch64_output_scalar_simd_mov_immediate (operands[1],
+-							mode);
+-     case 3:
+-       return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+-     case 4:
+-       return "ldr\t%w0, %1";
+-     case 5:
+-       return "ldr\t%0, %1";
+-     case 6:
+-       return "str\t%w1, %0";
+-     case 7:
+-       return "str\t%1, %0";
+-     case 8:
+-       return TARGET_SIMD ? "umov\t%w0, %1.[0]" : "fmov\t%w0, %s1";
+-     case 9:
+-       return TARGET_SIMD ? "dup\t%0., %w1" : "fmov\t%s0, %w1";
+-     case 10:
+-       return TARGET_SIMD ? "dup\t%0, %1.[0]" : "fmov\t%s0, %s1";
+-     default:
+-       gcc_unreachable ();
+-     }
+-}
++  "@
++   mov\t%w0, %w1
++   mov\t%w0, %1
++   * return aarch64_output_scalar_simd_mov_immediate (operands[1], mode);
++   * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
++   ldr\t%w0, %1
++   ldr\t%0, %1
++   str\t%w1, %0
++   str\t%1, %0
++   * return TARGET_SIMD ? \"umov\t%w0, %1.[0]\" : \"fmov\t%w0, %s1\";
++   * return TARGET_SIMD ? \"dup\t%0., %w1\" : \"fmov\t%s0, %w1\";
++   * return TARGET_SIMD ? \"dup\t%0, %1.[0]\" : \"fmov\t%s0, %s1\";"
+   ;; The "mov_imm" type for CNT is just a placeholder.
+   [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
+ 		     store_4,neon_to_gp,neon_from_gp,neon_dup")
+-- 
+2.33.0
+
diff --git a/0159-Backport-SME-Improve-immediate-expansion-PR106583.patch b/0159-Backport-SME-Improve-immediate-expansion-PR106583.patch
new file mode 100644
index 0000000..4ecbdd8
--- /dev/null
+++ b/0159-Backport-SME-Improve-immediate-expansion-PR106583.patch
@@ -0,0 +1,631 @@
+From d5293e2a8db54245553e01ad5d791b7492ad6101 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra 
+Date: Mon, 24 Oct 2022 15:14:14 +0100
+Subject: [PATCH 060/157] [Backport][SME] Improve immediate expansion
+ [PR106583]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a096036589d82175a0f729c2dab73c9a527d075d
+
+Improve immediate expansion of immediates which can be created from a
+bitmask immediate and 2 MOVKs.  Simplify, refactor and improve efficiency
+of bitmask checks.  Move various immediate handling functions together
+to avoid forward declarations.
+
+This reduces the number of 4-instruction immediates in SPECINT/FP by 10-15%.
+
+gcc/
+
+	PR target/106583
+	* config/aarch64/aarch64.cc (aarch64_internal_mov_immediate)
+	Add support for a bitmask immediate with 2 MOVKs.
+	(aarch64_check_bitmask): New function after refactorization.
+	(aarch64_bitmask_imm): Simplify replication of small modes.
+	Split function into 64-bit only version for efficiency.
+	(aarch64_move_imm): Move near other immediate functions.
+	(aarch64_uimm12_shift): Likewise.
+	(aarch64_clamp_to_uimm12_shift): Likewise.
+	(aarch64_movk_shift): Likewise.
+	(aarch64_replicate_bitmask_imm): Likewise.
+	(aarch64_and_split_imm1): Likewise.
+	(aarch64_and_split_imm2): Likewise.
+	(aarch64_and_bitmask_imm): Likewise.
+	(aarch64_movw_imm): Likewise.
+
+gcc/testsuite/
+	PR target/106583
+	* gcc.target/aarch64/pr106583.c: Add new test.
+---
+ gcc/config/aarch64/aarch64.cc               | 485 +++++++++++---------
+ gcc/testsuite/gcc.target/aarch64/pr106583.c |  41 ++
+ 2 files changed, 301 insertions(+), 225 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/pr106583.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index b4b646fa0..cf7736994 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -305,7 +305,6 @@ static bool aarch64_builtin_support_vector_misalignment (machine_mode mode,
+ static machine_mode aarch64_simd_container_mode (scalar_mode, poly_int64);
+ static bool aarch64_print_address_internal (FILE*, machine_mode, rtx,
+ 					    aarch64_addr_query_type);
+-static HOST_WIDE_INT aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val);
+ 
+ /* The processor for which instructions should be scheduled.  */
+ enum aarch64_processor aarch64_tune = cortexa53;
+@@ -5756,6 +5755,143 @@ aarch64_output_sve_vector_inc_dec (const char *operands, rtx x)
+ 					     factor, nelts_per_vq);
+ }
+ 
++/* Multipliers for repeating bitmasks of width 32, 16, 8, 4, and 2.  */
++
++static const unsigned HOST_WIDE_INT bitmask_imm_mul[] =
++  {
++    0x0000000100000001ull,
++    0x0001000100010001ull,
++    0x0101010101010101ull,
++    0x1111111111111111ull,
++    0x5555555555555555ull,
++  };
++
++
++
++/* Return true if 64-bit VAL is a valid bitmask immediate.  */
++static bool
++aarch64_bitmask_imm (unsigned HOST_WIDE_INT val)
++{
++  unsigned HOST_WIDE_INT tmp, mask, first_one, next_one;
++  int bits;
++
++  /* Check for a single sequence of one bits and return quickly if so.
++     The special cases of all ones and all zeroes returns false.  */
++  tmp = val + (val & -val);
++
++  if (tmp == (tmp & -tmp))
++    return (val + 1) > 1;
++
++  /* Invert if the immediate doesn't start with a zero bit - this means we
++     only need to search for sequences of one bits.  */
++  if (val & 1)
++    val = ~val;
++
++  /* Find the first set bit and set tmp to val with the first sequence of one
++     bits removed.  Return success if there is a single sequence of ones.  */
++  first_one = val & -val;
++  tmp = val & (val + first_one);
++
++  if (tmp == 0)
++    return true;
++
++  /* Find the next set bit and compute the difference in bit position.  */
++  next_one = tmp & -tmp;
++  bits = clz_hwi (first_one) - clz_hwi (next_one);
++  mask = val ^ tmp;
++
++  /* Check the bit position difference is a power of 2, and that the first
++     sequence of one bits fits within 'bits' bits.  */
++  if ((mask >> bits) != 0 || bits != (bits & -bits))
++    return false;
++
++  /* Check the sequence of one bits is repeated 64/bits times.  */
++  return val == mask * bitmask_imm_mul[__builtin_clz (bits) - 26];
++}
++
++
++/* Return true if VAL is a valid bitmask immediate for MODE.  */
++bool
++aarch64_bitmask_imm (HOST_WIDE_INT val_in, machine_mode mode)
++{
++  if (mode == DImode)
++    return aarch64_bitmask_imm (val_in);
++
++  unsigned HOST_WIDE_INT val = val_in;
++
++  if (mode == SImode)
++    return aarch64_bitmask_imm ((val & 0xffffffff) | (val << 32));
++
++  /* Replicate small immediates to fit 64 bits.  */
++  int size = GET_MODE_UNIT_PRECISION (mode);
++  val &= (HOST_WIDE_INT_1U << size) - 1;
++  val *= bitmask_imm_mul[__builtin_clz (size) - 26];
++
++  return aarch64_bitmask_imm (val);
++}
++
++
++/* Return true if the immediate VAL can be a bitfield immediate
++   by changing the given MASK bits in VAL to zeroes, ones or bits
++   from the other half of VAL.  Return the new immediate in VAL2.  */
++static inline bool
++aarch64_check_bitmask (unsigned HOST_WIDE_INT val,
++		       unsigned HOST_WIDE_INT &val2,
++		       unsigned HOST_WIDE_INT mask)
++{
++  val2 = val & ~mask;
++  if (val2 != val && aarch64_bitmask_imm (val2))
++    return true;
++  val2 = val | mask;
++  if (val2 != val && aarch64_bitmask_imm (val2))
++    return true;
++  val = val & ~mask;
++  val2 = val | (((val >> 32) | (val << 32)) & mask);
++  if (val2 != val && aarch64_bitmask_imm (val2))
++    return true;
++  val2 = val | (((val >> 16) | (val << 48)) & mask);
++  if (val2 != val && aarch64_bitmask_imm (val2))
++    return true;
++  return false;
++}
++
++
++/* Return true if val is an immediate that can be loaded into a
++   register by a MOVZ instruction.  */
++static bool
++aarch64_movw_imm (HOST_WIDE_INT val, scalar_int_mode mode)
++{
++  if (GET_MODE_SIZE (mode) > 4)
++    {
++      if ((val & (((HOST_WIDE_INT) 0xffff) << 32)) == val
++	   || (val & (((HOST_WIDE_INT) 0xffff) << 48)) == val)
++	return 1;
++    }
++  else
++    {
++      /* Ignore sign extension.  */
++      val &= (HOST_WIDE_INT) 0xffffffff;
++    }
++  return ((val & (((HOST_WIDE_INT) 0xffff) << 0)) == val
++	  || (val & (((HOST_WIDE_INT) 0xffff) << 16)) == val);
++}
++
++
++/* Return true if VAL is an immediate that can be loaded into a
++   register in a single instruction.  */
++bool
++aarch64_move_imm (HOST_WIDE_INT val, machine_mode mode)
++{
++  scalar_int_mode int_mode;
++  if (!is_a  (mode, &int_mode))
++    return false;
++
++  if (aarch64_movw_imm (val, int_mode) || aarch64_movw_imm (~val, int_mode))
++    return 1;
++  return aarch64_bitmask_imm (val, int_mode);
++}
++
++
+ static int
+ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
+ 				scalar_int_mode mode)
+@@ -5786,7 +5922,7 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
+ 	emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
+ 
+       /* Check if we have to emit a second instruction by checking to see
+-         if any of the upper 32 bits of the original DI mode value is set.  */
++	 if any of the upper 32 bits of the original DI mode value is set.  */
+       if (val == val2)
+ 	return 1;
+ 
+@@ -5822,36 +5958,43 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
+   one_match = ((~val & mask) == 0) + ((~val & (mask << 16)) == 0) +
+     ((~val & (mask << 32)) == 0) + ((~val & (mask << 48)) == 0);
+ 
+-  if (zero_match != 2 && one_match != 2)
++  if (zero_match < 2 && one_match < 2)
+     {
+       /* Try emitting a bitmask immediate with a movk replacing 16 bits.
+ 	 For a 64-bit bitmask try whether changing 16 bits to all ones or
+ 	 zeroes creates a valid bitmask.  To check any repeated bitmask,
+ 	 try using 16 bits from the other 32-bit half of val.  */
+ 
+-      for (i = 0; i < 64; i += 16, mask <<= 16)
+-	{
+-	  val2 = val & ~mask;
+-	  if (val2 != val && aarch64_bitmask_imm (val2, mode))
+-	    break;
+-	  val2 = val | mask;
+-	  if (val2 != val && aarch64_bitmask_imm (val2, mode))
+-	    break;
+-	  val2 = val2 & ~mask;
+-	  val2 = val2 | (((val2 >> 32) | (val2 << 32)) & mask);
+-	  if (val2 != val && aarch64_bitmask_imm (val2, mode))
+-	    break;
+-	}
+-      if (i != 64)
+-	{
+-	  if (generate)
++      for (i = 0; i < 64; i += 16)
++	if (aarch64_check_bitmask (val, val2, mask << i))
++	  {
++	    if (generate)
++	      {
++		emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
++		emit_insn (gen_insv_immdi (dest, GEN_INT (i),
++					   GEN_INT ((val >> i) & 0xffff)));
++	      }
++	    return 2;
++	  }
++    }
++
++  /* Try a bitmask plus 2 movk to generate the immediate in 3 instructions.  */
++  if (zero_match + one_match == 0)
++    {
++      for (i = 0; i < 48; i += 16)
++	for (int j = i + 16; j < 64; j += 16)
++	  if (aarch64_check_bitmask (val, val2, (mask << i) | (mask << j)))
+ 	    {
+-	      emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
+-	      emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+-					 GEN_INT ((val >> i) & 0xffff)));
++	      if (generate)
++		{
++		  emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
++		  emit_insn (gen_insv_immdi (dest, GEN_INT (i),
++					     GEN_INT ((val >> i) & 0xffff)));
++		  emit_insn (gen_insv_immdi (dest, GEN_INT (j),
++					       GEN_INT ((val >> j) & 0xffff)));
++		}
++	      return 3;
+ 	    }
+-	  return 2;
+-	}
+     }
+ 
+   /* Generate 2-4 instructions, skipping 16 bits of all zeroes or ones which
+@@ -5898,6 +6041,99 @@ aarch64_mov128_immediate (rtx imm)
+ }
+ 
+ 
++/* Return true if val can be encoded as a 12-bit unsigned immediate with
++   a left shift of 0 or 12 bits.  */
++bool
++aarch64_uimm12_shift (HOST_WIDE_INT val)
++{
++  return ((val & (((HOST_WIDE_INT) 0xfff) << 0)) == val
++	  || (val & (((HOST_WIDE_INT) 0xfff) << 12)) == val
++	  );
++}
++
++/* Returns the nearest value to VAL that will fit as a 12-bit unsigned immediate
++   that can be created with a left shift of 0 or 12.  */
++static HOST_WIDE_INT
++aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val)
++{
++  /* Check to see if the value fits in 24 bits, as that is the maximum we can
++     handle correctly.  */
++  gcc_assert ((val & 0xffffff) == val);
++
++  if (((val & 0xfff) << 0) == val)
++    return val;
++
++  return val & (0xfff << 12);
++}
++
++
++/* Test whether:
++
++     X = (X & AND_VAL) | IOR_VAL;
++
++   can be implemented using:
++
++     MOVK X, #(IOR_VAL >> shift), LSL #shift
++
++   Return the shift if so, otherwise return -1.  */
++int
++aarch64_movk_shift (const wide_int_ref &and_val,
++		    const wide_int_ref &ior_val)
++{
++  unsigned int precision = and_val.get_precision ();
++  unsigned HOST_WIDE_INT mask = 0xffff;
++  for (unsigned int shift = 0; shift < precision; shift += 16)
++    {
++      if (and_val == ~mask && (ior_val & mask) == ior_val)
++	return shift;
++      mask <<= 16;
++    }
++  return -1;
++}
++
++/* Create mask of ones, covering the lowest to highest bits set in VAL_IN.
++   Assumed precondition: VAL_IN Is not zero.  */
++
++unsigned HOST_WIDE_INT
++aarch64_and_split_imm1 (HOST_WIDE_INT val_in)
++{
++  int lowest_bit_set = ctz_hwi (val_in);
++  int highest_bit_set = floor_log2 (val_in);
++  gcc_assert (val_in != 0);
++
++  return ((HOST_WIDE_INT_UC (2) << highest_bit_set) -
++	  (HOST_WIDE_INT_1U << lowest_bit_set));
++}
++
++/* Create constant where bits outside of lowest bit set to highest bit set
++   are set to 1.  */
++
++unsigned HOST_WIDE_INT
++aarch64_and_split_imm2 (HOST_WIDE_INT val_in)
++{
++  return val_in | ~aarch64_and_split_imm1 (val_in);
++}
++
++/* Return true if VAL_IN is a valid 'and' bitmask immediate.  */
++
++bool
++aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode)
++{
++  scalar_int_mode int_mode;
++  if (!is_a  (mode, &int_mode))
++    return false;
++
++  if (aarch64_bitmask_imm (val_in, int_mode))
++    return false;
++
++  if (aarch64_move_imm (val_in, int_mode))
++    return false;
++
++  unsigned HOST_WIDE_INT imm2 = aarch64_and_split_imm2 (val_in);
++
++  return aarch64_bitmask_imm (imm2, int_mode);
++}
++
+ /* Return the number of temporary registers that aarch64_add_offset_1
+    would need to add OFFSET to a register.  */
+ 
+@@ -10379,207 +10615,6 @@ aarch64_tls_referenced_p (rtx x)
+ }
+ 
+ 
+-/* Return true if val can be encoded as a 12-bit unsigned immediate with
+-   a left shift of 0 or 12 bits.  */
+-bool
+-aarch64_uimm12_shift (HOST_WIDE_INT val)
+-{
+-  return ((val & (((HOST_WIDE_INT) 0xfff) << 0)) == val
+-	  || (val & (((HOST_WIDE_INT) 0xfff) << 12)) == val
+-	  );
+-}
+-
+-/* Returns the nearest value to VAL that will fit as a 12-bit unsigned immediate
+-   that can be created with a left shift of 0 or 12.  */
+-static HOST_WIDE_INT
+-aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val)
+-{
+-  /* Check to see if the value fits in 24 bits, as that is the maximum we can
+-     handle correctly.  */
+-  gcc_assert ((val & 0xffffff) == val);
+-
+-  if (((val & 0xfff) << 0) == val)
+-    return val;
+-
+-  return val & (0xfff << 12);
+-}
+-
+-/* Return true if val is an immediate that can be loaded into a
+-   register by a MOVZ instruction.  */
+-static bool
+-aarch64_movw_imm (HOST_WIDE_INT val, scalar_int_mode mode)
+-{
+-  if (GET_MODE_SIZE (mode) > 4)
+-    {
+-      if ((val & (((HOST_WIDE_INT) 0xffff) << 32)) == val
+-	  || (val & (((HOST_WIDE_INT) 0xffff) << 48)) == val)
+-	return 1;
+-    }
+-  else
+-    {
+-      /* Ignore sign extension.  */
+-      val &= (HOST_WIDE_INT) 0xffffffff;
+-    }
+-  return ((val & (((HOST_WIDE_INT) 0xffff) << 0)) == val
+-	  || (val & (((HOST_WIDE_INT) 0xffff) << 16)) == val);
+-}
+-
+-/* Test whether:
+-
+-     X = (X & AND_VAL) | IOR_VAL;
+-
+-   can be implemented using:
+-
+-     MOVK X, #(IOR_VAL >> shift), LSL #shift
+-
+-   Return the shift if so, otherwise return -1.  */
+-int
+-aarch64_movk_shift (const wide_int_ref &and_val,
+-		    const wide_int_ref &ior_val)
+-{
+-  unsigned int precision = and_val.get_precision ();
+-  unsigned HOST_WIDE_INT mask = 0xffff;
+-  for (unsigned int shift = 0; shift < precision; shift += 16)
+-    {
+-      if (and_val == ~mask && (ior_val & mask) == ior_val)
+-	return shift;
+-      mask <<= 16;
+-    }
+-  return -1;
+-}
+-
+-/* VAL is a value with the inner mode of MODE.  Replicate it to fill a
+-   64-bit (DImode) integer.  */
+-
+-static unsigned HOST_WIDE_INT
+-aarch64_replicate_bitmask_imm (unsigned HOST_WIDE_INT val, machine_mode mode)
+-{
+-  unsigned int size = GET_MODE_UNIT_PRECISION (mode);
+-  while (size < 64)
+-    {
+-      val &= (HOST_WIDE_INT_1U << size) - 1;
+-      val |= val << size;
+-      size *= 2;
+-    }
+-  return val;
+-}
+-
+-/* Multipliers for repeating bitmasks of width 32, 16, 8, 4, and 2.  */
+-
+-static const unsigned HOST_WIDE_INT bitmask_imm_mul[] =
+-  {
+-    0x0000000100000001ull,
+-    0x0001000100010001ull,
+-    0x0101010101010101ull,
+-    0x1111111111111111ull,
+-    0x5555555555555555ull,
+-  };
+-
+-
+-/* Return true if val is a valid bitmask immediate.  */
+-
+-bool
+-aarch64_bitmask_imm (HOST_WIDE_INT val_in, machine_mode mode)
+-{
+-  unsigned HOST_WIDE_INT val, tmp, mask, first_one, next_one;
+-  int bits;
+-
+-  /* Check for a single sequence of one bits and return quickly if so.
+-     The special cases of all ones and all zeroes returns false.  */
+-  val = aarch64_replicate_bitmask_imm (val_in, mode);
+-  tmp = val + (val & -val);
+-
+-  if (tmp == (tmp & -tmp))
+-    return (val + 1) > 1;
+-
+-  /* Replicate 32-bit immediates so we can treat them as 64-bit.  */
+-  if (mode == SImode)
+-    val = (val << 32) | (val & 0xffffffff);
+-
+-  /* Invert if the immediate doesn't start with a zero bit - this means we
+-     only need to search for sequences of one bits.  */
+-  if (val & 1)
+-    val = ~val;
+-
+-  /* Find the first set bit and set tmp to val with the first sequence of one
+-     bits removed.  Return success if there is a single sequence of ones.  */
+-  first_one = val & -val;
+-  tmp = val & (val + first_one);
+-
+-  if (tmp == 0)
+-    return true;
+-
+-  /* Find the next set bit and compute the difference in bit position.  */
+-  next_one = tmp & -tmp;
+-  bits = clz_hwi (first_one) - clz_hwi (next_one);
+-  mask = val ^ tmp;
+-
+-  /* Check the bit position difference is a power of 2, and that the first
+-     sequence of one bits fits within 'bits' bits.  */
+-  if ((mask >> bits) != 0 || bits != (bits & -bits))
+-    return false;
+-
+-  /* Check the sequence of one bits is repeated 64/bits times.  */
+-  return val == mask * bitmask_imm_mul[__builtin_clz (bits) - 26];
+-}
+-
+-/* Create mask of ones, covering the lowest to highest bits set in VAL_IN.  
+-   Assumed precondition: VAL_IN Is not zero.  */
+-
+-unsigned HOST_WIDE_INT
+-aarch64_and_split_imm1 (HOST_WIDE_INT val_in)
+-{
+-  int lowest_bit_set = ctz_hwi (val_in);
+-  int highest_bit_set = floor_log2 (val_in);
+-  gcc_assert (val_in != 0);
+-
+-  return ((HOST_WIDE_INT_UC (2) << highest_bit_set) -
+-	  (HOST_WIDE_INT_1U << lowest_bit_set));
+-}
+-
+-/* Create constant where bits outside of lowest bit set to highest bit set
+-   are set to 1.  */
+-
+-unsigned HOST_WIDE_INT
+-aarch64_and_split_imm2 (HOST_WIDE_INT val_in)
+-{
+-  return val_in | ~aarch64_and_split_imm1 (val_in);
+-}
+-
+-/* Return true if VAL_IN is a valid 'and' bitmask immediate.  */
+-
+-bool
+-aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode)
+-{
+-  scalar_int_mode int_mode;
+-  if (!is_a  (mode, &int_mode))
+-    return false;
+-
+-  if (aarch64_bitmask_imm (val_in, int_mode))
+-    return false;
+-
+-  if (aarch64_move_imm (val_in, int_mode))
+-    return false;
+-
+-  unsigned HOST_WIDE_INT imm2 = aarch64_and_split_imm2 (val_in);
+-
+-  return aarch64_bitmask_imm (imm2, int_mode);
+-}
+-
+-/* Return true if val is an immediate that can be loaded into a
+-   register in a single instruction.  */
+-bool
+-aarch64_move_imm (HOST_WIDE_INT val, machine_mode mode)
+-{
+-  scalar_int_mode int_mode;
+-  if (!is_a  (mode, &int_mode))
+-    return false;
+-
+-  if (aarch64_movw_imm (val, int_mode) || aarch64_movw_imm (~val, int_mode))
+-    return 1;
+-  return aarch64_bitmask_imm (val, int_mode);
+-}
+-
+ static bool
+ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+ {
+diff --git a/gcc/testsuite/gcc.target/aarch64/pr106583.c b/gcc/testsuite/gcc.target/aarch64/pr106583.c
+new file mode 100644
+index 000000000..0f9315808
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/pr106583.c
+@@ -0,0 +1,41 @@
++/* { dg-do assemble } */
++/* { dg-options "-O2 --save-temps" } */
++
++long f1 (void)
++{
++  return 0x7efefefefefefeff;
++}
++
++long f2 (void)
++{
++  return 0x12345678aaaaaaaa;
++}
++
++long f3 (void)
++{
++  return 0x1234cccccccc5678;
++}
++
++long f4 (void)
++{
++  return 0x7777123456787777;
++}
++
++long f5 (void)
++{
++  return 0x5555555512345678;
++}
++
++long f6 (void)
++{
++  return 0x1234bbbb5678bbbb;
++}
++
++long f7 (void)
++{
++  return 0x4444123444445678;
++}
++
++
++/* { dg-final { scan-assembler-times {\tmovk\t} 14 } } */
++/* { dg-final { scan-assembler-times {\tmov\t} 7 } } */
+-- 
+2.33.0
+
diff --git a/0160-Backport-SME-AArch64-Cleanup-move-immediate-code.patch b/0160-Backport-SME-AArch64-Cleanup-move-immediate-code.patch
new file mode 100644
index 0000000..dc06698
--- /dev/null
+++ b/0160-Backport-SME-AArch64-Cleanup-move-immediate-code.patch
@@ -0,0 +1,410 @@
+From d76be4acadc0641cc8e795cd6b8a1c3c83b4fdb2 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra 
+Date: Mon, 5 Dec 2022 10:49:25 +0000
+Subject: [PATCH 061/157] [Backport][SME] AArch64: Cleanup move immediate code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ba1536dac780f3f92c5eab999fda6931f6247fc1
+
+Simplify, refactor and improve various move immediate functions.
+Allow 32-bit MOVN/I as a valid 64-bit immediate which removes special
+cases in aarch64_internal_mov_immediate.  Add new constraint so the movdi
+pattern only needs a single alternative for move immediate.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_bitmask_imm): Use unsigned type.
+	(aarch64_is_mov_xn_imm): New function.
+	(aarch64_move_imm): Refactor, assert mode is SImode or DImode.
+	(aarch64_internal_mov_immediate): Assert mode is SImode or DImode.
+	Simplify special cases.
+	(aarch64_uimm12_shift): Simplify code.
+	(aarch64_clamp_to_uimm12_shift): Likewise.
+	(aarch64_movw_imm): Rename to aarch64_is_movz.
+	(aarch64_float_const_rtx_p): Pass either SImode or DImode to
+	aarch64_internal_mov_immediate.
+	(aarch64_rtx_costs): Likewise.
+	* config/aarch64/aarch64.md (movdi_aarch64): Merge 'N' and 'M'
+	constraints into single 'O'.
+	(mov_aarch64): Likewise.
+	* config/aarch64/aarch64-protos.h (aarch64_move_imm): Use unsigned.
+	(aarch64_bitmask_imm): Likewise.
+	(aarch64_uimm12_shift): Likewise.
+	(aarch64_is_mov_xn_imm): New prototype.
+	* config/aarch64/constraints.md: Add 'O' for 32/64-bit immediates,
+	limit 'N' to 64-bit only moves.
+---
+ gcc/config/aarch64/aarch64-protos.h |   7 +-
+ gcc/config/aarch64/aarch64.cc       | 158 ++++++++++++----------------
+ gcc/config/aarch64/aarch64.md       |  17 ++-
+ gcc/config/aarch64/constraints.md   |   5 +
+ 4 files changed, 85 insertions(+), 102 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 97984f3ab..3ff1a0163 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -755,7 +755,7 @@ void aarch64_post_cfi_startproc (void);
+ poly_int64 aarch64_initial_elimination_offset (unsigned, unsigned);
+ int aarch64_get_condition_code (rtx);
+ bool aarch64_address_valid_for_prefetch_p (rtx, bool);
+-bool aarch64_bitmask_imm (HOST_WIDE_INT val, machine_mode);
++bool aarch64_bitmask_imm (unsigned HOST_WIDE_INT val, machine_mode);
+ unsigned HOST_WIDE_INT aarch64_and_split_imm1 (HOST_WIDE_INT val_in);
+ unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in);
+ bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode);
+@@ -793,7 +793,7 @@ bool aarch64_masks_and_shift_for_bfi_p (scalar_int_mode, unsigned HOST_WIDE_INT,
+ 					unsigned HOST_WIDE_INT,
+ 					unsigned HOST_WIDE_INT);
+ bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
+-bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
++bool aarch64_move_imm (unsigned HOST_WIDE_INT, machine_mode);
+ machine_mode aarch64_sve_int_mode (machine_mode);
+ opt_machine_mode aarch64_sve_pred_mode (unsigned int);
+ machine_mode aarch64_sve_pred_mode (machine_mode);
+@@ -843,8 +843,9 @@ bool aarch64_sve_float_arith_immediate_p (rtx, bool);
+ bool aarch64_sve_float_mul_immediate_p (rtx);
+ bool aarch64_split_dimode_const_store (rtx, rtx);
+ bool aarch64_symbolic_address_p (rtx);
+-bool aarch64_uimm12_shift (HOST_WIDE_INT);
++bool aarch64_uimm12_shift (unsigned HOST_WIDE_INT);
+ int aarch64_movk_shift (const wide_int_ref &, const wide_int_ref &);
++bool aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT);
+ bool aarch64_use_return_insn_p (void);
+ const char *aarch64_output_casesi (rtx *);
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index cf7736994..acb659f53 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -5812,12 +5812,10 @@ aarch64_bitmask_imm (unsigned HOST_WIDE_INT val)
+ 
+ /* Return true if VAL is a valid bitmask immediate for MODE.  */
+ bool
+-aarch64_bitmask_imm (HOST_WIDE_INT val_in, machine_mode mode)
++aarch64_bitmask_imm (unsigned HOST_WIDE_INT val, machine_mode mode)
+ {
+   if (mode == DImode)
+-    return aarch64_bitmask_imm (val_in);
+-
+-  unsigned HOST_WIDE_INT val = val_in;
++    return aarch64_bitmask_imm (val);
+ 
+   if (mode == SImode)
+     return aarch64_bitmask_imm ((val & 0xffffffff) | (val << 32));
+@@ -5856,51 +5854,55 @@ aarch64_check_bitmask (unsigned HOST_WIDE_INT val,
+ }
+ 
+ 
+-/* Return true if val is an immediate that can be loaded into a
+-   register by a MOVZ instruction.  */
+-static bool
+-aarch64_movw_imm (HOST_WIDE_INT val, scalar_int_mode mode)
++/* Return true if VAL is a valid MOVZ immediate.  */
++static inline bool
++aarch64_is_movz (unsigned HOST_WIDE_INT val)
+ {
+-  if (GET_MODE_SIZE (mode) > 4)
+-    {
+-      if ((val & (((HOST_WIDE_INT) 0xffff) << 32)) == val
+-	   || (val & (((HOST_WIDE_INT) 0xffff) << 48)) == val)
+-	return 1;
+-    }
+-  else
+-    {
+-      /* Ignore sign extension.  */
+-      val &= (HOST_WIDE_INT) 0xffffffff;
+-    }
+-  return ((val & (((HOST_WIDE_INT) 0xffff) << 0)) == val
+-	  || (val & (((HOST_WIDE_INT) 0xffff) << 16)) == val);
++  return (val >> (ctz_hwi (val) & 48)) < 65536;
+ }
+ 
+ 
+-/* Return true if VAL is an immediate that can be loaded into a
+-   register in a single instruction.  */
++/* Return true if immediate VAL can be created by a 64-bit MOVI/MOVN/MOVZ.  */
+ bool
+-aarch64_move_imm (HOST_WIDE_INT val, machine_mode mode)
++aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT val)
+ {
+-  scalar_int_mode int_mode;
+-  if (!is_a  (mode, &int_mode))
+-    return false;
++  return aarch64_is_movz (val) || aarch64_is_movz (~val)
++    || aarch64_bitmask_imm (val);
++}
+ 
+-  if (aarch64_movw_imm (val, int_mode) || aarch64_movw_imm (~val, int_mode))
+-    return 1;
+-  return aarch64_bitmask_imm (val, int_mode);
++
++/* Return true if VAL is an immediate that can be created by a single
++   MOV instruction.  */
++bool
++aarch64_move_imm (unsigned HOST_WIDE_INT val, machine_mode mode)
++{
++  gcc_assert (mode == SImode || mode == DImode);
++
++  if (val < 65536)
++    return true;
++
++  unsigned HOST_WIDE_INT mask =
++    (val >> 32) == 0 || mode == SImode ? 0xffffffff : HOST_WIDE_INT_M1U;
++
++  if (aarch64_is_movz (val & mask) || aarch64_is_movz (~val & mask))
++    return true;
++
++  val = (val & mask) | ((val << 32) & ~mask);
++  return aarch64_bitmask_imm (val);
+ }
+ 
+ 
+ static int
+ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
+-				scalar_int_mode mode)
++				machine_mode mode)
+ {
+   int i;
+   unsigned HOST_WIDE_INT val, val2, mask;
+   int one_match, zero_match;
+   int num_insns;
+ 
++  gcc_assert (mode == SImode || mode == DImode);
++
+   val = INTVAL (imm);
+ 
+   if (aarch64_move_imm (val, mode))
+@@ -5910,31 +5912,6 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
+       return 1;
+     }
+ 
+-  /* Check to see if the low 32 bits are either 0xffffXXXX or 0xXXXXffff
+-     (with XXXX non-zero). In that case check to see if the move can be done in
+-     a smaller mode.  */
+-  val2 = val & 0xffffffff;
+-  if (mode == DImode
+-      && aarch64_move_imm (val2, SImode)
+-      && (((val >> 32) & 0xffff) == 0 || (val >> 48) == 0))
+-    {
+-      if (generate)
+-	emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
+-
+-      /* Check if we have to emit a second instruction by checking to see
+-	 if any of the upper 32 bits of the original DI mode value is set.  */
+-      if (val == val2)
+-	return 1;
+-
+-      i = (val >> 48) ? 48 : 32;
+-
+-      if (generate)
+-	 emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+-				    GEN_INT ((val >> i) & 0xffff)));
+-
+-      return 2;
+-    }
+-
+   if ((val >> 32) == 0 || mode == SImode)
+     {
+       if (generate)
+@@ -5958,24 +5935,31 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
+   one_match = ((~val & mask) == 0) + ((~val & (mask << 16)) == 0) +
+     ((~val & (mask << 32)) == 0) + ((~val & (mask << 48)) == 0);
+ 
++  /* Try a bitmask immediate and a movk to generate the immediate
++     in 2 instructions.  */
++
+   if (zero_match < 2 && one_match < 2)
+     {
+-      /* Try emitting a bitmask immediate with a movk replacing 16 bits.
+-	 For a 64-bit bitmask try whether changing 16 bits to all ones or
+-	 zeroes creates a valid bitmask.  To check any repeated bitmask,
+-	 try using 16 bits from the other 32-bit half of val.  */
+-
+       for (i = 0; i < 64; i += 16)
+-	if (aarch64_check_bitmask (val, val2, mask << i))
+-	  {
+-	    if (generate)
+-	      {
+-		emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
+-		emit_insn (gen_insv_immdi (dest, GEN_INT (i),
+-					   GEN_INT ((val >> i) & 0xffff)));
+-	      }
+-	    return 2;
+-	  }
++	{
++	  if (aarch64_check_bitmask (val, val2, mask << i))
++	    break;
++
++	  val2 = val & ~(mask << i);
++	  if ((val2 >> 32) == 0 && aarch64_move_imm (val2, DImode))
++	    break;
++	}
++
++      if (i != 64)
++	{
++	  if (generate)
++	    {
++	      emit_insn (gen_rtx_SET (dest, GEN_INT (val2)));
++	      emit_insn (gen_insv_immdi (dest, GEN_INT (i),
++					 GEN_INT ((val >> i) & 0xffff)));
++	    }
++	  return 2;
++	}
+     }
+ 
+   /* Try a bitmask plus 2 movk to generate the immediate in 3 instructions.  */
+@@ -6044,26 +6028,24 @@ aarch64_mov128_immediate (rtx imm)
+ /* Return true if val can be encoded as a 12-bit unsigned immediate with
+    a left shift of 0 or 12 bits.  */
+ bool
+-aarch64_uimm12_shift (HOST_WIDE_INT val)
++aarch64_uimm12_shift (unsigned HOST_WIDE_INT val)
+ {
+-  return ((val & (((HOST_WIDE_INT) 0xfff) << 0)) == val
+-	  || (val & (((HOST_WIDE_INT) 0xfff) << 12)) == val
+-	  );
++  return val < 4096 || (val & 0xfff000) == val;
+ }
+ 
+ /* Returns the nearest value to VAL that will fit as a 12-bit unsigned immediate
+    that can be created with a left shift of 0 or 12.  */
+ static HOST_WIDE_INT
+-aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val)
++aarch64_clamp_to_uimm12_shift (unsigned HOST_WIDE_INT val)
+ {
+   /* Check to see if the value fits in 24 bits, as that is the maximum we can
+      handle correctly.  */
+-  gcc_assert ((val & 0xffffff) == val);
++  gcc_assert (val < 0x1000000);
+ 
+-  if (((val & 0xfff) << 0) == val)
++  if (val < 4096)
+     return val;
+ 
+-  return val & (0xfff << 12);
++  return val & 0xfff000;
+ }
+ 
+ 
+@@ -7211,8 +7193,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+       return;
+     }
+ 
+-  aarch64_internal_mov_immediate (dest, imm, true,
+-				  as_a  (mode));
++  aarch64_internal_mov_immediate (dest, imm, true, mode);
+ }
+ 
+ /* Return the MEM rtx that provides the canary value that should be used
+@@ -11410,9 +11391,7 @@ aarch64_float_const_rtx_p (rtx x)
+       && SCALAR_FLOAT_MODE_P (mode)
+       && aarch64_reinterpret_float_as_int (x, &ival))
+     {
+-      scalar_int_mode imode = (mode == HFmode
+-			       ? SImode
+-			       : int_mode_for_mode (mode).require ());
++      machine_mode imode = known_eq (GET_MODE_SIZE (mode), 8) ? DImode : SImode;
+       int num_instr = aarch64_internal_mov_immediate
+ 			(NULL_RTX, gen_int_mode (ival, imode), false, imode);
+       return num_instr < 3;
+@@ -14049,10 +14028,10 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
+ 	     proportionally expensive to the number of instructions
+ 	     required to build that constant.  This is true whether we
+ 	     are compiling for SPEED or otherwise.  */
+-	  if (!is_a  (mode, &int_mode))
+-	    int_mode = word_mode;
++	  machine_mode imode = known_le (GET_MODE_SIZE (mode), 4)
++				? SImode : DImode;
+ 	  *cost = COSTS_N_INSNS (aarch64_internal_mov_immediate
+-				 (NULL_RTX, x, false, int_mode));
++				 (NULL_RTX, x, false, imode));
+ 	}
+       return true;
+ 
+@@ -14068,9 +14047,8 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
+ 	  bool succeed = aarch64_reinterpret_float_as_int (x, &ival);
+ 	  gcc_assert (succeed);
+ 
+-	  scalar_int_mode imode = (mode == HFmode
+-				   ? SImode
+-				   : int_mode_for_mode (mode).require ());
++	  machine_mode imode = known_eq (GET_MODE_SIZE (mode), 8)
++				? DImode : SImode;
+ 	  int ncost = aarch64_internal_mov_immediate
+ 		(NULL_RTX, gen_int_mode (ival, imode), false, imode);
+ 	  *cost += COSTS_N_INSNS (ncost);
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 7454a5c77..ea94152bf 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1288,16 +1288,15 @@
+ )
+ 
+ (define_insn_and_split "*movdi_aarch64"
+-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m,   r,  r,  r, w,r,w, w")
+-	(match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,N,M,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Dd"))]
++  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m,m,   r,  r,  r, w,r,w, w")
++	(match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,O,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Dd"))]
+   "(register_operand (operands[0], DImode)
+     || aarch64_reg_or_zero (operands[1], DImode))"
+   "@
+    mov\\t%x0, %x1
+    mov\\t%0, %x1
+    mov\\t%x0, %1
+-   mov\\t%x0, %1
+-   mov\\t%w0, %1
++   * return aarch64_is_mov_xn_imm (INTVAL (operands[1])) ? \"mov\\t%x0, %1\" : \"mov\\t%w0, %1\";
+    #
+    * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+    ldr\\t%x0, %1
+@@ -1319,11 +1318,11 @@
+        DONE;
+     }"
+   ;; The "mov_imm" type for CNTD is just a placeholder.
+-  [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
++  [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,
+ 		     load_8,load_8,store_8,store_8,load_8,adr,adr,f_mcr,f_mrc,
+ 		     fmov,neon_move")
+-   (set_attr "arch"   "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
+-   (set_attr "length" "4,4,4,4,4,*,  4,4, 4,4, 4,8,4,4, 4, 4, 4,   4")]
++   (set_attr "arch"   "*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
++   (set_attr "length" "4,4,4,4,*,  4,4, 4,4, 4,8,4,4, 4, 4, 4,   4")]
+ )
+ 
+ (define_insn "insv_imm"
+@@ -1487,7 +1486,7 @@
+ 
+ (define_insn "*mov_aarch64"
+   [(set (match_operand:DFD 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+-	(match_operand:DFD 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
++	(match_operand:DFD 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,O"))]
+   "TARGET_FLOAT && (register_operand (operands[0], mode)
+     || aarch64_reg_or_fp_zero (operands[1], mode))"
+   "@
+@@ -1502,7 +1501,7 @@
+    ldr\\t%x0, %1
+    str\\t%x1, %0
+    mov\\t%x0, %x1
+-   mov\\t%x0, %1"
++   * return aarch64_is_mov_xn_imm (INTVAL (operands[1])) ? \"mov\\t%x0, %1\" : \"mov\\t%w0, %1\";"
+   [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
+ 		     f_loadd,f_stored,load_8,store_8,mov_reg,\
+ 		     fconstd")
+diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
+index ee7587cca..750a42fb1 100644
+--- a/gcc/config/aarch64/constraints.md
++++ b/gcc/config/aarch64/constraints.md
+@@ -106,6 +106,11 @@
+ 
+ (define_constraint "N"
+  "A constant that can be used with a 64-bit MOV immediate operation."
++ (and (match_code "const_int")
++      (match_test "aarch64_is_mov_xn_imm (ival)")))
++
++(define_constraint "O"
++ "A constant that can be used with a 32 or 64-bit MOV immediate operation."
+  (and (match_code "const_int")
+       (match_test "aarch64_move_imm (ival, DImode)")))
+ 
+-- 
+2.33.0
+
diff --git a/0161-Backport-SME-AArch64-convert-some-patterns-to-compac.patch b/0161-Backport-SME-AArch64-convert-some-patterns-to-compac.patch
new file mode 100644
index 0000000..6ccc4c3
--- /dev/null
+++ b/0161-Backport-SME-AArch64-convert-some-patterns-to-compac.patch
@@ -0,0 +1,229 @@
+From 5db3e7b68d5a443e908011b8d53de625ae462f82 Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Mon, 19 Jun 2023 15:55:28 +0100
+Subject: [PATCH 062/157] [Backport][SME] AArch64: convert some patterns to
+ compact MD syntax
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c72a7b849853716d94e8d313be5dce3c22850113
+
+Hi All,
+
+This converts some patterns in the AArch64 backend to use the new
+compact syntax.
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64.md (arches): Add nosimd.
+	(*mov_aarch64, *movsi_aarch64, *movdi_aarch64): Rewrite to
+	compact syntax.
+---
+ gcc/config/aarch64/aarch64.md | 161 ++++++++++++++++------------------
+ 1 file changed, 78 insertions(+), 83 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index ea94152bf..5d02da42f 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -378,7 +378,7 @@
+ ;; As a convenience, "fp_q" means "fp" + the ability to move between
+ ;; Q registers and is equivalent to "simd".
+ 
+-(define_enum "arches" [ any rcpc8_4 fp fp_q simd sve fp16])
++(define_enum "arches" [ any rcpc8_4 fp fp_q simd nosimd sve fp16])
+ 
+ (define_enum_attr "arch" "arches" (const_string "any"))
+ 
+@@ -409,6 +409,9 @@
+ 	(and (eq_attr "arch" "fp_q, simd")
+ 	     (match_test "TARGET_SIMD"))
+ 
++	(and (eq_attr "arch" "nosimd")
++	     (match_test "!TARGET_SIMD"))
++
+ 	(and (eq_attr "arch" "fp16")
+ 	     (match_test "TARGET_FP_F16INST"))
+ 
+@@ -1194,26 +1197,27 @@
+ )
+ 
+ (define_insn "*mov_aarch64"
+-  [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,    w,r  ,r,w, m,m,r,w,w")
+-	(match_operand:SHORT 1 "aarch64_mov_operand"  " r,M,D,Usv,m,m,rZ,w,w,rZ,w"))]
++  [(set (match_operand:SHORT 0 "nonimmediate_operand")
++	(match_operand:SHORT 1 "aarch64_mov_operand"))]
+   "(register_operand (operands[0], mode)
+     || aarch64_reg_or_zero (operands[1], mode))"
+-  "@
+-   mov\t%w0, %w1
+-   mov\t%w0, %1
+-   * return aarch64_output_scalar_simd_mov_immediate (operands[1], mode);
+-   * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+-   ldr\t%w0, %1
+-   ldr\t%0, %1
+-   str\t%w1, %0
+-   str\t%1, %0
+-   * return TARGET_SIMD ? \"umov\t%w0, %1.[0]\" : \"fmov\t%w0, %s1\";
+-   * return TARGET_SIMD ? \"dup\t%0., %w1\" : \"fmov\t%s0, %w1\";
+-   * return TARGET_SIMD ? \"dup\t%0, %1.[0]\" : \"fmov\t%s0, %s1\";"
+-  ;; The "mov_imm" type for CNT is just a placeholder.
+-  [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
+-		     store_4,neon_to_gp,neon_from_gp,neon_dup")
+-   (set_attr "arch" "*,*,simd,sve,*,*,*,*,*,*,*")]
++  {@ [cons: =0, 1; attrs: type, arch]
++     [r, r    ; mov_reg        , *     ] mov\t%w0, %w1
++     [r, M    ; mov_imm        , *     ] mov\t%w0, %1
++     [w, D; neon_move      , simd  ] << aarch64_output_scalar_simd_mov_immediate (operands[1], mode);
++     /* The "mov_imm" type for CNT is just a placeholder.  */
++     [r, Usv  ; mov_imm        , sve   ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r, m    ; load_4         , *     ] ldr\t%w0, %1
++     [w, m    ; load_4         , *     ] ldr\t%0, %1
++     [m, r Z  ; store_4        , *     ] str\\t%w1, %0
++     [m, w    ; store_4        , *     ] str\t%1, %0
++     [r, w    ; neon_to_gp  , simd  ] umov\t%w0, %1.[0]
++     [r, w    ; neon_to_gp  , nosimd] fmov\t%w0, %s1 /*foo */
++     [w, r Z  ; neon_from_gp, simd  ] dup\t%0., %w1
++     [w, r Z  ; neon_from_gp, nosimd] fmov\t%s0, %w1
++     [w, w    ; neon_dup       , simd  ] dup\t%0, %1.[0]
++     [w, w    ; neon_dup       , nosimd] fmov\t%s0, %s1
++  }
+ )
+ 
+ (define_expand "mov"
+@@ -1250,79 +1254,70 @@
+ )
+ 
+ (define_insn_and_split "*movsi_aarch64"
+-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m,  r,  r,  r, w,r,w, w")
+-	(match_operand:SI 1 "aarch64_mov_operand"  " r,r,k,M,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Ds"))]
++  [(set (match_operand:SI 0 "nonimmediate_operand")
++	(match_operand:SI 1 "aarch64_mov_operand"))]
+   "(register_operand (operands[0], SImode)
+     || aarch64_reg_or_zero (operands[1], SImode))"
+-  "@
+-   mov\\t%w0, %w1
+-   mov\\t%w0, %w1
+-   mov\\t%w0, %w1
+-   mov\\t%w0, %1
+-   #
+-   * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+-   ldr\\t%w0, %1
+-   ldr\\t%s0, %1
+-   str\\t%w1, %0
+-   str\\t%s1, %0
+-   adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]
+-   adr\\t%x0, %c1
+-   adrp\\t%x0, %A1
+-   fmov\\t%s0, %w1
+-   fmov\\t%w0, %s1
+-   fmov\\t%s0, %s1
+-   * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
++  {@ [cons: =0, 1; attrs: type, arch, length]
++     [r k, r  ; mov_reg  , *   , 4] mov\t%w0, %w1
++     [r  , k  ; mov_reg  , *   , 4] ^
++     [r  , M  ; mov_imm  , *   , 4] mov\t%w0, %1
++     [r  , n  ; mov_imm  , *   ,16] #
++     /* The "mov_imm" type for CNT is just a placeholder.  */
++     [r  , Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r  , m  ; load_4   , *   , 4] ldr\t%w0, %1
++     [w  , m  ; load_4   , fp  , 4] ldr\t%s0, %1
++     [m  , r Z; store_4  , *   , 4] str\t%w1, %0
++     [m  , w  ; store_4  , fp  , 4] str\t%s1, %0
++     [r  , Usw; load_4   , *   , 8] adrp\t%x0, %A1;ldr\t%w0, [%x0, %L1]
++     [r  , Usa; adr      , *   , 4] adr\t%x0, %c1
++     [r  , Ush; adr      , *   , 4] adrp\t%x0, %A1
++     [w  , r Z; f_mcr    , fp  , 4] fmov\t%s0, %w1
++     [r  , w  ; f_mrc    , fp  , 4] fmov\t%w0, %s1
++     [w  , w  ; fmov     , fp  , 4] fmov\t%s0, %s1
++     [w  , Ds ; neon_move, simd, 4] << aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
++  }
+   "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
+     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
+-   [(const_int 0)]
+-   "{
+-       aarch64_expand_mov_immediate (operands[0], operands[1]);
+-       DONE;
+-    }"
+-  ;; The "mov_imm" type for CNT is just a placeholder.
+-  [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
+-		    load_4,store_4,store_4,load_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
+-   (set_attr "arch"   "*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
+-   (set_attr "length" "4,4,4,4,*,  4,4, 4,4, 4,8,4,4, 4, 4, 4,   4")
+-]
++  [(const_int 0)]
++  {
++    aarch64_expand_mov_immediate (operands[0], operands[1]);
++    DONE;
++  }
+ )
+ 
+ (define_insn_and_split "*movdi_aarch64"
+-  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m,m,   r,  r,  r, w,r,w, w")
+-	(match_operand:DI 1 "aarch64_mov_operand"  " r,r,k,O,n,Usv,m,m,rZ,w,Usw,Usa,Ush,rZ,w,w,Dd"))]
++  [(set (match_operand:DI 0 "nonimmediate_operand")
++	(match_operand:DI 1 "aarch64_mov_operand"))]
+   "(register_operand (operands[0], DImode)
+     || aarch64_reg_or_zero (operands[1], DImode))"
+-  "@
+-   mov\\t%x0, %x1
+-   mov\\t%0, %x1
+-   mov\\t%x0, %1
+-   * return aarch64_is_mov_xn_imm (INTVAL (operands[1])) ? \"mov\\t%x0, %1\" : \"mov\\t%w0, %1\";
+-   #
+-   * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
+-   ldr\\t%x0, %1
+-   ldr\\t%d0, %1
+-   str\\t%x1, %0
+-   str\\t%d1, %0
+-   * return TARGET_ILP32 ? \"adrp\\t%0, %A1\;ldr\\t%w0, [%0, %L1]\" : \"adrp\\t%0, %A1\;ldr\\t%0, [%0, %L1]\";
+-   adr\\t%x0, %c1
+-   adrp\\t%x0, %A1
+-   fmov\\t%d0, %x1
+-   fmov\\t%x0, %d1
+-   fmov\\t%d0, %d1
+-   * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
+-   "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode)
+-    && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
+-   [(const_int 0)]
+-   "{
+-       aarch64_expand_mov_immediate (operands[0], operands[1]);
+-       DONE;
+-    }"
+-  ;; The "mov_imm" type for CNTD is just a placeholder.
+-  [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,
+-		     load_8,load_8,store_8,store_8,load_8,adr,adr,f_mcr,f_mrc,
+-		     fmov,neon_move")
+-   (set_attr "arch"   "*,*,*,*,*,sve,*,fp,*,fp,*,*,*,fp,fp,fp,simd")
+-   (set_attr "length" "4,4,4,4,*,  4,4, 4,4, 4,8,4,4, 4, 4, 4,   4")]
++  {@ [cons: =0, 1; attrs: type, arch, length]
++     [r, r  ; mov_reg  , *   , 4] mov\t%x0, %x1
++     [k, r  ; mov_reg  , *   , 4] mov\t%0, %x1
++     [r, k  ; mov_reg  , *   , 4] mov\t%x0, %1
++     [r, O  ; mov_imm  , *   , 4] << aarch64_is_mov_xn_imm (INTVAL (operands[1])) ? "mov\t%x0, %1" : "mov\t%w0, %1";
++     [r, n  ; mov_imm  , *   ,16] #
++     /* The "mov_imm" type for CNT is just a placeholder.  */
++     [r, Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r, m  ; load_8   , *   , 4] ldr\t%x0, %1
++     [w, m  ; load_8   , fp  , 4] ldr\t%d0, %1
++     [m, r Z; store_8  , *   , 4] str\t%x1, %0
++     [m, w  ; store_8  , fp  , 4] str\t%d1, %0
++     [r, Usw; load_8   , *   , 8] << TARGET_ILP32 ? "adrp\t%0, %A1;ldr\t%w0, [%0, %L1]" : "adrp\t%0, %A1;ldr\t%0, [%0, %L1]";
++     [r, Usa; adr      , *   , 4] adr\t%x0, %c1
++     [r, Ush; adr      , *   , 4] adrp\t%x0, %A1
++     [w, r Z; f_mcr    , fp  , 4] fmov\t%d0, %x1
++     [r, w  ; f_mrc    , fp  , 4] fmov\t%x0, %d1
++     [w, w  ; fmov     , fp  , 4] fmov\t%d0, %d1
++     [w, Dd ; neon_move, simd, 4] << aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
++  }
++  "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode)
++   && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
++  [(const_int 0)]
++  {
++      aarch64_expand_mov_immediate (operands[0], operands[1]);
++      DONE;
++  }
+ )
+ 
+ (define_insn "insv_imm"
+-- 
+2.33.0
+
diff --git a/0162-Backport-SME-aarch64-Use-SVE-s-RDVL-instruction.patch b/0162-Backport-SME-aarch64-Use-SVE-s-RDVL-instruction.patch
new file mode 100644
index 0000000..f92df2d
--- /dev/null
+++ b/0162-Backport-SME-aarch64-Use-SVE-s-RDVL-instruction.patch
@@ -0,0 +1,792 @@
+From 46310765c05cde8732e07bfb0df9f0ec25a34018 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:18 +0000
+Subject: [PATCH 063/157] [Backport][SME] aarch64: Use SVE's RDVL instruction
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=80f47d7bbe38234e1530d27fe5c2f130223ca7a0
+
+We didn't previously use SVE's RDVL instruction, since the CNT*
+forms are preferred and provide most of the range.  However,
+there are some cases that RDVL can handle and CNT* can't,
+and using RDVL-like instructions becomes important for SME.
+
+gcc/
+	* config/aarch64/aarch64-protos.h (aarch64_sve_rdvl_immediate_p)
+	(aarch64_output_sve_rdvl): Declare.
+	* config/aarch64/aarch64.cc (aarch64_sve_cnt_factor_p): New
+	function, split out from...
+	(aarch64_sve_cnt_immediate_p): ...here.
+	(aarch64_sve_rdvl_factor_p): New function.
+	(aarch64_sve_rdvl_immediate_p): Likewise.
+	(aarch64_output_sve_rdvl): Likewise.
+	(aarch64_offset_temporaries): Rewrite the SVE handling to use RDVL
+	for some cases.
+	(aarch64_expand_mov_immediate): Handle RDVL immediates.
+	(aarch64_mov_operand_p): Likewise.
+	* config/aarch64/constraints.md (Usr): New constraint.
+	* config/aarch64/aarch64.md (*mov_aarch64): Add an RDVL
+	alternative.
+	(*movsi_aarch64, *movdi_aarch64): Likewise.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/acle/asm/cntb.c: Tweak expected output.
+	* gcc.target/aarch64/sve/acle/asm/cnth.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/cntw.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/cntd.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfb.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfh.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfw.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfd.c: Likewise.
+	* gcc.target/aarch64/sve/loop_add_4.c: Expect RDVL to be used
+	to calculate the -17 and 17 factors.
+	* gcc.target/aarch64/sve/pcs/stack_clash_1.c: Likewise the 18 factor.
+---
+ gcc/config/aarch64/aarch64-protos.h           |   2 +
+ gcc/config/aarch64/aarch64.cc                 | 191 ++++++++++++------
+ gcc/config/aarch64/aarch64.md                 |   3 +
+ gcc/config/aarch64/constraints.md             |   6 +
+ .../gcc.target/aarch64/sve/acle/asm/cntb.c    |  71 +++++--
+ .../gcc.target/aarch64/sve/acle/asm/cntd.c    |  12 +-
+ .../gcc.target/aarch64/sve/acle/asm/cnth.c    |  20 +-
+ .../gcc.target/aarch64/sve/acle/asm/cntw.c    |  16 +-
+ .../gcc.target/aarch64/sve/acle/asm/prfb.c    |   6 +-
+ .../gcc.target/aarch64/sve/acle/asm/prfd.c    |   4 +-
+ .../gcc.target/aarch64/sve/acle/asm/prfh.c    |   4 +-
+ .../gcc.target/aarch64/sve/acle/asm/prfw.c    |   4 +-
+ .../gcc.target/aarch64/sve/loop_add_4.c       |   6 +-
+ .../aarch64/sve/pcs/stack_clash_1.c           |   3 +-
+ 14 files changed, 225 insertions(+), 123 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 3ff1a0163..14a568140 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -802,6 +802,7 @@ bool aarch64_sve_mode_p (machine_mode);
+ HOST_WIDE_INT aarch64_fold_sve_cnt_pat (aarch64_svpattern, unsigned int);
+ bool aarch64_sve_cnt_immediate_p (rtx);
+ bool aarch64_sve_scalar_inc_dec_immediate_p (rtx);
++bool aarch64_sve_rdvl_immediate_p (rtx);
+ bool aarch64_sve_addvl_addpl_immediate_p (rtx);
+ bool aarch64_sve_vector_inc_dec_immediate_p (rtx);
+ int aarch64_add_offset_temporaries (rtx);
+@@ -814,6 +815,7 @@ char *aarch64_output_sve_prefetch (const char *, rtx, const char *);
+ char *aarch64_output_sve_cnt_immediate (const char *, const char *, rtx);
+ char *aarch64_output_sve_cnt_pat_immediate (const char *, const char *, rtx *);
+ char *aarch64_output_sve_scalar_inc_dec (rtx);
++char *aarch64_output_sve_rdvl (rtx);
+ char *aarch64_output_sve_addvl_addpl (rtx);
+ char *aarch64_output_sve_vector_inc_dec (const char *, rtx);
+ char *aarch64_output_scalar_simd_mov_immediate (rtx, scalar_int_mode);
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index acb659f53..4194dfc70 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -5520,6 +5520,18 @@ aarch64_fold_sve_cnt_pat (aarch64_svpattern pattern, unsigned int nelts_per_vq)
+   return -1;
+ }
+ 
++/* Return true if a single CNT[BHWD] instruction can multiply FACTOR
++   by the number of 128-bit quadwords in an SVE vector.  */
++
++static bool
++aarch64_sve_cnt_factor_p (HOST_WIDE_INT factor)
++{
++  /* The coefficient must be [1, 16] * {2, 4, 8, 16}.  */
++  return (IN_RANGE (factor, 2, 16 * 16)
++	  && (factor & 1) == 0
++	  && factor <= 16 * (factor & -factor));
++}
++
+ /* Return true if we can move VALUE into a register using a single
+    CNT[BHWD] instruction.  */
+ 
+@@ -5527,11 +5539,7 @@ static bool
+ aarch64_sve_cnt_immediate_p (poly_int64 value)
+ {
+   HOST_WIDE_INT factor = value.coeffs[0];
+-  /* The coefficient must be [1, 16] * {2, 4, 8, 16}.  */
+-  return (value.coeffs[1] == factor
+-	  && IN_RANGE (factor, 2, 16 * 16)
+-	  && (factor & 1) == 0
+-	  && factor <= 16 * (factor & -factor));
++  return value.coeffs[1] == factor && aarch64_sve_cnt_factor_p (factor);
+ }
+ 
+ /* Likewise for rtx X.  */
+@@ -5647,6 +5655,50 @@ aarch64_output_sve_scalar_inc_dec (rtx offset)
+ 					     -offset_value.coeffs[1], 0);
+ }
+ 
++/* Return true if a single RDVL instruction can multiply FACTOR by the
++   number of 128-bit quadwords in an SVE vector.  */
++
++static bool
++aarch64_sve_rdvl_factor_p (HOST_WIDE_INT factor)
++{
++  return (multiple_p (factor, 16)
++	  && IN_RANGE (factor, -32 * 16, 31 * 16));
++}
++
++/* Return true if we can move VALUE into a register using a single
++   RDVL instruction.  */
++
++static bool
++aarch64_sve_rdvl_immediate_p (poly_int64 value)
++{
++  HOST_WIDE_INT factor = value.coeffs[0];
++  return value.coeffs[1] == factor && aarch64_sve_rdvl_factor_p (factor);
++}
++
++/* Likewise for rtx X.  */
++
++bool
++aarch64_sve_rdvl_immediate_p (rtx x)
++{
++  poly_int64 value;
++  return poly_int_rtx_p (x, &value) && aarch64_sve_rdvl_immediate_p (value);
++}
++
++/* Return the asm string for moving RDVL immediate OFFSET into register
++   operand 0.  */
++
++char *
++aarch64_output_sve_rdvl (rtx offset)
++{
++  static char buffer[sizeof ("rdvl\t%x0, #-") + 3 * sizeof (int)];
++  poly_int64 offset_value = rtx_to_poly_int64 (offset);
++  gcc_assert (aarch64_sve_rdvl_immediate_p (offset_value));
++
++  int factor = offset_value.coeffs[1];
++  snprintf (buffer, sizeof (buffer), "rdvl\t%%x0, #%d", factor / 16);
++  return buffer;
++}
++
+ /* Return true if we can add VALUE to a register using a single ADDVL
+    or ADDPL instruction.  */
+ 
+@@ -6227,13 +6279,13 @@ aarch64_offset_temporaries (bool add_p, poly_int64 offset)
+     count += 1;
+   else if (factor != 0)
+     {
+-      factor = abs (factor);
+-      if (factor > 16 * (factor & -factor))
+-	/* Need one register for the CNT result and one for the multiplication
+-	   factor.  If necessary, the second temporary can be reused for the
+-	   constant part of the offset.  */
++      factor /= (HOST_WIDE_INT) least_bit_hwi (factor);
++      if (!IN_RANGE (factor, -32, 31))
++	/* Need one register for the CNT or RDVL result and one for the
++	   multiplication factor.  If necessary, the second temporary
++	   can be reused for the constant part of the offset.  */
+ 	return 2;
+-      /* Need one register for the CNT result (which might then
++      /* Need one register for the CNT or RDVL result (which might then
+ 	 be shifted).  */
+       count += 1;
+     }
+@@ -6322,85 +6374,100 @@ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+   /* Otherwise use a CNT-based sequence.  */
+   else if (factor != 0)
+     {
+-      /* Use a subtraction if we have a negative factor.  */
+-      rtx_code code = PLUS;
+-      if (factor < 0)
+-	{
+-	  factor = -factor;
+-	  code = MINUS;
+-	}
++      /* Calculate CNTB * FACTOR / 16 as CNTB * REL_FACTOR * 2**SHIFT,
++	 with negative shifts indicating a shift right.  */
++      HOST_WIDE_INT low_bit = least_bit_hwi (factor);
++      HOST_WIDE_INT rel_factor = factor / low_bit;
++      int shift = exact_log2 (low_bit) - 4;
++      gcc_assert (shift >= -4 && (rel_factor & 1) != 0);
++
++      /* Set CODE, VAL and SHIFT so that [+-] VAL * 2**SHIFT is
++	 equal to CNTB * FACTOR / 16, with CODE being the [+-].
+ 
+-      /* Calculate CNTD * FACTOR / 2.  First try to fold the division
+-	 into the multiplication.  */
++	 We can avoid a multiplication if REL_FACTOR is in the range
++	 of RDVL, although there are then various optimizations that
++	 we can try on top.  */
++      rtx_code code = PLUS;
+       rtx val;
+-      int shift = 0;
+-      if (factor & 1)
+-	/* Use a right shift by 1.  */
+-	shift = -1;
+-      else
+-	factor /= 2;
+-      HOST_WIDE_INT low_bit = factor & -factor;
+-      if (factor <= 16 * low_bit)
++      if (IN_RANGE (rel_factor, -32, 31))
+ 	{
+-	  if (factor > 16 * 8)
++	  /* Try to use an unshifted CNT[BHWD] or RDVL.  */
++	  if (aarch64_sve_cnt_factor_p (factor)
++	      || aarch64_sve_rdvl_factor_p (factor))
++	    {
++	      val = gen_int_mode (poly_int64 (factor, factor), mode);
++	      shift = 0;
++	    }
++	  /* Try to subtract an unshifted CNT[BHWD].  */
++	  else if (aarch64_sve_cnt_factor_p (-factor))
+ 	    {
+-	      /* "CNTB Xn, ALL, MUL #FACTOR" is out of range, so calculate
+-		 the value with the minimum multiplier and shift it into
+-		 position.  */
+-	      int extra_shift = exact_log2 (low_bit);
+-	      shift += extra_shift;
+-	      factor >>= extra_shift;
++	      code = MINUS;
++	      val = gen_int_mode (poly_int64 (-factor, -factor), mode);
++	      shift = 0;
+ 	    }
+-	  val = gen_int_mode (poly_int64 (factor * 2, factor * 2), mode);
++	  /* If subtraction is free, prefer to load a positive constant.
++	     In the best case this will fit a shifted CNTB.  */
++	  else if (src != const0_rtx && rel_factor < 0)
++	    {
++	      code = MINUS;
++	      val = gen_int_mode (-rel_factor * BYTES_PER_SVE_VECTOR, mode);
++	    }
++	  /* Otherwise use a shifted RDVL or CNT[BHWD].  */
++	  else
++	    val = gen_int_mode (rel_factor * BYTES_PER_SVE_VECTOR, mode);
+ 	}
+       else
+ 	{
+-	  /* Base the factor on LOW_BIT if we can calculate LOW_BIT
+-	     directly, since that should increase the chances of being
+-	     able to use a shift and add sequence.  If LOW_BIT itself
+-	     is out of range, just use CNTD.  */
+-	  if (low_bit <= 16 * 8)
+-	    factor /= low_bit;
++	  /* If we can calculate CNTB << SHIFT directly, prefer to do that,
++	     since it should increase the chances of being able to use
++	     a shift and add sequence for the multiplication.
++	     If CNTB << SHIFT is out of range, stick with the current
++	     shift factor.  */
++	  if (IN_RANGE (low_bit, 2, 16 * 16))
++	    {
++	      val = gen_int_mode (poly_int64 (low_bit, low_bit), mode);
++	      shift = 0;
++	    }
+ 	  else
+-	    low_bit = 1;
++	    val = gen_int_mode (BYTES_PER_SVE_VECTOR, mode);
+ 
+-	  val = gen_int_mode (poly_int64 (low_bit * 2, low_bit * 2), mode);
+ 	  val = aarch64_force_temporary (mode, temp1, val);
+ 
++	  /* Prefer to multiply by a positive factor and subtract rather
++	     than multiply by a negative factor and add, since positive
++	     values are usually easier to move.  */
++	  if (rel_factor < 0 && src != const0_rtx)
++	    {
++	      rel_factor = -rel_factor;
++	      code = MINUS;
++	    }
++
+ 	  if (can_create_pseudo_p ())
+ 	    {
+-	      rtx coeff1 = gen_int_mode (factor, mode);
++	      rtx coeff1 = gen_int_mode (rel_factor, mode);
+ 	      val = expand_mult (mode, val, coeff1, NULL_RTX, true, true);
+ 	    }
+ 	  else
+ 	    {
+-	      /* Go back to using a negative multiplication factor if we have
+-		 no register from which to subtract.  */
+-	      if (code == MINUS && src == const0_rtx)
+-		{
+-		  factor = -factor;
+-		  code = PLUS;
+-		}
+-	      rtx coeff1 = gen_int_mode (factor, mode);
++	      rtx coeff1 = gen_int_mode (rel_factor, mode);
+ 	      coeff1 = aarch64_force_temporary (mode, temp2, coeff1);
+ 	      val = gen_rtx_MULT (mode, val, coeff1);
+ 	    }
+ 	}
+ 
++      /* Multiply by 2 ** SHIFT.  */
+       if (shift > 0)
+ 	{
+-	  /* Multiply by 1 << SHIFT.  */
+ 	  val = aarch64_force_temporary (mode, temp1, val);
+ 	  val = gen_rtx_ASHIFT (mode, val, GEN_INT (shift));
+ 	}
+-      else if (shift == -1)
++      else if (shift < 0)
+ 	{
+-	  /* Divide by 2.  */
+ 	  val = aarch64_force_temporary (mode, temp1, val);
+-	  val = gen_rtx_ASHIFTRT (mode, val, const1_rtx);
++	  val = gen_rtx_ASHIFTRT (mode, val, GEN_INT (-shift));
+ 	}
+ 
+-      /* Calculate SRC +/- CNTD * FACTOR / 2.  */
++      /* Add the result to SRC or subtract the result from SRC.  */
+       if (src != const0_rtx)
+ 	{
+ 	  val = aarch64_force_temporary (mode, temp1, val);
+@@ -7045,7 +7112,9 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 	      aarch64_report_sve_required ();
+ 	      return;
+ 	    }
+-	  if (base == const0_rtx && aarch64_sve_cnt_immediate_p (offset))
++	  if (base == const0_rtx
++	      && (aarch64_sve_cnt_immediate_p (offset)
++		  || aarch64_sve_rdvl_immediate_p (offset)))
+ 	    emit_insn (gen_rtx_SET (dest, imm));
+ 	  else
+ 	    {
+@@ -21751,7 +21820,9 @@ aarch64_mov_operand_p (rtx x, machine_mode mode)
+   if (SYMBOL_REF_P (x) && mode == DImode && CONSTANT_ADDRESS_P (x))
+     return true;
+ 
+-  if (TARGET_SVE && aarch64_sve_cnt_immediate_p (x))
++  if (TARGET_SVE
++      && (aarch64_sve_cnt_immediate_p (x)
++	  || aarch64_sve_rdvl_immediate_p (x)))
+     return true;
+ 
+   return aarch64_classify_symbolic_expression (x)
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 5d02da42f..c0977a3da 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1207,6 +1207,7 @@
+      [w, D; neon_move      , simd  ] << aarch64_output_scalar_simd_mov_immediate (operands[1], mode);
+      /* The "mov_imm" type for CNT is just a placeholder.  */
+      [r, Usv  ; mov_imm        , sve   ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r, Usr  ; mov_imm        , sve   ] << aarch64_output_sve_rdvl (operands[1]);
+      [r, m    ; load_4         , *     ] ldr\t%w0, %1
+      [w, m    ; load_4         , *     ] ldr\t%0, %1
+      [m, r Z  ; store_4        , *     ] str\\t%w1, %0
+@@ -1265,6 +1266,7 @@
+      [r  , n  ; mov_imm  , *   ,16] #
+      /* The "mov_imm" type for CNT is just a placeholder.  */
+      [r  , Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r  , Usr; mov_imm  , sve,  4] << aarch64_output_sve_rdvl (operands[1]);
+      [r  , m  ; load_4   , *   , 4] ldr\t%w0, %1
+      [w  , m  ; load_4   , fp  , 4] ldr\t%s0, %1
+      [m  , r Z; store_4  , *   , 4] str\t%w1, %0
+@@ -1299,6 +1301,7 @@
+      [r, n  ; mov_imm  , *   ,16] #
+      /* The "mov_imm" type for CNT is just a placeholder.  */
+      [r, Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r, Usr; mov_imm  , sve,  4] << aarch64_output_sve_rdvl (operands[1]);
+      [r, m  ; load_8   , *   , 4] ldr\t%x0, %1
+      [w, m  ; load_8   , fp  , 4] ldr\t%d0, %1
+      [m, r Z; store_8  , *   , 4] str\t%x1, %0
+diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
+index 750a42fb1..212a73416 100644
+--- a/gcc/config/aarch64/constraints.md
++++ b/gcc/config/aarch64/constraints.md
+@@ -214,6 +214,12 @@
+  (and (match_code "const_int")
+       (match_test "aarch64_high_bits_all_ones_p (ival)")))
+ 
++(define_constraint "Usr"
++  "@internal
++   A constraint that matches a value produced by RDVL."
++ (and (match_code "const_poly_int")
++      (match_test "aarch64_sve_rdvl_immediate_p (op)")))
++
+ (define_constraint "Usv"
+   "@internal
+    A constraint that matches a VG-based constant that can be loaded by
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntb.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntb.c
+index 8b8fe8e4f..a22d8a28d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntb.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntb.c
+@@ -51,19 +51,24 @@ PROTO (cntb_15, uint64_t, ()) { return svcntb () * 15; }
+ */
+ PROTO (cntb_16, uint64_t, ()) { return svcntb () * 16; }
+ 
+-/* Other sequences would be OK.  */
+ /*
+ ** cntb_17:
+-**	cntb	x0, all, mul #16
+-**	incb	x0
++**	rdvl	x0, #17
+ **	ret
+ */
+ PROTO (cntb_17, uint64_t, ()) { return svcntb () * 17; }
+ 
++/*
++** cntb_31:
++**	rdvl	x0, #31
++**	ret
++*/
++PROTO (cntb_31, uint64_t, ()) { return svcntb () * 31; }
++
+ /*
+ ** cntb_32:
+-**	cntd	(x[0-9]+)
+-**	lsl	x0, \1, 8
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
+ **	ret
+ */
+ PROTO (cntb_32, uint64_t, ()) { return svcntb () * 32; }
+@@ -80,16 +85,16 @@ PROTO (cntb_33, uint64_t, ()) { return svcntb () * 33; }
+ 
+ /*
+ ** cntb_64:
+-**	cntd	(x[0-9]+)
+-**	lsl	x0, \1, 9
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 6
+ **	ret
+ */
+ PROTO (cntb_64, uint64_t, ()) { return svcntb () * 64; }
+ 
+ /*
+ ** cntb_128:
+-**	cntd	(x[0-9]+)
+-**	lsl	x0, \1, 10
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 7
+ **	ret
+ */
+ PROTO (cntb_128, uint64_t, ()) { return svcntb () * 128; }
+@@ -106,46 +111,70 @@ PROTO (cntb_129, uint64_t, ()) { return svcntb () * 129; }
+ 
+ /*
+ ** cntb_m1:
+-**	cntb	(x[0-9]+)
+-**	neg	x0, \1
++**	rdvl	x0, #-1
+ **	ret
+ */
+ PROTO (cntb_m1, uint64_t, ()) { return -svcntb (); }
+ 
+ /*
+ ** cntb_m13:
+-**	cntb	(x[0-9]+), all, mul #13
+-**	neg	x0, \1
++**	rdvl	x0, #-13
+ **	ret
+ */
+ PROTO (cntb_m13, uint64_t, ()) { return -svcntb () * 13; }
+ 
+ /*
+ ** cntb_m15:
+-**	cntb	(x[0-9]+), all, mul #15
+-**	neg	x0, \1
++**	rdvl	x0, #-15
+ **	ret
+ */
+ PROTO (cntb_m15, uint64_t, ()) { return -svcntb () * 15; }
+ 
+ /*
+ ** cntb_m16:
+-**	cntb	(x[0-9]+), all, mul #16
+-**	neg	x0, \1
++**	rdvl	x0, #-16
+ **	ret
+ */
+ PROTO (cntb_m16, uint64_t, ()) { return -svcntb () * 16; }
+ 
+-/* Other sequences would be OK.  */
+ /*
+ ** cntb_m17:
+-**	cntb	x0, all, mul #16
+-**	incb	x0
+-**	neg	x0, x0
++**	rdvl	x0, #-17
+ **	ret
+ */
+ PROTO (cntb_m17, uint64_t, ()) { return -svcntb () * 17; }
+ 
++/*
++** cntb_m32:
++**	rdvl	x0, #-32
++**	ret
++*/
++PROTO (cntb_m32, uint64_t, ()) { return -svcntb () * 32; }
++
++/*
++** cntb_m33:
++**	rdvl	x0, #-32
++**	decb	x0
++**	ret
++*/
++PROTO (cntb_m33, uint64_t, ()) { return -svcntb () * 33; }
++
++/*
++** cntb_m34:
++**	rdvl	(x[0-9]+), #-17
++**	lsl	x0, \1, #?1
++**	ret
++*/
++PROTO (cntb_m34, uint64_t, ()) { return -svcntb () * 34; }
++
++/*
++** cntb_m64:
++**	rdvl	(x[0-9]+), #-1
++**	lsl	x0, \1, #?6
++**	ret
++*/
++PROTO (cntb_m64, uint64_t, ()) { return -svcntb () * 64; }
++
+ /*
+ ** incb_1:
+ **	incb	x0
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntd.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntd.c
+index 0d0ed4849..090a643b4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntd.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntd.c
+@@ -54,8 +54,8 @@ PROTO (cntd_16, uint64_t, ()) { return svcntd () * 16; }
+ /* Other sequences would be OK.  */
+ /*
+ ** cntd_17:
+-**	cntb	x0, all, mul #2
+-**	incd	x0
++**	rdvl	(x[0-9]+), #17
++**	asr	x0, \1, 3
+ **	ret
+ */
+ PROTO (cntd_17, uint64_t, ()) { return svcntd () * 17; }
+@@ -107,8 +107,7 @@ PROTO (cntd_m15, uint64_t, ()) { return -svcntd () * 15; }
+ 
+ /*
+ ** cntd_m16:
+-**	cntb	(x[0-9]+), all, mul #2
+-**	neg	x0, \1
++**	rdvl	x0, #-2
+ **	ret
+ */
+ PROTO (cntd_m16, uint64_t, ()) { return -svcntd () * 16; }
+@@ -116,9 +115,8 @@ PROTO (cntd_m16, uint64_t, ()) { return -svcntd () * 16; }
+ /* Other sequences would be OK.  */
+ /*
+ ** cntd_m17:
+-**	cntb	x0, all, mul #2
+-**	incd	x0
+-**	neg	x0, x0
++**	rdvl	(x[0-9]+), #-17
++**	asr	x0, \1, 3
+ **	ret
+ */
+ PROTO (cntd_m17, uint64_t, ()) { return -svcntd () * 17; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnth.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnth.c
+index c29930f15..1a4e7dc0e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnth.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cnth.c
+@@ -54,8 +54,8 @@ PROTO (cnth_16, uint64_t, ()) { return svcnth () * 16; }
+ /* Other sequences would be OK.  */
+ /*
+ ** cnth_17:
+-**	cntb	x0, all, mul #8
+-**	inch	x0
++**	rdvl	(x[0-9]+), #17
++**	asr	x0, \1, 1
+ **	ret
+ */
+ PROTO (cnth_17, uint64_t, ()) { return svcnth () * 17; }
+@@ -69,16 +69,16 @@ PROTO (cnth_32, uint64_t, ()) { return svcnth () * 32; }
+ 
+ /*
+ ** cnth_64:
+-**	cntd	(x[0-9]+)
+-**	lsl	x0, \1, 8
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
+ **	ret
+ */
+ PROTO (cnth_64, uint64_t, ()) { return svcnth () * 64; }
+ 
+ /*
+ ** cnth_128:
+-**	cntd	(x[0-9]+)
+-**	lsl	x0, \1, 9
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 6
+ **	ret
+ */
+ PROTO (cnth_128, uint64_t, ()) { return svcnth () * 128; }
+@@ -109,8 +109,7 @@ PROTO (cnth_m15, uint64_t, ()) { return -svcnth () * 15; }
+ 
+ /*
+ ** cnth_m16:
+-**	cntb	(x[0-9]+), all, mul #8
+-**	neg	x0, \1
++**	rdvl	x0, #-8
+ **	ret
+ */
+ PROTO (cnth_m16, uint64_t, ()) { return -svcnth () * 16; }
+@@ -118,9 +117,8 @@ PROTO (cnth_m16, uint64_t, ()) { return -svcnth () * 16; }
+ /* Other sequences would be OK.  */
+ /*
+ ** cnth_m17:
+-**	cntb	x0, all, mul #8
+-**	inch	x0
+-**	neg	x0, x0
++**	rdvl	(x[0-9]+), #-17
++**	asr	x0, \1, 1
+ **	ret
+ */
+ PROTO (cnth_m17, uint64_t, ()) { return -svcnth () * 17; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntw.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntw.c
+index e26cc67a4..9d1697690 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntw.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/cntw.c
+@@ -54,8 +54,8 @@ PROTO (cntw_16, uint64_t, ()) { return svcntw () * 16; }
+ /* Other sequences would be OK.  */
+ /*
+ ** cntw_17:
+-**	cntb	x0, all, mul #4
+-**	incw	x0
++**	rdvl	(x[0-9]+), #17
++**	asr	x0, \1, 2
+ **	ret
+ */
+ PROTO (cntw_17, uint64_t, ()) { return svcntw () * 17; }
+@@ -76,8 +76,8 @@ PROTO (cntw_64, uint64_t, ()) { return svcntw () * 64; }
+ 
+ /*
+ ** cntw_128:
+-**	cntd	(x[0-9]+)
+-**	lsl	x0, \1, 8
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
+ **	ret
+ */
+ PROTO (cntw_128, uint64_t, ()) { return svcntw () * 128; }
+@@ -108,8 +108,7 @@ PROTO (cntw_m15, uint64_t, ()) { return -svcntw () * 15; }
+ 
+ /*
+ ** cntw_m16:
+-**	cntb	(x[0-9]+), all, mul #4
+-**	neg	x0, \1
++**	rdvl	(x[0-9]+), #-4
+ **	ret
+ */
+ PROTO (cntw_m16, uint64_t, ()) { return -svcntw () * 16; }
+@@ -117,9 +116,8 @@ PROTO (cntw_m16, uint64_t, ()) { return -svcntw () * 16; }
+ /* Other sequences would be OK.  */
+ /*
+ ** cntw_m17:
+-**	cntb	x0, all, mul #4
+-**	incw	x0
+-**	neg	x0, x0
++**	rdvl	(x[0-9]+), #-17
++**	asr	x0, \1, 2
+ **	ret
+ */
+ PROTO (cntw_m17, uint64_t, ()) { return -svcntw () * 17; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb.c
+index c90730a03..94cd3a066 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb.c
+@@ -218,8 +218,8 @@ TEST_PREFETCH (prfb_vnum_31, uint16_t,
+ 
+ /*
+ ** prfb_vnum_32:
+-**	cntd	(x[0-9]+)
+-**	lsl	(x[0-9]+), \1, #?8
++**	cntb	(x[0-9]+)
++**	lsl	(x[0-9]+), \1, #?5
+ **	add	(x[0-9]+), (\2, x0|x0, \2)
+ **	prfb	pldl1keep, p0, \[\3\]
+ **	ret
+@@ -240,7 +240,7 @@ TEST_PREFETCH (prfb_vnum_m32, uint16_t,
+ /*
+ ** prfb_vnum_m33:
+ **	...
+-**	prfb	pldl1keep, p0, \[x[0-9]+\]
++**	prfb	pldl1keep, p0, \[x[0-9]+(, x[0-9]+)?\]
+ **	ret
+ */
+ TEST_PREFETCH (prfb_vnum_m33, uint16_t,
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd.c
+index 869ef3d3e..b7a116cf0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd.c
+@@ -218,8 +218,8 @@ TEST_PREFETCH (prfd_vnum_31, uint16_t,
+ 
+ /*
+ ** prfd_vnum_32:
+-**	cntd	(x[0-9]+)
+-**	lsl	(x[0-9]+), \1, #?8
++**	cntb	(x[0-9]+)
++**	lsl	(x[0-9]+), \1, #?5
+ **	add	(x[0-9]+), (\2, x0|x0, \2)
+ **	prfd	pldl1keep, p0, \[\3\]
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh.c
+index 45a735eae..9d3df6bd3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh.c
+@@ -218,8 +218,8 @@ TEST_PREFETCH (prfh_vnum_31, uint16_t,
+ 
+ /*
+ ** prfh_vnum_32:
+-**	cntd	(x[0-9]+)
+-**	lsl	(x[0-9]+), \1, #?8
++**	cntb	(x[0-9]+)
++**	lsl	(x[0-9]+), \1, #?5
+ **	add	(x[0-9]+), (\2, x0|x0, \2)
+ **	prfh	pldl1keep, p0, \[\3\]
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw.c
+index 444187f45..6962abab6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw.c
+@@ -218,8 +218,8 @@ TEST_PREFETCH (prfw_vnum_31, uint16_t,
+ 
+ /*
+ ** prfw_vnum_32:
+-**	cntd	(x[0-9]+)
+-**	lsl	(x[0-9]+), \1, #?8
++**	cntb	(x[0-9]+)
++**	lsl	(x[0-9]+), \1, #?5
+ **	add	(x[0-9]+), (\2, x0|x0, \2)
+ **	prfw	pldl1keep, p0, \[\3\]
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/loop_add_4.c b/gcc/testsuite/gcc.target/aarch64/sve/loop_add_4.c
+index 9ead9c21b..7f02497e8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/loop_add_4.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/loop_add_4.c
+@@ -68,8 +68,7 @@ TEST_ALL (LOOP)
+ /* { dg-final { scan-assembler-times {\tindex\tz[0-9]+\.s, w[0-9]+, w[0-9]+\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1w\tz[0-9]+\.s, p[0-7]+/z, \[x[0-9]+, x[0-9]+, lsl 2\]} 8 } } */
+ /* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s, p[0-7]+, \[x[0-9]+, x[0-9]+, lsl 2\]} 8 } } */
+-/* 2 for the calculations of -17 and 17.  */
+-/* { dg-final { scan-assembler-times {\tincw\tx[0-9]+\n} 10 } } */
++/* { dg-final { scan-assembler-times {\tincw\tx[0-9]+\n} 8 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tdecw\tz[0-9]+\.s, all, mul #16\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tdecw\tz[0-9]+\.s, all, mul #15\n} 1 } } */
+@@ -86,8 +85,7 @@ TEST_ALL (LOOP)
+ /* { dg-final { scan-assembler-times {\tindex\tz[0-9]+\.d, x[0-9]+, x[0-9]+\n} 3 } } */
+ /* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d, p[0-7]+/z, \[x[0-9]+, x[0-9]+, lsl 3\]} 8 } } */
+ /* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d, p[0-7]+, \[x[0-9]+, x[0-9]+, lsl 3\]} 8 } } */
+-/* 2 for the calculations of -17 and 17.  */
+-/* { dg-final { scan-assembler-times {\tincd\tx[0-9]+\n} 10 } } */
++/* { dg-final { scan-assembler-times {\tincd\tx[0-9]+\n} 8 } } */
+ 
+ /* { dg-final { scan-assembler-times {\tdecd\tz[0-9]+\.d, all, mul #16\n} 1 } } */
+ /* { dg-final { scan-assembler-times {\tdecd\tz[0-9]+\.d, all, mul #15\n} 1 } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_1.c
+index 110947a6c..5de34fc61 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_1.c
+@@ -6,8 +6,7 @@
+ 
+ /*
+ ** test_1:
+-**	cntd	x12, all, mul #9
+-**	lsl	x12, x12, #?4
++**	rdvl	x12, #18
+ **	mov	x11, sp
+ **	...
+ **	sub	sp, sp, x12
+-- 
+2.33.0
+
diff --git a/0163-Backport-SME-aarch64-Make-AARCH64_FL_SVE-requirement.patch b/0163-Backport-SME-aarch64-Make-AARCH64_FL_SVE-requirement.patch
new file mode 100644
index 0000000..97108d8
--- /dev/null
+++ b/0163-Backport-SME-aarch64-Make-AARCH64_FL_SVE-requirement.patch
@@ -0,0 +1,137 @@
+From c0badff223a1f5ea5a0f75df72f5d0138d94d8e6 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:19 +0000
+Subject: [PATCH 064/157] [Backport][SME] aarch64: Make AARCH64_FL_SVE
+ requirements explicit
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=dd7aaef62a43efe52eece525eea4d7d252b0c148
+
+So far, all intrinsics covered by the aarch64-sve-builtins*
+framework have (naturally enough) required at least SVE.
+However, arm_sme.h defines a couple of intrinsics that can
+be called by any code.  It's therefore necessary to make
+the implicit SVE requirement explicit.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.cc (function_groups): Remove
+	implied requirement on SVE.
+	* config/aarch64/aarch64-sve-builtins-base.def: Explicitly require SVE.
+	* config/aarch64/aarch64-sve-builtins-sve2.def: Likewise.
+---
+ .../aarch64/aarch64-sve-builtins-base.def      | 10 +++++-----
+ .../aarch64/aarch64-sve-builtins-sve2.def      | 18 +++++++++++++-----
+ gcc/config/aarch64/aarch64-sve-builtins.cc     |  2 +-
+ 3 files changed, 19 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.def b/gcc/config/aarch64/aarch64-sve-builtins-base.def
+index ffdf7cb4c..3a58f76c3 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-base.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.def
+@@ -17,7 +17,7 @@
+    along with GCC; see the file COPYING3.  If not see
+    .  */
+ 
+-#define REQUIRED_EXTENSIONS 0
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE
+ DEF_SVE_FUNCTION (svabd, binary_opt_n, all_arith, mxz)
+ DEF_SVE_FUNCTION (svabs, unary, all_float_and_signed, mxz)
+ DEF_SVE_FUNCTION (svacge, compare_opt_n, all_float, implicit)
+@@ -318,7 +318,7 @@ DEF_SVE_FUNCTION (svzip2, binary, all_data, none)
+ DEF_SVE_FUNCTION (svzip2, binary_pred, all_pred, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS AARCH64_FL_BF16
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_BF16
+ DEF_SVE_FUNCTION (svbfdot, ternary_bfloat_opt_n, s_float, none)
+ DEF_SVE_FUNCTION (svbfdot_lane, ternary_bfloat_lanex2, s_float, none)
+ DEF_SVE_FUNCTION (svbfmlalb, ternary_bfloat_opt_n, s_float, none)
+@@ -330,7 +330,7 @@ DEF_SVE_FUNCTION (svcvt, unary_convert, cvt_bfloat, mxz)
+ DEF_SVE_FUNCTION (svcvtnt, unary_convert_narrowt, cvt_bfloat, mx)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS AARCH64_FL_I8MM
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_I8MM
+ DEF_SVE_FUNCTION (svmmla, mmla, s_integer, none)
+ DEF_SVE_FUNCTION (svusmmla, ternary_uintq_intq, s_signed, none)
+ DEF_SVE_FUNCTION (svsudot, ternary_intq_uintq_opt_n, s_signed, none)
+@@ -339,11 +339,11 @@ DEF_SVE_FUNCTION (svusdot, ternary_uintq_intq_opt_n, s_signed, none)
+ DEF_SVE_FUNCTION (svusdot_lane, ternary_uintq_intq_lane, s_signed, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS AARCH64_FL_F32MM
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_F32MM
+ DEF_SVE_FUNCTION (svmmla, mmla, s_float, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS AARCH64_FL_F64MM
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_F64MM
+ DEF_SVE_FUNCTION (svld1ro, load_replicate, all_data, implicit)
+ DEF_SVE_FUNCTION (svmmla, mmla, d_float, none)
+ DEF_SVE_FUNCTION (svtrn1q, binary, all_data, none)
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
+index 635089ffc..d5f23a887 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
+@@ -17,7 +17,7 @@
+    along with GCC; see the file COPYING3.  If not see
+    .  */
+ 
+-#define REQUIRED_EXTENSIONS AARCH64_FL_SVE2
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_SVE2
+ DEF_SVE_FUNCTION (svaba, ternary_opt_n, all_integer, none)
+ DEF_SVE_FUNCTION (svabalb, ternary_long_opt_n, hsd_integer, none)
+ DEF_SVE_FUNCTION (svabalt, ternary_long_opt_n, hsd_integer, none)
+@@ -189,7 +189,9 @@ DEF_SVE_FUNCTION (svwhilewr, compare_ptr, all_data, none)
+ DEF_SVE_FUNCTION (svxar, ternary_shift_right_imm, all_integer, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES)
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_SVE2 \
++			     | AARCH64_FL_SVE2_AES)
+ DEF_SVE_FUNCTION (svaesd, binary, b_unsigned, none)
+ DEF_SVE_FUNCTION (svaese, binary, b_unsigned, none)
+ DEF_SVE_FUNCTION (svaesmc, unary, b_unsigned, none)
+@@ -198,17 +200,23 @@ DEF_SVE_FUNCTION (svpmullb_pair, binary_opt_n, d_unsigned, none)
+ DEF_SVE_FUNCTION (svpmullt_pair, binary_opt_n, d_unsigned, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE2 | AARCH64_FL_SVE2_BITPERM)
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_SVE2 \
++			     | AARCH64_FL_SVE2_BITPERM)
+ DEF_SVE_FUNCTION (svbdep, binary_opt_n, all_unsigned, none)
+ DEF_SVE_FUNCTION (svbext, binary_opt_n, all_unsigned, none)
+ DEF_SVE_FUNCTION (svbgrp, binary_opt_n, all_unsigned, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE2 | AARCH64_FL_SVE2_SHA3)
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_SVE2 \
++			     | AARCH64_FL_SVE2_SHA3)
+ DEF_SVE_FUNCTION (svrax1, binary, d_integer, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE2 | AARCH64_FL_SVE2_SM4)
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_SVE2 \
++			     | AARCH64_FL_SVE2_SM4)
+ DEF_SVE_FUNCTION (svsm4e, binary, s_unsigned, none)
+ DEF_SVE_FUNCTION (svsm4ekey, binary, s_unsigned, none)
+ #undef REQUIRED_EXTENSIONS
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 7924cdf0f..dde01f676 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -525,7 +525,7 @@ static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+ static CONSTEXPR const function_group_info function_groups[] = {
+ #define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+   { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, preds_##PREDS, \
+-    REQUIRED_EXTENSIONS | AARCH64_FL_SVE },
++    REQUIRED_EXTENSIONS },
+ #include "aarch64-sve-builtins.def"
+ };
+ 
+-- 
+2.33.0
+
diff --git a/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch b/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch
new file mode 100644
index 0000000..4497814
--- /dev/null
+++ b/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch
@@ -0,0 +1,562 @@
+From e99332e15895156632949f3b6c3080fc9d994b13 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:19 +0000
+Subject: [PATCH 065/157] [Backport][SME] aarch64: Add group suffixes to SVE
+ intrinsics
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7b607f197967e052d7d7e29f6b41eded18f8c65d
+
+The SME2 ACLE adds a new "group" suffix component to the naming
+convention for SVE intrinsics.  This is also used in the new tuple
+forms of the svreinterpret intrinsics.
+
+This patch adds support for group suffixes and defines the
+x2, x3 and x4 suffixes that are needed for the svreinterprets.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins-shapes.cc (build_one): Take
+	a group suffix index parameter.
+	(build_32_64, build_all): Update accordingly.  Iterate over all
+	group suffixes.
+	* config/aarch64/aarch64-sve-builtins-sve2.cc (svqrshl_impl::fold)
+	(svqshl_impl::fold, svrshl_impl::fold): Update function_instance
+	constructors.
+	* config/aarch64/aarch64-sve-builtins.cc (group_suffixes): New array.
+	(groups_none): New constant.
+	(function_groups): Initialize the groups field.
+	(function_instance::hash): Hash the group index.
+	(function_builder::get_name): Add the group suffix.
+	(function_builder::add_overloaded_functions): Iterate over all
+	group suffixes.
+	(function_resolver::lookup_form): Take a group suffix parameter.
+	(function_resolver::resolve_to): Likewise.
+	* config/aarch64/aarch64-sve-builtins.def (DEF_SVE_GROUP_SUFFIX): New
+	macro.
+	(x2, x3, x4): New group suffixes.
+	* config/aarch64/aarch64-sve-builtins.h (group_suffix_index): New enum.
+	(group_suffix_info): New structure.
+	(function_group_info::groups): New member variable.
+	(function_instance::group_suffix_id): Likewise.
+	(group_suffixes): New array.
+	(function_instance::operator==): Compare the group suffixes.
+	(function_instance::group_suffix): New function.
+---
+ .../aarch64/aarch64-sve-builtins-shapes.cc    | 53 ++++++------
+ .../aarch64/aarch64-sve-builtins-sve2.cc      | 10 +--
+ gcc/config/aarch64/aarch64-sve-builtins.cc    | 84 +++++++++++++------
+ gcc/config/aarch64/aarch64-sve-builtins.def   |  9 ++
+ gcc/config/aarch64/aarch64-sve-builtins.h     | 81 ++++++++++++++----
+ 5 files changed, 165 insertions(+), 72 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index 4fa4181b9..3ecef026c 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -275,18 +275,20 @@ parse_signature (const function_instance &instance, const char *format,
+ }
+ 
+ /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
+-   the type suffixes at index TI and the predication suffix at index PI.
+-   The other arguments are as for build_all.  */
++   the type suffixes at index TI, the group suffixes at index GI, and the
++   predication suffix at index PI.  The other arguments are as for
++   build_all.  */
+ static void
+ build_one (function_builder &b, const char *signature,
+ 	   const function_group_info &group, mode_suffix_index mode_suffix_id,
+-	   unsigned int ti, unsigned int pi, bool force_direct_overloads)
++	   unsigned int ti, unsigned int gi, unsigned int pi,
++	   bool force_direct_overloads)
+ {
+   /* Byte forms of svdupq take 16 arguments.  */
+   auto_vec argument_types;
+   function_instance instance (group.base_name, *group.base, *group.shape,
+ 			      mode_suffix_id, group.types[ti],
+-			      group.preds[pi]);
++			      group.groups[gi], group.preds[pi]);
+   tree return_type = parse_signature (instance, signature, argument_types);
+   apply_predication (instance, return_type, argument_types);
+   b.add_unique_function (instance, return_type, argument_types,
+@@ -312,24 +314,26 @@ build_32_64 (function_builder &b, const char *signature,
+ 	     mode_suffix_index mode64, bool force_direct_overloads = false)
+ {
+   for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+-    if (group.types[0][0] == NUM_TYPE_SUFFIXES)
+-      {
+-	gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
+-	build_one (b, signature, group, mode32, 0, pi,
+-		   force_direct_overloads);
+-	build_one (b, signature, group, mode64, 0, pi,
+-		   force_direct_overloads);
+-      }
+-    else
+-      for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
++    for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
++      if (group.types[0][0] == NUM_TYPE_SUFFIXES)
+ 	{
+-	  unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
+-	  gcc_assert (bits == 32 || bits == 64);
+-	  mode_suffix_index mode = bits == 32 ? mode32 : mode64;
+-	  if (mode != MODE_none)
+-	    build_one (b, signature, group, mode, ti, pi,
+-		       force_direct_overloads);
++	  gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
++	  build_one (b, signature, group, mode32, 0, gi, pi,
++		     force_direct_overloads);
++	  build_one (b, signature, group, mode64, 0, gi, pi,
++		     force_direct_overloads);
+ 	}
++      else
++	for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
++	     ++ti)
++	  {
++	    unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
++	    gcc_assert (bits == 32 || bits == 64);
++	    mode_suffix_index mode = bits == 32 ? mode32 : mode64;
++	    if (mode != MODE_none)
++	      build_one (b, signature, group, mode, ti, gi, pi,
++			 force_direct_overloads);
++	  }
+ }
+ 
+ /* For every type and predicate combination in GROUP, add one function
+@@ -423,10 +427,11 @@ build_all (function_builder &b, const char *signature,
+ 	   bool force_direct_overloads = false)
+ {
+   for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+-    for (unsigned int ti = 0;
+-	 ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
+-      build_one (b, signature, group, mode_suffix_id, ti, pi,
+-		 force_direct_overloads);
++    for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
++      for (unsigned int ti = 0;
++	   ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
++	build_one (b, signature, group, mode_suffix_id, ti, gi, pi,
++		   force_direct_overloads);
+ }
+ 
+ /* TYPE is the largest type suffix associated with the arguments of R,
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
+index e066f096d..a94e5e269 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
+@@ -252,7 +252,7 @@ public:
+ 	       that we can use for sensible shift amounts.  */
+ 	    function_instance instance ("svqshl", functions::svqshl,
+ 					shapes::binary_int_opt_n, MODE_n,
+-					f.type_suffix_ids, f.pred);
++					f.type_suffix_ids, GROUP_none, f.pred);
+ 	    return f.redirect_call (instance);
+ 	  }
+ 	else
+@@ -261,7 +261,7 @@ public:
+ 	       that we can use for sensible shift amounts.  */
+ 	    function_instance instance ("svrshl", functions::svrshl,
+ 					shapes::binary_int_opt_n, MODE_n,
+-					f.type_suffix_ids, f.pred);
++					f.type_suffix_ids, GROUP_none, f.pred);
+ 	    return f.redirect_call (instance);
+ 	  }
+       }
+@@ -290,7 +290,7 @@ public:
+ 				       -wi::to_wide (amount));
+ 	    function_instance instance ("svasr", functions::svasr,
+ 					shapes::binary_uint_opt_n, MODE_n,
+-					f.type_suffix_ids, f.pred);
++					f.type_suffix_ids, GROUP_none, f.pred);
+ 	    if (f.type_suffix (0).unsigned_p)
+ 	      {
+ 		instance.base_name = "svlsr";
+@@ -322,7 +322,7 @@ public:
+ 	       that we can use for sensible shift amounts.  */
+ 	    function_instance instance ("svlsl", functions::svlsl,
+ 					shapes::binary_uint_opt_n, MODE_n,
+-					f.type_suffix_ids, f.pred);
++					f.type_suffix_ids, GROUP_none, f.pred);
+ 	    gcall *call = as_a  (f.redirect_call (instance));
+ 	    gimple_call_set_arg (call, 2, amount);
+ 	    return call;
+@@ -335,7 +335,7 @@ public:
+ 				       -wi::to_wide (amount));
+ 	    function_instance instance ("svrshr", functions::svrshr,
+ 					shapes::shift_right_imm, MODE_n,
+-					f.type_suffix_ids, f.pred);
++					f.type_suffix_ids, GROUP_none, f.pred);
+ 	    gcall *call = as_a  (f.redirect_call (instance));
+ 	    gimple_call_set_arg (call, 2, amount);
+ 	    return call;
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index dde01f676..dc3fd80da 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -144,6 +144,13 @@ CONSTEXPR const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
+     0, VOIDmode }
+ };
+ 
++CONSTEXPR const group_suffix_info group_suffixes[] = {
++#define DEF_SVE_GROUP_SUFFIX(NAME, VG, VECTORS_PER_TUPLE) \
++  { "_" #NAME, VG, VECTORS_PER_TUPLE },
++#include "aarch64-sve-builtins.def"
++  { "", 0, 1 }
++};
++
+ /* Define a TYPES_ macro for each combination of type
+    suffixes that an ACLE function can have, where  is the
+    name used in DEF_SVE_FUNCTION entries.
+@@ -483,6 +490,10 @@ DEF_SVE_TYPES_ARRAY (inc_dec_n);
+ DEF_SVE_TYPES_ARRAY (reinterpret);
+ DEF_SVE_TYPES_ARRAY (while);
+ 
++static const group_suffix_index groups_none[] = {
++  GROUP_none, NUM_GROUP_SUFFIXES
++};
++
+ /* Used by functions that have no governing predicate.  */
+ static const predication_index preds_none[] = { PRED_none, NUM_PREDS };
+ 
+@@ -524,8 +535,8 @@ static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+ /* A list of all SVE ACLE functions.  */
+ static CONSTEXPR const function_group_info function_groups[] = {
+ #define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+-  { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, preds_##PREDS, \
+-    REQUIRED_EXTENSIONS },
++  { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_none, \
++    preds_##PREDS, REQUIRED_EXTENSIONS },
+ #include "aarch64-sve-builtins.def"
+ };
+ 
+@@ -788,6 +799,7 @@ function_instance::hash () const
+   h.add_int (mode_suffix_id);
+   h.add_int (type_suffix_ids[0]);
+   h.add_int (type_suffix_ids[1]);
++  h.add_int (group_suffix_id);
+   h.add_int (pred);
+   return h.end ();
+ }
+@@ -957,6 +969,8 @@ function_builder::get_name (const function_instance &instance,
+   for (unsigned int i = 0; i < 2; ++i)
+     if (!overloaded_p || instance.shape->explicit_type_suffix_p (i))
+       append_name (instance.type_suffix (i).string);
++  if (!overloaded_p || instance.shape->explicit_group_suffix_p ())
++    append_name (instance.group_suffix ().string);
+   append_name (pred_suffixes[instance.pred]);
+   return finish_name ();
+ }
+@@ -1113,19 +1127,26 @@ void
+ function_builder::add_overloaded_functions (const function_group_info &group,
+ 					    mode_suffix_index mode)
+ {
+-  unsigned int explicit_type0 = (*group.shape)->explicit_type_suffix_p (0);
+-  unsigned int explicit_type1 = (*group.shape)->explicit_type_suffix_p (1);
+-  for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
++  bool explicit_type0 = (*group.shape)->explicit_type_suffix_p (0);
++  bool explicit_type1 = (*group.shape)->explicit_type_suffix_p (1);
++  bool explicit_group = (*group.shape)->explicit_group_suffix_p ();
++  auto add_function = [&](const type_suffix_pair &types,
++			  group_suffix_index group_suffix_id,
++			  unsigned int pi)
++    {
++      function_instance instance (group.base_name, *group.base,
++				  *group.shape, mode, types,
++				  group_suffix_id, group.preds[pi]);
++      add_overloaded_function (instance, group.required_extensions);
++    };
++
++  auto add_group_suffix = [&](group_suffix_index group_suffix_id,
++			      unsigned int pi)
+     {
+       if (!explicit_type0 && !explicit_type1)
+-	{
+-	  /* Deal with the common case in which there is one overloaded
+-	     function for all type combinations.  */
+-	  function_instance instance (group.base_name, *group.base,
+-				      *group.shape, mode, types_none[0],
+-				      group.preds[pi]);
+-	  add_overloaded_function (instance, group.required_extensions);
+-	}
++	/* Deal with the common case in which there is one overloaded
++	   function for all type combinations.  */
++	add_function (types_none[0], group_suffix_id, pi);
+       else
+ 	for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
+ 	     ++ti)
+@@ -1136,12 +1157,16 @@ function_builder::add_overloaded_functions (const function_group_info &group,
+ 	      explicit_type0 ? group.types[ti][0] : NUM_TYPE_SUFFIXES,
+ 	      explicit_type1 ? group.types[ti][1] : NUM_TYPE_SUFFIXES
+ 	    };
+-	    function_instance instance (group.base_name, *group.base,
+-					*group.shape, mode, types,
+-					group.preds[pi]);
+-	    add_overloaded_function (instance, group.required_extensions);
++	    add_function (types, group_suffix_id, pi);
+ 	  }
+-    }
++    };
++
++  for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
++    if (explicit_group)
++      for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
++	add_group_suffix (group.groups[gi], pi);
++    else
++      add_group_suffix (GROUP_none, pi);
+ }
+ 
+ /* Register all the functions in GROUP.  */
+@@ -1213,29 +1238,34 @@ function_resolver::report_no_such_form (type_suffix_index type)
+ }
+ 
+ /* Silently check whether there is an instance of the function with the
+-   mode suffix given by MODE and the type suffixes given by TYPE0 and TYPE1.
+-   Return its function decl if so, otherwise return null.  */
++   mode suffix given by MODE, the type suffixes given by TYPE0 and TYPE1,
++   and the group suffix given by GROUP.  Return its function decl if so,
++   otherwise return null.  */
+ tree
+ function_resolver::lookup_form (mode_suffix_index mode,
+ 				type_suffix_index type0,
+-				type_suffix_index type1)
++				type_suffix_index type1,
++				group_suffix_index group)
+ {
+   type_suffix_pair types = { type0, type1 };
+-  function_instance instance (base_name, base, shape, mode, types, pred);
++  function_instance instance (base_name, base, shape, mode, types,
++			      group, pred);
+   registered_function *rfn
+     = function_table->find_with_hash (instance, instance.hash ());
+   return rfn ? rfn->decl : NULL_TREE;
+ }
+ 
+-/* Resolve the function to one with the mode suffix given by MODE and the
+-   type suffixes given by TYPE0 and TYPE1.  Return its function decl on
+-   success, otherwise report an error and return error_mark_node.  */
++/* Resolve the function to one with the mode suffix given by MODE, the
++   type suffixes given by TYPE0 and TYPE1, and group suffix given by
++   GROUP.  Return its function decl on success, otherwise report an
++   error and return error_mark_node.  */
+ tree
+ function_resolver::resolve_to (mode_suffix_index mode,
+ 			       type_suffix_index type0,
+-			       type_suffix_index type1)
++			       type_suffix_index type1,
++			       group_suffix_index group)
+ {
+-  tree res = lookup_form (mode, type0, type1);
++  tree res = lookup_form (mode, type0, type1, group);
+   if (!res)
+     {
+       if (type1 == NUM_TYPE_SUFFIXES)
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def
+index 6e4dcdbc9..d9bf9c350 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins.def
+@@ -29,6 +29,10 @@
+ #define DEF_SVE_TYPE_SUFFIX(A, B, C, D, E)
+ #endif
+ 
++#ifndef DEF_SVE_GROUP_SUFFIX
++#define DEF_SVE_GROUP_SUFFIX(A, B, C)
++#endif
++
+ #ifndef DEF_SVE_FUNCTION
+ #define DEF_SVE_FUNCTION(A, B, C, D)
+ #endif
+@@ -95,10 +99,15 @@ DEF_SVE_TYPE_SUFFIX (u16, svuint16_t, unsigned, 16, VNx8HImode)
+ DEF_SVE_TYPE_SUFFIX (u32, svuint32_t, unsigned, 32, VNx4SImode)
+ DEF_SVE_TYPE_SUFFIX (u64, svuint64_t, unsigned, 64, VNx2DImode)
+ 
++DEF_SVE_GROUP_SUFFIX (x2, 0, 2)
++DEF_SVE_GROUP_SUFFIX (x3, 0, 3)
++DEF_SVE_GROUP_SUFFIX (x4, 0, 4)
++
+ #include "aarch64-sve-builtins-base.def"
+ #include "aarch64-sve-builtins-sve2.def"
+ 
+ #undef DEF_SVE_FUNCTION
++#undef DEF_SVE_GROUP_SUFFIX
+ #undef DEF_SVE_TYPE_SUFFIX
+ #undef DEF_SVE_TYPE
+ #undef DEF_SVE_MODE
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 824c31cd7..374c57e93 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -180,6 +180,17 @@ enum type_suffix_index
+   NUM_TYPE_SUFFIXES
+ };
+ 
++/* Enumerates the possible group suffixes.  Each suffix combines two
++   optional pieces of information: the vector group size in a ZA index,
++   and the number of vectors in the largest tuple argument.  */
++enum group_suffix_index
++{
++#define DEF_SVE_GROUP_SUFFIX(NAME, VG, VECTORS_PER_TUPLE) GROUP_##NAME,
++#include "aarch64-sve-builtins.def"
++  GROUP_none,
++  NUM_GROUP_SUFFIXES
++};
++
+ /* Combines two type suffixes.  */
+ typedef enum type_suffix_index type_suffix_pair[2];
+ 
+@@ -237,6 +248,21 @@ struct type_suffix_info
+   machine_mode vector_mode : 16;
+ };
+ 
++/* Static information about a group suffix.  */
++struct group_suffix_info
++{
++  /* The suffix string itself.  */
++  const char *string;
++
++  /* If the suffix describes a vector group in a ZA index, this is the
++     size of that group, otherwise it is zero.  */
++  unsigned int vg;
++
++  /* The number of vectors in the largest (or only) tuple argument,
++     or 1 if the suffix does not convey this information.  */
++  unsigned int vectors_per_tuple;
++};
++
+ /* Static information about a set of functions.  */
+ struct function_group_info
+ {
+@@ -251,14 +277,16 @@ struct function_group_info
+      shapes.  */
+   const function_shape *const *shape;
+ 
+-  /* A list of the available type suffixes, and of the available predication
+-     types.  The function supports every combination of the two.
++  /* A list of the available type suffixes, group suffixes, and predication
++     types.  The function supports every combination of the three.
++
++     The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES.
++     It is lexicographically ordered based on the index value.
+ 
+-     The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
+-     while the list of predication types is terminated by NUM_PREDS.
+-     The list of type suffixes is lexicographically ordered based
+-     on the index value.  */
++     The list of group suffixes is terminated by NUM_GROUP_SUFFIXES
++     and the list of predication types is terminated by NUM_PREDS.  */
+   const type_suffix_pair *types;
++  const group_suffix_index *groups;
+   const predication_index *preds;
+ 
+   /* The architecture extensions that the functions require, as a set of
+@@ -273,7 +301,8 @@ class GTY((user)) function_instance
+ public:
+   function_instance (const char *, const function_base *,
+ 		     const function_shape *, mode_suffix_index,
+-		     const type_suffix_pair &, predication_index);
++		     const type_suffix_pair &, group_suffix_index,
++		     predication_index);
+ 
+   bool operator== (const function_instance &) const;
+   bool operator!= (const function_instance &) const;
+@@ -294,6 +323,8 @@ public:
+   units_index displacement_units () const;
+ 
+   const type_suffix_info &type_suffix (unsigned int) const;
++  const group_suffix_info &group_suffix () const;
++
+   tree scalar_type (unsigned int) const;
+   tree vector_type (unsigned int) const;
+   tree tuple_type (unsigned int) const;
+@@ -301,14 +332,14 @@ public:
+   machine_mode vector_mode (unsigned int) const;
+   machine_mode gp_mode (unsigned int) const;
+ 
+-  /* The properties of the function.  (The explicit "enum"s are required
+-     for gengtype.)  */
++  /* The properties of the function.  */
+   const char *base_name;
+   const function_base *base;
+   const function_shape *shape;
+-  enum mode_suffix_index mode_suffix_id;
++  mode_suffix_index mode_suffix_id;
+   type_suffix_pair type_suffix_ids;
+-  enum predication_index pred;
++  group_suffix_index group_suffix_id;
++  predication_index pred;
+ };
+ 
+ class registered_function;
+@@ -390,10 +421,12 @@ public:
+   tree report_no_such_form (type_suffix_index);
+   tree lookup_form (mode_suffix_index,
+ 		    type_suffix_index = NUM_TYPE_SUFFIXES,
+-		    type_suffix_index = NUM_TYPE_SUFFIXES);
++		    type_suffix_index = NUM_TYPE_SUFFIXES,
++		    group_suffix_index = GROUP_none);
+   tree resolve_to (mode_suffix_index,
+ 		   type_suffix_index = NUM_TYPE_SUFFIXES,
+-		   type_suffix_index = NUM_TYPE_SUFFIXES);
++		   type_suffix_index = NUM_TYPE_SUFFIXES,
++		   group_suffix_index = GROUP_none);
+ 
+   type_suffix_index infer_integer_scalar_type (unsigned int);
+   type_suffix_index infer_pointer_type (unsigned int, bool = false);
+@@ -641,6 +674,11 @@ class function_shape
+ public:
+   virtual bool explicit_type_suffix_p (unsigned int) const = 0;
+ 
++  /* True if the group suffix is present in overloaded names.
++     This isn't meaningful for pre-SME intrinsics, and true is
++     more common than false, so provide a default definition.  */
++  virtual bool explicit_group_suffix_p () const { return true; }
++
+   /* Define all functions associated with the given group.  */
+   virtual void build (function_builder &,
+ 		      const function_group_info &) const = 0;
+@@ -669,6 +707,7 @@ private:
+ 
+ extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
+ extern const mode_suffix_info mode_suffixes[MODE_none + 1];
++extern const group_suffix_info group_suffixes[NUM_GROUP_SUFFIXES];
+ 
+ extern tree scalar_types[NUM_VECTOR_TYPES];
+ extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+@@ -728,9 +767,11 @@ function_instance (const char *base_name_in,
+ 		   const function_shape *shape_in,
+ 		   mode_suffix_index mode_suffix_id_in,
+ 		   const type_suffix_pair &type_suffix_ids_in,
++		   group_suffix_index group_suffix_id_in,
+ 		   predication_index pred_in)
+   : base_name (base_name_in), base (base_in), shape (shape_in),
+-    mode_suffix_id (mode_suffix_id_in), pred (pred_in)
++    mode_suffix_id (mode_suffix_id_in), group_suffix_id (group_suffix_id_in),
++    pred (pred_in)
+ {
+   memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
+ }
+@@ -741,9 +782,10 @@ function_instance::operator== (const function_instance &other) const
+   return (base == other.base
+ 	  && shape == other.shape
+ 	  && mode_suffix_id == other.mode_suffix_id
+-	  && pred == other.pred
+ 	  && type_suffix_ids[0] == other.type_suffix_ids[0]
+-	  && type_suffix_ids[1] == other.type_suffix_ids[1]);
++	  && type_suffix_ids[1] == other.type_suffix_ids[1]
++	  && group_suffix_id == other.group_suffix_id
++	  && pred == other.pred);
+ }
+ 
+ inline bool
+@@ -815,6 +857,13 @@ function_instance::type_suffix (unsigned int i) const
+   return type_suffixes[type_suffix_ids[i]];
+ }
+ 
++/* Return information about the function's group suffix.  */
++inline const group_suffix_info &
++function_instance::group_suffix () const
++{
++  return group_suffixes[group_suffix_id];
++}
++
+ /* Return the scalar type associated with type suffix I.  */
+ inline tree
+ function_instance::scalar_type (unsigned int i) const
+-- 
+2.33.0
+
diff --git a/0165-Backport-SME-aarch64-Add-sve_type-to-SVE-builtins-co.patch b/0165-Backport-SME-aarch64-Add-sve_type-to-SVE-builtins-co.patch
new file mode 100644
index 0000000..5e9a7eb
--- /dev/null
+++ b/0165-Backport-SME-aarch64-Add-sve_type-to-SVE-builtins-co.patch
@@ -0,0 +1,230 @@
+From a32a9321b3336907fe2d17148cb9e4652642a3e6 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:20 +0000
+Subject: [PATCH 066/157] [Backport][SME] aarch64: Add sve_type to SVE builtins
+ code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7f6de9861e5d7745a0af5174582519a39d545a92
+
+Until now, the SVE ACLE code had mostly been able to represent
+individual SVE arguments with just an element type suffix (s32, u32,
+etc.).  However, the SME2 ACLE provides many overloaded intrinsics
+that operate on tuples rather than single vectors.  This patch
+therefore adds a new type (sve_type) that combines an element
+type suffix with a vector count.  This is enough to uniquely
+represent all SVE ACLE types.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h (sve_type): New struct.
+	(sve_type::operator==): New function.
+	(function_resolver::get_vector_type): Delete.
+	(function_resolver::report_no_such_form): Take an sve_type rather
+	than a type_suffix_index.
+	* config/aarch64/aarch64-sve-builtins.cc (get_vector_type): New
+	function.
+	(function_resolver::get_vector_type): Delete.
+	(function_resolver::report_no_such_form): Take an sve_type rather
+	than a type_suffix_index.
+	(find_sve_type): New function, split out from...
+	(function_resolver::infer_vector_or_tuple_type): ...here.
+---
+ gcc/config/aarch64/aarch64-sve-builtins.cc | 93 ++++++++++++----------
+ gcc/config/aarch64/aarch64-sve-builtins.h  | 37 ++++++++-
+ 2 files changed, 88 insertions(+), 42 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index dc3fd80da..cc676bfe1 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -659,6 +659,14 @@ find_type_suffix_for_scalar_type (const_tree type)
+   return NUM_TYPE_SUFFIXES;
+ }
+ 
++/* Return the vector type associated with TYPE.  */
++static tree
++get_vector_type (sve_type type)
++{
++  auto vector_type = type_suffixes[type.type].vector_type;
++  return acle_vector_types[type.num_vectors - 1][vector_type];
++}
++
+ /* Report an error against LOCATION that the user has tried to use
+    function FNDECL when extension EXTENSION is disabled.  */
+ static void
+@@ -1190,13 +1198,6 @@ function_resolver::function_resolver (location_t location,
+ {
+ }
+ 
+-/* Return the vector type associated with type suffix TYPE.  */
+-tree
+-function_resolver::get_vector_type (type_suffix_index type)
+-{
+-  return acle_vector_types[0][type_suffixes[type].vector_type];
+-}
+-
+ /* Return the  name associated with TYPE.  Using the 
+    name should be more user-friendly than the underlying canonical type,
+    since it makes the signedness and bitwidth explicit.  */
+@@ -1227,10 +1228,10 @@ function_resolver::scalar_argument_p (unsigned int i)
+ 	  || SCALAR_FLOAT_TYPE_P (type));
+ }
+ 
+-/* Report that the function has no form that takes type suffix TYPE.
++/* Report that the function has no form that takes type TYPE.
+    Return error_mark_node.  */
+ tree
+-function_resolver::report_no_such_form (type_suffix_index type)
++function_resolver::report_no_such_form (sve_type type)
+ {
+   error_at (location, "%qE has no form that takes %qT arguments",
+ 	    fndecl, get_vector_type (type));
+@@ -1352,6 +1353,25 @@ function_resolver::infer_pointer_type (unsigned int argno,
+   return type;
+ }
+ 
++/* If TYPE is an SVE predicate or vector type, or a tuple of such a type,
++   return the associated sve_type, otherwise return an invalid sve_type.  */
++static sve_type
++find_sve_type (const_tree type)
++{
++  /* A linear search should be OK here, since the code isn't hot and
++     the number of types is only small.  */
++  for (unsigned int size_i = 0; size_i < MAX_TUPLE_SIZE; ++size_i)
++    for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
++      {
++	vector_type_index type_i = type_suffixes[suffix_i].vector_type;
++	tree this_type = acle_vector_types[size_i][type_i];
++	if (this_type && matches_type_p (this_type, type))
++	  return { type_suffix_index (suffix_i), size_i + 1 };
++      }
++
++  return {};
++}
++
+ /* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS
+    vectors; NUM_VECTORS is 1 for the former.  Return the associated type
+    suffix on success, using TYPE_SUFFIX_b for predicates.  Report an error
+@@ -1364,37 +1384,30 @@ function_resolver::infer_vector_or_tuple_type (unsigned int argno,
+   if (actual == error_mark_node)
+     return NUM_TYPE_SUFFIXES;
+ 
+-  /* A linear search should be OK here, since the code isn't hot and
+-     the number of types is only small.  */
+-  for (unsigned int size_i = 0; size_i < MAX_TUPLE_SIZE; ++size_i)
+-    for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+-      {
+-	vector_type_index type_i = type_suffixes[suffix_i].vector_type;
+-	tree type = acle_vector_types[size_i][type_i];
+-	if (type && matches_type_p (type, actual))
+-	  {
+-	    if (size_i + 1 == num_vectors)
+-	      return type_suffix_index (suffix_i);
+-
+-	    if (num_vectors == 1)
+-	      error_at (location, "passing %qT to argument %d of %qE, which"
+-			" expects a single SVE vector rather than a tuple",
+-			actual, argno + 1, fndecl);
+-	    else if (size_i == 0 && type_i != VECTOR_TYPE_svbool_t)
+-	      /* num_vectors is always != 1, so the singular isn't needed.  */
+-	      error_n (location, num_vectors, "%qT%d%qE%d",
+-		       "passing single vector %qT to argument %d"
+-		       " of %qE, which expects a tuple of %d vectors",
+-		       actual, argno + 1, fndecl, num_vectors);
+-	    else
+-	      /* num_vectors is always != 1, so the singular isn't needed.  */
+-	      error_n (location, num_vectors, "%qT%d%qE%d",
+-		       "passing %qT to argument %d of %qE, which"
+-		       " expects a tuple of %d vectors", actual, argno + 1,
+-		       fndecl, num_vectors);
+-	    return NUM_TYPE_SUFFIXES;
+-	  }
+-      }
++  if (auto sve_type = find_sve_type (actual))
++    {
++      if (sve_type.num_vectors == num_vectors)
++	return sve_type.type;
++
++      if (num_vectors == 1)
++	error_at (location, "passing %qT to argument %d of %qE, which"
++		  " expects a single SVE vector rather than a tuple",
++		  actual, argno + 1, fndecl);
++      else if (sve_type.num_vectors == 1
++	       && sve_type.type != TYPE_SUFFIX_b)
++	/* num_vectors is always != 1, so the singular isn't needed.  */
++	error_n (location, num_vectors, "%qT%d%qE%d",
++		 "passing single vector %qT to argument %d"
++		 " of %qE, which expects a tuple of %d vectors",
++		 actual, argno + 1, fndecl, num_vectors);
++      else
++	/* num_vectors is always != 1, so the singular isn't needed.  */
++	error_n (location, num_vectors, "%qT%d%qE%d",
++		 "passing %qT to argument %d of %qE, which"
++		 " expects a tuple of %d vectors", actual, argno + 1,
++		 fndecl, num_vectors);
++      return NUM_TYPE_SUFFIXES;
++    }
+ 
+   if (num_vectors == 1)
+     error_at (location, "passing %qT to argument %d of %qE, which"
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 374c57e93..f4f2c415f 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -263,6 +263,40 @@ struct group_suffix_info
+   unsigned int vectors_per_tuple;
+ };
+ 
++/* Represents an SVE vector, predicate, tuple of vectors, or tuple of
++   predicates.  There is also a representation of "no type"/"invalid type".  */
++struct sve_type
++{
++  sve_type () = default;
++  sve_type (type_suffix_index type) : type (type), num_vectors (1) {}
++  sve_type (type_suffix_index type, unsigned int num_vectors)
++    : type (type), num_vectors (num_vectors) {}
++
++  /* Return true if the type is valid.  */
++  explicit operator bool () const { return type != NUM_TYPE_SUFFIXES; }
++
++  bool operator== (const sve_type &) const;
++  bool operator!= (const sve_type &x) const { return !operator== (x); }
++
++  /* This is one of:
++
++     - TYPE_SUFFIX_b for svbool_t-based types
++     - TYPE_SUFFIX_c for svcount_t-based types
++     - the type suffix of a data element for SVE data vectors and tuples
++     - NUM_TYPE_SUFFIXES for invalid types.  */
++  type_suffix_index type = NUM_TYPE_SUFFIXES;
++
++  /* If the type is a tuple, this is the number of vectors in the tuple,
++     otherwise it is 1.  */
++  unsigned int num_vectors = 1;
++};
++
++inline bool
++sve_type::operator== (const sve_type &other) const
++{
++  return type == other.type && num_vectors == other.num_vectors;
++}
++
+ /* Static information about a set of functions.  */
+ struct function_group_info
+ {
+@@ -413,12 +447,11 @@ public:
+   function_resolver (location_t, const function_instance &, tree,
+ 		     vec &);
+ 
+-  tree get_vector_type (type_suffix_index);
+   const char *get_scalar_type_name (type_suffix_index);
+   tree get_argument_type (unsigned int);
+   bool scalar_argument_p (unsigned int);
+ 
+-  tree report_no_such_form (type_suffix_index);
++  tree report_no_such_form (sve_type);
+   tree lookup_form (mode_suffix_index,
+ 		    type_suffix_index = NUM_TYPE_SUFFIXES,
+ 		    type_suffix_index = NUM_TYPE_SUFFIXES,
+-- 
+2.33.0
+
diff --git a/0166-Backport-SME-aarch64-Generalise-some-SVE-ACLE-error-.patch b/0166-Backport-SME-aarch64-Generalise-some-SVE-ACLE-error-.patch
new file mode 100644
index 0000000..5c7889c
--- /dev/null
+++ b/0166-Backport-SME-aarch64-Generalise-some-SVE-ACLE-error-.patch
@@ -0,0 +1,1474 @@
+From 21839879d5f00db48cdacd472044a9bd4e23a2c6 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:20 +0000
+Subject: [PATCH 067/157] [Backport][SME] aarch64: Generalise some SVE ACLE
+ error messages
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=bb01ef94ff5096b907639aa3a1d77850921e7d37
+
+The current SVE ACLE function-resolution diagnostics assume
+that a function has a fixed choice between vectors or tuples
+of vectors.  If an argument was not an SVE type at all, the
+error message said the function "expects an SVE vector type"
+or "expects an SVE tuple type".
+
+This patch generalises the error to cope with cases where
+an argument can be either a vector or a tuple.  It also splits
+out the diagnostics for mismatched tuple sizes, so that they
+can be reused by later patches.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h
+	(function_resolver::infer_sve_type): New member function.
+	(function_resolver::report_incorrect_num_vectors): Likewise.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(function_resolver::infer_sve_type): New function,.
+	(function_resolver::report_incorrect_num_vectors): New function,
+	split out from...
+	(function_resolver::infer_vector_or_tuple_type): ...here.  Use
+	infer_sve_type.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/acle/general-c/*: Update expected error
+	messages.
+---
+ gcc/config/aarch64/aarch64-sve-builtins.cc    | 87 ++++++++++++-------
+ gcc/config/aarch64/aarch64-sve-builtins.h     |  3 +
+ .../aarch64/sve/acle/general-c/adr_index_1.c  |  6 +-
+ .../aarch64/sve/acle/general-c/adr_offset_1.c |  6 +-
+ .../aarch64/sve/acle/general-c/binary_1.c     |  2 +-
+ .../sve/acle/general-c/binary_int_opt_n.c     |  2 +-
+ .../sve/acle/general-c/binary_lane_1.c        |  4 +-
+ .../sve/acle/general-c/binary_long_lane_1.c   |  4 +-
+ .../sve/acle/general-c/binary_long_opt_n_1.c  |  2 +-
+ .../aarch64/sve/acle/general-c/binary_n_1.c   |  2 +-
+ .../acle/general-c/binary_narrowb_opt_n_1.c   |  2 +-
+ .../acle/general-c/binary_narrowt_opt_n_1.c   |  4 +-
+ .../sve/acle/general-c/binary_opt_n_2.c       |  2 +-
+ .../sve/acle/general-c/binary_opt_n_3.c       |  2 +-
+ .../sve/acle/general-c/binary_rotate_1.c      |  4 +-
+ .../sve/acle/general-c/binary_to_uint_1.c     |  4 +-
+ .../sve/acle/general-c/binary_uint64_n_1.c    |  2 +-
+ .../acle/general-c/binary_uint64_opt_n_2.c    |  2 +-
+ .../sve/acle/general-c/binary_uint_1.c        |  2 +-
+ .../sve/acle/general-c/binary_uint_n_1.c      |  2 +-
+ .../sve/acle/general-c/binary_uint_opt_n_1.c  |  2 +-
+ .../sve/acle/general-c/binary_wide_1.c        |  8 +-
+ .../sve/acle/general-c/binary_wide_opt_n_1.c  |  4 +-
+ .../aarch64/sve/acle/general-c/clast_1.c      |  4 +-
+ .../aarch64/sve/acle/general-c/compare_1.c    |  4 +-
+ .../sve/acle/general-c/compare_opt_n_1.c      |  2 +-
+ .../sve/acle/general-c/compare_wide_opt_n_1.c |  2 +-
+ .../sve/acle/general-c/count_vector_1.c       |  2 +-
+ .../aarch64/sve/acle/general-c/create_1.c     |  4 +-
+ .../aarch64/sve/acle/general-c/create_3.c     |  4 +-
+ .../aarch64/sve/acle/general-c/create_5.c     |  4 +-
+ .../aarch64/sve/acle/general-c/fold_left_1.c  |  4 +-
+ .../sve/acle/general-c/inc_dec_pred_1.c       |  2 +-
+ .../aarch64/sve/acle/general-c/mmla_1.c       | 10 +--
+ .../acle/general-c/prefetch_gather_offset_2.c |  2 +-
+ .../aarch64/sve/acle/general-c/reduction_1.c  |  2 +-
+ .../sve/acle/general-c/reduction_wide_1.c     |  2 +-
+ .../general-c/shift_right_imm_narrowb_1.c     |  2 +-
+ .../shift_right_imm_narrowb_to_uint_1.c       |  2 +-
+ .../general-c/shift_right_imm_narrowt_1.c     |  4 +-
+ .../shift_right_imm_narrowt_to_uint_1.c       |  4 +-
+ .../aarch64/sve/acle/general-c/store_1.c      |  2 +-
+ .../aarch64/sve/acle/general-c/store_2.c      |  2 +-
+ .../acle/general-c/store_scatter_offset_1.c   |  4 +-
+ .../sve/acle/general-c/ternary_bfloat16_1.c   |  2 +-
+ .../acle/general-c/ternary_bfloat16_lane_1.c  |  2 +-
+ .../general-c/ternary_bfloat16_lanex2_1.c     |  2 +-
+ .../acle/general-c/ternary_bfloat16_opt_n_1.c |  2 +-
+ .../general-c/ternary_intq_uintq_lane_1.c     |  6 +-
+ .../general-c/ternary_intq_uintq_opt_n_1.c    |  4 +-
+ .../sve/acle/general-c/ternary_lane_1.c       |  6 +-
+ .../acle/general-c/ternary_lane_rotate_1.c    |  6 +-
+ .../sve/acle/general-c/ternary_long_lane_1.c  |  6 +-
+ .../sve/acle/general-c/ternary_long_opt_n_1.c |  4 +-
+ .../sve/acle/general-c/ternary_opt_n_1.c      |  4 +-
+ .../sve/acle/general-c/ternary_qq_lane_1.c    |  6 +-
+ .../acle/general-c/ternary_qq_lane_rotate_1.c |  6 +-
+ .../sve/acle/general-c/ternary_qq_opt_n_2.c   |  4 +-
+ .../sve/acle/general-c/ternary_qq_rotate_1.c  |  6 +-
+ .../sve/acle/general-c/ternary_rotate_1.c     |  6 +-
+ .../general-c/ternary_shift_right_imm_1.c     |  4 +-
+ .../sve/acle/general-c/ternary_uint_1.c       |  6 +-
+ .../sve/acle/general-c/ternary_uintq_intq_1.c |  6 +-
+ .../general-c/ternary_uintq_intq_lane_1.c     |  6 +-
+ .../general-c/ternary_uintq_intq_opt_n_1.c    |  4 +-
+ .../aarch64/sve/acle/general-c/tmad_1.c       |  4 +-
+ .../aarch64/sve/acle/general-c/unary_1.c      |  2 +-
+ .../aarch64/sve/acle/general-c/unary_2.c      |  2 +-
+ .../sve/acle/general-c/unary_convert_1.c      |  2 +-
+ .../sve/acle/general-c/unary_convert_2.c      |  2 +-
+ .../acle/general-c/unary_convert_narrowt_1.c  |  2 +-
+ .../sve/acle/general-c/unary_narrowb_1.c      |  2 +-
+ .../acle/general-c/unary_narrowb_to_uint_1.c  |  2 +-
+ .../sve/acle/general-c/unary_narrowt_1.c      |  4 +-
+ .../acle/general-c/unary_narrowt_to_uint_1.c  |  4 +-
+ .../sve/acle/general-c/unary_to_int_1.c       |  2 +-
+ .../sve/acle/general-c/unary_to_uint_1.c      |  2 +-
+ .../sve/acle/general-c/unary_to_uint_2.c      |  2 +-
+ .../sve/acle/general-c/unary_to_uint_3.c      |  2 +-
+ .../aarch64/sve/acle/general-c/unary_uint_1.c |  2 +-
+ .../sve/acle/general-c/unary_widen_1.c        |  4 +-
+ 81 files changed, 195 insertions(+), 169 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index cc676bfe1..4e94e3633 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -1228,6 +1228,32 @@ function_resolver::scalar_argument_p (unsigned int i)
+ 	  || SCALAR_FLOAT_TYPE_P (type));
+ }
+ 
++/* Report that argument ARGNO was expected to have NUM_VECTORS vectors.
++   TYPE is the type that ARGNO actually has.  */
++void
++function_resolver::report_incorrect_num_vectors (unsigned int argno,
++						 sve_type type,
++						 unsigned int num_vectors)
++{
++  if (num_vectors == 1)
++    error_at (location, "passing %qT to argument %d of %qE, which"
++	      " expects a single SVE vector rather than a tuple",
++	      get_vector_type (type), argno + 1, fndecl);
++  else if (type.num_vectors == 1
++	   && type.type != TYPE_SUFFIX_b)
++    /* num_vectors is always != 1, so the singular isn't needed.  */
++    error_n (location, num_vectors, "%qT%d%qE%d",
++	     "passing single vector %qT to argument %d"
++	     " of %qE, which expects a tuple of %d vectors",
++	     get_vector_type (type), argno + 1, fndecl, num_vectors);
++  else
++    /* num_vectors is always != 1, so the singular isn't needed.  */
++    error_n (location, num_vectors, "%qT%d%qE%d",
++	     "passing %qT to argument %d of %qE, which"
++	     " expects a tuple of %d vectors", get_vector_type (type),
++	     argno + 1, fndecl, num_vectors);
++}
++
+ /* Report that the function has no form that takes type TYPE.
+    Return error_mark_node.  */
+ tree
+@@ -1372,6 +1398,30 @@ find_sve_type (const_tree type)
+   return {};
+ }
+ 
++/* Require argument ARGNO to be an SVE type (i.e. something that can be
++   represented by sve_type).  Return the (valid) type if it is, otherwise
++   report an error and return an invalid type.  */
++sve_type
++function_resolver::infer_sve_type (unsigned int argno)
++{
++  tree actual = get_argument_type (argno);
++  if (actual == error_mark_node)
++    return {};
++
++  if (sve_type type = find_sve_type (actual))
++    return type;
++
++  if (scalar_argument_p (argno))
++    error_at (location, "passing %qT to argument %d of %qE, which"
++	      " expects an SVE type rather than a scalar type",
++	      actual, argno + 1, fndecl);
++  else
++    error_at (location, "passing %qT to argument %d of %qE, which"
++	      " expects an SVE type",
++	      actual, argno + 1, fndecl);
++  return {};
++}
++
+ /* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS
+    vectors; NUM_VECTORS is 1 for the former.  Return the associated type
+    suffix on success, using TYPE_SUFFIX_b for predicates.  Report an error
+@@ -1380,41 +1430,14 @@ type_suffix_index
+ function_resolver::infer_vector_or_tuple_type (unsigned int argno,
+ 					       unsigned int num_vectors)
+ {
+-  tree actual = get_argument_type (argno);
+-  if (actual == error_mark_node)
++  auto type = infer_sve_type (argno);
++  if (!type)
+     return NUM_TYPE_SUFFIXES;
+ 
+-  if (auto sve_type = find_sve_type (actual))
+-    {
+-      if (sve_type.num_vectors == num_vectors)
+-	return sve_type.type;
+-
+-      if (num_vectors == 1)
+-	error_at (location, "passing %qT to argument %d of %qE, which"
+-		  " expects a single SVE vector rather than a tuple",
+-		  actual, argno + 1, fndecl);
+-      else if (sve_type.num_vectors == 1
+-	       && sve_type.type != TYPE_SUFFIX_b)
+-	/* num_vectors is always != 1, so the singular isn't needed.  */
+-	error_n (location, num_vectors, "%qT%d%qE%d",
+-		 "passing single vector %qT to argument %d"
+-		 " of %qE, which expects a tuple of %d vectors",
+-		 actual, argno + 1, fndecl, num_vectors);
+-      else
+-	/* num_vectors is always != 1, so the singular isn't needed.  */
+-	error_n (location, num_vectors, "%qT%d%qE%d",
+-		 "passing %qT to argument %d of %qE, which"
+-		 " expects a tuple of %d vectors", actual, argno + 1,
+-		 fndecl, num_vectors);
+-      return NUM_TYPE_SUFFIXES;
+-    }
++  if (type.num_vectors == num_vectors)
++    return type.type;
+ 
+-  if (num_vectors == 1)
+-    error_at (location, "passing %qT to argument %d of %qE, which"
+-	      " expects an SVE vector type", actual, argno + 1, fndecl);
+-  else
+-    error_at (location, "passing %qT to argument %d of %qE, which"
+-	      " expects an SVE tuple type", actual, argno + 1, fndecl);
++  report_incorrect_num_vectors (argno, type, num_vectors);
+   return NUM_TYPE_SUFFIXES;
+ }
+ 
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index f4f2c415f..5a4f35123 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -451,6 +451,8 @@ public:
+   tree get_argument_type (unsigned int);
+   bool scalar_argument_p (unsigned int);
+ 
++  void report_incorrect_num_vectors (unsigned int, sve_type, unsigned int);
++
+   tree report_no_such_form (sve_type);
+   tree lookup_form (mode_suffix_index,
+ 		    type_suffix_index = NUM_TYPE_SUFFIXES,
+@@ -463,6 +465,7 @@ public:
+ 
+   type_suffix_index infer_integer_scalar_type (unsigned int);
+   type_suffix_index infer_pointer_type (unsigned int, bool = false);
++  sve_type infer_sve_type (unsigned int);
+   type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
+   type_suffix_index infer_vector_type (unsigned int);
+   type_suffix_index infer_integer_vector_type (unsigned int);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c
+index 714265ed1..a17e99f5d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c
+@@ -10,14 +10,14 @@ f1 (svbool_t pg, uint32_t *u32_ptr, svuint8_t u8, svuint16_t u16,
+ {
+   svadrh_index (u32); /* { dg-error {too few arguments to function 'svadrh_index'} } */
+   svadrh_index (u32, u32, u32); /* { dg-error {too many arguments to function 'svadrh_index'} } */
+-  svadrh_index (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrh_index', which expects an SVE vector type} } */
+-  svadrh_index (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrh_index', which expects an SVE vector type} } */
++  svadrh_index (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrh_index', which expects an SVE type} } */
++  svadrh_index (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrh_index', which expects an SVE type rather than a scalar} } */
+   svadrh_index (u16, u16); /* { dg-error {passing 'svuint16_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svadrh_index (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svadrh_index (f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svadrh_index (pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ 
+-  svadrh_index (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrh_index', which expects an SVE vector type} } */
++  svadrh_index (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrh_index', which expects an SVE type rather than a scalar} } */
+   svadrh_index (u32, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svadrh_index', which expects a vector of 32-bit or 64-bit integers} } */
+   svadrh_index (u32, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svadrh_index', which expects a vector of 32-bit or 64-bit integers} } */
+   svadrh_index (u32, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c
+index 528d7ac51..627ae8ac5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c
+@@ -10,14 +10,14 @@ f1 (svbool_t pg, uint32_t *u32_ptr, svuint8_t u8, svuint16_t u16,
+ {
+   svadrb_offset (u32); /* { dg-error {too few arguments to function 'svadrb_offset'} } */
+   svadrb_offset (u32, u32, u32); /* { dg-error {too many arguments to function 'svadrb_offset'} } */
+-  svadrb_offset (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrb_offset', which expects an SVE vector type} } */
+-  svadrb_offset (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrb_offset', which expects an SVE vector type} } */
++  svadrb_offset (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrb_offset', which expects an SVE type} } */
++  svadrb_offset (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrb_offset', which expects an SVE type rather than a scalar} } */
+   svadrb_offset (u16, u16); /* { dg-error {passing 'svuint16_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svadrb_offset (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svadrb_offset (f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svadrb_offset (pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ 
+-  svadrb_offset (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrb_offset', which expects an SVE vector type} } */
++  svadrb_offset (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrb_offset', which expects an SVE type rather than a scalar} } */
+   svadrb_offset (u32, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svadrb_offset', which expects a vector of 32-bit or 64-bit integers} } */
+   svadrb_offset (u32, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svadrb_offset', which expects a vector of 32-bit or 64-bit integers} } */
+   svadrb_offset (u32, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
+index 8ce89fa10..4343146de 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
+@@ -10,5 +10,5 @@ f1 (svbool_t pg, svuint8_t u8, svint16_t s16)
+   svzip1 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svzip1', but previous arguments had type 'svbool_t'} } */
+   svzip1 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+   svzip1 (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+-  svzip1 (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svzip1', which expects an SVE vector type} } */
++  svzip1 (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svzip1', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c
+index 965e9a13c..9902379f6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c
+@@ -11,7 +11,7 @@ f1 (svbool_t pg, svfloat16_t f16, svint16_t s16, svuint16_t u16,
+   svscale_x (s32, f16, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svscale_x', which expects 'svbool_t'} } */
+   svscale_x (1, f16, s32); /* { dg-error {passing 'int' to argument 1 of 'svscale_x', which expects 'svbool_t'} } */
+   svscale_x (pg, pg, s16); /* { dg-error {'svscale_x' has no form that takes 'svbool_t' arguments} } */
+-  svscale_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svscale_x', which expects an SVE vector type} } */
++  svscale_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svscale_x', which expects an SVE type rather than a scalar} } */
+   svscale_x (pg, f16, s16);
+   svscale_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+   svscale_x (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
+index 3913ff63d..10b6b7e81 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
+@@ -10,8 +10,8 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+   svmul_lane (f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svmul_lane'} } */
+   svmul_lane (pg, pg, 0); /* { dg-error {'svmul_lane' has no form that takes 'svbool_t' arguments} } */
+   svmul_lane (s32, s32, 0); /* { dg-error {ACLE function 'svmul_lane_s32' requires ISA extension 'sve2'} "" { xfail aarch64_sve2 } } */
+-  svmul_lane (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmul_lane', which expects an SVE vector type} } */
+-  svmul_lane (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmul_lane', which expects an SVE vector type} } */
++  svmul_lane (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmul_lane', which expects an SVE type rather than a scalar} } */
++  svmul_lane (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmul_lane', which expects an SVE type rather than a scalar} } */
+   svmul_lane (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmul_lane', but previous arguments had type 'svfloat32_t'} } */
+   svmul_lane (f32, f32, s32); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+   svmul_lane (f32, f32, i); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c
+index bfe78088b..805863f76 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c
+@@ -19,8 +19,8 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+   svmullb_lane (f16, f16, 0); /* { dg-error {'svmullb_lane' has no form that takes 'svfloat16_t' arguments} } */
+   svmullb_lane (f32, f32, 0); /* { dg-error {'svmullb_lane' has no form that takes 'svfloat32_t' arguments} } */
+   svmullb_lane (f64, f64, 0); /* { dg-error {'svmullb_lane' has no form that takes 'svfloat64_t' arguments} } */
+-  svmullb_lane (1, u32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmullb_lane', which expects an SVE vector type} } */
+-  svmullb_lane (u32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmullb_lane', which expects an SVE vector type} } */
++  svmullb_lane (1, u32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmullb_lane', which expects an SVE type rather than a scalar} } */
++  svmullb_lane (u32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmullb_lane', which expects an SVE type rather than a scalar} } */
+   svmullb_lane (u32, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svmullb_lane', but previous arguments had type 'svuint32_t'} } */
+   svmullb_lane (u32, u32, s32); /* { dg-error {argument 3 of 'svmullb_lane' must be an integer constant expression} } */
+   svmullb_lane (u32, u32, i); /* { dg-error {argument 3 of 'svmullb_lane' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c
+index 27893c6fb..ee704eeae 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c
+@@ -23,7 +23,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddlb (u64, u64); /* { dg-error {'svaddlb' has no form that takes 'svuint64_t' arguments} } */
+   svaddlb (s64, s64); /* { dg-error {'svaddlb' has no form that takes 'svint64_t' arguments} } */
+   svaddlb (f16, f16); /* { dg-error {'svaddlb' has no form that takes 'svfloat16_t' arguments} } */
+-  svaddlb (1, u8); /* { dg-error {passing 'int' to argument 1 of 'svaddlb', which expects an SVE vector type} } */
++  svaddlb (1, u8); /* { dg-error {passing 'int' to argument 1 of 'svaddlb', which expects an SVE type rather than a scalar} } */
+   svaddlb (u8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint8_t'} } */
+   svaddlb (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint8_t'} } */
+   svaddlb (u8, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint8_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c
+index 0c69e66a1..ff4f0ff75 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c
+@@ -7,7 +7,7 @@ f1 (svbool_t pg, svuint8_t u8, svfloat16_t f16, int i, float f)
+ {
+   svinsr (u8); /* { dg-error {too few arguments to function 'svinsr'} } */
+   svinsr (u8, 0, 0); /* { dg-error {too many arguments to function 'svinsr'} } */
+-  svinsr (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svinsr', which expects an SVE vector type} } */
++  svinsr (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svinsr', which expects an SVE type rather than a scalar} } */
+   svinsr (u8, 0);
+   svinsr (u8, -1);
+   svinsr (u8, i);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c
+index 920cbd1b0..8ca549ba9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c
+@@ -23,7 +23,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddhnb (u64, u64);
+   svaddhnb (s64, s64);
+   svaddhnb (f32, f32); /* { dg-error {'svaddhnb' has no form that takes 'svfloat32_t' arguments} } */
+-  svaddhnb (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svaddhnb', which expects an SVE vector type} } */
++  svaddhnb (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svaddhnb', which expects an SVE type rather than a scalar} } */
+   svaddhnb (u16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
+   svaddhnb (u16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
+   svaddhnb (u16, u32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c
+index eb70d058e..2b537965b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c
+@@ -26,8 +26,8 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddhnt (u32, u64, u64);
+   svaddhnt (s32, s64, s64);
+   svaddhnt (f16, f32, f32); /* { dg-error {'svaddhnt' has no form that takes 'svfloat32_t' arguments} } */
+-  svaddhnt (1, u16, u16); /* { dg-error {passing 'int' to argument 1 of 'svaddhnt', which expects an SVE vector type} } */
+-  svaddhnt (u8, 1, u16); /* { dg-error {passing 'int' to argument 2 of 'svaddhnt', which expects an SVE vector type} } */
++  svaddhnt (1, u16, u16); /* { dg-error {passing 'int' to argument 1 of 'svaddhnt', which expects an SVE type rather than a scalar} } */
++  svaddhnt (u8, 1, u16); /* { dg-error {passing 'int' to argument 2 of 'svaddhnt', which expects an SVE type rather than a scalar} } */
+   svaddhnt (u8, u16, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
+   svaddhnt (u8, u16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
+   svaddhnt (u8, u16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
+index 9fa83ca99..a151f90d1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svadd_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svadd_x'} } */
+   svadd_x (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svadd_x', which expects 'svbool_t'} } */
+   svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+-  svadd_x (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svadd_x', which expects an SVE vector type} } */
++  svadd_x (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svadd_x', which expects an SVE type rather than a scalar} } */
+   svadd_x (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+   svadd_x (pg, u8, u8);
+   svadd_x (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
+index 4d0b253e3..70ec9c585 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svand_z (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svand_z'} } */
+   svand_z (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svand_z', which expects 'svbool_t'} } */
+   svand_z (pg, pg, pg);
+-  svand_z (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svand_z', which expects an SVE vector type} } */
++  svand_z (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svand_z', which expects an SVE type rather than a scalar} } */
+   svand_z (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+   svand_z (pg, u8, u8);
+   svand_z (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
+index 8ffe91bce..7669e4a02 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
+@@ -10,8 +10,8 @@ f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+   svcadd_x (f32, f32, f32, 90); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcadd_x', which expects 'svbool_t'} } */
+   svcadd_x (pg, pg, pg, 90); /* { dg-error {'svcadd_x' has no form that takes 'svbool_t' arguments} } */
+   svcadd_x (pg, s32, s32, 90); /* { dg-error {'svcadd_x' has no form that takes 'svint32_t' arguments} } */
+-  svcadd_x (pg, 1, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcadd_x', which expects an SVE vector type} } */
+-  svcadd_x (pg, f32, 1, 90); /* { dg-error {passing 'int' to argument 3 of 'svcadd_x', which expects an SVE vector type} } */
++  svcadd_x (pg, 1, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcadd_x', which expects an SVE type rather than a scalar} } */
++  svcadd_x (pg, f32, 1, 90); /* { dg-error {passing 'int' to argument 3 of 'svcadd_x', which expects an SVE type rather than a scalar} } */
+   svcadd_x (pg, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcadd_x', but previous arguments had type 'svfloat32_t'} } */
+   svcadd_x (pg, f32, f32, s32); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+   svcadd_x (pg, f32, f32, i); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c
+index 213defc66..154662487 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c
+@@ -11,9 +11,9 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32)
+   svhistcnt_z (pg, s32, s32, 0); /* { dg-error {too many arguments to function 'svhistcnt_z'} } */
+   svhistcnt_z (0, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svhistcnt_z', which expects 'svbool_t'} } */
+   svhistcnt_z (s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svhistcnt_z', which expects 'svbool_t'} } */
+-  svhistcnt_z (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svhistcnt_z', which expects an SVE vector type} } */
++  svhistcnt_z (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svhistcnt_z', which expects an SVE type rather than a scalar} } */
+   svhistcnt_z (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svhistcnt_z', but previous arguments had type 'svbool_t'} } */
+   svhistcnt_z (pg, s32, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svhistcnt_z', but previous arguments had type 'svint32_t'} } */
+-  svhistcnt_z (pg, s32, 0); /* { dg-error {passing 'int' to argument 3 of 'svhistcnt_z', which expects an SVE vector type} } */
++  svhistcnt_z (pg, s32, 0); /* { dg-error {passing 'int' to argument 3 of 'svhistcnt_z', which expects an SVE type rather than a scalar} } */
+   svhistcnt_z (pg, pg, pg); /* { dg-error {'svhistcnt_z' has no form that takes 'svbool_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c
+index c8ca5f746..207552a3b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c
+@@ -7,7 +7,7 @@ f1 (svbool_t pg, svuint8_t u8, int i, float f)
+ {
+   svdupq_lane (u8); /* { dg-error {too few arguments to function 'svdupq_lane'} } */
+   svdupq_lane (u8, 0, 0); /* { dg-error {too many arguments to function 'svdupq_lane'} } */
+-  svdupq_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdupq_lane', which expects an SVE vector type} } */
++  svdupq_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdupq_lane', which expects an SVE type rather than a scalar} } */
+   svdupq_lane (u8, 0);
+   svdupq_lane (u8, -1);
+   svdupq_lane (u8, i);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c
+index be217394f..c661a66f3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c
+@@ -8,7 +8,7 @@ f1 (svbool_t pg, svuint8_t u8, svuint64_t u64)
+   svlsl_wide_x (pg, u8); /* { dg-error {too few arguments to function 'svlsl_wide_x'} } */
+   svlsl_wide_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svlsl_wide_x'} } */
+   svlsl_wide_x (u8, u8, u64); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svlsl_wide_x', which expects 'svbool_t'} } */
+-  svlsl_wide_x (pg, 1, u64); /* { dg-error {passing 'int' to argument 2 of 'svlsl_wide_x', which expects an SVE vector type} } */
++  svlsl_wide_x (pg, 1, u64); /* { dg-error {passing 'int' to argument 2 of 'svlsl_wide_x', which expects an SVE type rather than a scalar} } */
+   svlsl_wide_x (pg, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svlsl_wide_x', which expects 'svuint64_t'} } */
+   svlsl_wide_x (pg, u64, u64); /* { dg-error {'svlsl_wide_x' has no form that takes 'svuint64_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c
+index 8f86c50b6..8493d5d68 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c
+@@ -11,7 +11,7 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+   svtbl (pg, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+   svtbl (pg, u8); /* { dg-error {'svtbl' has no form that takes 'svbool_t' arguments} } */
+ 
+-  svtbl (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svtbl', which expects an SVE vector type} } */
++  svtbl (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svtbl', which expects an SVE type rather than a scalar} } */
+   svtbl (u8, u8);
+   svtbl (u8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+   svtbl (u8, u16); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svuint8_t' and 'svuint16_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c
+index 36a902e69..d74cb46f7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c
+@@ -7,7 +7,7 @@ f1 (svbool_t pg, svuint8_t u8, int i, float f)
+ {
+   svdup_lane (u8); /* { dg-error {too few arguments to function 'svdup_lane'} } */
+   svdup_lane (u8, 0, 0); /* { dg-error {too many arguments to function 'svdup_lane'} } */
+-  svdup_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdup_lane', which expects an SVE vector type} } */
++  svdup_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdup_lane', which expects an SVE type rather than a scalar} } */
+   svdup_lane (u8, 0);
+   svdup_lane (u8, -1);
+   svdup_lane (u8, i);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c
+index b162ab405..f44d7a9fa 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c
+@@ -11,7 +11,7 @@ f1 (svbool_t pg, svfloat16_t f16, svint16_t s16, svuint16_t u16,
+   svlsl_x (s32, s32, u32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svlsl_x', which expects 'svbool_t'} } */
+   svlsl_x (1, s32, u32); /* { dg-error {passing 'int' to argument 1 of 'svlsl_x', which expects 'svbool_t'} } */
+   svlsl_x (pg, pg, u16); /* { dg-error {'svlsl_x' has no form that takes 'svbool_t' arguments} } */
+-  svlsl_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svlsl_x', which expects an SVE vector type} } */
++  svlsl_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svlsl_x', which expects an SVE type rather than a scalar} } */
+   svlsl_x (pg, s16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+   svlsl_x (pg, s16, u16);
+   svlsl_x (pg, s16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_1.c
+index f58ab75d7..ba38361ab 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_1.c
+@@ -30,8 +30,8 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svadalp_m (pg, s16, s8);
+   svadalp_m (pg, f32, f16); /* { dg-error {'svadalp_m' has no form that takes 'svfloat32_t' arguments} } */
+   svadalp_m (pg, f16, f32); /* { dg-error {'svadalp_m' has no form that takes 'svfloat16_t' arguments} } */
+-  svadalp_m (pg, 0, u32); /* { dg-error {passing 'int' to argument 2 of 'svadalp_m', which expects an SVE vector type} } */
+-  svadalp_m (pg, 0, u64); /* { dg-error {passing 'int' to argument 2 of 'svadalp_m', which expects an SVE vector type} } */
+-  svadalp_m (pg, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svadalp_m', which expects an SVE vector type} } */
+-  svadalp_m (pg, u16, 0); /* { dg-error {passing 'int' to argument 3 of 'svadalp_m', which expects an SVE vector type} } */
++  svadalp_m (pg, 0, u32); /* { dg-error {passing 'int' to argument 2 of 'svadalp_m', which expects an SVE type rather than a scalar} } */
++  svadalp_m (pg, 0, u64); /* { dg-error {passing 'int' to argument 2 of 'svadalp_m', which expects an SVE type rather than a scalar} } */
++  svadalp_m (pg, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svadalp_m', which expects an SVE type rather than a scalar} } */
++  svadalp_m (pg, u16, 0); /* { dg-error {passing 'int' to argument 3 of 'svadalp_m', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_opt_n_1.c
+index 5a58211a0..fd27d8559 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_wide_opt_n_1.c
+@@ -27,8 +27,8 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddwb (s16, s8);
+   svaddwb (f32, f16); /* { dg-error {'svaddwb' has no form that takes 'svfloat32_t' arguments} } */
+   svaddwb (f16, f32); /* { dg-error {'svaddwb' has no form that takes 'svfloat16_t' arguments} } */
+-  svaddwb (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svaddwb', which expects an SVE vector type} } */
+-  svaddwb (0, u64); /* { dg-error {passing 'int' to argument 1 of 'svaddwb', which expects an SVE vector type} } */
++  svaddwb (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svaddwb', which expects an SVE type rather than a scalar} } */
++  svaddwb (0, u64); /* { dg-error {passing 'int' to argument 1 of 'svaddwb', which expects an SVE type rather than a scalar} } */
+   svaddwb (u8, 0); /* { dg-error {'svaddwb' has no form that takes 'svuint8_t' arguments} } */
+   svaddwb (u16, 0);
+   svaddwb (u32, 0);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
+index cb9ac946c..ba1b2520f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
+@@ -6,10 +6,10 @@ test (svbool_t pg, svint32_t s32, svint64_t s64, int i)
+   svclasta (pg, 1); /* { dg-error {too few arguments to function 'svclasta'} } */
+   svclasta (pg, 1, s32, 1); /* { dg-error {too many arguments to function 'svclasta'} } */
+   svclasta (1, 1, s32); /* { dg-error {passing 'int' to argument 1 of 'svclasta', which expects 'svbool_t'} } */
+-  svclasta (pg, 1, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE vector type} } */
++  svclasta (pg, 1, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE type rather than a scalar} } */
+   svclasta (pg, 1, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+   svclasta (pg, i, s32);
+-  svclasta (pg, s32, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE vector type} } */
++  svclasta (pg, s32, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE type rather than a scalar} } */
+   svclasta (pg, s32, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svclasta', but previous arguments had type 'svint32_t'} } */
+   svclasta (pg, pg, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c
+index 12511a85b..5474124cc 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c
+@@ -12,14 +12,14 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svmatch (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svmatch'} } */
+   svmatch (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svmatch', which expects 'svbool_t'} } */
+   svmatch (pg, pg, pg); /* { dg-error {'svmatch' has no form that takes 'svbool_t' arguments} } */
+-  svmatch (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svmatch', which expects an SVE vector type} } */
++  svmatch (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svmatch', which expects an SVE type rather than a scalar} } */
+   svmatch (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+   svmatch (pg, u8, u8);
+   svmatch (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+   svmatch (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+   svmatch (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+   svmatch (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+-  svmatch (pg, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmatch', which expects an SVE vector type} } */
++  svmatch (pg, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmatch', which expects an SVE type rather than a scalar} } */
+ 
+   svmatch (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svfloat16_t'} } */
+   svmatch (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svfloat16_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
+index 71c8e86d5..6faa73972 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svcmpeq (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svcmpeq'} } */
+   svcmpeq (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcmpeq', which expects 'svbool_t'} } */
+   svcmpeq (pg, pg, pg); /* { dg-error {'svcmpeq' has no form that takes 'svbool_t' arguments} } */
+-  svcmpeq (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq', which expects an SVE vector type} } */
++  svcmpeq (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq', which expects an SVE type rather than a scalar} } */
+   svcmpeq (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+   svcmpeq (pg, u8, u8);
+   svcmpeq (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c
+index fc5e45663..655f03360 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c
+@@ -9,7 +9,7 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint64_t s64, svuint64_t u64,
+   svcmpeq_wide (pg, s8); /* { dg-error {too few arguments to function 'svcmpeq_wide'} } */
+   svcmpeq_wide (pg, s8, s64, s8); /* { dg-error {too many arguments to function 'svcmpeq_wide'} } */
+   svcmpeq_wide (s8, s8, s64); /* { dg-error {passing 'svint8_t' to argument 1 of 'svcmpeq_wide', which expects 'svbool_t'} } */
+-  svcmpeq_wide (pg, 0, s64); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq_wide', which expects an SVE vector type} } */
++  svcmpeq_wide (pg, 0, s64); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq_wide', which expects an SVE type rather than a scalar} } */
+   svcmpeq_wide (pg, s8, 0);
+   svcmpeq_wide (pg, s8, x);
+   svcmpeq_wide (pg, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c
+index daf9e0d5b..b57d9de1d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c
+@@ -7,7 +7,7 @@ f1 (svbool_t pg, svuint32_t u32, svuint32x2_t u32x2)
+ {
+   svlen (); /* { dg-error {too few arguments to function 'svlen'} } */
+   svlen (u32, u32); /* { dg-error {too many arguments to function 'svlen'} } */
+-  svlen (0); /* { dg-error {passing 'int' to argument 1 of 'svlen', which expects an SVE vector type} } */
++  svlen (0); /* { dg-error {passing 'int' to argument 1 of 'svlen', which expects an SVE type rather than a scalar} } */
+   svlen (pg); /* { dg-error {'svlen' has no form that takes 'svbool_t' arguments} } */
+   svlen (u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 1 of 'svlen', which expects a single SVE vector rather than a tuple} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
+index 31321a046..83e4a5600 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
+@@ -12,8 +12,8 @@ f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+   *ptr = svcreate2 (u8x2, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 1 of 'svcreate2', which expects a single SVE vector rather than a tuple} } */
+   *ptr = svcreate2 (u8, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+   *ptr = svcreate2 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+-  *ptr = svcreate2 (u8, x); /* { dg-error {passing 'int' to argument 2 of 'svcreate2', which expects an SVE vector type} } */
+-  *ptr = svcreate2 (x, u8); /* { dg-error {passing 'int' to argument 1 of 'svcreate2', which expects an SVE vector type} } */
++  *ptr = svcreate2 (u8, x); /* { dg-error {passing 'int' to argument 2 of 'svcreate2', which expects an SVE type rather than a scalar} } */
++  *ptr = svcreate2 (x, u8); /* { dg-error {passing 'int' to argument 1 of 'svcreate2', which expects an SVE type rather than a scalar} } */
+   *ptr = svcreate2 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svcreate2', but previous arguments had type 'svbool_t'} } */
+   *ptr = svcreate2 (pg, pg); /* { dg-error {'svcreate2' has no form that takes 'svbool_t' arguments} } */
+   *ptr = svcreate2 (u8, u8);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
+index a88e56b31..e3302f7e7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
+@@ -13,8 +13,8 @@ f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+   *ptr = svcreate3 (f16x3, f16x3, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 1 of 'svcreate3', which expects a single SVE vector rather than a tuple} } */
+   *ptr = svcreate3 (f16, f16, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+   *ptr = svcreate3 (f16, pg, f16); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+-  *ptr = svcreate3 (f16, x, f16); /* { dg-error {passing 'int' to argument 2 of 'svcreate3', which expects an SVE vector type} } */
+-  *ptr = svcreate3 (x, f16, f16); /* { dg-error {passing 'int' to argument 1 of 'svcreate3', which expects an SVE vector type} } */
++  *ptr = svcreate3 (f16, x, f16); /* { dg-error {passing 'int' to argument 2 of 'svcreate3', which expects an SVE type rather than a scalar} } */
++  *ptr = svcreate3 (x, f16, f16); /* { dg-error {passing 'int' to argument 1 of 'svcreate3', which expects an SVE type rather than a scalar} } */
+   *ptr = svcreate3 (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svcreate3', but previous arguments had type 'svbool_t'} } */
+   *ptr = svcreate3 (pg, pg, pg); /* { dg-error {'svcreate3' has no form that takes 'svbool_t' arguments} } */
+   *ptr = svcreate3 (f16, f16, f16);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
+index fed124506..c850c94f0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
+@@ -14,8 +14,8 @@ f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+   *ptr = svcreate4 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 1 of 'svcreate4', which expects a single SVE vector rather than a tuple} } */
+   *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+   *ptr = svcreate4 (s32, s32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+-  *ptr = svcreate4 (s32, x, s32, s32); /* { dg-error {passing 'int' to argument 2 of 'svcreate4', which expects an SVE vector type} } */
+-  *ptr = svcreate4 (x, s32, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svcreate4', which expects an SVE vector type} } */
++  *ptr = svcreate4 (s32, x, s32, s32); /* { dg-error {passing 'int' to argument 2 of 'svcreate4', which expects an SVE type rather than a scalar} } */
++  *ptr = svcreate4 (x, s32, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svcreate4', which expects an SVE type rather than a scalar} } */
+   *ptr = svcreate4 (pg, s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcreate4', but previous arguments had type 'svbool_t'} } */
+   *ptr = svcreate4 (pg, pg, pg, pg); /* { dg-error {'svcreate4' has no form that takes 'svbool_t' arguments} } */
+   *ptr = svcreate4 (s32, s32, s32, s32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c
+index 1d292786d..181d1b01b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c
+@@ -15,7 +15,7 @@ f1 (svbool_t pg, int i, float f, double d, void *ptr, svfloat32_t f32,
+   svadda (pg, ptr, f32); /* { dg-error {incompatible type for argument 2 of 'svadda_f32'} } */
+   svadda (pg, pg, f32); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadda', which expects a scalar element} } */
+   svadda (pg, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadda', which expects a scalar element} } */
+-  svadda (pg, f, f); /* { dg-error {passing 'float' to argument 3 of 'svadda', which expects an SVE vector type} } */
++  svadda (pg, f, f); /* { dg-error {passing 'float' to argument 3 of 'svadda', which expects an SVE type rather than a scalar} } */
+   svadda (pg, i, i32); /* { dg-error {'svadda' has no form that takes 'svint32_t' arguments} } */
+-  svadda (pg, i, i); /* { dg-error {passing 'int' to argument 3 of 'svadda', which expects an SVE vector type} } */
++  svadda (pg, i, i); /* { dg-error {passing 'int' to argument 3 of 'svadda', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c
+index a61afcd2d..4de082d01 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c
+@@ -7,7 +7,7 @@ test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ {
+   svqincp (s32); /* { dg-error {too few arguments to function 'svqincp'} } */
+   svqincp (s32, pg, pg); /* { dg-error {too many arguments to function 'svqincp'} } */
+-  svqincp (i, pg); /* { dg-error {passing 'int' to argument 1 of 'svqincp', which expects an SVE vector type} } */
++  svqincp (i, pg); /* { dg-error {passing 'int' to argument 1 of 'svqincp', which expects an SVE type rather than a scalar} } */
+   svqincp (pg, pg); /* { dg-error {'svqincp' has no form that takes 'svbool_t' arguments} } */
+   svqincp (s8, pg); /* { dg-error {'svqincp' has no form that takes 'svint8_t' arguments} } */
+   svqincp (u8, pg); /* { dg-error {'svqincp' has no form that takes 'svuint8_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c
+index 5b0b00e96..7fc7bb67b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c
+@@ -23,22 +23,22 @@ f2 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32, svint32_t s32,
+ {
+   svmmla (s32, s8); /* { dg-error {too few arguments to function 'svmmla'} } */
+   svmmla (s32, s8, s8, s8); /* { dg-error {too many arguments to function 'svmmla'} } */
+-  svmmla (0, s8, s8); /* { dg-error {passing 'int' to argument 1 of 'svmmla', which expects an SVE vector type} } */
++  svmmla (0, s8, s8); /* { dg-error {passing 'int' to argument 1 of 'svmmla', which expects an SVE type rather than a scalar} } */
+   svmmla (pg, s8, s8); /* { dg-error {'svmmla' has no form that takes 'svbool_t' arguments} } */
+   svmmla (u8, s8, s8); /* { dg-error {'svmmla' has no form that takes 'svuint8_t' arguments} } */
+ 
+-  svmmla (s32, 0, s8); /* { dg-error {passing 'int' to argument 2 of 'svmmla', which expects an SVE vector type} } */
++  svmmla (s32, 0, s8); /* { dg-error {passing 'int' to argument 2 of 'svmmla', which expects an SVE type rather than a scalar} } */
+   svmmla (s32, u8, s8); /* { dg-error {arguments 1 and 2 of 'svmmla' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+   svmmla (s32, s8, u8); /* { dg-error {arguments 1 and 3 of 'svmmla' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+-  svmmla (s32, s8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmmla', which expects an SVE vector type} } */
++  svmmla (s32, s8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmmla', which expects an SVE type rather than a scalar} } */
+   svmmla (s32, s8, s8);
+   svmmla (s32, s32, s32); /* { dg-error {passing 'svint32_t' instead of the expected 'svint8_t' to argument 2 of 'svmmla', after passing 'svint32_t' to argument 1} } */
+   svmmla (s32, u32, u32); /* { dg-error {passing 'svuint32_t' instead of the expected 'svint8_t' to argument 2 of 'svmmla', after passing 'svint32_t' to argument 1} } */
+ 
+-  svmmla (u32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svmmla', which expects an SVE vector type} } */
++  svmmla (u32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svmmla', which expects an SVE type rather than a scalar} } */
+   svmmla (u32, s8, u8); /* { dg-error {arguments 1 and 2 of 'svmmla' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+   svmmla (u32, u8, s8); /* { dg-error {arguments 1 and 3 of 'svmmla' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+-  svmmla (u32, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmmla', which expects an SVE vector type} } */
++  svmmla (u32, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmmla', which expects an SVE type rather than a scalar} } */
+   svmmla (u32, u8, u8);
+   svmmla (u32, s32, s32); /* { dg-error {passing 'svint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svmmla', after passing 'svuint32_t' to argument 1} } */
+   svmmla (u32, u32, u32); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svmmla', after passing 'svuint32_t' to argument 1} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c
+index b74721fad..88e0c35e7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c
+@@ -12,7 +12,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svprfb_gather (pg, u32); /* { dg-error {too few arguments to function 'svprfb_gather'} } */
+   svprfb_gather (pg, u32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfb_gather'} } */
+   svprfb_gather (0, u32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfb_gather', which expects 'svbool_t'} } */
+-  svprfb_gather (pg, 0, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 2 of 'svprfb_gather', which expects an SVE vector type} } */
++  svprfb_gather (pg, 0, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 2 of 'svprfb_gather', which expects an SVE type rather than a scalar} } */
+ 
+   svprfb_gather (pg, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+   svprfb_gather (pg, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c
+index ab0ef304a..025795e3d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+   svorv (pg, u32, u32); /* { dg-error {too many arguments to function 'svorv'} } */
+   svorv (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svorv', which expects 'svbool_t'} } */
+   svorv (u32, u32); /* { dg-error {passing 'svuint32_t' to argument 1 of 'svorv', which expects 'svbool_t'} } */
+-  svorv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svorv', which expects an SVE vector type} } */
++  svorv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svorv', which expects an SVE type rather than a scalar} } */
+   svorv (pg, pg); /* { dg-error {'svorv' has no form that takes 'svbool_t' arguments} } */
+   svorv (pg, s32);
+   svorv (pg, u32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c
+index f99a2887b..68bacd0a3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+   svaddv (pg, u32, u32); /* { dg-error {too many arguments to function 'svaddv'} } */
+   svaddv (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svaddv', which expects 'svbool_t'} } */
+   svaddv (u32, u32); /* { dg-error {passing 'svuint32_t' to argument 1 of 'svaddv', which expects 'svbool_t'} } */
+-  svaddv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svaddv', which expects an SVE vector type} } */
++  svaddv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svaddv', which expects an SVE type rather than a scalar} } */
+   svaddv (pg, pg); /* { dg-error {'svaddv' has no form that takes 'svbool_t' arguments} } */
+   svaddv (pg, s32);
+   svaddv (pg, u32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_1.c
+index 6536679d5..c5942c701 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_1.c
+@@ -66,5 +66,5 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ 
+   svshrnb (f32, 1); /* { dg-error {'svshrnb' has no form that takes 'svfloat32_t' arguments} } */
+ 
+-  svshrnb (1, 1); /* { dg-error {passing 'int' to argument 1 of 'svshrnb', which expects an SVE vector type} } */
++  svshrnb (1, 1); /* { dg-error {passing 'int' to argument 1 of 'svshrnb', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_to_uint_1.c
+index 51f9388bf..3ecd20a22 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowb_to_uint_1.c
+@@ -54,5 +54,5 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ 
+   svqshrunb (f32, 1); /* { dg-error {'svqshrunb' has no form that takes 'svfloat32_t' arguments} } */
+ 
+-  svqshrunb (1, 1); /* { dg-error {passing 'int' to argument 1 of 'svqshrunb', which expects an SVE vector type} } */
++  svqshrunb (1, 1); /* { dg-error {passing 'int' to argument 1 of 'svqshrunb', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_1.c
+index 6c31cf8ec..e9d1d1337 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_1.c
+@@ -76,6 +76,6 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ 
+   svshrnt (f32, f32, 1); /* { dg-error {'svshrnt' has no form that takes 'svfloat32_t' arguments} } */
+ 
+-  svshrnt (1, s32, 1); /* { dg-error {passing 'int' to argument 1 of 'svshrnt', which expects an SVE vector type} } */
+-  svshrnt (s32, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svshrnt', which expects an SVE vector type} } */
++  svshrnt (1, s32, 1); /* { dg-error {passing 'int' to argument 1 of 'svshrnt', which expects an SVE type rather than a scalar} } */
++  svshrnt (s32, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svshrnt', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_to_uint_1.c
+index 2e35ad304..741495609 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_narrowt_to_uint_1.c
+@@ -59,6 +59,6 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ 
+   svqshrunt (u16, f32, 1); /* { dg-error {'svqshrunt' has no form that takes 'svfloat32_t' arguments} } */
+ 
+-  svqshrunt (1, u32, 1); /* { dg-error {passing 'int' to argument 1 of 'svqshrunt', which expects an SVE vector type} } */
+-  svqshrunt (u32, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svqshrunt', which expects an SVE vector type} } */
++  svqshrunt (1, u32, 1); /* { dg-error {passing 'int' to argument 1 of 'svqshrunt', which expects an SVE type rather than a scalar} } */
++  svqshrunt (u32, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svqshrunt', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c
+index 625f059af..0b2a3e837 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c
+@@ -13,7 +13,7 @@ f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+   svst1 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svst1'} } */
+   svst1 (pg, s8_ptr, s8, 0); /* { dg-error {too many arguments to function 'svst1'} } */
+   svst1 (0, s8_ptr, s8); /* { dg-error {passing 'int' to argument 1 of 'svst1', which expects 'svbool_t'} } */
+-  svst1 (pg, void_ptr, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1', which expects an SVE vector type} } */
++  svst1 (pg, void_ptr, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1', which expects an SVE type rather than a scalar} } */
+   svst1 (pg, void_ptr, pg); /* { dg-error {'svst1' has no form that takes 'svbool_t' arguments} } */
+   svst1 (pg, 0, s8);
+   svst1 (pg, (int32_t *) 0, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c
+index c718b3ee0..b35e8955f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c
+@@ -15,7 +15,7 @@ f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+   svst1_vnum (pg, s8_ptr, pg, s8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_vnum', which expects 'int64_t'} } */
+   svst1_vnum (pg, s8_ptr, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svst1_vnum', which expects 'int64_t'} } */
+   svst1_vnum (pg, s8_ptr, void_ptr, s8); /* { dg-warning "passing argument 3 of 'svst1_vnum_s8' makes integer from pointer without a cast" } */
+-  svst1_vnum (pg, void_ptr, 0, 0); /* { dg-error {passing 'int' to argument 4 of 'svst1_vnum', which expects an SVE vector type} } */
++  svst1_vnum (pg, void_ptr, 0, 0); /* { dg-error {passing 'int' to argument 4 of 'svst1_vnum', which expects an SVE type rather than a scalar} } */
+   svst1_vnum (pg, void_ptr, 0, pg); /* { dg-error {'svst1_vnum' has no form that takes 'svbool_t' arguments} } */
+   svst1_vnum (pg, 0, 0, s8);
+   svst1_vnum (pg, (int32_t *) 0, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c
+index 10abf758c..3b3b56222 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c
+@@ -13,8 +13,8 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+   svst1_scatter (pg, u32); /* { dg-error {too few arguments to function 'svst1_scatter'} } */
+   svst1_scatter (pg, u32, u32, 0); /* { dg-error {too many arguments to function 'svst1_scatter'} } */
+   svst1_scatter (0, u32, u32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter', which expects 'svbool_t'} } */
+-  svst1_scatter (pg, 0, u32); /* { dg-error {passing 'int' to argument 2 of 'svst1_scatter', which expects an SVE vector type} } */
+-  svst1_scatter (pg, u32, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1_scatter', which expects an SVE vector type} } */
++  svst1_scatter (pg, 0, u32); /* { dg-error {passing 'int' to argument 2 of 'svst1_scatter', which expects an SVE type rather than a scalar} } */
++  svst1_scatter (pg, u32, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1_scatter', which expects an SVE type rather than a scalar} } */
+ 
+   svst1_scatter (pg, u32, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_1.c
+index a9233324c..9a554f54f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svuint8_t u8, svuint16_t u16, svint32_t s32,
+ {
+   svbfmmla (f32, bf16); /* { dg-error {too few arguments to function 'svbfmmla'} } */
+   svbfmmla (f32, bf16, bf16, 0); /* { dg-error {too many arguments to function 'svbfmmla'} } */
+-  svbfmmla (0, bf16, bf16); /* { dg-error {passing 'int' to argument 1 of 'svbfmmla', which expects an SVE vector type} } */
++  svbfmmla (0, bf16, bf16); /* { dg-error {passing 'int' to argument 1 of 'svbfmmla', which expects an SVE type rather than a scalar} } */
+   svbfmmla (pg, bf16, bf16); /* { dg-error {'svbfmmla' has no form that takes 'svbool_t' arguments} } */
+   svbfmmla (u8, bf16, bf16); /* { dg-error {'svbfmmla' has no form that takes 'svuint8_t' arguments} } */
+   svbfmmla (u16, bf16, bf16); /* { dg-error {'svbfmmla' has no form that takes 'svuint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lane_1.c
+index 23f027f2d..87e74fbcf 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lane_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svuint8_t u8, svuint16_t u16, svint32_t s32,
+ {
+   svbfmlalb_lane (f32, bf16, bf16); /* { dg-error {too few arguments to function 'svbfmlalb_lane'} } */
+   svbfmlalb_lane (f32, bf16, bf16, 0, 0); /* { dg-error {too many arguments to function 'svbfmlalb_lane'} } */
+-  svbfmlalb_lane (0, bf16, bf16, 0); /* { dg-error {passing 'int' to argument 1 of 'svbfmlalb_lane', which expects an SVE vector type} } */
++  svbfmlalb_lane (0, bf16, bf16, 0); /* { dg-error {passing 'int' to argument 1 of 'svbfmlalb_lane', which expects an SVE type rather than a scalar} } */
+   svbfmlalb_lane (pg, bf16, bf16, 0); /* { dg-error {'svbfmlalb_lane' has no form that takes 'svbool_t' arguments} } */
+   svbfmlalb_lane (u8, bf16, bf16, 0); /* { dg-error {'svbfmlalb_lane' has no form that takes 'svuint8_t' arguments} } */
+   svbfmlalb_lane (u16, bf16, bf16, 0); /* { dg-error {'svbfmlalb_lane' has no form that takes 'svuint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lanex2_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lanex2_1.c
+index 4755ca79a..ca1852644 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lanex2_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_lanex2_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svuint8_t u8, svuint16_t u16, svint32_t s32,
+ {
+   svbfdot_lane (f32, bf16, bf16); /* { dg-error {too few arguments to function 'svbfdot_lane'} } */
+   svbfdot_lane (f32, bf16, bf16, 0, 0); /* { dg-error {too many arguments to function 'svbfdot_lane'} } */
+-  svbfdot_lane (0, bf16, bf16, 0); /* { dg-error {passing 'int' to argument 1 of 'svbfdot_lane', which expects an SVE vector type} } */
++  svbfdot_lane (0, bf16, bf16, 0); /* { dg-error {passing 'int' to argument 1 of 'svbfdot_lane', which expects an SVE type rather than a scalar} } */
+   svbfdot_lane (pg, bf16, bf16, 0); /* { dg-error {'svbfdot_lane' has no form that takes 'svbool_t' arguments} } */
+   svbfdot_lane (u8, bf16, bf16, 0); /* { dg-error {'svbfdot_lane' has no form that takes 'svuint8_t' arguments} } */
+   svbfdot_lane (u16, bf16, bf16, 0); /* { dg-error {'svbfdot_lane' has no form that takes 'svuint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_opt_n_1.c
+index 2d09a8eeb..efdfb8955 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_bfloat16_opt_n_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svuint8_t u8, svuint16_t u16, svint32_t s32,
+ {
+   svbfdot (f32, bf16); /* { dg-error {too few arguments to function 'svbfdot'} } */
+   svbfdot (f32, bf16, bf16, 0); /* { dg-error {too many arguments to function 'svbfdot'} } */
+-  svbfdot (0, bf16, bf16); /* { dg-error {passing 'int' to argument 1 of 'svbfdot', which expects an SVE vector type} } */
++  svbfdot (0, bf16, bf16); /* { dg-error {passing 'int' to argument 1 of 'svbfdot', which expects an SVE type rather than a scalar} } */
+   svbfdot (pg, bf16, bf16); /* { dg-error {'svbfdot' has no form that takes 'svbool_t' arguments} } */
+   svbfdot (u8, bf16, bf16); /* { dg-error {'svbfdot' has no form that takes 'svuint8_t' arguments} } */
+   svbfdot (u16, bf16, bf16); /* { dg-error {'svbfdot' has no form that takes 'svuint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_lane_1.c
+index 600be05a8..934b7bd60 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_lane_1.c
+@@ -10,14 +10,14 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ {
+   svsudot_lane (s32, s8, u8); /* { dg-error {too few arguments to function 'svsudot_lane'} } */
+   svsudot_lane (s32, s8, u8, 0, 0); /* { dg-error {too many arguments to function 'svsudot_lane'} } */
+-  svsudot_lane (0, s8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svsudot_lane', which expects an SVE vector type} } */
++  svsudot_lane (0, s8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svsudot_lane', which expects an SVE type rather than a scalar} } */
+   svsudot_lane (pg, s8, u8, 0); /* { dg-error {'svsudot_lane' has no form that takes 'svbool_t' arguments} } */
+   svsudot_lane (u8, s8, u8, 0); /* { dg-error {'svsudot_lane' has no form that takes 'svuint8_t' arguments} } */
+   svsudot_lane (f32, s8, u8, 0); /* { dg-error {'svsudot_lane' has no form that takes 'svfloat32_t' arguments} } */
+   svsudot_lane (u32, s8, u8, 0); /* { dg-error {'svsudot_lane' has no form that takes 'svuint32_t' arguments} } */
+   svsudot_lane (s32, s8, u8, 0);
+-  svsudot_lane (s32, 0, u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svsudot_lane', which expects an SVE vector type} } */
+-  svsudot_lane (s32, s8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svsudot_lane', which expects an SVE vector type} } */
++  svsudot_lane (s32, 0, u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svsudot_lane', which expects an SVE type rather than a scalar} } */
++  svsudot_lane (s32, s8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svsudot_lane', which expects an SVE type rather than a scalar} } */
+ 
+   svsudot_lane (s32, s8, u8, 0);
+   svsudot_lane (s32, u8, u8, 0); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svsudot_lane', which expects a vector of signed integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_opt_n_1.c
+index f95ac582f..c481996d3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_intq_uintq_opt_n_1.c
+@@ -23,12 +23,12 @@ f2 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32,
+ {
+   svsudot (s32, s8); /* { dg-error {too few arguments to function 'svsudot'} } */
+   svsudot (s32, s8, u8, u8); /* { dg-error {too many arguments to function 'svsudot'} } */
+-  svsudot (0, s8, u8); /* { dg-error {passing 'int' to argument 1 of 'svsudot', which expects an SVE vector type} } */
++  svsudot (0, s8, u8); /* { dg-error {passing 'int' to argument 1 of 'svsudot', which expects an SVE type rather than a scalar} } */
+   svsudot (pg, s8, u8); /* { dg-error {'svsudot' has no form that takes 'svbool_t' arguments} } */
+   svsudot (u8, s8, u8); /* { dg-error {'svsudot' has no form that takes 'svuint8_t' arguments} } */
+   svsudot (f32, s8, u8); /* { dg-error {'svsudot' has no form that takes 'svfloat32_t' arguments} } */
+   svsudot (s32, s8, u8);
+-  svsudot (s32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svsudot', which expects an SVE vector type} } */
++  svsudot (s32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svsudot', which expects an SVE type rather than a scalar} } */
+   svsudot (s32, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svsudot', which expects a vector of signed integers} } */
+   svsudot (s32, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svsudot', which expects a vector of unsigned integers} } */
+   svsudot (s32, s8, 0);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
+index d59ffab40..520c11f79 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
+@@ -10,9 +10,9 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+   svmla_lane (f32, f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svmla_lane'} } */
+   svmla_lane (pg, pg, pg, 0); /* { dg-error {'svmla_lane' has no form that takes 'svbool_t' arguments} } */
+   svmla_lane (s32, s32, s32, 0); /* { dg-error {ACLE function 'svmla_lane_s32' requires ISA extension 'sve2'} "" { xfail aarch64_sve2 } } */
+-  svmla_lane (1, f32, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmla_lane', which expects an SVE vector type} } */
+-  svmla_lane (f32, 1, f32, 0); /* { dg-error {passing 'int' to argument 2 of 'svmla_lane', which expects an SVE vector type} } */
+-  svmla_lane (f32, f32, 1, 0); /* { dg-error {passing 'int' to argument 3 of 'svmla_lane', which expects an SVE vector type} } */
++  svmla_lane (1, f32, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmla_lane', which expects an SVE type rather than a scalar} } */
++  svmla_lane (f32, 1, f32, 0); /* { dg-error {passing 'int' to argument 2 of 'svmla_lane', which expects an SVE type rather than a scalar} } */
++  svmla_lane (f32, f32, 1, 0); /* { dg-error {passing 'int' to argument 3 of 'svmla_lane', which expects an SVE type rather than a scalar} } */
+   svmla_lane (f32, f64, f32, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+   svmla_lane (f32, f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+   svmla_lane (f32, f32, f32, s32); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
+index 68e51724c..3163d130c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
+@@ -11,9 +11,9 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+   svcmla_lane (pg, pg, pg, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svbool_t' arguments} } */
+   svcmla_lane (s32, s32, s32, 0, 90); /* { dg-error {ACLE function 'svcmla_lane_s32' requires ISA extension 'sve2'} "" { xfail aarch64_sve2 } } */
+   svcmla_lane (f64, f64, f64, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svfloat64_t' arguments} } */
+-  svcmla_lane (1, f32, f32, 0, 90); /* { dg-error {passing 'int' to argument 1 of 'svcmla_lane', which expects an SVE vector type} } */
+-  svcmla_lane (f32, 1, f32, 0, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_lane', which expects an SVE vector type} } */
+-  svcmla_lane (f32, f32, 1, 0, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_lane', which expects an SVE vector type} } */
++  svcmla_lane (1, f32, f32, 0, 90); /* { dg-error {passing 'int' to argument 1 of 'svcmla_lane', which expects an SVE type rather than a scalar} } */
++  svcmla_lane (f32, 1, f32, 0, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_lane', which expects an SVE type rather than a scalar} } */
++  svcmla_lane (f32, f32, 1, 0, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_lane', which expects an SVE type rather than a scalar} } */
+   svcmla_lane (f32, f64, f32, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+   svcmla_lane (f32, f32, f64, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+   svcmla_lane (f32, f32, f32, s32, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_lane_1.c
+index e20e1a122..dd67b4e4e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_lane_1.c
+@@ -11,16 +11,16 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ {
+   svmlalb_lane (u64, u32, u32); /* { dg-error {too few arguments to function 'svmlalb_lane'} } */
+   svmlalb_lane (u64, u32, u32, 0, 0); /* { dg-error {too many arguments to function 'svmlalb_lane'} } */
+-  svmlalb_lane (0, u16, u16, 0); /* { dg-error {passing 'int' to argument 1 of 'svmlalb_lane', which expects an SVE vector type} } */
++  svmlalb_lane (0, u16, u16, 0); /* { dg-error {passing 'int' to argument 1 of 'svmlalb_lane', which expects an SVE type rather than a scalar} } */
+   svmlalb_lane (pg, u16, u16, 0); /* { dg-error {'svmlalb_lane' has no form that takes 'svbool_t' arguments} } */
+   svmlalb_lane (u8, u8, u8, 0); /* { dg-error {'svmlalb_lane' has no form that takes 'svuint8_t' arguments} } */
+   svmlalb_lane (u16, u8, u8, 0); /* { dg-error {'svmlalb_lane' has no form that takes 'svuint16_t' arguments} } */
+   svmlalb_lane (f16, u16, u16, 0); /* { dg-error {'svmlalb_lane' has no form that takes 'svfloat16_t' arguments} } */
+   svmlalb_lane (f32, f16, f16, 0);
+   svmlalb_lane (u32, u16, u16, 0);
+-  svmlalb_lane (u32, 0, u16, 0); /* { dg-error {passing 'int' to argument 2 of 'svmlalb_lane', which expects an SVE vector type} } */
++  svmlalb_lane (u32, 0, u16, 0); /* { dg-error {passing 'int' to argument 2 of 'svmlalb_lane', which expects an SVE type rather than a scalar} } */
+   svmlalb_lane (u32, s16, u16, 0); /* { dg-error {arguments 1 and 2 of 'svmlalb_lane' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint16_t' respectively} } */
+-  svmlalb_lane (u32, u16, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svmlalb_lane', which expects an SVE vector type} } */
++  svmlalb_lane (u32, u16, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svmlalb_lane', which expects an SVE type rather than a scalar} } */
+   svmlalb_lane (u32, u16, s16, 0); /* { dg-error {arguments 1 and 3 of 'svmlalb_lane' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint16_t' respectively} } */
+   svmlalb_lane (u32, u32, u32, 0); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint16_t' to argument 2 of 'svmlalb_lane', after passing 'svuint32_t' to argument 1} } */
+   svmlalb_lane (u32, u8, u16, 0); /* { dg-error {passing 'svuint8_t' instead of the expected 'svuint16_t' to argument 2 of 'svmlalb_lane', after passing 'svuint32_t' to argument 1} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_opt_n_1.c
+index c6718cf37..157fd7cd5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_long_opt_n_1.c
+@@ -10,13 +10,13 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint16_t u16, svuint32_t u32,
+ {
+   svabalb (u16, u8); /* { dg-error {too few arguments to function 'svabalb'} } */
+   svabalb (u16, u8, u8, u8); /* { dg-error {too many arguments to function 'svabalb'} } */
+-  svabalb (0, u8, u8); /* { dg-error {passing 'int' to argument 1 of 'svabalb', which expects an SVE vector type} } */
++  svabalb (0, u8, u8); /* { dg-error {passing 'int' to argument 1 of 'svabalb', which expects an SVE type rather than a scalar} } */
+   svabalb (pg, u8, u8); /* { dg-error {'svabalb' has no form that takes 'svbool_t' arguments} } */
+   svabalb (u8, u8, u8); /* { dg-error {'svabalb' has no form that takes 'svuint8_t' arguments} } */
+   svabalb (f16, u8, u8); /* { dg-error {'svabalb' has no form that takes 'svfloat16_t' arguments} } */
+   svabalb (f32, f16, f16); /* { dg-error {'svabalb' has no form that takes 'svfloat32_t' arguments} } */
+   svabalb (u16, u8, u8);
+-  svabalb (u16, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svabalb', which expects an SVE vector type} } */
++  svabalb (u16, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svabalb', which expects an SVE type rather than a scalar} } */
+   svabalb (u16, s8, u8); /* { dg-error {arguments 1 and 2 of 'svabalb' must have the same signedness, but the values passed here have type 'svuint16_t' and 'svint8_t' respectively} } */
+   svabalb (u16, u8, 0);
+   svabalb (u16, u8, s8); /* { dg-error {arguments 1 and 3 of 'svabalb' must have the same signedness, but the values passed here have type 'svuint16_t' and 'svint8_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
+index c4a80e9da..ac789c2be 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
+@@ -10,14 +10,14 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svmla_x (pg, u8, u8, u8, u8); /* { dg-error {too many arguments to function 'svmla_x'} } */
+   svmla_x (u8, u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svmla_x', which expects 'svbool_t'} } */
+   svmla_x (pg, pg, pg, pg); /* { dg-error {'svmla_x' has no form that takes 'svbool_t' arguments} } */
+-  svmla_x (pg, 1, u8, u8); /* { dg-error {passing 'int' to argument 2 of 'svmla_x', which expects an SVE vector type} } */
++  svmla_x (pg, 1, u8, u8); /* { dg-error {passing 'int' to argument 2 of 'svmla_x', which expects an SVE type rather than a scalar} } */
+   svmla_x (pg, u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+   svmla_x (pg, u8, u8, u8);
+   svmla_x (pg, u8, s16, u8); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+   svmla_x (pg, u8, u16, u8); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+   svmla_x (pg, u8, f16, u8); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+   svmla_x (pg, u8, pg, u8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, 0, u8); /* { dg-error {passing 'int' to argument 3 of 'svmla_x', which expects an SVE vector type} } */
++  svmla_x (pg, u8, 0, u8); /* { dg-error {passing 'int' to argument 3 of 'svmla_x', which expects an SVE type rather than a scalar} } */
+   svmla_x (pg, u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+   svmla_x (pg, u8, u8, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+   svmla_x (pg, u8, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c
+index e81552b64..c69b2d575 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c
+@@ -9,13 +9,13 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ {
+   svdot_lane (u32, u8, u8); /* { dg-error {too few arguments to function 'svdot_lane'} } */
+   svdot_lane (u32, u8, u8, 0, 0); /* { dg-error {too many arguments to function 'svdot_lane'} } */
+-  svdot_lane (0, u8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svdot_lane', which expects an SVE vector type} } */
++  svdot_lane (0, u8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svdot_lane', which expects an SVE type rather than a scalar} } */
+   svdot_lane (pg, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svbool_t' arguments} } */
+   svdot_lane (u8, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svuint8_t' arguments} } */
+   svdot_lane (f32, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svfloat32_t' arguments} } */
+   svdot_lane (u32, u8, u8, 0);
+-  svdot_lane (u32, 0, u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svdot_lane', which expects an SVE vector type} } */
+-  svdot_lane (u32, u8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svdot_lane', which expects an SVE vector type} } */
++  svdot_lane (u32, 0, u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svdot_lane', which expects an SVE type rather than a scalar} } */
++  svdot_lane (u32, u8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svdot_lane', which expects an SVE type rather than a scalar} } */
+ 
+   svdot_lane (s32, s8, s8, 0);
+   svdot_lane (s32, u8, s8, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_rotate_1.c
+index a748a8627..9e84e7a89 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_rotate_1.c
+@@ -11,13 +11,13 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ {
+   svcdot_lane (u32, u8, u8, 0); /* { dg-error {too few arguments to function 'svcdot_lane'} } */
+   svcdot_lane (u32, u8, u8, 0, 0, 0); /* { dg-error {too many arguments to function 'svcdot_lane'} } */
+-  svcdot_lane (0, u8, u8, 0, 0); /* { dg-error {passing 'int' to argument 1 of 'svcdot_lane', which expects an SVE vector type} } */
++  svcdot_lane (0, u8, u8, 0, 0); /* { dg-error {passing 'int' to argument 1 of 'svcdot_lane', which expects an SVE type rather than a scalar} } */
+   svcdot_lane (pg, u8, u8, 0, 0); /* { dg-error {'svcdot_lane' has no form that takes 'svbool_t' arguments} } */
+   svcdot_lane (s8, s8, s8, 0, 0); /* { dg-error {'svcdot_lane' has no form that takes 'svint8_t' arguments} } */
+   svcdot_lane (f32, s8, s8, 0, 0); /* { dg-error {'svcdot_lane' has no form that takes 'svfloat32_t' arguments} } */
+   svcdot_lane (s32, s8, s8, 0, 0);
+-  svcdot_lane (s32, 0, s8, 0, 0); /* { dg-error {passing 'int' to argument 2 of 'svcdot_lane', which expects an SVE vector type} } */
+-  svcdot_lane (s32, s8, 0, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svcdot_lane', which expects an SVE vector type} } */
++  svcdot_lane (s32, 0, s8, 0, 0); /* { dg-error {passing 'int' to argument 2 of 'svcdot_lane', which expects an SVE type rather than a scalar} } */
++  svcdot_lane (s32, s8, 0, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svcdot_lane', which expects an SVE type rather than a scalar} } */
+ 
+   svcdot_lane (s32, s8, s8, 0, 0);
+   svcdot_lane (s32, u8, s8, 0, 0); /* { dg-error {arguments 1 and 2 of 'svcdot_lane' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c
+index fee4096fe..85d4b2dd8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c
+@@ -8,12 +8,12 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32,
+ {
+   svdot (u32, u8); /* { dg-error {too few arguments to function 'svdot'} } */
+   svdot (u32, u8, u8, u8); /* { dg-error {too many arguments to function 'svdot'} } */
+-  svdot (0, u8, u8); /* { dg-error {passing 'int' to argument 1 of 'svdot', which expects an SVE vector type} } */
++  svdot (0, u8, u8); /* { dg-error {passing 'int' to argument 1 of 'svdot', which expects an SVE type rather than a scalar} } */
+   svdot (pg, u8, u8); /* { dg-error {'svdot' has no form that takes 'svbool_t' arguments} } */
+   svdot (u8, u8, u8); /* { dg-error {'svdot' has no form that takes 'svuint8_t' arguments} } */
+   svdot (f32, u8, u8); /* { dg-error {'svdot' has no form that takes 'svfloat32_t' arguments} } */
+   svdot (u32, u8, u8);
+-  svdot (u32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svdot', which expects an SVE vector type} } */
++  svdot (u32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svdot', which expects an SVE type rather than a scalar} } */
+   svdot (u32, s8, u8); /* { dg-error {arguments 1 and 2 of 'svdot' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+   svdot (u32, u8, 0);
+   svdot (u32, u8, s8); /* { dg-error {arguments 1 and 3 of 'svdot' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_rotate_1.c
+index 65e749ba7..9dd7eaf3c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_rotate_1.c
+@@ -11,13 +11,13 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ {
+   svcdot (u32, u8, u8); /* { dg-error {too few arguments to function 'svcdot'} } */
+   svcdot (u32, u8, u8, 0, 0); /* { dg-error {too many arguments to function 'svcdot'} } */
+-  svcdot (0, u8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svcdot', which expects an SVE vector type} } */
++  svcdot (0, u8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svcdot', which expects an SVE type rather than a scalar} } */
+   svcdot (pg, u8, u8, 0); /* { dg-error {'svcdot' has no form that takes 'svbool_t' arguments} } */
+   svcdot (s8, s8, s8, 0); /* { dg-error {'svcdot' has no form that takes 'svint8_t' arguments} } */
+   svcdot (f32, s8, s8, 0); /* { dg-error {'svcdot' has no form that takes 'svfloat32_t' arguments} } */
+   svcdot (s32, s8, s8, 0);
+-  svcdot (s32, 0, s8, 0); /* { dg-error {passing 'int' to argument 2 of 'svcdot', which expects an SVE vector type} } */
+-  svcdot (s32, s8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svcdot', which expects an SVE vector type} } */
++  svcdot (s32, 0, s8, 0); /* { dg-error {passing 'int' to argument 2 of 'svcdot', which expects an SVE type rather than a scalar} } */
++  svcdot (s32, s8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svcdot', which expects an SVE type rather than a scalar} } */
+ 
+   svcdot (s32, s8, s8, 0);
+   svcdot (s32, u8, s8, 0); /* { dg-error {arguments 1 and 2 of 'svcdot' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
+index f340e3d1e..bb6740289 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
+@@ -10,9 +10,9 @@ f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+   svcmla_x (f32, f32, f32, f32, 90); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcmla_x', which expects 'svbool_t'} } */
+   svcmla_x (pg, pg, pg, pg, 90); /* { dg-error {'svcmla_x' has no form that takes 'svbool_t' arguments} } */
+   svcmla_x (pg, s32, s32, s32, 90); /* { dg-error {'svcmla_x' has no form that takes 'svint32_t' arguments} } */
+-  svcmla_x (pg, 1, f32, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_x', which expects an SVE vector type} } */
+-  svcmla_x (pg, f32, 1, f32, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_x', which expects an SVE vector type} } */
+-  svcmla_x (pg, f32, f32, 1, 90); /* { dg-error {passing 'int' to argument 4 of 'svcmla_x', which expects an SVE vector type} } */
++  svcmla_x (pg, 1, f32, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_x', which expects an SVE type rather than a scalar} } */
++  svcmla_x (pg, f32, 1, f32, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_x', which expects an SVE type rather than a scalar} } */
++  svcmla_x (pg, f32, f32, 1, 90); /* { dg-error {passing 'int' to argument 4 of 'svcmla_x', which expects an SVE type rather than a scalar} } */
+   svcmla_x (pg, f32, f64, f32, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+   svcmla_x (pg, f32, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+   svcmla_x (pg, f32, f32, f32, s32); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c
+index 28111375f..cfe601631 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c
+@@ -12,10 +12,10 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+   const int one = 1;
+   pg = svsra (pg, pg, 1); /* { dg-error {'svsra' has no form that takes 'svbool_t' arguments} } */
+   pg = svsra (pg, s8, 1); /* { dg-error {passing 'svint8_t' to argument 2 of 'svsra', but previous arguments had type 'svbool_t'} } */
+-  s8 = svsra (1, s8, 1); /* { dg-error {passing 'int' to argument 1 of 'svsra', which expects an SVE vector type} } */
++  s8 = svsra (1, s8, 1); /* { dg-error {passing 'int' to argument 1 of 'svsra', which expects an SVE type rather than a scalar} } */
+   s8 = svsra (s8, u8, 1); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svsra', but previous arguments had type 'svint8_t'} } */
+   s8 = svsra (s8, pg, 1); /* { dg-error {passing 'svbool_t' to argument 2 of 'svsra', but previous arguments had type 'svint8_t'} } */
+-  s8 = svsra (s8, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svsra', which expects an SVE vector type} } */
++  s8 = svsra (s8, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svsra', which expects an SVE type rather than a scalar} } */
+   s8 = svsra (s8, s8, x); /* { dg-error {argument 3 of 'svsra' must be an integer constant expression} } */
+   s8 = svsra (s8, s8, one); /* { dg-error {argument 3 of 'svsra' must be an integer constant expression} } */
+   s8 = svsra (s8, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svsra', which expects a value in the range \[1, 8\]} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c
+index 711b6a133..5fb497701 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c
+@@ -13,8 +13,8 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+   svtbx (pg, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (pg, pg, u8); /* { dg-error {'svtbx' has no form that takes 'svbool_t' arguments} } */
+ 
+-  svtbx (u8, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svtbx', which expects an SVE vector type} } */
+-  svtbx (u8, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svtbx', which expects an SVE vector type} } */
++  svtbx (u8, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svtbx', which expects an SVE type rather than a scalar} } */
++  svtbx (u8, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svtbx', which expects an SVE type rather than a scalar} } */
+   svtbx (u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbx', but previous arguments had type 'svuint8_t'} } */
+   svtbx (u8, u8, u8);
+   svtbx (u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+@@ -29,7 +29,7 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+   svtbx (s8, s8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (s8, s8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+ 
+-  svtbx (u16, 0, u16); /* { dg-error {passing 'int' to argument 2 of 'svtbx', which expects an SVE vector type} } */
++  svtbx (u16, 0, u16); /* { dg-error {passing 'int' to argument 2 of 'svtbx', which expects an SVE type rather than a scalar} } */
+   svtbx (u16, u16, u8); /* { dg-error {arguments 1 and 3 of 'svtbx' must have the same element size, but the values passed here have type 'svuint16_t' and 'svuint8_t' respectively} } */
+   svtbx (u16, u16, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (u16, u16, u16);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_1.c
+index f52fb39bf..d1aad1de1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_1.c
+@@ -23,15 +23,15 @@ f2 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32,
+ {
+   svusmmla (s32, u8); /* { dg-error {too few arguments to function 'svusmmla'} } */
+   svusmmla (s32, u8, s8, u8); /* { dg-error {too many arguments to function 'svusmmla'} } */
+-  svusmmla (0, u8, s8); /* { dg-error {passing 'int' to argument 1 of 'svusmmla', which expects an SVE vector type} } */
++  svusmmla (0, u8, s8); /* { dg-error {passing 'int' to argument 1 of 'svusmmla', which expects an SVE type rather than a scalar} } */
+   svusmmla (pg, u8, s8); /* { dg-error {'svusmmla' has no form that takes 'svbool_t' arguments} } */
+   svusmmla (u8, u8, s8); /* { dg-error {'svusmmla' has no form that takes 'svuint8_t' arguments} } */
+   svusmmla (f32, u8, s8); /* { dg-error {'svusmmla' has no form that takes 'svfloat32_t' arguments} } */
+   svusmmla (s32, u8, s8);
+-  svusmmla (s32, 0, s8); /* { dg-error {passing 'int' to argument 2 of 'svusmmla', which expects an SVE vector type} } */
++  svusmmla (s32, 0, s8); /* { dg-error {passing 'int' to argument 2 of 'svusmmla', which expects an SVE type rather than a scalar} } */
+   svusmmla (s32, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svusmmla', which expects a vector of signed integers} } */
+   svusmmla (s32, s8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svusmmla', which expects a vector of unsigned integers} } */
+-  svusmmla (s32, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svusmmla', which expects an SVE vector type} } */
++  svusmmla (s32, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svusmmla', which expects an SVE type rather than a scalar} } */
+   svusmmla (s32, u8, s8);
+   svusmmla (s32, u32, u32); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svusmmla', after passing 'svint32_t' to argument 1} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_lane_1.c
+index b40cfe9e8..0cc5c7497 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_lane_1.c
+@@ -10,14 +10,14 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ {
+   svusdot_lane (s32, u8, s8); /* { dg-error {too few arguments to function 'svusdot_lane'} } */
+   svusdot_lane (s32, u8, s8, 0, 0); /* { dg-error {too many arguments to function 'svusdot_lane'} } */
+-  svusdot_lane (0, u8, s8, 0); /* { dg-error {passing 'int' to argument 1 of 'svusdot_lane', which expects an SVE vector type} } */
++  svusdot_lane (0, u8, s8, 0); /* { dg-error {passing 'int' to argument 1 of 'svusdot_lane', which expects an SVE type rather than a scalar} } */
+   svusdot_lane (pg, u8, s8, 0); /* { dg-error {'svusdot_lane' has no form that takes 'svbool_t' arguments} } */
+   svusdot_lane (u8, u8, s8, 0); /* { dg-error {'svusdot_lane' has no form that takes 'svuint8_t' arguments} } */
+   svusdot_lane (f32, u8, s8, 0); /* { dg-error {'svusdot_lane' has no form that takes 'svfloat32_t' arguments} } */
+   svusdot_lane (u32, u8, s8, 0); /* { dg-error {'svusdot_lane' has no form that takes 'svuint32_t' arguments} } */
+   svusdot_lane (s32, u8, s8, 0);
+-  svusdot_lane (s32, 0, s8, 0); /* { dg-error {passing 'int' to argument 2 of 'svusdot_lane', which expects an SVE vector type} } */
+-  svusdot_lane (s32, u8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svusdot_lane', which expects an SVE vector type} } */
++  svusdot_lane (s32, 0, s8, 0); /* { dg-error {passing 'int' to argument 2 of 'svusdot_lane', which expects an SVE type rather than a scalar} } */
++  svusdot_lane (s32, u8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svusdot_lane', which expects an SVE type rather than a scalar} } */
+ 
+   svusdot_lane (s32, u8, s8, 0);
+   svusdot_lane (s32, s8, s8, 0); /* { dg-error {passing 'svint8_t' to argument 2 of 'svusdot_lane', which expects a vector of unsigned integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_opt_n_1.c
+index 896b80390..f6585ae77 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uintq_intq_opt_n_1.c
+@@ -23,12 +23,12 @@ f2 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32,
+ {
+   svusdot (s32, u8); /* { dg-error {too few arguments to function 'svusdot'} } */
+   svusdot (s32, u8, s8, u8); /* { dg-error {too many arguments to function 'svusdot'} } */
+-  svusdot (0, u8, s8); /* { dg-error {passing 'int' to argument 1 of 'svusdot', which expects an SVE vector type} } */
++  svusdot (0, u8, s8); /* { dg-error {passing 'int' to argument 1 of 'svusdot', which expects an SVE type rather than a scalar} } */
+   svusdot (pg, u8, s8); /* { dg-error {'svusdot' has no form that takes 'svbool_t' arguments} } */
+   svusdot (u8, u8, s8); /* { dg-error {'svusdot' has no form that takes 'svuint8_t' arguments} } */
+   svusdot (f32, u8, s8); /* { dg-error {'svusdot' has no form that takes 'svfloat32_t' arguments} } */
+   svusdot (s32, u8, s8);
+-  svusdot (s32, 0, s8); /* { dg-error {passing 'int' to argument 2 of 'svusdot', which expects an SVE vector type} } */
++  svusdot (s32, 0, s8); /* { dg-error {passing 'int' to argument 2 of 'svusdot', which expects an SVE type rather than a scalar} } */
+   svusdot (s32, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svusdot', which expects a vector of signed integers} } */
+   svusdot (s32, s8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svusdot', which expects a vector of unsigned integers} } */
+   svusdot (s32, u8, 0);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
+index 8b98fc24d..c2eda93e3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
+@@ -9,8 +9,8 @@ f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+   svtmad (f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svtmad'} } */
+   svtmad (pg, pg, 0); /* { dg-error {'svtmad' has no form that takes 'svbool_t' arguments} } */
+   svtmad (s32, s32, 0); /* { dg-error {'svtmad' has no form that takes 'svint32_t' arguments} } */
+-  svtmad (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svtmad', which expects an SVE vector type} } */
+-  svtmad (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svtmad', which expects an SVE vector type} } */
++  svtmad (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svtmad', which expects an SVE type rather than a scalar} } */
++  svtmad (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svtmad', which expects an SVE type rather than a scalar} } */
+   svtmad (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svtmad', but previous arguments had type 'svfloat32_t'} } */
+   svtmad (f32, f32, s32); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+   svtmad (f32, f32, i); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
+index eef85a01d..8c865a0e6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
+@@ -7,7 +7,7 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32)
+ {
+   svabs_m (s32, pg); /* { dg-error {too few arguments to function 'svabs_m'} } */
+   svabs_m (s32, pg, s32, s32); /* { dg-error {too many arguments to function 'svabs_m'} } */
+-  svabs_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svabs_m', which expects an SVE vector type} } */
++  svabs_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svabs_m', which expects an SVE type rather than a scalar} } */
+   svabs_m (s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svabs_m', which expects 'svbool_t'} } */
+   svabs_m (s32, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svabs_m', which expects 'svbool_t'} } */
+   svabs_m (s32, pg, s32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c
+index e94673a66..bf93e21a4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c
+@@ -9,7 +9,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8)
+   svabs_x (pg, s8, s8); /* { dg-error {too many arguments to function 'svabs_x'} } */
+   svabs_x (s8, s8); /* { dg-error {passing 'svint8_t' to argument 1 of 'svabs_x', which expects 'svbool_t'} } */
+   svabs_x (pg, pg); /* { dg-error {'svabs_x' has no form that takes 'svbool_t' arguments} } */
+-  svabs_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svabs_x', which expects an SVE vector type} } */
++  svabs_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svabs_x', which expects an SVE type rather than a scalar} } */
+   svabs_x (pg, s8);
+   svabs_x (pg, u8); /* { dg-error {'svabs_x' has no form that takes 'svuint8_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c
+index caa4e623d..f59ad590b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c
+@@ -9,7 +9,7 @@ test (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svcvt_f64_x (pg); /* { dg-error {too few arguments to function 'svcvt_f64_x'} } */
+   svcvt_f64_x (pg, s32, 0); /* { dg-error {too many arguments to function 'svcvt_f64_x'} } */
+   svcvt_f64_x (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svcvt_f64_x', which expects 'svbool_t'} } */
+-  svcvt_f64_x (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svcvt_f64_x', which expects an SVE vector type} } */
++  svcvt_f64_x (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svcvt_f64_x', which expects an SVE type rather than a scalar} } */
+ 
+   svcvt_f64_x (pg, s8); /* { dg-error {'svcvt_f64_x' has no form that takes 'svint8_t' arguments} } */
+   svcvt_f64_x (pg, s16); /* { dg-error {'svcvt_f64_x' has no form that takes 'svint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c
+index ddbd93b69..2649fd694 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c
+@@ -12,7 +12,7 @@ test (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svcvt_f64_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+   svcvt_f64_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+   svcvt_f64_m (f64, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcvt_f64_m', which expects 'svbool_t'} } */
+-  svcvt_f64_m (f64, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svcvt_f64_m', which expects an SVE vector type} } */
++  svcvt_f64_m (f64, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svcvt_f64_m', which expects an SVE type rather than a scalar} } */
+ 
+   svcvt_f64_m (f64, pg, s8); /* { dg-error {'svcvt_f64_m' has no form that takes 'svint8_t' arguments} } */
+   svcvt_f64_m (f64, pg, s16); /* { dg-error {'svcvt_f64_m' has no form that takes 'svint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_narrowt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_narrowt_1.c
+index 92c07b8c1..a5d56dec0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_narrowt_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_narrowt_1.c
+@@ -14,7 +14,7 @@ test (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svcvtnt_f32_m (0, pg, f64); /* { dg-error {passing 'int' to argument 1 of 'svcvtnt_f32_m', which expects 'svfloat32_t'} } */
+   svcvtnt_f32_m (pg, pg, f64); /* { dg-error {passing 'svbool_t' to argument 1 of 'svcvtnt_f32_m', which expects 'svfloat32_t'} } */
+   svcvtnt_f32_m (f32, s32, f64); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcvtnt_f32_m', which expects 'svbool_t'} } */
+-  svcvtnt_f32_m (f32, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svcvtnt_f32_m', which expects an SVE vector type} } */
++  svcvtnt_f32_m (f32, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svcvtnt_f32_m', which expects an SVE type rather than a scalar} } */
+ 
+   svcvtnt_f32_m (f32, pg, s8); /* { dg-error {'svcvtnt_f32_m' has no form that takes 'svint8_t' arguments} } */
+   svcvtnt_f32_m (f32, pg, s16); /* { dg-error {'svcvtnt_f32_m' has no form that takes 'svint16_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_1.c
+index c03d644ed..c2465e3e2 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_1.c
+@@ -23,5 +23,5 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svqxtnb (u64);
+   svqxtnb (s64);
+   svqxtnb (f32); /* { dg-error {'svqxtnb' has no form that takes 'svfloat32_t' arguments} } */
+-  svqxtnb (1); /* { dg-error {passing 'int' to argument 1 of 'svqxtnb', which expects an SVE vector type} } */
++  svqxtnb (1); /* { dg-error {passing 'int' to argument 1 of 'svqxtnb', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_to_uint_1.c
+index c3e210380..60051f80c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowb_to_uint_1.c
+@@ -23,5 +23,5 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svqxtunb (u64); /* { dg-error {'svqxtunb' has no form that takes 'svuint64_t' arguments} } */
+   svqxtunb (s64);
+   svqxtunb (f32); /* { dg-error {'svqxtunb' has no form that takes 'svfloat32_t' arguments} } */
+-  svqxtunb (1); /* { dg-error {passing 'int' to argument 1 of 'svqxtunb', which expects an SVE vector type} } */
++  svqxtunb (1); /* { dg-error {passing 'int' to argument 1 of 'svqxtunb', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_1.c
+index 4ed179cb3..a0612dcb7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_1.c
+@@ -26,6 +26,6 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svqxtnt (u32, u64);
+   svqxtnt (s32, s64);
+   svqxtnt (f16, f32); /* { dg-error {'svqxtnt' has no form that takes 'svfloat32_t' arguments} } */
+-  svqxtnt (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svqxtnt', which expects an SVE vector type} } */
+-  svqxtnt (u8, 1); /* { dg-error {passing 'int' to argument 2 of 'svqxtnt', which expects an SVE vector type} } */
++  svqxtnt (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svqxtnt', which expects an SVE type rather than a scalar} } */
++  svqxtnt (u8, 1); /* { dg-error {passing 'int' to argument 2 of 'svqxtnt', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_to_uint_1.c
+index acaa546ee..8e5fa5b3d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_narrowt_to_uint_1.c
+@@ -26,6 +26,6 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svqxtunt (u32, u64); /* { dg-error {'svqxtunt' has no form that takes 'svuint64_t' arguments} } */
+   svqxtunt (u32, s64);
+   svqxtunt (u16, f32); /* { dg-error {'svqxtunt' has no form that takes 'svfloat32_t' arguments} } */
+-  svqxtunt (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svqxtunt', which expects an SVE vector type} } */
+-  svqxtunt (u8, 1); /* { dg-error {passing 'int' to argument 2 of 'svqxtunt', which expects an SVE vector type} } */
++  svqxtunt (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svqxtunt', which expects an SVE type rather than a scalar} } */
++  svqxtunt (u8, 1); /* { dg-error {passing 'int' to argument 2 of 'svqxtunt', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_int_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_int_1.c
+index 517d11ff0..e2e172d2d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_int_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_int_1.c
+@@ -10,7 +10,7 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ {
+   svlogb_m (s32, pg); /* { dg-error {too few arguments to function 'svlogb_m'} } */
+   svlogb_m (s32, pg, f32, s32); /* { dg-error {too many arguments to function 'svlogb_m'} } */
+-  svlogb_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svlogb_m', which expects an SVE vector type} } */
++  svlogb_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svlogb_m', which expects an SVE type rather than a scalar} } */
+   svlogb_m (s32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svlogb_m', which expects 'svbool_t'} } */
+   svlogb_m (s32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svlogb_m', which expects 'svbool_t'} } */
+   svlogb_m (s32, pg, s32); /* { dg-error {'svlogb_m' has no form that takes 'svint32_t' arguments} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_1.c
+index 888b52513..b3cf0b9f5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_1.c
+@@ -8,7 +8,7 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ {
+   svclz_m (u32, pg); /* { dg-error {too few arguments to function 'svclz_m'} } */
+   svclz_m (u32, pg, s32, s32); /* { dg-error {too many arguments to function 'svclz_m'} } */
+-  svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE vector type} } */
++  svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE type rather than a scalar} } */
+   svclz_m (u32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+   svclz_m (u32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+   svclz_m (u32, pg, s32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_2.c
+index 233e847e9..da02d12fb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_2.c
+@@ -9,7 +9,7 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ {
+   svclz_m (u32, pg); /* { dg-error {too few arguments to function 'svclz_m'} } */
+   svclz_m (u32, pg, s32, s32); /* { dg-error {too many arguments to function 'svclz_m'} } */
+-  svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE vector type} } */
++  svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE type rather than a scalar} } */
+   svclz_m (u32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+   svclz_m (u32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+   svclz_m (u32, pg, s32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_3.c
+index da57b07ea..858a2a5e0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_to_uint_3.c
+@@ -9,6 +9,6 @@ f1 (svbool_t pg, svuint8_t u8)
+   svcnt_x (pg, u8, u8); /* { dg-error {too many arguments to function 'svcnt_x'} } */
+   svcnt_x (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcnt_x', which expects 'svbool_t'} } */
+   svcnt_x (pg, pg); /* { dg-error {'svcnt_x' has no form that takes 'svbool_t' arguments} } */
+-  svcnt_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svcnt_x', which expects an SVE vector type} } */
++  svcnt_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svcnt_x', which expects an SVE type rather than a scalar} } */
+   svcnt_x (pg, u8);
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c
+index 9c8acdf2d..e3275a8ce 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c
+@@ -8,7 +8,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ {
+   svexpa (); /* { dg-error {too few arguments to function 'svexpa'} } */
+   svexpa (u16, u16); /* { dg-error {too many arguments to function 'svexpa'} } */
+-  svexpa (1); /* { dg-error {passing 'int' to argument 1 of 'svexpa', which expects an SVE vector type} } */
++  svexpa (1); /* { dg-error {passing 'int' to argument 1 of 'svexpa', which expects an SVE type rather than a scalar} } */
+   svexpa (pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+   svexpa (s8); /* { dg-error {passing 'svint8_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+   svexpa (s16); /* { dg-error {passing 'svint16_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c
+index 95a97a72e..a194bd6ab 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c
+@@ -8,8 +8,8 @@ test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ {
+   svunpklo (); /* { dg-error {too few arguments to function 'svunpklo'} } */
+   svunpklo (pg, s8); /* { dg-error {too many arguments to function 'svunpklo'} } */
+-  svunpklo (i); /* { dg-error {passing 'int' to argument 1 of 'svunpklo', which expects an SVE vector type} } */
+-  svunpklo (f); /* { dg-error {passing 'float' to argument 1 of 'svunpklo', which expects an SVE vector type} } */
++  svunpklo (i); /* { dg-error {passing 'int' to argument 1 of 'svunpklo', which expects an SVE type rather than a scalar} } */
++  svunpklo (f); /* { dg-error {passing 'float' to argument 1 of 'svunpklo', which expects an SVE type rather than a scalar} } */
+   svunpklo (pg);
+   svunpklo (s8);
+   svunpklo (s16);
+-- 
+2.33.0
+
diff --git a/0167-Backport-SME-aarch64-Replace-vague-previous-argument.patch b/0167-Backport-SME-aarch64-Replace-vague-previous-argument.patch
new file mode 100644
index 0000000..840ad1d
--- /dev/null
+++ b/0167-Backport-SME-aarch64-Replace-vague-previous-argument.patch
@@ -0,0 +1,698 @@
+From 6a7cb5074824416ae562de0589550a930e9dbcaf Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:21 +0000
+Subject: [PATCH 068/157] [Backport][SME] aarch64: Replace vague "previous
+ arguments" message
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b52d4b66e8b91ec1e3de9c0b79aaf258824b875
+
+If an SVE ACLE intrinsic requires two arguments to have the
+same type, the C resolver would report mismatches as "argument N
+has type T2, but previous arguments had type T1".  This patch makes
+the message say which argument had type T1.
+
+This is needed to give decent error messages for some SME cases.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h
+	(function_resolver::require_matching_vector_type): Add a parameter
+	that specifies the number of the earlier argument that is being
+	matched against.
+	* config/aarch64/aarch64-sve-builtins.cc
+	(function_resolver::require_matching_vector_type): Likewise.
+	(require_derived_vector_type): Update calls accordingly.
+	(function_resolver::resolve_unary): Likewise.
+	(function_resolver::resolve_uniform): Likewise.
+	(function_resolver::resolve_uniform_opt_n): Likewise.
+	* config/aarch64/aarch64-sve-builtins-shapes.cc
+	(binary_long_lane_def::resolve): Likewise.
+	(clast_def::resolve, ternary_uint_def::resolve): Likewise.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/acle/general-c/*: Replace "but previous
+	arguments had" with "but argument N had".
+---
+ .../aarch64/aarch64-sve-builtins-shapes.cc    |  6 ++--
+ gcc/config/aarch64/aarch64-sve-builtins.cc    | 17 +++++------
+ gcc/config/aarch64/aarch64-sve-builtins.h     |  3 +-
+ .../aarch64/sve/acle/general-c/binary_1.c     |  6 ++--
+ .../sve/acle/general-c/binary_lane_1.c        |  2 +-
+ .../sve/acle/general-c/binary_long_lane_1.c   |  2 +-
+ .../sve/acle/general-c/binary_long_opt_n_1.c  |  8 +++---
+ .../acle/general-c/binary_narrowb_opt_n_1.c   |  8 +++---
+ .../acle/general-c/binary_narrowt_opt_n_1.c   |  8 +++---
+ .../sve/acle/general-c/binary_opt_n_2.c       | 14 +++++-----
+ .../sve/acle/general-c/binary_opt_n_3.c       | 16 +++++------
+ .../sve/acle/general-c/binary_rotate_1.c      |  2 +-
+ .../sve/acle/general-c/binary_to_uint_1.c     |  4 +--
+ .../aarch64/sve/acle/general-c/clast_1.c      |  2 +-
+ .../aarch64/sve/acle/general-c/compare_1.c    | 14 +++++-----
+ .../sve/acle/general-c/compare_opt_n_1.c      | 14 +++++-----
+ .../aarch64/sve/acle/general-c/create_1.c     |  6 ++--
+ .../aarch64/sve/acle/general-c/create_3.c     |  6 ++--
+ .../aarch64/sve/acle/general-c/create_5.c     |  6 ++--
+ .../aarch64/sve/acle/general-c/mmla_1.c       | 14 +++++-----
+ .../sve/acle/general-c/ternary_lane_1.c       |  4 +--
+ .../acle/general-c/ternary_lane_rotate_1.c    |  4 +--
+ .../sve/acle/general-c/ternary_opt_n_1.c      | 28 +++++++++----------
+ .../sve/acle/general-c/ternary_rotate_1.c     |  4 +--
+ .../general-c/ternary_shift_right_imm_1.c     |  6 ++--
+ .../sve/acle/general-c/ternary_uint_1.c       |  6 ++--
+ .../aarch64/sve/acle/general-c/tmad_1.c       |  2 +-
+ .../aarch64/sve/acle/general-c/unary_1.c      |  8 +++---
+ .../aarch64/sve/acle/general-c/undeclared_2.c |  2 +-
+ 29 files changed, 112 insertions(+), 110 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index 3ecef026c..40aa418e0 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -1153,7 +1153,7 @@ struct binary_long_lane_def : public overloaded_base<0>
+     type_suffix_index type, result_type;
+     if (!r.check_gp_argument (3, i, nargs)
+ 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+-	|| !r.require_matching_vector_type (i + 1, type)
++	|| !r.require_matching_vector_type (i + 1, i, type)
+ 	|| !r.require_integer_immediate (i + 2)
+ 	|| (result_type = long_type_suffix (r, type)) == NUM_TYPE_SUFFIXES)
+       return error_mark_node;
+@@ -1608,7 +1608,7 @@ struct clast_def : public overloaded_base<0>
+       {
+ 	type_suffix_index type;
+ 	if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+-	    || !r.require_matching_vector_type (i + 1, type))
++	    || !r.require_matching_vector_type (i + 1, i, type))
+ 	  return error_mark_node;
+ 	return r.resolve_to (MODE_none, type);
+       }
+@@ -3108,7 +3108,7 @@ struct ternary_uint_def : public overloaded_base<0>
+     type_suffix_index type;
+     if (!r.check_gp_argument (3, i, nargs)
+ 	|| (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+-	|| !r.require_matching_vector_type (i + 1, type)
++	|| !r.require_matching_vector_type (i + 1, i, type)
+ 	|| !r.require_derived_vector_type (i + 2, i, type, TYPE_unsigned))
+       return error_mark_node;
+ 
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 4e94e3633..1545fd78d 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -1561,11 +1561,12 @@ function_resolver::require_vector_type (unsigned int argno,
+   return true;
+ }
+ 
+-/* Like require_vector_type, but TYPE is inferred from previous arguments
++/* Like require_vector_type, but TYPE is inferred from argument FIRST_ARGNO
+    rather than being a fixed part of the function signature.  This changes
+    the nature of the error messages.  */
+ bool
+ function_resolver::require_matching_vector_type (unsigned int argno,
++						 unsigned int first_argno,
+ 						 type_suffix_index type)
+ {
+   type_suffix_index new_type = infer_vector_type (argno);
+@@ -1575,9 +1576,9 @@ function_resolver::require_matching_vector_type (unsigned int argno,
+   if (type != new_type)
+     {
+       error_at (location, "passing %qT to argument %d of %qE, but"
+-		" previous arguments had type %qT",
++		" argument %d had type %qT",
+ 		get_vector_type (new_type), argno + 1, fndecl,
+-		get_vector_type (type));
++		first_argno + 1, get_vector_type (type));
+       return false;
+     }
+   return true;
+@@ -1626,7 +1627,7 @@ require_derived_vector_type (unsigned int argno,
+     {
+       /* There's no need to resolve this case out of order.  */
+       gcc_assert (argno > first_argno);
+-      return require_matching_vector_type (argno, first_type);
++      return require_matching_vector_type (argno, first_argno, first_type);
+     }
+ 
+   /* Use FIRST_TYPE to get the expected type class and element size.  */
+@@ -2314,7 +2315,7 @@ function_resolver::resolve_unary (type_class_index merge_tclass,
+ 	     so we can use normal left-to-right resolution.  */
+ 	  if ((type = infer_vector_type (0)) == NUM_TYPE_SUFFIXES
+ 	      || !require_vector_type (1, VECTOR_TYPE_svbool_t)
+-	      || !require_matching_vector_type (2, type))
++	      || !require_matching_vector_type (2, 0, type))
+ 	    return error_mark_node;
+ 	}
+       else
+@@ -2359,9 +2360,9 @@ function_resolver::resolve_uniform (unsigned int nops, unsigned int nimm)
+       || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+     return error_mark_node;
+ 
+-  i += 1;
++  unsigned int first_arg = i++;
+   for (; i < nargs - nimm; ++i)
+-    if (!require_matching_vector_type (i, type))
++    if (!require_matching_vector_type (i, first_arg, type))
+       return error_mark_node;
+ 
+   for (; i < nargs; ++i)
+@@ -2390,7 +2391,7 @@ function_resolver::resolve_uniform_opt_n (unsigned int nops)
+ 
+   unsigned int first_arg = i++;
+   for (; i < nargs - 1; ++i)
+-    if (!require_matching_vector_type (i, type))
++    if (!require_matching_vector_type (i, first_arg, type))
+       return error_mark_node;
+ 
+   return finish_opt_n_resolution (i, first_arg, type);
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 5a4f35123..f7d6cc084 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -476,7 +476,8 @@ public:
+   bool require_vector_or_scalar_type (unsigned int);
+ 
+   bool require_vector_type (unsigned int, vector_type_index);
+-  bool require_matching_vector_type (unsigned int, type_suffix_index);
++  bool require_matching_vector_type (unsigned int, unsigned int,
++				     type_suffix_index);
+   bool require_derived_vector_type (unsigned int, unsigned int,
+ 				    type_suffix_index,
+ 				    type_class_index = SAME_TYPE_CLASS,
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
+index 4343146de..2e919d287 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
+@@ -7,8 +7,8 @@ f1 (svbool_t pg, svuint8_t u8, svint16_t s16)
+ {
+   svzip1 (pg); /* { dg-error {too few arguments to function 'svzip1'} } */
+   svzip1 (pg, u8, u8); /* { dg-error {too many arguments to function 'svzip1'} } */
+-  svzip1 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svzip1', but previous arguments had type 'svbool_t'} } */
+-  svzip1 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+-  svzip1 (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
++  svzip1 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svzip1', but argument 1 had type 'svbool_t'} } */
++  svzip1 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svzip1', but argument 1 had type 'svuint8_t'} } */
++  svzip1 (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svzip1', but argument 1 had type 'svuint8_t'} } */
+   svzip1 (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svzip1', which expects an SVE type rather than a scalar} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
+index 10b6b7e81..81533b25d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
+@@ -12,7 +12,7 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+   svmul_lane (s32, s32, 0); /* { dg-error {ACLE function 'svmul_lane_s32' requires ISA extension 'sve2'} "" { xfail aarch64_sve2 } } */
+   svmul_lane (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmul_lane', which expects an SVE type rather than a scalar} } */
+   svmul_lane (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmul_lane', which expects an SVE type rather than a scalar} } */
+-  svmul_lane (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmul_lane', but previous arguments had type 'svfloat32_t'} } */
++  svmul_lane (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmul_lane', but argument 1 had type 'svfloat32_t'} } */
+   svmul_lane (f32, f32, s32); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+   svmul_lane (f32, f32, i); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c
+index 805863f76..25b620877 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_lane_1.c
+@@ -21,7 +21,7 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+   svmullb_lane (f64, f64, 0); /* { dg-error {'svmullb_lane' has no form that takes 'svfloat64_t' arguments} } */
+   svmullb_lane (1, u32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmullb_lane', which expects an SVE type rather than a scalar} } */
+   svmullb_lane (u32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmullb_lane', which expects an SVE type rather than a scalar} } */
+-  svmullb_lane (u32, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svmullb_lane', but previous arguments had type 'svuint32_t'} } */
++  svmullb_lane (u32, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svmullb_lane', but argument 1 had type 'svuint32_t'} } */
+   svmullb_lane (u32, u32, s32); /* { dg-error {argument 3 of 'svmullb_lane' must be an integer constant expression} } */
+   svmullb_lane (u32, u32, i); /* { dg-error {argument 3 of 'svmullb_lane' must be an integer constant expression} } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c
+index ee704eeae..1f513dde9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_long_opt_n_1.c
+@@ -24,10 +24,10 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddlb (s64, s64); /* { dg-error {'svaddlb' has no form that takes 'svint64_t' arguments} } */
+   svaddlb (f16, f16); /* { dg-error {'svaddlb' has no form that takes 'svfloat16_t' arguments} } */
+   svaddlb (1, u8); /* { dg-error {passing 'int' to argument 1 of 'svaddlb', which expects an SVE type rather than a scalar} } */
+-  svaddlb (u8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint8_t'} } */
+-  svaddlb (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint8_t'} } */
+-  svaddlb (u8, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint8_t'} } */
+-  svaddlb (u16, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svaddlb', but previous arguments had type 'svuint16_t'} } */
++  svaddlb (u8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svaddlb', but argument 1 had type 'svuint8_t'} } */
++  svaddlb (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svaddlb', but argument 1 had type 'svuint8_t'} } */
++  svaddlb (u8, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svaddlb', but argument 1 had type 'svuint8_t'} } */
++  svaddlb (u16, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svaddlb', but argument 1 had type 'svuint16_t'} } */
+   svaddlb (u8, 0);
+   svaddlb (u16, 0);
+   svaddlb (u32, 0);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c
+index 8ca549ba9..4a29b5c43 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowb_opt_n_1.c
+@@ -24,10 +24,10 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddhnb (s64, s64);
+   svaddhnb (f32, f32); /* { dg-error {'svaddhnb' has no form that takes 'svfloat32_t' arguments} } */
+   svaddhnb (1, u16); /* { dg-error {passing 'int' to argument 1 of 'svaddhnb', which expects an SVE type rather than a scalar} } */
+-  svaddhnb (u16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
+-  svaddhnb (u16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
+-  svaddhnb (u16, u32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
+-  svaddhnb (u16, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svaddhnb', but previous arguments had type 'svuint16_t'} } */
++  svaddhnb (u16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svaddhnb', but argument 1 had type 'svuint16_t'} } */
++  svaddhnb (u16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svaddhnb', but argument 1 had type 'svuint16_t'} } */
++  svaddhnb (u16, u32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svaddhnb', but argument 1 had type 'svuint16_t'} } */
++  svaddhnb (u16, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svaddhnb', but argument 1 had type 'svuint16_t'} } */
+   svaddhnb (u8, 0); /* { dg-error {'svaddhnb' has no form that takes 'svuint8_t' arguments} } */
+   svaddhnb (u16, 0);
+   svaddhnb (u32, 0);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c
+index 2b537965b..4a442616e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_narrowt_opt_n_1.c
+@@ -28,10 +28,10 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svaddhnt (f16, f32, f32); /* { dg-error {'svaddhnt' has no form that takes 'svfloat32_t' arguments} } */
+   svaddhnt (1, u16, u16); /* { dg-error {passing 'int' to argument 1 of 'svaddhnt', which expects an SVE type rather than a scalar} } */
+   svaddhnt (u8, 1, u16); /* { dg-error {passing 'int' to argument 2 of 'svaddhnt', which expects an SVE type rather than a scalar} } */
+-  svaddhnt (u8, u16, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
+-  svaddhnt (u8, u16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
+-  svaddhnt (u8, u16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
+-  svaddhnt (u8, u16, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svaddhnt', but previous arguments had type 'svuint16_t'} } */
++  svaddhnt (u8, u16, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svaddhnt', but argument 2 had type 'svuint16_t'} } */
++  svaddhnt (u8, u16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svaddhnt', but argument 2 had type 'svuint16_t'} } */
++  svaddhnt (u8, u16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svaddhnt', but argument 2 had type 'svuint16_t'} } */
++  svaddhnt (u8, u16, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svaddhnt', but argument 2 had type 'svuint16_t'} } */
+   svaddhnt (u8, u8, 0); /* { dg-error {'svaddhnt' has no form that takes 'svuint8_t' arguments} } */
+   svaddhnt (u16, u16, 0); /* { dg-error {passing 'svuint16_t' instead of the expected 'svuint8_t' to argument 1 of 'svaddhnt', after passing 'svuint16_t' to argument 2} } */
+   svaddhnt (s8, u16, 0); /* { dg-error {arguments 1 and 2 of 'svaddhnt' must have the same signedness, but the values passed here have type 'svint8_t' and 'svuint16_t' respectively} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
+index a151f90d1..40447cf83 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
+@@ -11,16 +11,16 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svadd_x (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svadd_x', which expects 'svbool_t'} } */
+   svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+   svadd_x (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svadd_x', which expects an SVE type rather than a scalar} } */
+-  svadd_x (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
++  svadd_x (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svadd_x', but argument 2 had type 'svuint8_t'} } */
+   svadd_x (pg, u8, u8);
+-  svadd_x (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+-  svadd_x (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+-  svadd_x (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+-  svadd_x (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
++  svadd_x (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but argument 2 had type 'svuint8_t'} } */
++  svadd_x (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but argument 2 had type 'svuint8_t'} } */
++  svadd_x (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svadd_x', but argument 2 had type 'svuint8_t'} } */
++  svadd_x (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svadd_x', but argument 2 had type 'svuint8_t'} } */
+   svadd_x (pg, u8, 0);
+ 
+-  svadd_x (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svfloat16_t'} } */
+-  svadd_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svfloat16_t'} } */
++  svadd_x (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but argument 2 had type 'svfloat16_t'} } */
++  svadd_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but argument 2 had type 'svfloat16_t'} } */
+   svadd_x (pg, f16, f16);
+   svadd_x (pg, f16, 1);
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
+index 70ec9c585..94e20bc91 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
+@@ -11,19 +11,19 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svand_z (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svand_z', which expects 'svbool_t'} } */
+   svand_z (pg, pg, pg);
+   svand_z (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svand_z', which expects an SVE type rather than a scalar} } */
+-  svand_z (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
++  svand_z (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svand_z', but argument 2 had type 'svuint8_t'} } */
+   svand_z (pg, u8, u8);
+-  svand_z (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+-  svand_z (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+-  svand_z (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+-  svand_z (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
++  svand_z (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but argument 2 had type 'svuint8_t'} } */
++  svand_z (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but argument 2 had type 'svuint8_t'} } */
++  svand_z (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svand_z', but argument 2 had type 'svuint8_t'} } */
++  svand_z (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svand_z', but argument 2 had type 'svuint8_t'} } */
+   svand_z (pg, u8, 0);
+ 
+-  svand_z (pg, pg, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svbool_t'} } */
++  svand_z (pg, pg, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svand_z', but argument 2 had type 'svbool_t'} } */
+   svand_z (pg, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svand_z', but its 'svbool_t' form does not accept scalars} } */
+ 
+-  svand_z (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svfloat16_t'} } */
+-  svand_z (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svfloat16_t'} } */
++  svand_z (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but argument 2 had type 'svfloat16_t'} } */
++  svand_z (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but argument 2 had type 'svfloat16_t'} } */
+   svand_z (pg, f16, f16); /* { dg-error {'svand_z' has no form that takes 'svfloat16_t' arguments} } */
+   svand_z (pg, f16, 1); /* { dg-error {'svand_z' has no form that takes 'svfloat16_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
+index 7669e4a02..8939ce258 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
+@@ -12,7 +12,7 @@ f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+   svcadd_x (pg, s32, s32, 90); /* { dg-error {'svcadd_x' has no form that takes 'svint32_t' arguments} } */
+   svcadd_x (pg, 1, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcadd_x', which expects an SVE type rather than a scalar} } */
+   svcadd_x (pg, f32, 1, 90); /* { dg-error {passing 'int' to argument 3 of 'svcadd_x', which expects an SVE type rather than a scalar} } */
+-  svcadd_x (pg, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcadd_x', but previous arguments had type 'svfloat32_t'} } */
++  svcadd_x (pg, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcadd_x', but argument 2 had type 'svfloat32_t'} } */
+   svcadd_x (pg, f32, f32, s32); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+   svcadd_x (pg, f32, f32, i); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+   svcadd_x (pg, f32, f32, -90); /* { dg-error {passing -90 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c
+index 154662487..2c3fe5df1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_to_uint_1.c
+@@ -12,8 +12,8 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32)
+   svhistcnt_z (0, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svhistcnt_z', which expects 'svbool_t'} } */
+   svhistcnt_z (s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svhistcnt_z', which expects 'svbool_t'} } */
+   svhistcnt_z (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svhistcnt_z', which expects an SVE type rather than a scalar} } */
+-  svhistcnt_z (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svhistcnt_z', but previous arguments had type 'svbool_t'} } */
+-  svhistcnt_z (pg, s32, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svhistcnt_z', but previous arguments had type 'svint32_t'} } */
++  svhistcnt_z (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svhistcnt_z', but argument 2 had type 'svbool_t'} } */
++  svhistcnt_z (pg, s32, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svhistcnt_z', but argument 2 had type 'svint32_t'} } */
+   svhistcnt_z (pg, s32, 0); /* { dg-error {passing 'int' to argument 3 of 'svhistcnt_z', which expects an SVE type rather than a scalar} } */
+   svhistcnt_z (pg, pg, pg); /* { dg-error {'svhistcnt_z' has no form that takes 'svbool_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
+index ba1b2520f..47ce47328 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
+@@ -10,6 +10,6 @@ test (svbool_t pg, svint32_t s32, svint64_t s64, int i)
+   svclasta (pg, 1, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+   svclasta (pg, i, s32);
+   svclasta (pg, s32, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE type rather than a scalar} } */
+-  svclasta (pg, s32, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svclasta', but previous arguments had type 'svint32_t'} } */
++  svclasta (pg, s32, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svclasta', but argument 2 had type 'svint32_t'} } */
+   svclasta (pg, pg, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c
+index 5474124cc..0dd0ad910 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_1.c
+@@ -13,15 +13,15 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svmatch (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svmatch', which expects 'svbool_t'} } */
+   svmatch (pg, pg, pg); /* { dg-error {'svmatch' has no form that takes 'svbool_t' arguments} } */
+   svmatch (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svmatch', which expects an SVE type rather than a scalar} } */
+-  svmatch (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
++  svmatch (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmatch', but argument 2 had type 'svuint8_t'} } */
+   svmatch (pg, u8, u8);
+-  svmatch (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+-  svmatch (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+-  svmatch (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
+-  svmatch (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmatch', but previous arguments had type 'svuint8_t'} } */
++  svmatch (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmatch', but argument 2 had type 'svuint8_t'} } */
++  svmatch (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmatch', but argument 2 had type 'svuint8_t'} } */
++  svmatch (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmatch', but argument 2 had type 'svuint8_t'} } */
++  svmatch (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmatch', but argument 2 had type 'svuint8_t'} } */
+   svmatch (pg, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svmatch', which expects an SVE type rather than a scalar} } */
+ 
+-  svmatch (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svfloat16_t'} } */
+-  svmatch (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmatch', but previous arguments had type 'svfloat16_t'} } */
++  svmatch (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmatch', but argument 2 had type 'svfloat16_t'} } */
++  svmatch (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmatch', but argument 2 had type 'svfloat16_t'} } */
+   svmatch (pg, f16, f16); /* { dg-error {'svmatch' has no form that takes 'svfloat16_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
+index 6faa73972..cfa50d387 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
+@@ -11,16 +11,16 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svcmpeq (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcmpeq', which expects 'svbool_t'} } */
+   svcmpeq (pg, pg, pg); /* { dg-error {'svcmpeq' has no form that takes 'svbool_t' arguments} } */
+   svcmpeq (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq', which expects an SVE type rather than a scalar} } */
+-  svcmpeq (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
++  svcmpeq (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svuint8_t'} } */
+   svcmpeq (pg, u8, u8);
+-  svcmpeq (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+-  svcmpeq (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+-  svcmpeq (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+-  svcmpeq (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
++  svcmpeq (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svuint8_t'} } */
++  svcmpeq (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svuint8_t'} } */
++  svcmpeq (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svuint8_t'} } */
++  svcmpeq (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svuint8_t'} } */
+   svcmpeq (pg, u8, 0);
+ 
+-  svcmpeq (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svfloat16_t'} } */
+-  svcmpeq (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svfloat16_t'} } */
++  svcmpeq (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svfloat16_t'} } */
++  svcmpeq (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but argument 2 had type 'svfloat16_t'} } */
+   svcmpeq (pg, f16, f16);
+   svcmpeq (pg, f16, 1);
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
+index 83e4a5600..7a617aa15 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
+@@ -10,11 +10,11 @@ f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+   *ptr = svcreate2 (u8); /* { dg-error {too few arguments to function 'svcreate2'} } */
+   *ptr = svcreate2 (u8, u8, u8); /* { dg-error {too many arguments to function 'svcreate2'} } */
+   *ptr = svcreate2 (u8x2, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 1 of 'svcreate2', which expects a single SVE vector rather than a tuple} } */
+-  *ptr = svcreate2 (u8, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+-  *ptr = svcreate2 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
++  *ptr = svcreate2 (u8, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcreate2', but argument 1 had type 'svuint8_t'} } */
++  *ptr = svcreate2 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate2', but argument 1 had type 'svuint8_t'} } */
+   *ptr = svcreate2 (u8, x); /* { dg-error {passing 'int' to argument 2 of 'svcreate2', which expects an SVE type rather than a scalar} } */
+   *ptr = svcreate2 (x, u8); /* { dg-error {passing 'int' to argument 1 of 'svcreate2', which expects an SVE type rather than a scalar} } */
+-  *ptr = svcreate2 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svcreate2', but previous arguments had type 'svbool_t'} } */
++  *ptr = svcreate2 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svcreate2', but argument 1 had type 'svbool_t'} } */
+   *ptr = svcreate2 (pg, pg); /* { dg-error {'svcreate2' has no form that takes 'svbool_t' arguments} } */
+   *ptr = svcreate2 (u8, u8);
+   *ptr = svcreate2 (f64, f64); /* { dg-error {incompatible types when assigning to type 'svuint8x2_t' from type 'svfloat64x2_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
+index e3302f7e7..40f3a1fed 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
+@@ -11,11 +11,11 @@ f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+   *ptr = svcreate3 (f16, f16); /* { dg-error {too few arguments to function 'svcreate3'} } */
+   *ptr = svcreate3 (f16, f16, f16, f16); /* { dg-error {too many arguments to function 'svcreate3'} } */
+   *ptr = svcreate3 (f16x3, f16x3, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 1 of 'svcreate3', which expects a single SVE vector rather than a tuple} } */
+-  *ptr = svcreate3 (f16, f16, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+-  *ptr = svcreate3 (f16, pg, f16); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
++  *ptr = svcreate3 (f16, f16, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcreate3', but argument 1 had type 'svfloat16_t'} } */
++  *ptr = svcreate3 (f16, pg, f16); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate3', but argument 1 had type 'svfloat16_t'} } */
+   *ptr = svcreate3 (f16, x, f16); /* { dg-error {passing 'int' to argument 2 of 'svcreate3', which expects an SVE type rather than a scalar} } */
+   *ptr = svcreate3 (x, f16, f16); /* { dg-error {passing 'int' to argument 1 of 'svcreate3', which expects an SVE type rather than a scalar} } */
+-  *ptr = svcreate3 (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svcreate3', but previous arguments had type 'svbool_t'} } */
++  *ptr = svcreate3 (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svcreate3', but argument 1 had type 'svbool_t'} } */
+   *ptr = svcreate3 (pg, pg, pg); /* { dg-error {'svcreate3' has no form that takes 'svbool_t' arguments} } */
+   *ptr = svcreate3 (f16, f16, f16);
+   *ptr = svcreate3 (f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svfloat16x3_t' from type 'svfloat64x3_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
+index c850c94f0..bf3dd5d75 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
+@@ -12,11 +12,11 @@ f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+   *ptr = svcreate4 (s32, s32, s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+   *ptr = svcreate4 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function 'svcreate4'} } */
+   *ptr = svcreate4 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 1 of 'svcreate4', which expects a single SVE vector rather than a tuple} } */
+-  *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+-  *ptr = svcreate4 (s32, s32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
++  *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcreate4', but argument 1 had type 'svint32_t'} } */
++  *ptr = svcreate4 (s32, s32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcreate4', but argument 1 had type 'svint32_t'} } */
+   *ptr = svcreate4 (s32, x, s32, s32); /* { dg-error {passing 'int' to argument 2 of 'svcreate4', which expects an SVE type rather than a scalar} } */
+   *ptr = svcreate4 (x, s32, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svcreate4', which expects an SVE type rather than a scalar} } */
+-  *ptr = svcreate4 (pg, s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcreate4', but previous arguments had type 'svbool_t'} } */
++  *ptr = svcreate4 (pg, s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcreate4', but argument 1 had type 'svbool_t'} } */
+   *ptr = svcreate4 (pg, pg, pg, pg); /* { dg-error {'svcreate4' has no form that takes 'svbool_t' arguments} } */
+   *ptr = svcreate4 (s32, s32, s32, s32);
+   *ptr = svcreate4 (f64, f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svint32x4_t' from type 'svfloat64x4_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c
+index 7fc7bb67b..ca2ab8a6f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/mmla_1.c
+@@ -44,13 +44,13 @@ f2 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32, svint32_t s32,
+   svmmla (u32, u32, u32); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svmmla', after passing 'svuint32_t' to argument 1} } */
+ 
+   svmmla (f16, s8, s8); /* { dg-error {'svmmla' has no form that takes 'svfloat16_t' arguments} } */
+-  svmmla (f32, s8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svmmla', but previous arguments had type 'svfloat32_t'} } */
+-  svmmla (f32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svmmla', but previous arguments had type 'svfloat32_t'} } */
+-  svmmla (f32, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svmmla', but previous arguments had type 'svfloat32_t'} } */
+-  svmmla (f64, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svmmla', but previous arguments had type 'svfloat64_t'} } */
+-  svmmla (f32, f32, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmmla', but previous arguments had type 'svfloat32_t'} } */
+-  svmmla (f64, f32, f16); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svmmla', but previous arguments had type 'svfloat64_t'} } */
+-  svmmla (f64, f64, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmmla', but previous arguments had type 'svfloat64_t'} } */
++  svmmla (f32, s8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svmmla', but argument 1 had type 'svfloat32_t'} } */
++  svmmla (f32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svmmla', but argument 1 had type 'svfloat32_t'} } */
++  svmmla (f32, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svmmla', but argument 1 had type 'svfloat32_t'} } */
++  svmmla (f64, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svmmla', but argument 1 had type 'svfloat64_t'} } */
++  svmmla (f32, f32, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmmla', but argument 1 had type 'svfloat32_t'} } */
++  svmmla (f64, f32, f16); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svmmla', but argument 1 had type 'svfloat64_t'} } */
++  svmmla (f64, f64, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmmla', but argument 1 had type 'svfloat64_t'} } */
+ 
+   svmmla (f16, f16, f16); /* { dg-error {'svmmla' has no form that takes 'svfloat16_t' arguments} } */
+   svmmla (f32, f32, f32);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
+index 520c11f79..0a67f82bf 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
+@@ -13,8 +13,8 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+   svmla_lane (1, f32, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmla_lane', which expects an SVE type rather than a scalar} } */
+   svmla_lane (f32, 1, f32, 0); /* { dg-error {passing 'int' to argument 2 of 'svmla_lane', which expects an SVE type rather than a scalar} } */
+   svmla_lane (f32, f32, 1, 0); /* { dg-error {passing 'int' to argument 3 of 'svmla_lane', which expects an SVE type rather than a scalar} } */
+-  svmla_lane (f32, f64, f32, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+-  svmla_lane (f32, f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
++  svmla_lane (f32, f64, f32, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmla_lane', but argument 1 had type 'svfloat32_t'} } */
++  svmla_lane (f32, f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svmla_lane', but argument 1 had type 'svfloat32_t'} } */
+   svmla_lane (f32, f32, f32, s32); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+   svmla_lane (f32, f32, f32, i); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
+index 3163d130c..60c9c466e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
+@@ -14,8 +14,8 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+   svcmla_lane (1, f32, f32, 0, 90); /* { dg-error {passing 'int' to argument 1 of 'svcmla_lane', which expects an SVE type rather than a scalar} } */
+   svcmla_lane (f32, 1, f32, 0, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_lane', which expects an SVE type rather than a scalar} } */
+   svcmla_lane (f32, f32, 1, 0, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_lane', which expects an SVE type rather than a scalar} } */
+-  svcmla_lane (f32, f64, f32, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+-  svcmla_lane (f32, f32, f64, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
++  svcmla_lane (f32, f64, f32, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcmla_lane', but argument 1 had type 'svfloat32_t'} } */
++  svcmla_lane (f32, f32, f64, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_lane', but argument 1 had type 'svfloat32_t'} } */
+   svcmla_lane (f32, f32, f32, s32, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+   svcmla_lane (f32, f32, f32, i, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
+index ac789c2be..6ca223475 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
+@@ -11,24 +11,24 @@ f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+   svmla_x (u8, u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svmla_x', which expects 'svbool_t'} } */
+   svmla_x (pg, pg, pg, pg); /* { dg-error {'svmla_x' has no form that takes 'svbool_t' arguments} } */
+   svmla_x (pg, 1, u8, u8); /* { dg-error {passing 'int' to argument 2 of 'svmla_x', which expects an SVE type rather than a scalar} } */
+-  svmla_x (pg, u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
++  svmla_x (pg, u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
+   svmla_x (pg, u8, u8, u8);
+-  svmla_x (pg, u8, s16, u8); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, u16, u8); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, f16, u8); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, pg, u8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
++  svmla_x (pg, u8, s16, u8); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, u16, u8); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, f16, u8); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, pg, u8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
+   svmla_x (pg, u8, 0, u8); /* { dg-error {passing 'int' to argument 3 of 'svmla_x', which expects an SVE type rather than a scalar} } */
+-  svmla_x (pg, u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, u8, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+-  svmla_x (pg, u8, u8, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
++  svmla_x (pg, u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, u8, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
++  svmla_x (pg, u8, u8, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svmla_x', but argument 2 had type 'svuint8_t'} } */
+   svmla_x (pg, u8, u8, 0);
+ 
+-  svmla_x (pg, f16, s16, f16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+-  svmla_x (pg, f16, u16, f16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+-  svmla_x (pg, f16, f16, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+-  svmla_x (pg, f16, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
++  svmla_x (pg, f16, s16, f16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but argument 2 had type 'svfloat16_t'} } */
++  svmla_x (pg, f16, u16, f16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but argument 2 had type 'svfloat16_t'} } */
++  svmla_x (pg, f16, f16, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but argument 2 had type 'svfloat16_t'} } */
++  svmla_x (pg, f16, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but argument 2 had type 'svfloat16_t'} } */
+   svmla_x (pg, f16, f16, f16);
+   svmla_x (pg, f16, f16, 1);
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
+index bb6740289..68b2cfc1d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
+@@ -13,8 +13,8 @@ f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+   svcmla_x (pg, 1, f32, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_x', which expects an SVE type rather than a scalar} } */
+   svcmla_x (pg, f32, 1, f32, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_x', which expects an SVE type rather than a scalar} } */
+   svcmla_x (pg, f32, f32, 1, 90); /* { dg-error {passing 'int' to argument 4 of 'svcmla_x', which expects an SVE type rather than a scalar} } */
+-  svcmla_x (pg, f32, f64, f32, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+-  svcmla_x (pg, f32, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
++  svcmla_x (pg, f32, f64, f32, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_x', but argument 2 had type 'svfloat32_t'} } */
++  svcmla_x (pg, f32, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcmla_x', but argument 2 had type 'svfloat32_t'} } */
+   svcmla_x (pg, f32, f32, f32, s32); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+   svcmla_x (pg, f32, f32, f32, i); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+   svcmla_x (pg, f32, f32, f32, -90); /* { dg-error {passing -90 to argument 5 of 'svcmla_x', which expects 0, 90, 180 or 270} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c
+index cfe601631..134cf98fd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_shift_right_imm_1.c
+@@ -11,10 +11,10 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+ {
+   const int one = 1;
+   pg = svsra (pg, pg, 1); /* { dg-error {'svsra' has no form that takes 'svbool_t' arguments} } */
+-  pg = svsra (pg, s8, 1); /* { dg-error {passing 'svint8_t' to argument 2 of 'svsra', but previous arguments had type 'svbool_t'} } */
++  pg = svsra (pg, s8, 1); /* { dg-error {passing 'svint8_t' to argument 2 of 'svsra', but argument 1 had type 'svbool_t'} } */
+   s8 = svsra (1, s8, 1); /* { dg-error {passing 'int' to argument 1 of 'svsra', which expects an SVE type rather than a scalar} } */
+-  s8 = svsra (s8, u8, 1); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svsra', but previous arguments had type 'svint8_t'} } */
+-  s8 = svsra (s8, pg, 1); /* { dg-error {passing 'svbool_t' to argument 2 of 'svsra', but previous arguments had type 'svint8_t'} } */
++  s8 = svsra (s8, u8, 1); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svsra', but argument 1 had type 'svint8_t'} } */
++  s8 = svsra (s8, pg, 1); /* { dg-error {passing 'svbool_t' to argument 2 of 'svsra', but argument 1 had type 'svint8_t'} } */
+   s8 = svsra (s8, 1, 1); /* { dg-error {passing 'int' to argument 2 of 'svsra', which expects an SVE type rather than a scalar} } */
+   s8 = svsra (s8, s8, x); /* { dg-error {argument 3 of 'svsra' must be an integer constant expression} } */
+   s8 = svsra (s8, s8, one); /* { dg-error {argument 3 of 'svsra' must be an integer constant expression} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c
+index 5fb497701..a639562b1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_uint_1.c
+@@ -15,14 +15,14 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+ 
+   svtbx (u8, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svtbx', which expects an SVE type rather than a scalar} } */
+   svtbx (u8, u8, 0); /* { dg-error {passing 'int' to argument 3 of 'svtbx', which expects an SVE type rather than a scalar} } */
+-  svtbx (u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbx', but previous arguments had type 'svuint8_t'} } */
++  svtbx (u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbx', but argument 1 had type 'svuint8_t'} } */
+   svtbx (u8, u8, u8);
+   svtbx (u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (u8, u8, u16); /* { dg-error {arguments 1 and 3 of 'svtbx' must have the same element size, but the values passed here have type 'svuint8_t' and 'svuint16_t' respectively} } */
+   svtbx (u8, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (u8, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+ 
+-  svtbx (s8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svtbx', but previous arguments had type 'svint8_t'} } */
++  svtbx (s8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svtbx', but argument 1 had type 'svint8_t'} } */
+   svtbx (s8, s8, u8);
+   svtbx (s8, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (s8, s8, u16); /* { dg-error {arguments 1 and 3 of 'svtbx' must have the same element size, but the values passed here have type 'svint8_t' and 'svuint16_t' respectively} } */
+@@ -36,7 +36,7 @@ f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+   svtbx (u16, u16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (u16, u16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+ 
+-  svtbx (s16, u16, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svtbx', but previous arguments had type 'svint16_t'} } */
++  svtbx (s16, u16, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svtbx', but argument 1 had type 'svint16_t'} } */
+   svtbx (s16, s16, u8); /* { dg-error {arguments 1 and 3 of 'svtbx' must have the same element size, but the values passed here have type 'svint16_t' and 'svuint8_t' respectively} } */
+   svtbx (s16, s16, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svtbx', which expects a vector of unsigned integers} } */
+   svtbx (s16, s16, u16);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
+index c2eda93e3..992b50199 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
+@@ -11,7 +11,7 @@ f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+   svtmad (s32, s32, 0); /* { dg-error {'svtmad' has no form that takes 'svint32_t' arguments} } */
+   svtmad (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svtmad', which expects an SVE type rather than a scalar} } */
+   svtmad (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svtmad', which expects an SVE type rather than a scalar} } */
+-  svtmad (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svtmad', but previous arguments had type 'svfloat32_t'} } */
++  svtmad (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svtmad', but argument 1 had type 'svfloat32_t'} } */
+   svtmad (f32, f32, s32); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+   svtmad (f32, f32, i); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+   svtmad (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svtmad', which expects a value in the range \[0, 7\]} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
+index 8c865a0e6..9c9c383dd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
+@@ -13,9 +13,9 @@ f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32)
+   svabs_m (s32, pg, s32);
+   svabs_m (u32, pg, u32); /* { dg-error {'svabs_m' has no form that takes 'svuint32_t' arguments} } */
+   svabs_m (f32, pg, f32);
+-  svabs_m (s32, pg, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+-  svabs_m (s32, pg, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+-  svabs_m (s32, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+-  svabs_m (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svbool_t'} } */
++  svabs_m (s32, pg, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svabs_m', but argument 1 had type 'svint32_t'} } */
++  svabs_m (s32, pg, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svabs_m', but argument 1 had type 'svint32_t'} } */
++  svabs_m (s32, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svabs_m', but argument 1 had type 'svint32_t'} } */
++  svabs_m (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svabs_m', but argument 1 had type 'svbool_t'} } */
+   svabs_m (pg, pg, pg); /* { dg-error {'svabs_m' has no form that takes 'svbool_t' arguments} } */
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c
+index 7e869bda8..6ffd3d9e8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c
+@@ -9,7 +9,7 @@ f (svint8_t s8, svuint16_t u16, svfloat32_t f32,
+   u16 = svneg_x (pg, u16); /* { dg-error {'svneg_x' has no form that takes 'svuint16_t' arguments} } */
+   f32 = svclz_x (pg, f32); /* { dg-error {'svclz_x' has no form that takes 'svfloat32_t' arguments} } */
+   s16x2 = svcreate2 (s8); /* { dg-error {too few arguments to function 'svcreate2'} } */
+-  u32x3 = svcreate3 (u16, u16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svcreate3', but previous arguments had type 'svuint16_t'} } */
++  u32x3 = svcreate3 (u16, u16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svcreate3', but argument 1 had type 'svuint16_t'} } */
+   f64x4 = svcreate4 (f32, f32, f32, f32, f32); /* { dg-error {too many arguments to function 'svcreate4'} } */
+   pg = svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+ }
+-- 
+2.33.0
+
diff --git a/0168-Backport-SME-aarch64-Make-more-use-of-sve_type-in-AC.patch b/0168-Backport-SME-aarch64-Make-more-use-of-sve_type-in-AC.patch
new file mode 100644
index 0000000..d293e4e
--- /dev/null
+++ b/0168-Backport-SME-aarch64-Make-more-use-of-sve_type-in-AC.patch
@@ -0,0 +1,368 @@
+From 05dee9ad331c27345b014fe9aec0067a6f3b07d9 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:21 +0000
+Subject: [PATCH 069/157] [Backport][SME] aarch64: Make more use of sve_type in
+ ACLE code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1f7f076ad6293cad19d35efdf726eb48cf78e3dd
+
+This patch makes some functions operate on sve_type, rather than just
+on type suffixes.  It also allows an overload to be resolved based on
+a mode and sve_type.  In this case the sve_type is used to derive the
+group size as well as a type suffix.
+
+This is needed for the SME2 intrinsics and the new tuple forms of
+svreinterpret.  No functional change intended on its own.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h
+	(function_resolver::lookup_form): Add an overload that takes
+	an sve_type rather than type and group suffixes.
+	(function_resolver::resolve_to): Likewise.
+	(function_resolver::infer_vector_or_tuple_type): Return an sve_type.
+	(function_resolver::infer_tuple_type): Likewise.
+	(function_resolver::require_matching_vector_type): Take an sve_type
+	rather than a type_suffix_index.
+	(function_resolver::require_derived_vector_type): Likewise.
+	* config/aarch64/aarch64-sve-builtins.cc (num_vectors_to_group):
+	New function.
+	(function_resolver::lookup_form): Add an overload that takes
+	an sve_type rather than type and group suffixes.
+	(function_resolver::resolve_to): Likewise.
+	(function_resolver::infer_vector_or_tuple_type): Return an sve_type.
+	(function_resolver::infer_tuple_type): Likewise.
+	(function_resolver::infer_vector_type): Update accordingly.
+	(function_resolver::require_matching_vector_type): Take an sve_type
+	rather than a type_suffix_index.
+	(function_resolver::require_derived_vector_type): Likewise.
+	* config/aarch64/aarch64-sve-builtins-shapes.cc (get_def::resolve)
+	(set_def::resolve, store_def::resolve, tbl_tuple_def::resolve): Update
+	calls accordingly.
+---
+ .../aarch64/aarch64-sve-builtins-shapes.cc    |  16 +--
+ gcc/config/aarch64/aarch64-sve-builtins.cc    | 111 +++++++++++++-----
+ gcc/config/aarch64/aarch64-sve-builtins.h     |  12 +-
+ 3 files changed, 95 insertions(+), 44 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index 40aa418e0..f187b4cb2 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -1904,9 +1904,9 @@ struct get_def : public overloaded_base<0>
+   resolve (function_resolver &r) const OVERRIDE
+   {
+     unsigned int i, nargs;
+-    type_suffix_index type;
++    sve_type type;
+     if (!r.check_gp_argument (2, i, nargs)
+-	|| (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
++	|| !(type = r.infer_tuple_type (i))
+ 	|| !r.require_integer_immediate (i + 1))
+       return error_mark_node;
+ 
+@@ -2417,9 +2417,9 @@ struct set_def : public overloaded_base<0>
+   resolve (function_resolver &r) const OVERRIDE
+   {
+     unsigned int i, nargs;
+-    type_suffix_index type;
++    sve_type type;
+     if (!r.check_gp_argument (3, i, nargs)
+-	|| (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
++	|| !(type = r.infer_tuple_type (i))
+ 	|| !r.require_integer_immediate (i + 1)
+ 	|| !r.require_derived_vector_type (i + 2, i, type))
+       return error_mark_node;
+@@ -2592,11 +2592,11 @@ struct store_def : public overloaded_base<0>
+     gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
+ 
+     unsigned int i, nargs;
+-    type_suffix_index type;
++    sve_type type;
+     if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs)
+ 	|| !r.require_pointer_type (i)
+ 	|| (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))
+-	|| ((type = r.infer_tuple_type (nargs - 1)) == NUM_TYPE_SUFFIXES))
++	|| !(type = r.infer_tuple_type (nargs - 1)))
+       return error_mark_node;
+ 
+     return r.resolve_to (r.mode_suffix_id, type);
+@@ -2713,9 +2713,9 @@ struct tbl_tuple_def : public overloaded_base<0>
+   resolve (function_resolver &r) const OVERRIDE
+   {
+     unsigned int i, nargs;
+-    type_suffix_index type;
++    sve_type type;
+     if (!r.check_gp_argument (2, i, nargs)
+-	|| (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
++	|| !(type = r.infer_tuple_type (i))
+ 	|| !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
+       return error_mark_node;
+ 
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 1545fd78d..e98274f8a 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -659,6 +659,21 @@ find_type_suffix_for_scalar_type (const_tree type)
+   return NUM_TYPE_SUFFIXES;
+ }
+ 
++/* Return the implicit group suffix for intrinsics that operate on NVECTORS
++   vectors.  */
++static group_suffix_index
++num_vectors_to_group (unsigned int nvectors)
++{
++  switch (nvectors)
++    {
++    case 1: return GROUP_none;
++    case 2: return GROUP_x2;
++    case 3: return GROUP_x3;
++    case 4: return GROUP_x4;
++    }
++  gcc_unreachable ();
++}
++
+ /* Return the vector type associated with TYPE.  */
+ static tree
+ get_vector_type (sve_type type)
+@@ -1282,6 +1297,27 @@ function_resolver::lookup_form (mode_suffix_index mode,
+   return rfn ? rfn->decl : NULL_TREE;
+ }
+ 
++/* Silently check whether there is an instance of the function that has the
++   mode suffix given by MODE and the type and group suffixes implied by TYPE.
++   If the overloaded function has an explicit first type suffix (like
++   conversions do), TYPE describes the implicit second type suffix.
++   Otherwise, TYPE describes the only type suffix.
++
++   Return the decl of the function if it exists, otherwise return null.  */
++tree
++function_resolver::lookup_form (mode_suffix_index mode, sve_type type)
++{
++  type_suffix_index type0 = type_suffix_ids[0];
++  type_suffix_index type1 = type_suffix_ids[1];
++  (type0 == NUM_TYPE_SUFFIXES ? type0 : type1) = type.type;
++
++  group_suffix_index group = group_suffix_id;
++  if (group == GROUP_none && type.num_vectors != vectors_per_tuple ())
++    group = num_vectors_to_group (type.num_vectors);
++
++  return lookup_form (mode, type0, type1, group);
++}
++
+ /* Resolve the function to one with the mode suffix given by MODE, the
+    type suffixes given by TYPE0 and TYPE1, and group suffix given by
+    GROUP.  Return its function decl on success, otherwise report an
+@@ -1305,6 +1341,19 @@ function_resolver::resolve_to (mode_suffix_index mode,
+   return res;
+ }
+ 
++/* Resolve the function to one that has the suffixes associated with MODE
++   and TYPE; see lookup_form for how TYPE is interpreted.  Return the
++   function decl on success, otherwise report an error and return
++   error_mark_node.  */
++tree
++function_resolver::resolve_to (mode_suffix_index mode, sve_type type)
++{
++  if (tree res = lookup_form (mode, type))
++    return res;
++
++  return report_no_such_form (type);
++}
++
+ /* Require argument ARGNO to be a 32-bit or 64-bit scalar integer type.
+    Return the associated type suffix on success, otherwise report an
+    error and return NUM_TYPE_SUFFIXES.  */
+@@ -1424,21 +1473,20 @@ function_resolver::infer_sve_type (unsigned int argno)
+ 
+ /* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS
+    vectors; NUM_VECTORS is 1 for the former.  Return the associated type
+-   suffix on success, using TYPE_SUFFIX_b for predicates.  Report an error
+-   and return NUM_TYPE_SUFFIXES on failure.  */
+-type_suffix_index
++   on success.  Report an error on failure.  */
++sve_type
+ function_resolver::infer_vector_or_tuple_type (unsigned int argno,
+ 					       unsigned int num_vectors)
+ {
+   auto type = infer_sve_type (argno);
+   if (!type)
+-    return NUM_TYPE_SUFFIXES;
++    return type;
+ 
+   if (type.num_vectors == num_vectors)
+-    return type.type;
++    return type;
+ 
+   report_incorrect_num_vectors (argno, type, num_vectors);
+-  return NUM_TYPE_SUFFIXES;
++  return {};
+ }
+ 
+ /* Require argument ARGNO to have some form of vector type.  Return the
+@@ -1447,7 +1495,9 @@ function_resolver::infer_vector_or_tuple_type (unsigned int argno,
+ type_suffix_index
+ function_resolver::infer_vector_type (unsigned int argno)
+ {
+-  return infer_vector_or_tuple_type (argno, 1);
++  if (auto type = infer_vector_or_tuple_type (argno, 1))
++    return type.type;
++  return NUM_TYPE_SUFFIXES;
+ }
+ 
+ /* Like infer_vector_type, but also require the type to be integral.  */
+@@ -1512,10 +1562,9 @@ function_resolver::infer_sd_vector_type (unsigned int argno)
+ 
+ /* If the function operates on tuples of vectors, require argument ARGNO to be
+    a tuple with the appropriate number of vectors, otherwise require it to be
+-   a single vector.  Return the associated type suffix on success, using
+-   TYPE_SUFFIX_b for predicates.  Report an error and return NUM_TYPE_SUFFIXES
++   a single vector.  Return the associated type on success.  Report an error
+    on failure.  */
+-type_suffix_index
++sve_type
+ function_resolver::infer_tuple_type (unsigned int argno)
+ {
+   return infer_vector_or_tuple_type (argno, vectors_per_tuple ());
+@@ -1567,10 +1616,10 @@ function_resolver::require_vector_type (unsigned int argno,
+ bool
+ function_resolver::require_matching_vector_type (unsigned int argno,
+ 						 unsigned int first_argno,
+-						 type_suffix_index type)
++						 sve_type type)
+ {
+-  type_suffix_index new_type = infer_vector_type (argno);
+-  if (new_type == NUM_TYPE_SUFFIXES)
++  sve_type new_type = infer_sve_type (argno);
++  if (!new_type)
+     return false;
+ 
+   if (type != new_type)
+@@ -1613,15 +1662,13 @@ function_resolver::require_matching_vector_type (unsigned int argno,
+ bool function_resolver::
+ require_derived_vector_type (unsigned int argno,
+ 			     unsigned int first_argno,
+-			     type_suffix_index first_type,
++			     sve_type first_type,
+ 			     type_class_index expected_tclass,
+ 			     unsigned int expected_bits)
+ {
+   /* If the type needs to match FIRST_ARGNO exactly, use the preferred
+-     error message for that case.  The VECTOR_TYPE_P test excludes tuple
+-     types, which we handle below instead.  */
+-  bool both_vectors_p = VECTOR_TYPE_P (get_argument_type (first_argno));
+-  if (both_vectors_p
++     error message for that case.  */
++  if (first_type.num_vectors == 1
+       && expected_tclass == SAME_TYPE_CLASS
+       && expected_bits == SAME_SIZE)
+     {
+@@ -1631,17 +1678,18 @@ require_derived_vector_type (unsigned int argno,
+     }
+ 
+   /* Use FIRST_TYPE to get the expected type class and element size.  */
++  auto &first_type_suffix = type_suffixes[first_type.type];
+   type_class_index orig_expected_tclass = expected_tclass;
+   if (expected_tclass == NUM_TYPE_CLASSES)
+-    expected_tclass = type_suffixes[first_type].tclass;
++    expected_tclass = first_type_suffix.tclass;
+ 
+   unsigned int orig_expected_bits = expected_bits;
+   if (expected_bits == SAME_SIZE)
+-    expected_bits = type_suffixes[first_type].element_bits;
++    expected_bits = first_type_suffix.element_bits;
+   else if (expected_bits == HALF_SIZE)
+-    expected_bits = type_suffixes[first_type].element_bits / 2;
++    expected_bits = first_type_suffix.element_bits / 2;
+   else if (expected_bits == QUARTER_SIZE)
+-    expected_bits = type_suffixes[first_type].element_bits / 4;
++    expected_bits = first_type_suffix.element_bits / 4;
+ 
+   /* If the expected type doesn't depend on FIRST_TYPE at all,
+      just check for the fixed choice of vector type.  */
+@@ -1655,13 +1703,14 @@ require_derived_vector_type (unsigned int argno,
+ 
+   /* Require the argument to be some form of SVE vector type,
+      without being specific about the type of vector we want.  */
+-  type_suffix_index actual_type = infer_vector_type (argno);
+-  if (actual_type == NUM_TYPE_SUFFIXES)
++  sve_type actual_type = infer_vector_type (argno);
++  if (!actual_type)
+     return false;
+ 
+   /* Exit now if we got the right type.  */
+-  bool tclass_ok_p = (type_suffixes[actual_type].tclass == expected_tclass);
+-  bool size_ok_p = (type_suffixes[actual_type].element_bits == expected_bits);
++  auto &actual_type_suffix = type_suffixes[actual_type.type];
++  bool tclass_ok_p = (actual_type_suffix.tclass == expected_tclass);
++  bool size_ok_p = (actual_type_suffix.element_bits == expected_bits);
+   if (tclass_ok_p && size_ok_p)
+     return true;
+ 
+@@ -1701,7 +1750,9 @@ require_derived_vector_type (unsigned int argno,
+ 
+   /* If the arguments have consistent type classes, but a link between
+      the sizes has been broken, try to describe the error in those terms.  */
+-  if (both_vectors_p && tclass_ok_p && orig_expected_bits == SAME_SIZE)
++  if (first_type.num_vectors == 1
++      && tclass_ok_p
++      && orig_expected_bits == SAME_SIZE)
+     {
+       if (argno < first_argno)
+ 	{
+@@ -1718,11 +1769,11 @@ require_derived_vector_type (unsigned int argno,
+ 
+   /* Likewise in reverse: look for cases in which the sizes are consistent
+      but a link between the type classes has been broken.  */
+-  if (both_vectors_p
++  if (first_type.num_vectors == 1
+       && size_ok_p
+       && orig_expected_tclass == SAME_TYPE_CLASS
+-      && type_suffixes[first_type].integer_p
+-      && type_suffixes[actual_type].integer_p)
++      && first_type_suffix.integer_p
++      && actual_type_suffix.integer_p)
+     {
+       if (argno < first_argno)
+ 	{
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index f7d6cc084..a7cfff7c1 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -458,28 +458,28 @@ public:
+ 		    type_suffix_index = NUM_TYPE_SUFFIXES,
+ 		    type_suffix_index = NUM_TYPE_SUFFIXES,
+ 		    group_suffix_index = GROUP_none);
++  tree lookup_form (mode_suffix_index, sve_type);
+   tree resolve_to (mode_suffix_index,
+ 		   type_suffix_index = NUM_TYPE_SUFFIXES,
+ 		   type_suffix_index = NUM_TYPE_SUFFIXES,
+ 		   group_suffix_index = GROUP_none);
++  tree resolve_to (mode_suffix_index, sve_type);
+ 
+   type_suffix_index infer_integer_scalar_type (unsigned int);
+   type_suffix_index infer_pointer_type (unsigned int, bool = false);
+   sve_type infer_sve_type (unsigned int);
+-  type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
++  sve_type infer_vector_or_tuple_type (unsigned int, unsigned int);
+   type_suffix_index infer_vector_type (unsigned int);
+   type_suffix_index infer_integer_vector_type (unsigned int);
+   type_suffix_index infer_unsigned_vector_type (unsigned int);
+   type_suffix_index infer_sd_vector_type (unsigned int);
+-  type_suffix_index infer_tuple_type (unsigned int);
++  sve_type infer_tuple_type (unsigned int);
+ 
+   bool require_vector_or_scalar_type (unsigned int);
+ 
+   bool require_vector_type (unsigned int, vector_type_index);
+-  bool require_matching_vector_type (unsigned int, unsigned int,
+-				     type_suffix_index);
+-  bool require_derived_vector_type (unsigned int, unsigned int,
+-				    type_suffix_index,
++  bool require_matching_vector_type (unsigned int, unsigned int, sve_type);
++  bool require_derived_vector_type (unsigned int, unsigned int, sve_type,
+ 				    type_class_index = SAME_TYPE_CLASS,
+ 				    unsigned int = SAME_SIZE);
+ 
+-- 
+2.33.0
+
diff --git a/0169-Backport-SME-aarch64-Tweak-error-message-for-tuple-v.patch b/0169-Backport-SME-aarch64-Tweak-error-message-for-tuple-v.patch
new file mode 100644
index 0000000..f2f2fd0
--- /dev/null
+++ b/0169-Backport-SME-aarch64-Tweak-error-message-for-tuple-v.patch
@@ -0,0 +1,106 @@
+From 1abb02c636eef4f9a5f55f243bc0c4d38ee1f849 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:22 +0000
+Subject: [PATCH 070/157] [Backport][SME] aarch64: Tweak error message for
+ (tuple,vector) pairs
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5ce2e22b7e02c7fbd1ab8145b632559b67ae9958
+
+SME2 adds more intrinsics that take a tuple of vectors followed
+by a single vector, with the two arguments expected to have the
+same element type.  Unlike with the existing svset* intrinsics,
+the size of the tuple is not fixed by the overloaded function name.
+
+This patch adds an error message that (hopefully) copes better
+with that combination.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.cc
+	(function_resolver::require_derived_vector_type): Add a specific
+	error message for the case in which the caller wants a single
+	vector whose element type matches a previous tuyple argument.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/acle/general-c/set_1.c: Tweak expected
+	error message.
+	* gcc.target/aarch64/sve/acle/general-c/set_3.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/set_5.c: Likewise.
+---
+ gcc/config/aarch64/aarch64-sve-builtins.cc          | 13 +++++++++++++
+ .../gcc.target/aarch64/sve/acle/general-c/set_1.c   |  4 ++--
+ .../gcc.target/aarch64/sve/acle/general-c/set_3.c   |  4 ++--
+ .../gcc.target/aarch64/sve/acle/general-c/set_5.c   |  4 ++--
+ 4 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index e98274f8a..9224916a7 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -1707,6 +1707,19 @@ require_derived_vector_type (unsigned int argno,
+   if (!actual_type)
+     return false;
+ 
++  if (orig_expected_tclass == SAME_TYPE_CLASS
++      && orig_expected_bits == SAME_SIZE)
++    {
++      if (actual_type.type == first_type.type)
++	return true;
++
++      error_at (location, "passing %qT to argument %d of %qE, but"
++		" argument %d was a tuple of %qT",
++		get_vector_type (actual_type), argno + 1, fndecl,
++		first_argno + 1, get_vector_type (first_type.type));
++      return false;
++    }
++
+   /* Exit now if we got the right type.  */
+   auto &actual_type_suffix = type_suffixes[actual_type.type];
+   bool tclass_ok_p = (actual_type_suffix.tclass == expected_tclass);
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c
+index f07c76102..f2a6da536 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c
+@@ -16,8 +16,8 @@ f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+   u8x2 = svset2 (u8x3, 0, u8); /* { dg-error {passing 'svuint8x3_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+   u8x2 = svset2 (pg, 0, u8); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+   u8x2 = svset2 (u8x2, 0, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 3 of 'svset2', which expects a single SVE vector rather than a tuple} } */
+-  u8x2 = svset2 (u8x2, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svuint8_t' to argument 3 of 'svset2', after passing 'svuint8x2_t' to argument 1} } */
+-  u8x2 = svset2 (u8x2, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svuint8_t' to argument 3 of 'svset2', after passing 'svuint8x2_t' to argument 1} } */
++  u8x2 = svset2 (u8x2, 0, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svset2', but argument 1 was a tuple of 'svuint8_t'} } */
++  u8x2 = svset2 (u8x2, 0, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svset2', but argument 1 was a tuple of 'svuint8_t'} } */
+   u8x2 = svset2 (u8x2, x, u8); /* { dg-error {argument 2 of 'svset2' must be an integer constant expression} } */
+   u8x2 = svset2 (u8x2, 0, u8);
+   f64 = svset2 (u8x2, 0, u8); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8x2_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c
+index 543a1bea8..92b955f83 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c
+@@ -17,8 +17,8 @@ f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+   f16x3 = svset3 (f16x4, 0, f16); /* { dg-error {passing 'svfloat16x4_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+   f16x3 = svset3 (pg, 0, f16); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+   f16x3 = svset3 (f16x3, 0, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 3 of 'svset3', which expects a single SVE vector rather than a tuple} } */
+-  f16x3 = svset3 (f16x3, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svfloat16_t' to argument 3 of 'svset3', after passing 'svfloat16x3_t' to argument 1} } */
+-  f16x3 = svset3 (f16x3, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svfloat16_t' to argument 3 of 'svset3', after passing 'svfloat16x3_t' to argument 1} } */
++  f16x3 = svset3 (f16x3, 0, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svset3', but argument 1 was a tuple of 'svfloat16_t'} } */
++  f16x3 = svset3 (f16x3, 0, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svset3', but argument 1 was a tuple of 'svfloat16_t'} } */
+   f16x3 = svset3 (f16x3, x, f16); /* { dg-error {argument 2 of 'svset3' must be an integer constant expression} } */
+   f16x3 = svset3 (f16x3, 0, f16);
+   f64 = svset3 (f16x3, 0, f16); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16x3_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c
+index be911a731..f0696fb07 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c
+@@ -16,8 +16,8 @@ f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+   s32x4 = svset4 (s32x2, 0, s32); /* { dg-error {passing 'svint32x2_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+   s32x4 = svset4 (pg, 0, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+   s32x4 = svset4 (s32x4, 0, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 3 of 'svset4', which expects a single SVE vector rather than a tuple} } */
+-  s32x4 = svset4 (s32x4, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svint32_t' to argument 3 of 'svset4', after passing 'svint32x4_t' to argument 1} } */
+-  s32x4 = svset4 (s32x4, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svint32_t' to argument 3 of 'svset4', after passing 'svint32x4_t' to argument 1} } */
++  s32x4 = svset4 (s32x4, 0, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svset4', but argument 1 was a tuple of 'svint32_t'} } */
++  s32x4 = svset4 (s32x4, 0, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svset4', but argument 1 was a tuple of 'svint32_t'} } */
+   s32x4 = svset4 (s32x4, x, s32); /* { dg-error {argument 2 of 'svset4' must be an integer constant expression} } */
+   s32x4 = svset4 (s32x4, 0, s32);
+   f64 = svset4 (s32x4, 0, s32); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32x4_t'} } */
+-- 
+2.33.0
+
diff --git a/0170-Backport-SME-aarch64-Add-tuple-forms-of-svreinterpre.patch b/0170-Backport-SME-aarch64-Add-tuple-forms-of-svreinterpre.patch
new file mode 100644
index 0000000..b4807e2
--- /dev/null
+++ b/0170-Backport-SME-aarch64-Add-tuple-forms-of-svreinterpre.patch
@@ -0,0 +1,1236 @@
+From 95234ef07c47dda7ac6a13f75619580a6683118c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:22 +0000
+Subject: [PATCH 071/157] [Backport][SME] aarch64: Add tuple forms of
+ svreinterpret
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1ce9dc263c2f6d455b2013fc58932beda2a4ae92
+
+SME2 adds a number of intrinsics that operate on tuples of 2 and 4
+vectors.  The ACLE therefore extends the existing svreinterpret
+intrinsics to handle tuples as well.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins-base.cc
+	(svreinterpret_impl::fold): Punt on tuple forms.
+	(svreinterpret_impl::expand): Use tuple_mode instead of vector_mode.
+	* config/aarch64/aarch64-sve-builtins-base.def (svreinterpret):
+	Extend to x1234 groups.
+	* config/aarch64/aarch64-sve-builtins-functions.h
+	(multi_vector_function::vectors_per_tuple): If the function has
+	a group suffix, get the number of vectors from there.
+	* config/aarch64/aarch64-sve-builtins-shapes.h (reinterpret): Declare.
+	* config/aarch64/aarch64-sve-builtins-shapes.cc (reinterpret_def)
+	(reinterpret): New function shape.
+	* config/aarch64/aarch64-sve-builtins.cc (function_groups): Handle
+	DEF_SVE_FUNCTION_GS.
+	* config/aarch64/aarch64-sve-builtins.def (DEF_SVE_FUNCTION_GS): New
+	macro.
+	(DEF_SVE_FUNCTION): Forward to DEF_SVE_FUNCTION_GS by default.
+	* config/aarch64/aarch64-sve-builtins.h
+	(function_instance::tuple_mode): New member function.
+	(function_base::vectors_per_tuple): Take the function instance
+	as argument and get the number from the group suffix.
+	(function_instance::vectors_per_tuple): Update accordingly.
+	* config/aarch64/iterators.md (SVE_FULLx2, SVE_FULLx3, SVE_FULLx4)
+	(SVE_ALL_STRUCT): New mode iterators.
+	(SVE_STRUCT): Redefine in terms of SVE_FULL*.
+	* config/aarch64/aarch64-sve.md (@aarch64_sve_reinterpret)
+	(*aarch64_sve_reinterpret): Extend to SVE structure modes.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/acle/asm/test_sve_acle.h (TEST_DUAL_XN):
+	New macro.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_bf16.c: Add tests for
+	tuple forms.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_s8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/reinterpret_u8.c: Likewise.
+---
+ .../aarch64/aarch64-sve-builtins-base.cc      |  5 +-
+ .../aarch64/aarch64-sve-builtins-base.def     |  2 +-
+ .../aarch64/aarch64-sve-builtins-functions.h  |  7 ++-
+ .../aarch64/aarch64-sve-builtins-shapes.cc    | 28 +++++++++
+ .../aarch64/aarch64-sve-builtins-shapes.h     |  1 +
+ gcc/config/aarch64/aarch64-sve-builtins.cc    |  8 ++-
+ gcc/config/aarch64/aarch64-sve-builtins.def   |  8 ++-
+ gcc/config/aarch64/aarch64-sve-builtins.h     | 20 +++++-
+ gcc/config/aarch64/aarch64-sve.md             |  8 +--
+ gcc/config/aarch64/iterators.md               | 26 +++++---
+ .../aarch64/sve/acle/asm/reinterpret_bf16.c   | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_f16.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_f32.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_f64.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_s16.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_s32.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_s64.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_s8.c     | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_u16.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_u32.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_u64.c    | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/reinterpret_u8.c     | 62 +++++++++++++++++++
+ .../aarch64/sve/acle/asm/test_sve_acle.h      | 14 +++++
+ 23 files changed, 851 insertions(+), 20 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+index c9bf13792..53f3f28f9 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+@@ -1928,6 +1928,9 @@ public:
+   gimple *
+   fold (gimple_folder &f) const OVERRIDE
+   {
++    if (f.vectors_per_tuple () > 1)
++      return NULL;
++
+     /* Punt to rtl if the effect of the reinterpret on registers does not
+        conform to GCC's endianness model.  */
+     if (!targetm.can_change_mode_class (f.vector_mode (0),
+@@ -1944,7 +1947,7 @@ public:
+   rtx
+   expand (function_expander &e) const OVERRIDE
+   {
+-    machine_mode mode = e.vector_mode (0);
++    machine_mode mode = e.tuple_mode (0);
+     return e.use_exact_insn (code_for_aarch64_sve_reinterpret (mode));
+   }
+ };
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.def b/gcc/config/aarch64/aarch64-sve-builtins-base.def
+index 3a58f76c3..756469959 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-base.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.def
+@@ -248,7 +248,7 @@ DEF_SVE_FUNCTION (svrdffr, rdffr, none, z_or_none)
+ DEF_SVE_FUNCTION (svrecpe, unary, all_float, none)
+ DEF_SVE_FUNCTION (svrecps, binary, all_float, none)
+ DEF_SVE_FUNCTION (svrecpx, unary, all_float, mxz)
+-DEF_SVE_FUNCTION (svreinterpret, unary_convert, reinterpret, none)
++DEF_SVE_FUNCTION_GS (svreinterpret, reinterpret, reinterpret, x1234, none)
+ DEF_SVE_FUNCTION (svrev, unary, all_data, none)
+ DEF_SVE_FUNCTION (svrev, unary_pred, all_pred, none)
+ DEF_SVE_FUNCTION (svrevb, unary, hsd_integer, mxz)
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+index 9d346b6ff..94a6d1207 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+@@ -59,8 +59,13 @@ public:
+     : m_vectors_per_tuple (vectors_per_tuple) {}
+ 
+   unsigned int
+-  vectors_per_tuple () const OVERRIDE
++  vectors_per_tuple (const function_instance &fi) const override
+   {
++    if (fi.group_suffix_id != GROUP_none)
++      {
++	gcc_checking_assert (m_vectors_per_tuple == 1);
++	return fi.group_suffix ().vectors_per_tuple;
++      }
+     return m_vectors_per_tuple;
+   }
+ 
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index f187b4cb2..95e40d8f3 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -2400,6 +2400,34 @@ struct reduction_wide_def : public overloaded_base<0>
+ };
+ SHAPE (reduction_wide)
+ 
++/* svx_t svfoo_t0[_t1_g](svx_t)
++
++   where the target type  must be specified explicitly but the source
++   type  can be inferred.  */
++struct reinterpret_def : public overloaded_base<1>
++{
++  bool explicit_group_suffix_p () const override { return false; }
++
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    build_all (b, "t0,t1", group, MODE_none);
++  }
++
++  tree
++  resolve (function_resolver &r) const override
++  {
++    sve_type type;
++    if (!r.check_num_arguments (1)
++	|| !(type = r.infer_sve_type (0)))
++      return error_mark_node;
++
++    return r.resolve_to (r.mode_suffix_id, type);
++  }
++};
++SHAPE (reinterpret)
++
+ /* svxN_t svfoo[_t0](svxN_t, uint64_t, sv_t)
+ 
+    where the second argument is an integer constant expression in the
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
+index 3b0025f85..2b06152d4 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
+@@ -133,6 +133,7 @@ namespace aarch64_sve
+     extern const function_shape *const rdffr;
+     extern const function_shape *const reduction;
+     extern const function_shape *const reduction_wide;
++    extern const function_shape *const reinterpret;
+     extern const function_shape *const set;
+     extern const function_shape *const setffr;
+     extern const function_shape *const shift_left_imm_long;
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 9224916a7..c439f2e8a 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -494,6 +494,10 @@ static const group_suffix_index groups_none[] = {
+   GROUP_none, NUM_GROUP_SUFFIXES
+ };
+ 
++static const group_suffix_index groups_x1234[] = {
++  GROUP_none, GROUP_x2, GROUP_x3, GROUP_x4, NUM_GROUP_SUFFIXES
++};
++
+ /* Used by functions that have no governing predicate.  */
+ static const predication_index preds_none[] = { PRED_none, NUM_PREDS };
+ 
+@@ -534,8 +538,8 @@ static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+ 
+ /* A list of all SVE ACLE functions.  */
+ static CONSTEXPR const function_group_info function_groups[] = {
+-#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+-  { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_none, \
++#define DEF_SVE_FUNCTION_GS(NAME, SHAPE, TYPES, GROUPS, PREDS) \
++  { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_##GROUPS, \
+     preds_##PREDS, REQUIRED_EXTENSIONS },
+ #include "aarch64-sve-builtins.def"
+ };
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def
+index d9bf9c350..be10b5ea1 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins.def
+@@ -33,8 +33,13 @@
+ #define DEF_SVE_GROUP_SUFFIX(A, B, C)
+ #endif
+ 
++#ifndef DEF_SVE_FUNCTION_GS
++#define DEF_SVE_FUNCTION_GS(A, B, C, D, E)
++#endif
++
+ #ifndef DEF_SVE_FUNCTION
+-#define DEF_SVE_FUNCTION(A, B, C, D)
++#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
++  DEF_SVE_FUNCTION_GS (NAME, SHAPE, TYPES, none, PREDS)
+ #endif
+ 
+ DEF_SVE_MODE (n, none, none, none)
+@@ -107,6 +112,7 @@ DEF_SVE_GROUP_SUFFIX (x4, 0, 4)
+ #include "aarch64-sve-builtins-sve2.def"
+ 
+ #undef DEF_SVE_FUNCTION
++#undef DEF_SVE_FUNCTION_GS
+ #undef DEF_SVE_GROUP_SUFFIX
+ #undef DEF_SVE_TYPE_SUFFIX
+ #undef DEF_SVE_TYPE
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index a7cfff7c1..7132b6e77 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -364,6 +364,7 @@ public:
+   tree tuple_type (unsigned int) const;
+   unsigned int elements_per_vq (unsigned int i) const;
+   machine_mode vector_mode (unsigned int) const;
++  machine_mode tuple_mode (unsigned int) const;
+   machine_mode gp_mode (unsigned int) const;
+ 
+   /* The properties of the function.  */
+@@ -664,7 +665,7 @@ public:
+ 
+   /* If the function operates on tuples of vectors, return the number
+      of vectors in the tuples, otherwise return 1.  */
+-  virtual unsigned int vectors_per_tuple () const { return 1; }
++  virtual unsigned int vectors_per_tuple (const function_instance &) const;
+ 
+   /* If the function addresses memory, return the type of a single
+      scalar memory element.  */
+@@ -836,7 +837,7 @@ function_instance::operator!= (const function_instance &other) const
+ inline unsigned int
+ function_instance::vectors_per_tuple () const
+ {
+-  return base->vectors_per_tuple ();
++  return base->vectors_per_tuple (*this);
+ }
+ 
+ /* If the function addresses memory, return the type of a single
+@@ -940,6 +941,15 @@ function_instance::vector_mode (unsigned int i) const
+   return type_suffix (i).vector_mode;
+ }
+ 
++/* Return the mode of tuple_type (I).  */
++inline machine_mode
++function_instance::tuple_mode (unsigned int i) const
++{
++  if (group_suffix ().vectors_per_tuple > 1)
++    return TYPE_MODE (tuple_type (i));
++  return vector_mode (i);
++}
++
+ /* Return the mode of the governing predicate to use when operating on
+    type suffix I.  */
+ inline machine_mode
+@@ -966,6 +976,12 @@ function_base::call_properties (const function_instance &instance) const
+   return flags;
+ }
+ 
++inline unsigned int
++function_base::vectors_per_tuple (const function_instance &instance) const
++{
++  return instance.group_suffix ().vectors_per_tuple;
++}
++
+ /* Return the mode of the result of a call.  */
+ inline machine_mode
+ function_expander::result_mode () const
+diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
+index b8cc47ef5..28b73d807 100644
+--- a/gcc/config/aarch64/aarch64-sve.md
++++ b/gcc/config/aarch64/aarch64-sve.md
+@@ -784,8 +784,8 @@
+ ;; This is equivalent to a subreg on little-endian targets but not for
+ ;; big-endian; see the comment at the head of the file for details.
+ (define_expand "@aarch64_sve_reinterpret"
+-  [(set (match_operand:SVE_ALL 0 "register_operand")
+-	(unspec:SVE_ALL
++  [(set (match_operand:SVE_ALL_STRUCT 0 "register_operand")
++	(unspec:SVE_ALL_STRUCT
+ 	  [(match_operand 1 "aarch64_any_register_operand")]
+ 	  UNSPEC_REINTERPRET))]
+   "TARGET_SVE"
+@@ -802,8 +802,8 @@
+ ;; A pattern for handling type punning on big-endian targets.  We use a
+ ;; special predicate for operand 1 to reduce the number of patterns.
+ (define_insn_and_split "*aarch64_sve_reinterpret"
+-  [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+-	(unspec:SVE_ALL
++  [(set (match_operand:SVE_ALL_STRUCT 0 "register_operand" "=w")
++	(unspec:SVE_ALL_STRUCT
+ 	  [(match_operand 1 "aarch64_any_register_operand" "w")]
+ 	  UNSPEC_REINTERPRET))]
+   "TARGET_SVE"
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index a8a39b65a..8dd2035bc 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -451,14 +451,6 @@
+ (define_mode_iterator VNx2DI_ONLY [VNx2DI])
+ (define_mode_iterator VNx2DF_ONLY [VNx2DF])
+ 
+-;; All SVE vector structure modes.
+-(define_mode_iterator SVE_STRUCT [VNx32QI VNx16HI VNx8SI VNx4DI
+-				  VNx16BF VNx16HF VNx8SF VNx4DF
+-				  VNx48QI VNx24HI VNx12SI VNx6DI
+-				  VNx24BF VNx24HF VNx12SF VNx6DF
+-				  VNx64QI VNx32HI VNx16SI VNx8DI
+-				  VNx32BF VNx32HF VNx16SF VNx8DF])
+-
+ ;; All fully-packed SVE vector modes.
+ (define_mode_iterator SVE_FULL [VNx16QI VNx8HI VNx4SI VNx2DI
+ 			        VNx8BF VNx8HF VNx4SF VNx2DF])
+@@ -530,6 +522,24 @@
+ 			       VNx2DI
+ 			       VNx2DF])
+ 
++;; All SVE 2-vector modes.
++(define_mode_iterator SVE_FULLx2 [VNx32QI VNx16HI VNx8SI VNx4DI
++			          VNx16BF VNx16HF VNx8SF VNx4DF])
++
++;; All SVE 3-vector modes.
++(define_mode_iterator SVE_FULLx3 [VNx48QI VNx24HI VNx12SI VNx6DI
++			          VNx24BF VNx24HF VNx12SF VNx6DF])
++
++;; All SVE 4-vector modes.
++(define_mode_iterator SVE_FULLx4 [VNx64QI VNx32HI VNx16SI VNx8DI
++			          VNx32BF VNx32HF VNx16SF VNx8DF])
++
++;; All SVE vector structure modes.
++(define_mode_iterator SVE_STRUCT [SVE_FULLx2 SVE_FULLx3 SVE_FULLx4])
++
++;; All SVE vector and structure modes.
++(define_mode_iterator SVE_ALL_STRUCT [SVE_ALL SVE_STRUCT])
++
+ ;; All SVE integer vector modes.
+ (define_mode_iterator SVE_I [VNx16QI VNx8QI VNx4QI VNx2QI
+ 			     VNx8HI VNx4HI VNx2HI
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_bf16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_bf16.c
+index 2d2c2a714..dd0daf2ef 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_bf16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_bf16.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_bf16_u64_tied1, svbfloat16_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_bf16_u64_untied, svbfloat16_t, svuint64_t,
+ 	     z0 = svreinterpret_bf16_u64 (z4),
+ 	     z0 = svreinterpret_bf16 (z4))
++
++/*
++** reinterpret_bf16_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_bf16_bf16_x2_tied1, svbfloat16x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_bf16_bf16_x2 (z0),
++		 z0_res = svreinterpret_bf16 (z0))
++
++/*
++** reinterpret_bf16_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_bf16_f32_x2_untied, svbfloat16x2_t, svfloat32x2_t, z0,
++	      svreinterpret_bf16_f32_x2 (z4),
++	      svreinterpret_bf16 (z4))
++
++/*
++** reinterpret_bf16_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_bf16_s64_x3_tied1, svbfloat16x3_t, svint64x3_t,
++		 z0_res = svreinterpret_bf16_s64_x3 (z0),
++		 z0_res = svreinterpret_bf16 (z0))
++
++/*
++** reinterpret_bf16_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_bf16_u8_x3_untied, svbfloat16x3_t, svuint8x3_t, z18,
++	      svreinterpret_bf16_u8_x3 (z23),
++	      svreinterpret_bf16 (z23))
++
++/*
++** reinterpret_bf16_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_bf16_u32_x4_tied1, svbfloat16x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_bf16_u32_x4 (z0),
++		 z0_res = svreinterpret_bf16 (z0))
++
++/*
++** reinterpret_bf16_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_bf16_f64_x4_untied, svbfloat16x4_t, svfloat64x4_t, z28,
++	      svreinterpret_bf16_f64_x4 (z4),
++	      svreinterpret_bf16 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f16.c
+index 60705e628..9b6f8227d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f16.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_f16_u64_tied1, svfloat16_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_f16_u64_untied, svfloat16_t, svuint64_t,
+ 	     z0 = svreinterpret_f16_u64 (z4),
+ 	     z0 = svreinterpret_f16 (z4))
++
++/*
++** reinterpret_f16_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f16_bf16_x2_tied1, svfloat16x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_f16_bf16_x2 (z0),
++		 z0_res = svreinterpret_f16 (z0))
++
++/*
++** reinterpret_f16_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f16_f32_x2_untied, svfloat16x2_t, svfloat32x2_t, z0,
++	      svreinterpret_f16_f32_x2 (z4),
++	      svreinterpret_f16 (z4))
++
++/*
++** reinterpret_f16_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f16_s64_x3_tied1, svfloat16x3_t, svint64x3_t,
++		 z0_res = svreinterpret_f16_s64_x3 (z0),
++		 z0_res = svreinterpret_f16 (z0))
++
++/*
++** reinterpret_f16_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f16_u8_x3_untied, svfloat16x3_t, svuint8x3_t, z18,
++	      svreinterpret_f16_u8_x3 (z23),
++	      svreinterpret_f16 (z23))
++
++/*
++** reinterpret_f16_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f16_u32_x4_tied1, svfloat16x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_f16_u32_x4 (z0),
++		 z0_res = svreinterpret_f16 (z0))
++
++/*
++** reinterpret_f16_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f16_f64_x4_untied, svfloat16x4_t, svfloat64x4_t, z28,
++	      svreinterpret_f16_f64_x4 (z4),
++	      svreinterpret_f16 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f32.c
+index 06fc46f25..ce981fce9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f32.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_f32_u64_tied1, svfloat32_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_f32_u64_untied, svfloat32_t, svuint64_t,
+ 	     z0 = svreinterpret_f32_u64 (z4),
+ 	     z0 = svreinterpret_f32 (z4))
++
++/*
++** reinterpret_f32_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f32_bf16_x2_tied1, svfloat32x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_f32_bf16_x2 (z0),
++		 z0_res = svreinterpret_f32 (z0))
++
++/*
++** reinterpret_f32_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f32_f32_x2_untied, svfloat32x2_t, svfloat32x2_t, z0,
++	      svreinterpret_f32_f32_x2 (z4),
++	      svreinterpret_f32 (z4))
++
++/*
++** reinterpret_f32_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f32_s64_x3_tied1, svfloat32x3_t, svint64x3_t,
++		 z0_res = svreinterpret_f32_s64_x3 (z0),
++		 z0_res = svreinterpret_f32 (z0))
++
++/*
++** reinterpret_f32_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f32_u8_x3_untied, svfloat32x3_t, svuint8x3_t, z18,
++	      svreinterpret_f32_u8_x3 (z23),
++	      svreinterpret_f32 (z23))
++
++/*
++** reinterpret_f32_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f32_u32_x4_tied1, svfloat32x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_f32_u32_x4 (z0),
++		 z0_res = svreinterpret_f32 (z0))
++
++/*
++** reinterpret_f32_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f32_f64_x4_untied, svfloat32x4_t, svfloat64x4_t, z28,
++	      svreinterpret_f32_f64_x4 (z4),
++	      svreinterpret_f32 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f64.c
+index 003ee3fe2..4f51824ab 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_f64.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_f64_u64_tied1, svfloat64_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_f64_u64_untied, svfloat64_t, svuint64_t,
+ 	     z0 = svreinterpret_f64_u64 (z4),
+ 	     z0 = svreinterpret_f64 (z4))
++
++/*
++** reinterpret_f64_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f64_bf16_x2_tied1, svfloat64x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_f64_bf16_x2 (z0),
++		 z0_res = svreinterpret_f64 (z0))
++
++/*
++** reinterpret_f64_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f64_f32_x2_untied, svfloat64x2_t, svfloat32x2_t, z0,
++	      svreinterpret_f64_f32_x2 (z4),
++	      svreinterpret_f64 (z4))
++
++/*
++** reinterpret_f64_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f64_s64_x3_tied1, svfloat64x3_t, svint64x3_t,
++		 z0_res = svreinterpret_f64_s64_x3 (z0),
++		 z0_res = svreinterpret_f64 (z0))
++
++/*
++** reinterpret_f64_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f64_u8_x3_untied, svfloat64x3_t, svuint8x3_t, z18,
++	      svreinterpret_f64_u8_x3 (z23),
++	      svreinterpret_f64 (z23))
++
++/*
++** reinterpret_f64_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_f64_u32_x4_tied1, svfloat64x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_f64_u32_x4 (z0),
++		 z0_res = svreinterpret_f64 (z0))
++
++/*
++** reinterpret_f64_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_f64_f64_x4_untied, svfloat64x4_t, svfloat64x4_t, z28,
++	      svreinterpret_f64_f64_x4 (z4),
++	      svreinterpret_f64 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s16.c
+index d62817c2c..7e15f3e9b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s16.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_s16_u64_tied1, svint16_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_s16_u64_untied, svint16_t, svuint64_t,
+ 	     z0 = svreinterpret_s16_u64 (z4),
+ 	     z0 = svreinterpret_s16 (z4))
++
++/*
++** reinterpret_s16_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s16_bf16_x2_tied1, svint16x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_s16_bf16_x2 (z0),
++		 z0_res = svreinterpret_s16 (z0))
++
++/*
++** reinterpret_s16_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s16_f32_x2_untied, svint16x2_t, svfloat32x2_t, z0,
++	      svreinterpret_s16_f32_x2 (z4),
++	      svreinterpret_s16 (z4))
++
++/*
++** reinterpret_s16_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s16_s64_x3_tied1, svint16x3_t, svint64x3_t,
++		 z0_res = svreinterpret_s16_s64_x3 (z0),
++		 z0_res = svreinterpret_s16 (z0))
++
++/*
++** reinterpret_s16_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s16_u8_x3_untied, svint16x3_t, svuint8x3_t, z18,
++	      svreinterpret_s16_u8_x3 (z23),
++	      svreinterpret_s16 (z23))
++
++/*
++** reinterpret_s16_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s16_u32_x4_tied1, svint16x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_s16_u32_x4 (z0),
++		 z0_res = svreinterpret_s16 (z0))
++
++/*
++** reinterpret_s16_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s16_f64_x4_untied, svint16x4_t, svfloat64x4_t, z28,
++	      svreinterpret_s16_f64_x4 (z4),
++	      svreinterpret_s16 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s32.c
+index e1068f244..60da8aef3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s32.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_s32_u64_tied1, svint32_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_s32_u64_untied, svint32_t, svuint64_t,
+ 	     z0 = svreinterpret_s32_u64 (z4),
+ 	     z0 = svreinterpret_s32 (z4))
++
++/*
++** reinterpret_s32_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s32_bf16_x2_tied1, svint32x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_s32_bf16_x2 (z0),
++		 z0_res = svreinterpret_s32 (z0))
++
++/*
++** reinterpret_s32_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s32_f32_x2_untied, svint32x2_t, svfloat32x2_t, z0,
++	      svreinterpret_s32_f32_x2 (z4),
++	      svreinterpret_s32 (z4))
++
++/*
++** reinterpret_s32_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s32_s64_x3_tied1, svint32x3_t, svint64x3_t,
++		 z0_res = svreinterpret_s32_s64_x3 (z0),
++		 z0_res = svreinterpret_s32 (z0))
++
++/*
++** reinterpret_s32_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s32_u8_x3_untied, svint32x3_t, svuint8x3_t, z18,
++	      svreinterpret_s32_u8_x3 (z23),
++	      svreinterpret_s32 (z23))
++
++/*
++** reinterpret_s32_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s32_u32_x4_tied1, svint32x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_s32_u32_x4 (z0),
++		 z0_res = svreinterpret_s32 (z0))
++
++/*
++** reinterpret_s32_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s32_f64_x4_untied, svint32x4_t, svfloat64x4_t, z28,
++	      svreinterpret_s32_f64_x4 (z4),
++	      svreinterpret_s32 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s64.c
+index cada7533c..d705c60df 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s64.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_s64_u64_tied1, svint64_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_s64_u64_untied, svint64_t, svuint64_t,
+ 	     z0 = svreinterpret_s64_u64 (z4),
+ 	     z0 = svreinterpret_s64 (z4))
++
++/*
++** reinterpret_s64_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s64_bf16_x2_tied1, svint64x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_s64_bf16_x2 (z0),
++		 z0_res = svreinterpret_s64 (z0))
++
++/*
++** reinterpret_s64_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s64_f32_x2_untied, svint64x2_t, svfloat32x2_t, z0,
++	      svreinterpret_s64_f32_x2 (z4),
++	      svreinterpret_s64 (z4))
++
++/*
++** reinterpret_s64_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s64_s64_x3_tied1, svint64x3_t, svint64x3_t,
++		 z0_res = svreinterpret_s64_s64_x3 (z0),
++		 z0_res = svreinterpret_s64 (z0))
++
++/*
++** reinterpret_s64_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s64_u8_x3_untied, svint64x3_t, svuint8x3_t, z18,
++	      svreinterpret_s64_u8_x3 (z23),
++	      svreinterpret_s64 (z23))
++
++/*
++** reinterpret_s64_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s64_u32_x4_tied1, svint64x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_s64_u32_x4 (z0),
++		 z0_res = svreinterpret_s64 (z0))
++
++/*
++** reinterpret_s64_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s64_f64_x4_untied, svint64x4_t, svfloat64x4_t, z28,
++	      svreinterpret_s64_f64_x4 (z4),
++	      svreinterpret_s64 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s8.c
+index 23a40d0ba..ab90a54d7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_s8.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_s8_u64_tied1, svint8_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_s8_u64_untied, svint8_t, svuint64_t,
+ 	     z0 = svreinterpret_s8_u64 (z4),
+ 	     z0 = svreinterpret_s8 (z4))
++
++/*
++** reinterpret_s8_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s8_bf16_x2_tied1, svint8x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_s8_bf16_x2 (z0),
++		 z0_res = svreinterpret_s8 (z0))
++
++/*
++** reinterpret_s8_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s8_f32_x2_untied, svint8x2_t, svfloat32x2_t, z0,
++	      svreinterpret_s8_f32_x2 (z4),
++	      svreinterpret_s8 (z4))
++
++/*
++** reinterpret_s8_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s8_s64_x3_tied1, svint8x3_t, svint64x3_t,
++		 z0_res = svreinterpret_s8_s64_x3 (z0),
++		 z0_res = svreinterpret_s8 (z0))
++
++/*
++** reinterpret_s8_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s8_u8_x3_untied, svint8x3_t, svuint8x3_t, z18,
++	      svreinterpret_s8_u8_x3 (z23),
++	      svreinterpret_s8 (z23))
++
++/*
++** reinterpret_s8_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_s8_u32_x4_tied1, svint8x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_s8_u32_x4 (z0),
++		 z0_res = svreinterpret_s8 (z0))
++
++/*
++** reinterpret_s8_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_s8_f64_x4_untied, svint8x4_t, svfloat64x4_t, z28,
++	      svreinterpret_s8_f64_x4 (z4),
++	      svreinterpret_s8 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u16.c
+index 48e8ecaff..fcfc0eb9d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u16.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_u16_u64_tied1, svuint16_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_u16_u64_untied, svuint16_t, svuint64_t,
+ 	     z0 = svreinterpret_u16_u64 (z4),
+ 	     z0 = svreinterpret_u16 (z4))
++
++/*
++** reinterpret_u16_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u16_bf16_x2_tied1, svuint16x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_u16_bf16_x2 (z0),
++		 z0_res = svreinterpret_u16 (z0))
++
++/*
++** reinterpret_u16_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u16_f32_x2_untied, svuint16x2_t, svfloat32x2_t, z0,
++	      svreinterpret_u16_f32_x2 (z4),
++	      svreinterpret_u16 (z4))
++
++/*
++** reinterpret_u16_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u16_s64_x3_tied1, svuint16x3_t, svint64x3_t,
++		 z0_res = svreinterpret_u16_s64_x3 (z0),
++		 z0_res = svreinterpret_u16 (z0))
++
++/*
++** reinterpret_u16_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u16_u8_x3_untied, svuint16x3_t, svuint8x3_t, z18,
++	      svreinterpret_u16_u8_x3 (z23),
++	      svreinterpret_u16 (z23))
++
++/*
++** reinterpret_u16_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u16_u32_x4_tied1, svuint16x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_u16_u32_x4 (z0),
++		 z0_res = svreinterpret_u16 (z0))
++
++/*
++** reinterpret_u16_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u16_f64_x4_untied, svuint16x4_t, svfloat64x4_t, z28,
++	      svreinterpret_u16_f64_x4 (z4),
++	      svreinterpret_u16 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u32.c
+index 1d4e85712..6d7e05857 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u32.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_u32_u64_tied1, svuint32_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_u32_u64_untied, svuint32_t, svuint64_t,
+ 	     z0 = svreinterpret_u32_u64 (z4),
+ 	     z0 = svreinterpret_u32 (z4))
++
++/*
++** reinterpret_u32_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u32_bf16_x2_tied1, svuint32x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_u32_bf16_x2 (z0),
++		 z0_res = svreinterpret_u32 (z0))
++
++/*
++** reinterpret_u32_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u32_f32_x2_untied, svuint32x2_t, svfloat32x2_t, z0,
++	      svreinterpret_u32_f32_x2 (z4),
++	      svreinterpret_u32 (z4))
++
++/*
++** reinterpret_u32_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u32_s64_x3_tied1, svuint32x3_t, svint64x3_t,
++		 z0_res = svreinterpret_u32_s64_x3 (z0),
++		 z0_res = svreinterpret_u32 (z0))
++
++/*
++** reinterpret_u32_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u32_u8_x3_untied, svuint32x3_t, svuint8x3_t, z18,
++	      svreinterpret_u32_u8_x3 (z23),
++	      svreinterpret_u32 (z23))
++
++/*
++** reinterpret_u32_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u32_u32_x4_tied1, svuint32x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_u32_u32_x4 (z0),
++		 z0_res = svreinterpret_u32 (z0))
++
++/*
++** reinterpret_u32_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u32_f64_x4_untied, svuint32x4_t, svfloat64x4_t, z28,
++	      svreinterpret_u32_f64_x4 (z4),
++	      svreinterpret_u32 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u64.c
+index 07af69dce..55c0baefb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u64.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_u64_u64_tied1, svuint64_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_u64_u64_untied, svuint64_t, svuint64_t,
+ 	     z0 = svreinterpret_u64_u64 (z4),
+ 	     z0 = svreinterpret_u64 (z4))
++
++/*
++** reinterpret_u64_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u64_bf16_x2_tied1, svuint64x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_u64_bf16_x2 (z0),
++		 z0_res = svreinterpret_u64 (z0))
++
++/*
++** reinterpret_u64_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u64_f32_x2_untied, svuint64x2_t, svfloat32x2_t, z0,
++	      svreinterpret_u64_f32_x2 (z4),
++	      svreinterpret_u64 (z4))
++
++/*
++** reinterpret_u64_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u64_s64_x3_tied1, svuint64x3_t, svint64x3_t,
++		 z0_res = svreinterpret_u64_s64_x3 (z0),
++		 z0_res = svreinterpret_u64 (z0))
++
++/*
++** reinterpret_u64_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u64_u8_x3_untied, svuint64x3_t, svuint8x3_t, z18,
++	      svreinterpret_u64_u8_x3 (z23),
++	      svreinterpret_u64 (z23))
++
++/*
++** reinterpret_u64_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u64_u32_x4_tied1, svuint64x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_u64_u32_x4 (z0),
++		 z0_res = svreinterpret_u64 (z0))
++
++/*
++** reinterpret_u64_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u64_f64_x4_untied, svuint64x4_t, svfloat64x4_t, z28,
++	      svreinterpret_u64_f64_x4 (z4),
++	      svreinterpret_u64 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u8.c
+index a4c7f4c8d..f73021961 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/reinterpret_u8.c
+@@ -205,3 +205,65 @@ TEST_DUAL_Z_REV (reinterpret_u8_u64_tied1, svuint8_t, svuint64_t,
+ TEST_DUAL_Z (reinterpret_u8_u64_untied, svuint8_t, svuint64_t,
+ 	     z0 = svreinterpret_u8_u64 (z4),
+ 	     z0 = svreinterpret_u8 (z4))
++
++/*
++** reinterpret_u8_bf16_x2_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u8_bf16_x2_tied1, svuint8x2_t, svbfloat16x2_t,
++		 z0_res = svreinterpret_u8_bf16_x2 (z0),
++		 z0_res = svreinterpret_u8 (z0))
++
++/*
++** reinterpret_u8_f32_x2_untied:
++** (
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** |
++**	mov	z0\.d, z4\.d
++**	mov	z1\.d, z5\.d
++** )
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u8_f32_x2_untied, svuint8x2_t, svfloat32x2_t, z0,
++	      svreinterpret_u8_f32_x2 (z4),
++	      svreinterpret_u8 (z4))
++
++/*
++** reinterpret_u8_s64_x3_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u8_s64_x3_tied1, svuint8x3_t, svint64x3_t,
++		 z0_res = svreinterpret_u8_s64_x3 (z0),
++		 z0_res = svreinterpret_u8 (z0))
++
++/*
++** reinterpret_u8_u8_x3_untied:
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	mov	(z18|z19|z20)\.d, (z23|z24|z25)\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u8_u8_x3_untied, svuint8x3_t, svuint8x3_t, z18,
++	      svreinterpret_u8_u8_x3 (z23),
++	      svreinterpret_u8 (z23))
++
++/*
++** reinterpret_u8_u32_x4_tied1:
++**	ret
++*/
++TEST_DUAL_Z_REV (reinterpret_u8_u32_x4_tied1, svuint8x4_t, svuint32x4_t,
++		 z0_res = svreinterpret_u8_u32_x4 (z0),
++		 z0_res = svreinterpret_u8 (z0))
++
++/*
++** reinterpret_u8_f64_x4_untied:
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	mov	(z28|z29|z30|z31)\.d, z[4-7]\.d
++**	ret
++*/
++TEST_DUAL_XN (reinterpret_u8_f64_x4_untied, svuint8x4_t, svfloat64x4_t, z28,
++	      svreinterpret_u8_f64_x4 (z4),
++	      svreinterpret_u8 (z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
+index fbf392b3e..2da61ff5c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
+@@ -421,4 +421,18 @@
+     return z0_res;						\
+   }
+ 
++#define TEST_DUAL_XN(NAME, TTYPE1, TTYPE2, RES, CODE1, CODE2)	\
++  PROTO (NAME, void, ())					\
++  {								\
++    register TTYPE1 z0 __asm ("z0");				\
++    register TTYPE2 z4 __asm ("z4");				\
++    register TTYPE1 z18 __asm ("z18");				\
++    register TTYPE2 z23 __asm ("z23");				\
++    register TTYPE1 z28 __asm ("z28");				\
++    __asm volatile ("" : "=w" (z0), "=w" (z4), "=w" (z18),	\
++		    "=w" (z23), "=w" (z28));			\
++    INVOKE (RES = CODE1, RES = CODE2);				\
++    __asm volatile ("" :: "w" (RES));				\
++  }
++
+ #endif
+-- 
+2.33.0
+
diff --git a/0171-Backport-SME-attribs-Use-existing-traits-for-excl_ha.patch b/0171-Backport-SME-attribs-Use-existing-traits-for-excl_ha.patch
new file mode 100644
index 0000000..ecd15bd
--- /dev/null
+++ b/0171-Backport-SME-attribs-Use-existing-traits-for-excl_ha.patch
@@ -0,0 +1,90 @@
+From 11f813112629dbad432134f7b4c7c9a93551eb3c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Mon, 27 Nov 2023 13:38:16 +0000
+Subject: [PATCH 072/157] [Backport][SME] attribs: Use existing traits for
+ excl_hash_traits
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5b33cf3a3a2025a4856f90fea8bd04884c2f6b31
+
+excl_hash_traits can be defined more simply by reusing existing traits.
+
+gcc/
+	* attribs.cc (excl_hash_traits): Delete.
+	(test_attribute_exclusions): Use pair_hash and nofree_string_hash
+	instead.
+---
+ gcc/attribs.cc | 45 +++------------------------------------------
+ 1 file changed, 3 insertions(+), 42 deletions(-)
+
+diff --git a/gcc/attribs.cc b/gcc/attribs.cc
+index b219f8780..16d05b1da 100644
+--- a/gcc/attribs.cc
++++ b/gcc/attribs.cc
+@@ -2555,47 +2555,6 @@ namespace selftest
+ 
+ typedef std::pair excl_pair;
+ 
+-struct excl_hash_traits: typed_noop_remove
+-{
+-  typedef excl_pair  value_type;
+-  typedef value_type compare_type;
+-
+-  static hashval_t hash (const value_type &x)
+-  {
+-    hashval_t h1 = htab_hash_string (x.first);
+-    hashval_t h2 = htab_hash_string (x.second);
+-    return h1 ^ h2;
+-  }
+-
+-  static bool equal (const value_type &x, const value_type &y)
+-  {
+-    return !strcmp (x.first, y.first) && !strcmp (x.second, y.second);
+-  }
+-
+-  static void mark_deleted (value_type &x)
+-  {
+-    x = value_type (NULL, NULL);
+-  }
+-
+-  static const bool empty_zero_p = false;
+-
+-  static void mark_empty (value_type &x)
+-  {
+-    x = value_type ("", "");
+-  }
+-
+-  static bool is_deleted (const value_type &x)
+-  {
+-    return !x.first && !x.second;
+-  }
+-
+-  static bool is_empty (const value_type &x)
+-  {
+-    return !*x.first && !*x.second;
+-  }
+-};
+-
+-
+ /* Self-test to verify that each attribute exclusion is symmetric,
+    meaning that if attribute A is encoded as incompatible with
+    attribute B then the opposite relationship is also encoded.
+@@ -2605,13 +2564,15 @@ struct excl_hash_traits: typed_noop_remove
+ static void
+ test_attribute_exclusions ()
+ {
++  using excl_hash_traits = pair_hash;
++
+   /* Iterate over the array of attribute tables first (with TI0 as
+      the index) and over the array of attribute_spec in each table
+      (with SI0 as the index).  */
+   const size_t ntables = ARRAY_SIZE (attribute_tables);
+ 
+   /* Set of pairs of mutually exclusive attributes.  */
+-  typedef hash_set exclusion_set;
++  typedef hash_set exclusion_set;
+   exclusion_set excl_set;
+ 
+   for (size_t ti0 = 0; ti0 != ntables; ++ti0)
+-- 
+2.33.0
+
diff --git a/0172-Backport-SME-Allow-target-attributes-in-non-gnu-name.patch b/0172-Backport-SME-Allow-target-attributes-in-non-gnu-name.patch
new file mode 100644
index 0000000..5f5b8f3
--- /dev/null
+++ b/0172-Backport-SME-Allow-target-attributes-in-non-gnu-name.patch
@@ -0,0 +1,2369 @@
+From 82d654912e3671055034e789a8f7110f6d87d447 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 2 Dec 2023 13:49:52 +0000
+Subject: [PATCH 073/157] [Backport][SME] Allow target attributes in non-gnu
+ namespaces
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7fa24687aa3a683fd105ce5ff6b176f48dca3b6c
+
+Currently there are four static sources of attributes:
+
+- LANG_HOOKS_ATTRIBUTE_TABLE
+- LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+- LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+- TARGET_ATTRIBUTE_TABLE
+
+All of the attributes in these tables go in the "gnu" namespace.
+This means that they can use the traditional GNU __attribute__((...))
+syntax and the standard [[gnu::...]] syntax.
+
+Standard attributes are registered dynamically with a null namespace.
+There are no supported attributes in other namespaces (clang, vendor
+namespaces, etc.).
+
+This patch tries to generalise things by making the namespace
+part of the attribute specification.
+
+It's usual for multiple attributes to be defined in the same namespace,
+so rather than adding the namespace to each individual definition,
+it seemed better to group attributes in the same namespace together.
+This would also allow us to reuse the same table for clang attributes
+that are written with the GNU syntax, or other similar situations
+where the attribute can be accessed via multiple "spellings".
+
+The patch therefore adds a scoped_attribute_specs that contains
+a namespace and a list of attributes in that namespace.
+
+It's still possible to have multiple scoped_attribute_specs
+for the same namespace.  E.g. it makes sense to keep the
+C++-specific, C/C++-common, and format-related attributes in
+separate tables, even though they're all GNU attributes.
+
+Current lists of attributes are terminated by a null name.
+Rather than keep that for the new structure, it seemed neater
+to use an array_slice.  This also makes the tables slighly more
+compact.
+
+In general, a target might want to support attributes in multiple
+namespaces.  Rather than have a separate hook for each possibility
+(like the three langhooks above), it seemed better to make
+TARGET_ATTRIBUTE_TABLE a table of tables.  Specifically, it's
+an array_slice of scoped_attribute_specs.
+
+We can do the same thing for langhooks, which allows the three hooks
+above to be merged into a single LANG_HOOKS_ATTRIBUTE_TABLE.
+It also allows the standard attributes to be registered statically
+and checked by the usual attribs.cc checks.
+
+The patch adds a TARGET_GNU_ATTRIBUTES helper for the common case
+in which a target wants a single table of gnu attributes.  It can
+only be used if the table is free of preprocessor directives.
+
+There are probably other things we need to do to make vendor namespaces
+work smoothly.  E.g. in principle it would be good to make exclusion
+sets namespace-aware.  But to some extent we have that with standard
+vs. gnu attributes too.  This patch is just supposed to be a first step.
+
+gcc/
+	* attribs.h (scoped_attribute_specs): New structure.
+	(register_scoped_attributes): Take a reference to a
+	scoped_attribute_specs instead of separate namespace and array
+	parameters.
+	* plugin.h (register_scoped_attributes): Likewise.
+	* attribs.cc (register_scoped_attributes): Likewise.
+	(attribute_tables): Change into an array of scoped_attribute_specs
+	pointers.  Reduce to 1 element for frontends and 1 element for targets.
+	(empty_attribute_table): Delete.
+	(check_attribute_tables): Update for changes to attribute_tables.
+	Use a hash_set to identify duplicates.
+	(handle_ignored_attributes_option): Update for above changes.
+	(init_attributes): Likewise.
+	(excl_pair): Delete.
+	(test_attribute_exclusions): Update for above changes.  Don't
+	enforce symmetry for standard attributes in the top-level namespace.
+	* langhooks-def.h (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Likewise.
+	(LANG_HOOKS_INITIALIZER): Update accordingly.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Define to an empty constructor.
+	* langhooks.h (lang_hooks::common_attribute_table): Delete.
+	(lang_hooks::format_attribute_table): Likewise.
+	(lang_hooks::attribute_table): Redefine to an array of
+	scoped_attribute_specs pointers.
+	* target-def.h (TARGET_GNU_ATTRIBUTES): New macro.
+	* target.def (attribute_spec): Redefine to return an array of
+	scoped_attribute_specs pointers.
+	* tree-inline.cc (function_attribute_inlinable_p): Update accordingly.
+	* doc/tm.texi: Regenerate.
+	* config/aarch64/aarch64.cc (aarch64_attribute_table): Define using
+	TARGET_GNU_ATTRIBUTES.
+	* config/alpha/alpha.cc (vms_attribute_table): Likewise.
+	* config/avr/avr.cc (avr_attribute_table): Likewise.
+	* config/bfin/bfin.cc (bfin_attribute_table): Likewise.
+	* config/bpf/bpf.cc (bpf_attribute_table): Likewise.
+	* config/csky/csky.cc (csky_attribute_table): Likewise.
+	* config/epiphany/epiphany.cc (epiphany_attribute_table): Likewise.
+	* config/gcn/gcn.cc (gcn_attribute_table): Likewise.
+	* config/h8300/h8300.cc (h8300_attribute_table): Likewise.
+	* config/loongarch/loongarch.cc (loongarch_attribute_table): Likewise.
+	* config/m32c/m32c.cc (m32c_attribute_table): Likewise.
+	* config/m32r/m32r.cc (m32r_attribute_table): Likewise.
+	* config/m68k/m68k.cc (m68k_attribute_table): Likewise.
+	* config/mcore/mcore.cc (mcore_attribute_table): Likewise.
+	* config/microblaze/microblaze.cc (microblaze_attribute_table):
+	Likewise.
+	* config/mips/mips.cc (mips_attribute_table): Likewise.
+	* config/msp430/msp430.cc (msp430_attribute_table): Likewise.
+	* config/nds32/nds32.cc (nds32_attribute_table): Likewise.
+	* config/nvptx/nvptx.cc (nvptx_attribute_table): Likewise.
+	* config/riscv/riscv.cc (riscv_attribute_table): Likewise.
+	* config/rl78/rl78.cc (rl78_attribute_table): Likewise.
+	* config/rx/rx.cc (rx_attribute_table): Likewise.
+	* config/s390/s390.cc (s390_attribute_table): Likewise.
+	* config/sh/sh.cc (sh_attribute_table): Likewise.
+	* config/sparc/sparc.cc (sparc_attribute_table): Likewise.
+	* config/stormy16/stormy16.cc (xstormy16_attribute_table): Likewise.
+	* config/v850/v850.cc (v850_attribute_table): Likewise.
+	* config/visium/visium.cc (visium_attribute_table): Likewise.
+	* config/arc/arc.cc (arc_attribute_table): Likewise.  Move further
+	down file.
+	* config/arm/arm.cc (arm_attribute_table): Update for above changes,
+	using...
+	(arm_gnu_attributes, arm_gnu_attribute_table): ...these new globals.
+	* config/i386/i386-options.h (ix86_attribute_table): Delete.
+	(ix86_gnu_attribute_table): Declare.
+	* config/i386/i386-options.cc (ix86_attribute_table): Replace with...
+	(ix86_gnu_attributes, ix86_gnu_attribute_table): ...these two globals.
+	* config/i386/i386.cc (ix86_attribute_table): Define as an array of
+	scoped_attribute_specs pointers.
+	* config/ia64/ia64.cc (ia64_attribute_table): Update for above changes,
+	using...
+	(ia64_gnu_attributes, ia64_gnu_attribute_table): ...these new globals.
+	* config/rs6000/rs6000.cc (rs6000_attribute_table): Update for above
+	changes, using...
+	(rs6000_gnu_attributes, rs6000_gnu_attribute_table): ...these new
+	globals.
+
+gcc/ada/
+	* gcc-interface/gigi.h (gnat_internal_attribute_table): Change
+	type to scoped_attribute_specs.
+	* gcc-interface/utils.cc (gnat_internal_attribute_table): Likewise,
+	using...
+	(gnat_internal_attributes): ...this as the underlying array.
+	* gcc-interface/misc.cc (gnat_attribute_table): New global.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Use it.
+
+gcc/c-family/
+	* c-common.h (c_common_attribute_table): Replace with...
+	(c_common_gnu_attribute_table): ...this.
+	(c_common_format_attribute_table): Change type to
+	scoped_attribute_specs.
+	* c-attribs.cc (c_common_attribute_table): Replace with...
+	(c_common_gnu_attributes, c_common_gnu_attribute_table): ...these
+	new globals.
+	(c_common_format_attribute_table): Change type to
+	scoped_attribute_specs, using...
+	(c_common_format_attributes): ...this as the underlying array.
+
+gcc/c/
+	* c-tree.h (std_attribute_table): Declare.
+	* c-decl.cc (std_attribute_table): Change type to
+	scoped_attribute_specs, using...
+	(std_attributes): ...this as the underlying array.
+	(c_init_decl_processing): Remove call to register_scoped_attributes.
+	* c-objc-common.h (c_objc_attribute_table): New global.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Use it.
+	(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
+
+gcc/cp/
+	* cp-tree.h (cxx_attribute_table): Delete.
+	(cxx_gnu_attribute_table, std_attribute_table): Declare.
+	* cp-objcp-common.h (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
+	(cp_objcp_attribute_table): New table.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Redefine.
+	* tree.cc (cxx_attribute_table): Replace with...
+	(cxx_gnu_attributes, cxx_gnu_attribute_table): ...these globals.
+	(std_attribute_table): Change type to scoped_attribute_specs, using...
+	(std_attributes): ...this as the underlying array.
+	(init_tree): Remove call to register_scoped_attributes.
+
+gcc/d/
+	* d-tree.h (d_langhook_attribute_table): Replace with...
+	(d_langhook_gnu_attribute_table): ...this.
+	(d_langhook_common_attribute_table): Change type to
+	scoped_attribute_specs.
+	* d-attribs.cc (d_langhook_common_attribute_table): Change type to
+	scoped_attribute_specs, using...
+	(d_langhook_common_attributes): ...this as the underlying array.
+	(d_langhook_attribute_table): Replace with...
+	(d_langhook_gnu_attributes, d_langhook_gnu_attribute_table): ...these
+	new globals.
+	(uda_attribute_p): Update accordingly, and update for new
+	targetm.attribute_table type.
+	* d-lang.cc (d_langhook_attribute_table): New global.
+	(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
+
+gcc/fortran/
+	* f95-lang.cc: Include attribs.h.
+	(gfc_attribute_table): Change to an array of scoped_attribute_specs
+	pointers, using...
+	(gfc_gnu_attributes, gfc_gnu_attribute_table): ...these new globals.
+
+gcc/jit/
+	* dummy-frontend.cc (jit_format_attribute_table): Change type to
+	scoped_attribute_specs, using...
+	(jit_format_attributes): ...this as the underlying array.
+	(jit_attribute_table): Change to an array of scoped_attribute_specs
+	pointers, using...
+	(jit_gnu_attributes, jit_gnu_attribute_table): ...these new globals
+	for the original array.  Include the format attributes.
+	(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Define.
+
+gcc/lto/
+	* lto-lang.cc (lto_format_attribute_table): Change type to
+	scoped_attribute_specs, using...
+	(lto_format_attributes): ...this as the underlying array.
+	(lto_attribute_table): Change to an array of scoped_attribute_specs
+	pointers, using...
+	(lto_gnu_attributes, lto_gnu_attribute_table): ...these new globals
+	for the original array.  Include the format attributes.
+	(LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Delete.
+	(LANG_HOOKS_ATTRIBUTE_TABLE): Define.
+---
+ gcc/ada/gcc-interface/gigi.h        |   2 +-
+ gcc/ada/gcc-interface/misc.cc       |   7 +-
+ gcc/ada/gcc-interface/utils.cc      |   8 +-
+ gcc/attribs.cc                      | 221 ++++++++++++----------------
+ gcc/attribs.h                       |  12 +-
+ gcc/c-family/c-attribs.cc           |  20 ++-
+ gcc/c-family/c-common.h             |   4 +-
+ gcc/c/c-decl.cc                     |  12 +-
+ gcc/c/c-objc-common.h               |  14 +-
+ gcc/c/c-tree.h                      |   2 +
+ gcc/config/aarch64/aarch64.cc       |   7 +-
+ gcc/config/alpha/alpha.cc           |   7 +-
+ gcc/config/arc/arc.cc               |  74 +++++-----
+ gcc/config/arm/arm.cc               |  15 +-
+ gcc/config/avr/avr.cc               |   7 +-
+ gcc/config/bfin/bfin.cc             |   7 +-
+ gcc/config/bpf/bpf.cc               |   9 +-
+ gcc/config/csky/csky.cc             |   7 +-
+ gcc/config/epiphany/epiphany.cc     |   7 +-
+ gcc/config/gcn/gcn.cc               |   8 +-
+ gcc/config/h8300/h8300.cc           |   7 +-
+ gcc/config/i386/i386-options.cc     |  10 +-
+ gcc/config/i386/i386-options.h      |   2 +-
+ gcc/config/i386/i386.cc             |   5 +
+ gcc/config/ia64/ia64.cc             |  15 +-
+ gcc/config/m32c/m32c.cc             |   7 +-
+ gcc/config/m32r/m32r.cc             |   7 +-
+ gcc/config/m68k/m68k.cc             |   7 +-
+ gcc/config/mcore/mcore.cc           |   7 +-
+ gcc/config/microblaze/microblaze.cc |   7 +-
+ gcc/config/mips/mips.cc             |   7 +-
+ gcc/config/msp430/msp430.cc         |   8 +-
+ gcc/config/nds32/nds32.cc           |   9 +-
+ gcc/config/nvptx/nvptx.cc           |   7 +-
+ gcc/config/riscv/riscv.cc           |   9 +-
+ gcc/config/rl78/rl78.cc             |   7 +-
+ gcc/config/rs6000/rs6000.cc         |  13 +-
+ gcc/config/rx/rx.cc                 |   7 +-
+ gcc/config/s390/s390.cc             |   9 +-
+ gcc/config/sh/sh.cc                 |   7 +-
+ gcc/config/sparc/sparc.cc           |   7 +-
+ gcc/config/stormy16/stormy16.cc     |   7 +-
+ gcc/config/v850/v850.cc             |   7 +-
+ gcc/config/visium/visium.cc         |   7 +-
+ gcc/cp/cp-objcp-common.h            |  15 +-
+ gcc/cp/cp-tree.h                    |   3 +-
+ gcc/cp/tree.cc                      |  16 +-
+ gcc/d/d-attribs.cc                  |  35 ++---
+ gcc/d/d-lang.cc                     |   8 +-
+ gcc/d/d-tree.h                      |   4 +-
+ gcc/doc/tm.texi                     |  33 ++++-
+ gcc/fortran/f95-lang.cc             |  14 +-
+ gcc/jit/dummy-frontend.cc           |  32 ++--
+ gcc/langhooks-def.h                 |   6 +-
+ gcc/langhooks.h                     |   4 +-
+ gcc/lto/lto-lang.cc                 |  30 ++--
+ gcc/plugin.h                        |   3 +-
+ gcc/target-def.h                    |  14 ++
+ gcc/target.def                      |  35 ++++-
+ gcc/tree-inline.cc                  |   7 +-
+ 60 files changed, 491 insertions(+), 403 deletions(-)
+
+diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
+index bd559d176..6ababfcbb 100644
+--- a/gcc/ada/gcc-interface/gigi.h
++++ b/gcc/ada/gcc-interface/gigi.h
+@@ -349,7 +349,7 @@ struct attrib
+ };
+ 
+ /* Table of machine-independent internal attributes.  */
+-extern const struct attribute_spec gnat_internal_attribute_table[];
++extern const struct scoped_attribute_specs gnat_internal_attribute_table;
+ 
+ /* Define the entries in the standard data array.  */
+ enum standard_datatypes
+diff --git a/gcc/ada/gcc-interface/misc.cc b/gcc/ada/gcc-interface/misc.cc
+index 2caa83ff8..8dd055772 100644
+--- a/gcc/ada/gcc-interface/misc.cc
++++ b/gcc/ada/gcc-interface/misc.cc
+@@ -1339,6 +1339,11 @@ get_lang_specific (tree node)
+   return TYPE_LANG_SPECIFIC (node);
+ }
+ 
++const struct scoped_attribute_specs *const gnat_attribute_table[] =
++{
++  &gnat_internal_attribute_table
++};
++
+ /* Definitions for our language-specific hooks.  */
+ 
+ #undef  LANG_HOOKS_NAME
+@@ -1404,7 +1409,7 @@ get_lang_specific (tree node)
+ #undef  LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO
+ #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO gnat_get_fixed_point_type_info
+ #undef  LANG_HOOKS_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_ATTRIBUTE_TABLE	gnat_internal_attribute_table
++#define LANG_HOOKS_ATTRIBUTE_TABLE	gnat_attribute_table
+ #undef  LANG_HOOKS_BUILTIN_FUNCTION
+ #define LANG_HOOKS_BUILTIN_FUNCTION	gnat_builtin_function
+ #undef  LANG_HOOKS_INIT_TS
+diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
+index 049cf74eb..ef8524fa9 100644
+--- a/gcc/ada/gcc-interface/utils.cc
++++ b/gcc/ada/gcc-interface/utils.cc
+@@ -134,7 +134,7 @@ static tree fake_attribute_handler (tree *, tree, tree, int, bool *);
+ 
+ /* Table of machine-independent internal attributes for Ada.  We support
+    this minimal set of attributes to accommodate the needs of builtins.  */
+-const struct attribute_spec gnat_internal_attribute_table[] =
++static const attribute_spec gnat_internal_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -207,9 +207,11 @@ const struct attribute_spec gnat_internal_attribute_table[] =
+     fake_attribute_handler, NULL },
+   { "format_arg",   1, 1,  false, true,  true,  false,
+     fake_attribute_handler, NULL },
++};
+ 
+-  { NULL,           0, 0,  false, false, false, false,
+-    NULL, NULL }
++const scoped_attribute_specs gnat_internal_attribute_table =
++{
++  "gnu", gnat_internal_attributes
+ };
+ 
+ /* Associates a GNAT tree node to a GCC tree node. It is used in
+diff --git a/gcc/attribs.cc b/gcc/attribs.cc
+index 16d05b1da..656ea739e 100644
+--- a/gcc/attribs.cc
++++ b/gcc/attribs.cc
+@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ /* Table of the tables of attributes (common, language, format, machine)
+    searched.  */
+-static const struct attribute_spec *attribute_tables[4];
++static array_slice attribute_tables[2];
+ 
+ /* Substring representation.  */
+ 
+@@ -102,13 +102,6 @@ static const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
+ 
+ static bool attributes_initialized = false;
+ 
+-/* Default empty table of attributes.  */
+-
+-static const struct attribute_spec empty_attribute_table[] =
+-{
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+-};
+-
+ /* Return base name of the attribute.  Ie '__attr__' is turned into 'attr'.
+    To avoid need for copying, we simply return length of the string.  */
+ 
+@@ -118,21 +111,19 @@ extract_attribute_substring (struct substring *str)
+   canonicalize_attr_name (str->str, str->length);
+ }
+ 
+-/* Insert an array of attributes ATTRIBUTES into a namespace.  This
+-   array must be NULL terminated.  NS is the name of attribute
+-   namespace.  IGNORED_P is true iff all unknown attributes in this
+-   namespace should be ignored for the purposes of -Wattributes.  The
+-   function returns the namespace into which the attributes have been
+-   registered.  */
++/* Insert SPECS into its namespace.  IGNORED_P is true iff all unknown
++   attributes in this namespace should be ignored for the purposes of
++   -Wattributes.  The function returns the namespace into which the
++   attributes have been registered.  */
+ 
+ scoped_attributes *
+-register_scoped_attributes (const struct attribute_spec *attributes,
+-			    const char *ns, bool ignored_p /*=false*/)
++register_scoped_attributes (const scoped_attribute_specs &specs,
++			    bool ignored_p /*=false*/)
+ {
+   scoped_attributes *result = NULL;
+ 
+   /* See if we already have attributes in the namespace NS.  */
+-  result = find_attribute_namespace (ns);
++  result = find_attribute_namespace (specs.ns);
+ 
+   if (result == NULL)
+     {
+@@ -143,7 +134,7 @@ register_scoped_attributes (const struct attribute_spec *attributes,
+ 	attributes_table.create (64);
+ 
+       memset (&sa, 0, sizeof (sa));
+-      sa.ns = ns;
++      sa.ns = specs.ns;
+       sa.attributes.create (64);
+       sa.ignored_p = ignored_p;
+       result = attributes_table.safe_push (sa);
+@@ -153,10 +144,10 @@ register_scoped_attributes (const struct attribute_spec *attributes,
+     result->ignored_p |= ignored_p;
+ 
+   /* Really add the attributes to their namespace now.  */
+-  for (unsigned i = 0; attributes[i].name != NULL; ++i)
++  for (const attribute_spec &attribute : specs.attributes)
+     {
+-      result->attributes.safe_push (attributes[i]);
+-      register_scoped_attribute (&attributes[i], result);
++      result->attributes.safe_push (attribute);
++      register_scoped_attribute (&attribute, result);
+     }
+ 
+   gcc_assert (result != NULL);
+@@ -183,49 +174,40 @@ find_attribute_namespace (const char* ns)
+ static void
+ check_attribute_tables (void)
+ {
+-  for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
+-    for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
+-      {
+-	/* The name must not begin and end with __.  */
+-	const char *name = attribute_tables[i][j].name;
+-	int len = strlen (name);
++  hash_set> names;
+ 
+-	gcc_assert (!(name[0] == '_' && name[1] == '_'
+-		      && name[len - 1] == '_' && name[len - 2] == '_'));
++  for (auto scoped_array : attribute_tables)
++    for (auto scoped_attributes : scoped_array)
++      for (const attribute_spec &attribute : scoped_attributes->attributes)
++	{
++	  /* The name must not begin and end with __.  */
++	  const char *name = attribute.name;
++	  int len = strlen (name);
++
++	  gcc_assert (!(name[0] == '_' && name[1] == '_'
++			&& name[len - 1] == '_' && name[len - 2] == '_'));
+ 
+-	/* The minimum and maximum lengths must be consistent.  */
+-	gcc_assert (attribute_tables[i][j].min_length >= 0);
++	  /* The minimum and maximum lengths must be consistent.  */
++	  gcc_assert (attribute.min_length >= 0);
+ 
+-	gcc_assert (attribute_tables[i][j].max_length == -1
+-		    || (attribute_tables[i][j].max_length
+-			>= attribute_tables[i][j].min_length));
++	  gcc_assert (attribute.max_length == -1
++		      || attribute.max_length >= attribute.min_length);
+ 
+-	/* An attribute cannot require both a DECL and a TYPE.  */
+-	gcc_assert (!attribute_tables[i][j].decl_required
+-		    || !attribute_tables[i][j].type_required);
++	  /* An attribute cannot require both a DECL and a TYPE.  */
++	  gcc_assert (!attribute.decl_required
++		      || !attribute.type_required);
+ 
+ 	  /* If an attribute requires a function type, in particular
+ 	     it requires a type.  */
+-	gcc_assert (!attribute_tables[i][j].function_type_required
+-		    || attribute_tables[i][j].type_required);
+-      }
+-
+-  /* Check that each name occurs just once in each table.  */
+-  for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
+-    for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
+-      for (size_t k = j + 1; attribute_tables[i][k].name != NULL; k++)
+-	gcc_assert (strcmp (attribute_tables[i][j].name,
+-			    attribute_tables[i][k].name));
+-
+-  /* Check that no name occurs in more than one table.  Names that
+-     begin with '*' are exempt, and may be overridden.  */
+-  for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
+-    for (size_t j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
+-      for (size_t k = 0; attribute_tables[i][k].name != NULL; k++)
+-	for (size_t l = 0; attribute_tables[j][l].name != NULL; l++)
+-	  gcc_assert (attribute_tables[i][k].name[0] == '*'
+-		      || strcmp (attribute_tables[i][k].name,
+-				 attribute_tables[j][l].name));
++	  gcc_assert (!attribute.function_type_required
++		      || attribute.type_required);
++
++	  /* Check that no name occurs more than once.  Names that
++	     begin with '*' are exempt, and may be overridden.  */
++	  const char *ns = scoped_attributes->ns;
++	  if (name[0] != '*' && names.add ({ ns ? ns : "", name }))
++	    gcc_unreachable ();
++	}
+ }
+ 
+ /* Used to stash pointers to allocated memory so that we can free them at
+@@ -280,7 +262,7 @@ handle_ignored_attributes_option (vec *v)
+       canonicalize_attr_name (vendor_start, vendor_len);
+       /* We perform all this hijinks so that we don't have to copy OPT.  */
+       tree vendor_id = get_identifier_with_length (vendor_start, vendor_len);
+-      const char *attr;
++      array_slice attrs;
+       /* In the "vendor::" case, we should ignore *any* attribute coming
+ 	 from this attribute namespace.  */
+       if (attr_len > 0)
+@@ -292,22 +274,23 @@ handle_ignored_attributes_option (vec *v)
+ 	    }
+ 	  canonicalize_attr_name (attr_start, attr_len);
+ 	  tree attr_id = get_identifier_with_length (attr_start, attr_len);
+-	  attr = IDENTIFIER_POINTER (attr_id);
++	  const char *attr = IDENTIFIER_POINTER (attr_id);
+ 	  /* If we've already seen this vendor::attr, ignore it.  Attempting to
+ 	     register it twice would lead to a crash.  */
+ 	  if (lookup_scoped_attribute_spec (vendor_id, attr_id))
+ 	    continue;
++	  /* Create a table with extra attributes which we will register.
++	     We can't free it here, so squirrel away the pointers.  */
++	  attribute_spec *table = new attribute_spec {
++	    attr, 0, -2, false, false, false, false, nullptr, nullptr
++	  };
++	  ignored_attributes_table.safe_push (table);
++	  attrs = { table, 1 };
+ 	}
+-      else
+-	attr = nullptr;
+-      /* Create a table with extra attributes which we will register.
+-	 We can't free it here, so squirrel away the pointers.  */
+-      attribute_spec *table = new attribute_spec[2];
+-      ignored_attributes_table.safe_push (table);
+-      table[0] = { attr, 0, -2, false, false, false, false, nullptr, nullptr };
+-      table[1] = { nullptr, 0, 0, false, false, false, false, nullptr,
+-		   nullptr };
+-      register_scoped_attributes (table, IDENTIFIER_POINTER (vendor_id), !attr);
++      const scoped_attribute_specs scoped_specs = {
++	IDENTIFIER_POINTER (vendor_id), attrs
++      };
++      register_scoped_attributes (scoped_specs, attrs.empty ());
+     }
+ }
+ 
+@@ -327,27 +310,18 @@ free_attr_data ()
+ void
+ init_attributes (void)
+ {
+-  size_t i;
+-
+   if (attributes_initialized)
+     return;
+ 
+-  attribute_tables[0] = lang_hooks.common_attribute_table;
+-  attribute_tables[1] = lang_hooks.attribute_table;
+-  attribute_tables[2] = lang_hooks.format_attribute_table;
+-  attribute_tables[3] = targetm.attribute_table;
+-
+-  /* Translate NULL pointers to pointers to the empty table.  */
+-  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
+-    if (attribute_tables[i] == NULL)
+-      attribute_tables[i] = empty_attribute_table;
++  attribute_tables[0] = lang_hooks.attribute_table;
++  attribute_tables[1] = targetm.attribute_table;
+ 
+   if (flag_checking)
+     check_attribute_tables ();
+ 
+-  for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
+-    /* Put all the GNU attributes into the "gnu" namespace.  */
+-    register_scoped_attributes (attribute_tables[i], "gnu");
++  for (auto scoped_array : attribute_tables)
++    for (auto scoped_attributes : scoped_array)
++      register_scoped_attributes (*scoped_attributes);
+ 
+   vec *ignored = (vec *) flag_ignored_attributes;
+   handle_ignored_attributes_option (ignored);
+@@ -2551,10 +2525,6 @@ attr_access::array_as_string (tree type) const
+ namespace selftest
+ {
+ 
+-/* Helper types to verify the consistency attribute exclusions.  */
+-
+-typedef std::pair excl_pair;
+-
+ /* Self-test to verify that each attribute exclusion is symmetric,
+    meaning that if attribute A is encoded as incompatible with
+    attribute B then the opposite relationship is also encoded.
+@@ -2569,55 +2539,54 @@ test_attribute_exclusions ()
+   /* Iterate over the array of attribute tables first (with TI0 as
+      the index) and over the array of attribute_spec in each table
+      (with SI0 as the index).  */
+-  const size_t ntables = ARRAY_SIZE (attribute_tables);
++  hash_set excl_set;
+ 
+-  /* Set of pairs of mutually exclusive attributes.  */
+-  typedef hash_set exclusion_set;
+-  exclusion_set excl_set;
++  for (auto scoped_array : attribute_tables)
++    for (auto scoped_attributes : scoped_array)
++      for (const attribute_spec &attribute : scoped_attributes->attributes)
++	{
++	  const attribute_spec::exclusions *excl = attribute.exclude;
+ 
+-  for (size_t ti0 = 0; ti0 != ntables; ++ti0)
+-    for (size_t s0 = 0; attribute_tables[ti0][s0].name; ++s0)
+-      {
+-	const attribute_spec::exclusions *excl
+-	  = attribute_tables[ti0][s0].exclude;
++	  /* Skip each attribute that doesn't define exclusions.  */
++	  if (!excl)
++	    continue;
+ 
+-	/* Skip each attribute that doesn't define exclusions.  */
+-	if (!excl)
+-	  continue;
++	  /* Skip standard (non-GNU) attributes, since currently the
++	     exclusions are implicitly for GNU attributes only.
++	     Also, C++ likely and unlikely get rewritten to gnu::hot
++	     and gnu::cold, so symmetry isn't necessary there.  */
++	  if (!scoped_attributes->ns)
++	    continue;
+ 
+-	const char *attr_name = attribute_tables[ti0][s0].name;
++	  const char *attr_name = attribute.name;
+ 
+-	/* Iterate over the set of exclusions for every attribute
+-	   (with EI0 as the index) adding the exclusions defined
+-	   for each to the set.  */
+-	for (size_t ei0 = 0; excl[ei0].name; ++ei0)
+-	  {
+-	    const char *excl_name = excl[ei0].name;
++	  /* Iterate over the set of exclusions for every attribute
++	     (with EI0 as the index) adding the exclusions defined
++	     for each to the set.  */
++	  for (size_t ei0 = 0; excl[ei0].name; ++ei0)
++	    {
++	      const char *excl_name = excl[ei0].name;
+ 
+-	    if (!strcmp (attr_name, excl_name))
+-	      continue;
++	      if (!strcmp (attr_name, excl_name))
++		continue;
+ 
+-	    excl_set.add (excl_pair (attr_name, excl_name));
+-	  }
+-      }
++	      excl_set.add ({ attr_name, excl_name });
++	    }
++	}
+ 
+   /* Traverse the set of mutually exclusive pairs of attributes
+      and verify that they are symmetric.  */
+-  for (exclusion_set::iterator it = excl_set.begin ();
+-       it != excl_set.end ();
+-       ++it)
+-    {
+-      if (!excl_set.contains (excl_pair ((*it).second, (*it).first)))
+-	{
+-	  /* An exclusion for an attribute has been found that
+-	     doesn't have a corresponding exclusion in the opposite
+-	     direction.  */
+-	  char desc[120];
+-	  sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
+-		   (*it).first, (*it).second);
+-	  fail (SELFTEST_LOCATION, desc);
+-	}
+-    }
++  for (auto excl_pair : excl_set)
++    if (!excl_set.contains ({ excl_pair.second, excl_pair.first }))
++      {
++	/* An exclusion for an attribute has been found that
++	   doesn't have a corresponding exclusion in the opposite
++	   direction.  */
++	char desc[120];
++	sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
++		 excl_pair.first, excl_pair.second);
++	fail (SELFTEST_LOCATION, desc);
++      }
+ }
+ 
+ void
+diff --git a/gcc/attribs.h b/gcc/attribs.h
+index 5b6f63ede..0856f98fb 100644
+--- a/gcc/attribs.h
++++ b/gcc/attribs.h
+@@ -20,6 +20,13 @@ along with GCC; see the file COPYING3.  If not see
+ #ifndef GCC_ATTRIBS_H
+ #define GCC_ATTRIBS_H
+ 
++/* A set of attributes that belong to the same namespace, given by NS.  */
++struct scoped_attribute_specs
++{
++  const char *ns;
++  array_slice attributes;
++};
++
+ extern const struct attribute_spec *lookup_attribute_spec (const_tree);
+ extern void free_attr_data ();
+ extern void init_attributes (void);
+@@ -42,9 +49,8 @@ extern tree make_attribute (const char *, const char *, tree);
+ extern bool attribute_ignored_p (tree);
+ extern bool attribute_ignored_p (const attribute_spec *const);
+ 
+-extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
+-							     const char *,
+-							     bool = false);
++extern struct scoped_attributes *
++  register_scoped_attributes (const scoped_attribute_specs &, bool = false);
+ 
+ extern char *sorted_attr_string (tree);
+ extern bool common_function_versions (tree, tree);
+diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
+index 111a33f40..d5c0392b7 100644
+--- a/gcc/c-family/c-attribs.cc
++++ b/gcc/c-family/c-attribs.cc
+@@ -282,7 +282,7 @@ static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
+ /* Table of machine-independent attributes common to all C-like languages.
+ 
+    Current list of processed common attributes: nonnull.  */
+-const struct attribute_spec c_common_attribute_table[] =
++const struct attribute_spec c_common_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -554,23 +554,31 @@ const struct attribute_spec c_common_attribute_table[] =
+   { "*dealloc",                1, 2, true, false, false, false,
+ 			      handle_dealloc_attribute, NULL },
+   { "tainted_args",	      0, 0, true,  false, false, false,
+-			      handle_tainted_args_attribute, NULL },
+-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
++			      handle_tainted_args_attribute, NULL }
++};
++
++const struct scoped_attribute_specs c_common_gnu_attribute_table =
++{
++  "gnu", c_common_gnu_attributes
+ };
+ 
+ /* Give the specifications for the format attributes, used by C and all
+    descendants.
+ 
+    Current list of processed format attributes: format, format_arg.  */
+-const struct attribute_spec c_common_format_attribute_table[] =
++const struct attribute_spec c_common_format_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "format",                 3, 3, false, true,  true, false,
+ 			      handle_format_attribute, NULL },
+   { "format_arg",             1, 1, false, true,  true, false,
+-			      handle_format_arg_attribute, NULL },
+-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
++			      handle_format_arg_attribute, NULL }
++};
++
++const struct scoped_attribute_specs c_common_format_attribute_table =
++{
++  "gnu", c_common_format_attributes
+ };
+ 
+ /* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
+diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
+index 3d5b9c40e..d1503c5a7 100644
+--- a/gcc/c-family/c-common.h
++++ b/gcc/c-family/c-common.h
+@@ -819,8 +819,8 @@ enum conversion_safety {
+ extern struct visibility_flags visibility_options;
+ 
+ /* Attribute table common to the C front ends.  */
+-extern const struct attribute_spec c_common_attribute_table[];
+-extern const struct attribute_spec c_common_format_attribute_table[];
++extern const struct scoped_attribute_specs c_common_gnu_attribute_table;
++extern const struct scoped_attribute_specs c_common_format_attribute_table;
+ 
+ /* Pointer to function to lazily generate the VAR_DECL for __FUNCTION__ etc.
+    ID is the identifier to use, NAME is the string.
+diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
+index 619a20909..9d87a8cdb 100644
+--- a/gcc/c/c-decl.cc
++++ b/gcc/c/c-decl.cc
+@@ -4460,7 +4460,7 @@ handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
+   return NULL_TREE;
+ }
+ /* Table of supported standard (C2x) attributes.  */
+-const struct attribute_spec std_attribute_table[] =
++static const attribute_spec std_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -4471,8 +4471,12 @@ const struct attribute_spec std_attribute_table[] =
+   { "maybe_unused", 0, 0, false, false, false, false,
+     handle_unused_attribute, NULL },
+   { "nodiscard", 0, 1, false, false, false, false,
+-    handle_nodiscard_attribute, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
++    handle_nodiscard_attribute, NULL }
++};
++
++const scoped_attribute_specs std_attribute_table =
++{
++  nullptr, std_attributes
+ };
+ 
+ /* Create the predefined scalar types of C,
+@@ -4488,8 +4492,6 @@ c_init_decl_processing (void)
+   /* Initialize reserved words for parser.  */
+   c_parse_init ();
+ 
+-  register_scoped_attributes (std_attribute_table, NULL);
+-
+   current_function_decl = NULL_TREE;
+ 
+   gcc_obstack_init (&parser_obstack);
+diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h
+index 0b60df975..bc3dded23 100644
+--- a/gcc/c/c-objc-common.h
++++ b/gcc/c/c-objc-common.h
+@@ -70,11 +70,15 @@ along with GCC; see the file COPYING3.  If not see
+ #undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
+ #define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
+ 
+-/* Attribute hooks.  */
+-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
++static const scoped_attribute_specs *const c_objc_attribute_table[] =
++{
++  &std_attribute_table,
++  &c_common_gnu_attribute_table,
++  &c_common_format_attribute_table
++};
++
++#undef LANG_HOOKS_ATTRIBUTE_TABLE
++#define LANG_HOOKS_ATTRIBUTE_TABLE c_objc_attribute_table
+ 
+ #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
+ #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
+diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
+index c70f0ba5a..654bd4094 100644
+--- a/gcc/c/c-tree.h
++++ b/gcc/c/c-tree.h
+@@ -835,6 +835,8 @@ set_c_expr_source_range (c_expr *expr,
+ /* In c-fold.cc */
+ extern vec incomplete_record_decls;
+ 
++extern const struct scoped_attribute_specs std_attribute_table;
++
+ #if CHECKING_P
+ namespace selftest {
+   extern void run_c_tests (void);
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 4194dfc70..114252a3c 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2986,7 +2986,7 @@ handle_aarch64_vector_pcs_attribute (tree *node, tree name, tree,
+ }
+ 
+ /* Table of machine attributes.  */
+-static const struct attribute_spec aarch64_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (aarch64_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -2997,9 +2997,8 @@ static const struct attribute_spec aarch64_attribute_table[] =
+ 			  NULL },
+   { "Advanced SIMD type", 1, 1, false, true,  false, true,  NULL, NULL },
+   { "SVE type",		  3, 3, false, true,  false, true,  NULL, NULL },
+-  { "SVE sizeless type",  0, 0, false, true,  false, true,  NULL, NULL },
+-  { NULL,                 0, 0, false, false, false, false, NULL, NULL }
+-};
++  { "SVE sizeless type",  0, 0, false, true,  false, true,  NULL, NULL }
++});
+ 
+ /* An ISA extension in the co-processor and main instruction set space.  */
+ struct aarch64_option_extension
+diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
+index 66c17149d..7fb491918 100644
+--- a/gcc/config/alpha/alpha.cc
++++ b/gcc/config/alpha/alpha.cc
+@@ -7475,14 +7475,13 @@ common_object_handler (tree *node, tree name ATTRIBUTE_UNUSED,
+   return NULL_TREE;
+ }
+ 
+-static const struct attribute_spec vms_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (vms_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { COMMON_OBJECT,   0, 1, true,  false, false, false, common_object_handler,
+-    NULL },
+-  { NULL,            0, 0, false, false, false, false, NULL, NULL }
+-};
++    NULL }
++});
+ 
+ void
+ vms_output_aligned_decl_common(FILE *file, tree decl, const char *name,
+diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
+index fbc17e684..1c6adcab4 100644
+--- a/gcc/config/arc/arc.cc
++++ b/gcc/config/arc/arc.cc
+@@ -230,44 +230,6 @@ static tree arc_handle_secure_attribute (tree *, tree, tree, int, bool *);
+ static tree arc_handle_uncached_attribute (tree *, tree, tree, int, bool *);
+ static tree arc_handle_aux_attribute (tree *, tree, tree, int, bool *);
+ 
+-/* Initialized arc_attribute_table to NULL since arc doesnot have any
+-   machine specific supported attributes.  */
+-const struct attribute_spec arc_attribute_table[] =
+-{
+- /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+-      affects_type_identity, handler, exclude } */
+-  { "interrupt", 1, 1, true, false, false, true,
+-    arc_handle_interrupt_attribute, NULL },
+-  /* Function calls made to this symbol must be done indirectly, because
+-     it may lie outside of the 21/25 bit addressing range of a normal function
+-     call.  */
+-  { "long_call",    0, 0, false, true,  true,  false, NULL, NULL },
+-  /* Whereas these functions are always known to reside within the 25 bit
+-     addressing range of unconditionalized bl.  */
+-  { "medium_call",   0, 0, false, true,  true, false, NULL, NULL },
+-  /* And these functions are always known to reside within the 21 bit
+-     addressing range of blcc.  */
+-  { "short_call",   0, 0, false, true,  true,  false, NULL, NULL },
+-  /* Function which are not having the prologue and epilogue generated
+-     by the compiler.  */
+-  { "naked", 0, 0, true, false, false,  false, arc_handle_fndecl_attribute,
+-    NULL },
+-  /* Functions calls made using jli instruction.  The pointer in JLI
+-     table is found latter.  */
+-  { "jli_always",    0, 0, false, true,  true, false,  NULL, NULL },
+-  /* Functions calls made using jli instruction.  The pointer in JLI
+-     table is given as input parameter.  */
+-  { "jli_fixed",    1, 1, false, true,  true, false, arc_handle_jli_attribute,
+-    NULL },
+-  /* Call a function using secure-mode.  */
+-  { "secure_call",  1, 1, false, true, true, false, arc_handle_secure_attribute,
+-    NULL },
+-   /* Bypass caches using .di flag.  */
+-  { "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute,
+-    NULL },
+-  { "aux", 0, 1, true, false, false, false, arc_handle_aux_attribute, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+-};
+ static int arc_comp_type_attributes (const_tree, const_tree);
+ static void arc_file_start (void);
+ static void arc_internal_label (FILE *, const char *, unsigned long);
+@@ -819,6 +781,42 @@ static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode);
+ 
+ #include "target-def.h"
+ 
++TARGET_GNU_ATTRIBUTES (arc_attribute_table,
++{
++ /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
++      affects_type_identity, handler, exclude } */
++  { "interrupt", 1, 1, true, false, false, true,
++    arc_handle_interrupt_attribute, NULL },
++  /* Function calls made to this symbol must be done indirectly, because
++     it may lie outside of the 21/25 bit addressing range of a normal function
++     call.  */
++  { "long_call",    0, 0, false, true,  true,  false, NULL, NULL },
++  /* Whereas these functions are always known to reside within the 25 bit
++     addressing range of unconditionalized bl.  */
++  { "medium_call",   0, 0, false, true,  true, false, NULL, NULL },
++  /* And these functions are always known to reside within the 21 bit
++     addressing range of blcc.  */
++  { "short_call",   0, 0, false, true,  true,  false, NULL, NULL },
++  /* Function which are not having the prologue and epilogue generated
++     by the compiler.  */
++  { "naked", 0, 0, true, false, false,  false, arc_handle_fndecl_attribute,
++    NULL },
++  /* Functions calls made using jli instruction.  The pointer in JLI
++     table is found latter.  */
++  { "jli_always",    0, 0, false, true,  true, false,  NULL, NULL },
++  /* Functions calls made using jli instruction.  The pointer in JLI
++     table is given as input parameter.  */
++  { "jli_fixed",    1, 1, false, true,  true, false, arc_handle_jli_attribute,
++    NULL },
++  /* Call a function using secure-mode.  */
++  { "secure_call",  1, 1, false, true, true, false, arc_handle_secure_attribute,
++    NULL },
++   /* Bypass caches using .di flag.  */
++  { "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute,
++    NULL },
++  { "aux", 0, 1, true, false, false, false, arc_handle_aux_attribute, NULL }
++});
++
+ #undef TARGET_ASM_ALIGNED_HI_OP
+ #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
+ #undef TARGET_ASM_ALIGNED_SI_OP
+diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
+index c72e9c0b0..3bdc7e18e 100644
+--- a/gcc/config/arm/arm.cc
++++ b/gcc/config/arm/arm.cc
+@@ -329,7 +329,7 @@ static rtx_insn *thumb1_md_asm_adjust (vec &, vec &,
+ static const char *arm_identify_fpu_from_isa (sbitmap);
+ 
+ /* Table of machine attributes.  */
+-static const struct attribute_spec arm_attribute_table[] =
++static const attribute_spec arm_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -377,8 +377,17 @@ static const struct attribute_spec arm_attribute_table[] =
+     arm_handle_cmse_nonsecure_entry, NULL },
+   { "cmse_nonsecure_call", 0, 0, true, false, false, true,
+     arm_handle_cmse_nonsecure_call, NULL },
+-  { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
++  { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL }
++};
++
++static const scoped_attribute_specs arm_gnu_attribute_table =
++{
++  "gnu", arm_gnu_attributes
++};
++
++static const scoped_attribute_specs *const arm_attribute_table[] =
++{
++  &arm_gnu_attribute_table
+ };
+ 
+ /* Initialize the GCC target structure.  */
+diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
+index 1b5a95410..7b37278ca 100644
+--- a/gcc/config/avr/avr.cc
++++ b/gcc/config/avr/avr.cc
+@@ -9723,7 +9723,7 @@ avr_eval_addr_attrib (rtx x)
+ 
+ 
+ /* AVR attributes.  */
+-static const struct attribute_spec avr_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (avr_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -9748,9 +9748,8 @@ static const struct attribute_spec avr_attribute_table[] =
+   { "address",   1, 1, true, false, false,  false,
+     avr_handle_addr_attribute, NULL },
+   { "absdata",   0, 0, true, false, false,  false,
+-    avr_handle_absdata_attribute, NULL },
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+-};
++    avr_handle_absdata_attribute, NULL }
++});
+ 
+ 
+ /* Return true if we support address space AS for the architecture in effect
+diff --git a/gcc/config/bfin/bfin.cc b/gcc/config/bfin/bfin.cc
+index b2a9142f5..fbc5c84d1 100644
+--- a/gcc/config/bfin/bfin.cc
++++ b/gcc/config/bfin/bfin.cc
+@@ -4895,7 +4895,7 @@ bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
+ }
+ 
+ /* Table of valid machine attributes.  */
+-static const struct attribute_spec bfin_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (bfin_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -4920,9 +4920,8 @@ static const struct attribute_spec bfin_attribute_table[] =
+     bfin_handle_l1_data_attribute, NULL },
+   { "l1_data_B", 0, 0, true, false, false, false,
+     bfin_handle_l1_data_attribute, NULL },
+-  { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+-};
++  { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL }
++});
+ 
+ /* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
+    tell the assembler to generate pointers to function descriptors in
+diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
+index 6a0e3bbca..0343af9c7 100644
+--- a/gcc/config/bpf/bpf.cc
++++ b/gcc/config/bpf/bpf.cc
+@@ -146,7 +146,7 @@ bpf_handle_preserve_access_index_attribute (tree *node, tree name,
+ 
+ /* Target-specific attributes.  */
+ 
+-static const struct attribute_spec bpf_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (bpf_attribute_table,
+ {
+   /* Syntax: { name, min_len, max_len, decl_required, type_required,
+ 	       function_type_required, affects_type_identity, handler,
+@@ -159,11 +159,8 @@ static const struct attribute_spec bpf_attribute_table[] =
+  /* 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 }
+-};
++   bpf_handle_preserve_access_index_attribute, NULL }
++});
+ 
+ #undef TARGET_ATTRIBUTE_TABLE
+ #define TARGET_ATTRIBUTE_TABLE bpf_attribute_table
+diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc
+index e315e09a8..b511fafe5 100644
+--- a/gcc/config/csky/csky.cc
++++ b/gcc/config/csky/csky.cc
+@@ -211,16 +211,15 @@ const int csky_dbx_regno[FIRST_PSEUDO_REGISTER] =
+ /* Table of machine attributes.  */
+ static tree csky_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+ static tree csky_handle_isr_attribute (tree *, tree, tree, int, bool *);
+-static const struct attribute_spec csky_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (csky_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "naked",	 0, 0, true,  false, false, false, csky_handle_fndecl_attribute, NULL },
+   /* Interrupt Service Routines have special prologue and epilogue requirements.  */
+   { "interrupt", 0, 1, false, false, false, false, csky_handle_isr_attribute,	 NULL },
+-  { "isr",	 0, 1, false, false, false, false, csky_handle_isr_attribute,	 NULL },
+-  { NULL,	 0, 0, false, false, false, false, NULL,			 NULL }
+-};
++  { "isr",	 0, 1, false, false, false, false, csky_handle_isr_attribute,	 NULL }
++});
+ 
+ /* A C structure for machine-specific, per-function data.
+    This is added to the cfun structure.  */
+diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
+index 62636b1ec..8a7c0a988 100644
+--- a/gcc/config/epiphany/epiphany.cc
++++ b/gcc/config/epiphany/epiphany.cc
+@@ -460,7 +460,7 @@ epiphany_init_reg_tables (void)
+                      They unmask them while calling an interruptible
+ 		     function, though.  */
+ 
+-static const struct attribute_spec epiphany_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (epiphany_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -470,9 +470,8 @@ static const struct attribute_spec epiphany_attribute_table[] =
+     epiphany_handle_forwarder_attribute, NULL },
+   { "long_call",  0, 0, false, true, true, false, NULL, NULL },
+   { "short_call", 0, 0, false, true, true, false, NULL, NULL },
+-  { "disinterrupt", 0, 0, false, true, true, true, NULL, NULL },
+-  { NULL,         0, 0, false, false, false, false, NULL, NULL }
+-};
++  { "disinterrupt", 0, 0, false, true, true, true, NULL, NULL }
++});
+ 
+ /* Handle an "interrupt" attribute; arguments as in
+    struct attribute_spec.handler.  */
+diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
+index e2cbdd1ac..0b049abcc 100644
+--- a/gcc/config/gcn/gcn.cc
++++ b/gcc/config/gcn/gcn.cc
+@@ -363,14 +363,12 @@ gcn_handle_amdgpu_hsa_kernel_attribute (tree *node, tree name,
+  
+    Create target-specific __attribute__ types.  */
+ 
+-static const struct attribute_spec gcn_attribute_table[] = {
++TARGET_GNU_ATTRIBUTES (gcn_attribute_table, {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+      affects_type_identity } */
+   {"amdgpu_hsa_kernel", 0, GCN_KERNEL_ARG_TYPES, false, true,
+-   true, true, gcn_handle_amdgpu_hsa_kernel_attribute, NULL},
+-  /* End element.  */
+-  {NULL, 0, 0, false, false, false, false, NULL, NULL}
+-};
++   true, true, gcn_handle_amdgpu_hsa_kernel_attribute, NULL}
++});
+ 
+ /* }}}  */
+ /* {{{ Registers and modes.  */
+diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
+index 78cf15f15..a0fa689de 100644
+--- a/gcc/config/h8300/h8300.cc
++++ b/gcc/config/h8300/h8300.cc
+@@ -4909,7 +4909,7 @@ h8300_insert_attributes (tree node, tree *attributes)
+    tiny_data: This variable lives in the tiny data area and can be
+    referenced with 16-bit absolute memory references.  */
+ 
+-static const struct attribute_spec h8300_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (h8300_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -4926,9 +4926,8 @@ static const struct attribute_spec h8300_attribute_table[] =
+   { "eightbit_data",     0, 0, true,  false, false, false,
+     h8300_handle_eightbit_data_attribute, NULL },
+   { "tiny_data",         0, 0, true,  false, false, false,
+-    h8300_handle_tiny_data_attribute, NULL },
+-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
+-};
++    h8300_handle_tiny_data_attribute, NULL }
++});
+ 
+ 
+ /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 86932d719..991661fe4 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -3875,7 +3875,7 @@ handle_nodirect_extern_access_attribute (tree *pnode, tree name,
+ }
+ 
+ /* Table of valid machine attributes.  */
+-const struct attribute_spec ix86_attribute_table[] =
++static const attribute_spec ix86_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -3955,10 +3955,12 @@ const struct attribute_spec ix86_attribute_table[] =
+   { "cf_check", 0, 0, true, false, false, false,
+     ix86_handle_fndecl_attribute, NULL },
+   { "nodirect_extern_access", 0, 0, true, false, false, false,
+-    handle_nodirect_extern_access_attribute, NULL },
++    handle_nodirect_extern_access_attribute, NULL }
++};
+ 
+-  /* End element.  */
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
++const scoped_attribute_specs ix86_gnu_attribute_table =
++{
++  "gnu", ix86_gnu_attributes
+ };
+ 
+ #include "gt-i386-options.h"
+diff --git a/gcc/config/i386/i386-options.h b/gcc/config/i386/i386-options.h
+index ce4034f62..a7bdb22c0 100644
+--- a/gcc/config/i386/i386-options.h
++++ b/gcc/config/i386/i386-options.h
+@@ -82,7 +82,7 @@ void ix86_function_specific_print (FILE *, int,
+ 				   struct cl_target_option *);
+ bool ix86_valid_target_attribute_p (tree, tree, tree, int);
+ 
+-extern const struct attribute_spec ix86_attribute_table[];
++extern const struct scoped_attribute_specs ix86_gnu_attribute_table;
+ 
+ 
+ #endif  /* GCC_I386_OPTIONS_H */
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index 83a0d8abb..ade965927 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -24293,6 +24293,11 @@ ix86_run_selftests (void)
+ 
+ #endif /* CHECKING_P */
+ 
++static const scoped_attribute_specs *const ix86_attribute_table[] =
++{
++  &ix86_gnu_attribute_table
++};
++
+ /* Initialize the GCC target structure.  */
+ #undef TARGET_RETURN_IN_MEMORY
+ #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
+diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
+index f9fb681a3..b9ced1c46 100644
+--- a/gcc/config/ia64/ia64.cc
++++ b/gcc/config/ia64/ia64.cc
+@@ -357,7 +357,7 @@ static bool ia64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d);
+ 
+ 
+ /* Table of valid machine attributes.  */
+-static const struct attribute_spec ia64_attribute_table[] =
++static const attribute_spec ia64_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -369,8 +369,17 @@ static const struct attribute_spec ia64_attribute_table[] =
+     ia64_vms_common_object_attribute, NULL },
+ #endif
+   { "version_id",      1, 1, true, false, false, false,
+-    ia64_handle_version_id_attribute, NULL },
+-  { NULL,	       0, 0, false, false, false, false, NULL, NULL }
++    ia64_handle_version_id_attribute, NULL }
++};
++
++static const scoped_attribute_specs ia64_gnu_attribute_table =
++{
++  "gnu", ia64_gnu_attributes
++};
++
++static const scoped_attribute_specs *const ia64_attribute_table[] =
++{
++  &ia64_gnu_attribute_table
+ };
+ 
+ /* Initialize the GCC target structure.  */
+diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc
+index 11ca9a43a..a8f6523df 100644
+--- a/gcc/config/m32c/m32c.cc
++++ b/gcc/config/m32c/m32c.cc
+@@ -2996,7 +2996,7 @@ current_function_special_page_vector (rtx x)
+ 
+ #undef TARGET_ATTRIBUTE_TABLE
+ #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
+-static const struct attribute_spec m32c_attribute_table[] = {
++TARGET_GNU_ATTRIBUTES (m32c_attribute_table, {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "interrupt", 0, 0, false, false, false, false, interrupt_handler, NULL },
+@@ -3004,9 +3004,8 @@ static const struct attribute_spec m32c_attribute_table[] = {
+   { "fast_interrupt", 0, 0, false, false, false, false,
+     interrupt_handler, NULL },
+   { "function_vector", 1, 1, true,  false, false, false,
+-    function_vector_handler, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+-};
++    function_vector_handler, NULL }
++});
+ 
+ #undef TARGET_COMP_TYPE_ATTRIBUTES
+ #define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
+diff --git a/gcc/config/m32r/m32r.cc b/gcc/config/m32r/m32r.cc
+index bca768172..78a17f0a1 100644
+--- a/gcc/config/m32r/m32r.cc
++++ b/gcc/config/m32r/m32r.cc
+@@ -111,15 +111,14 @@ static HOST_WIDE_INT m32r_starting_frame_offset (void);
+ 
+ /* M32R specific attributes.  */
+ 
+-static const struct attribute_spec m32r_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (m32r_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "interrupt", 0, 0, true,  false, false, false, NULL, NULL },
+   { "model",     1, 1, true,  false, false, false, m32r_handle_model_attribute,
+-    NULL },
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+-};
++    NULL }
++});
+ 
+ /* Initialize the GCC target structure.  */
+ #undef  TARGET_ATTRIBUTE_TABLE
+diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc
+index 62898dafe..effb6db8d 100644
+--- a/gcc/config/m68k/m68k.cc
++++ b/gcc/config/m68k/m68k.cc
+@@ -360,7 +360,7 @@ static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
+ #undef TARGET_ASM_FINAL_POSTSCAN_INSN
+ #define TARGET_ASM_FINAL_POSTSCAN_INSN m68k_asm_final_postscan_insn
+ 
+-static const struct attribute_spec m68k_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (m68k_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -369,9 +369,8 @@ static const struct attribute_spec m68k_attribute_table[] =
+   { "interrupt_handler", 0, 0, true,  false, false, false,
+     m68k_handle_fndecl_attribute, NULL },
+   { "interrupt_thread", 0, 0, true,  false, false, false,
+-    m68k_handle_fndecl_attribute, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+-};
++    m68k_handle_fndecl_attribute, NULL }
++});
+ 
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ 
+diff --git a/gcc/config/mcore/mcore.cc b/gcc/config/mcore/mcore.cc
+index 28e707496..e497b0f44 100644
+--- a/gcc/config/mcore/mcore.cc
++++ b/gcc/config/mcore/mcore.cc
+@@ -150,16 +150,15 @@ static bool	  mcore_modes_tieable_p		(machine_mode, machine_mode);
+ 
+ /* MCore specific attributes.  */
+ 
+-static const struct attribute_spec mcore_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (mcore_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "dllexport", 0, 0, true,  false, false, false, NULL, NULL },
+   { "dllimport", 0, 0, true,  false, false, false, NULL, NULL },
+   { "naked",     0, 0, true,  false, false, false,
+-    mcore_handle_naked_attribute, NULL },
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+-};
++    mcore_handle_naked_attribute, NULL }
++});
+ 
+ /* Initialize the GCC target structure.  */
+ #undef  TARGET_ASM_EXTERNAL_LIBCALL
+diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc
+index f32effecf..6b14d3e29 100644
+--- a/gcc/config/microblaze/microblaze.cc
++++ b/gcc/config/microblaze/microblaze.cc
+@@ -218,15 +218,14 @@ int break_handler;
+ int fast_interrupt;
+ int save_volatiles;
+ 
+-const struct attribute_spec microblaze_attribute_table[] = {
++TARGET_GNU_ATTRIBUTES (microblaze_attribute_table, {
+   /* name         min_len, max_len, decl_req, type_req, fn_type_req,
+      affects_type_identity, handler, exclude */
+   {"interrupt_handler",	0,       0,    true, false, false, false, NULL, NULL },
+   {"break_handler",	0,       0,    true, false, false, false, NULL, NULL },
+   {"fast_interrupt",	0,       0,    true, false, false, false, NULL, NULL },
+-  {"save_volatiles",	0,       0,    true, false, false, false, NULL, NULL },
+-  { NULL,        	0,       0,   false, false, false, false, NULL, NULL }
+-};
++  {"save_volatiles",	0,       0,    true, false, false, false, NULL, NULL }
++});
+ 
+ static int microblaze_interrupt_function_p (tree);
+ 
+diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
+index 02d11ddbf..5474ca152 100644
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -607,7 +607,7 @@ static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int,
+ 						      bool *);
+ 
+ /* The value of TARGET_ATTRIBUTE_TABLE.  */
+-static const struct attribute_spec mips_attribute_table[] = {
++TARGET_GNU_ATTRIBUTES (mips_attribute_table, {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "long_call",   0, 0, false, true,  true,  false, NULL, NULL },
+@@ -629,9 +629,8 @@ static const struct attribute_spec mips_attribute_table[] = {
+   { "use_shadow_register_set",	0, 1, false, true,  true, false,
+     mips_handle_use_shadow_register_set_attr, NULL },
+   { "keep_interrupts_masked",	0, 0, false, true,  true, false, NULL, NULL },
+-  { "use_debug_exception_return", 0, 0, false, true, true, false, NULL, NULL },
+-  { NULL,	   0, 0, false, false, false, false, NULL, NULL }
+-};
++  { "use_debug_exception_return", 0, 0, false, true, true, false, NULL, NULL }
++});
+ 
+ /* A table describing all the processors GCC knows about; see
+    mips-cpus.def for details.  */
+diff --git a/gcc/config/msp430/msp430.cc b/gcc/config/msp430/msp430.cc
+index 7a378ceac..f58855978 100644
+--- a/gcc/config/msp430/msp430.cc
++++ b/gcc/config/msp430/msp430.cc
+@@ -2055,7 +2055,7 @@ static const struct attribute_spec::exclusions attr_either_exclusions[] =
+ #define TARGET_ATTRIBUTE_TABLE		msp430_attribute_table
+ 
+ /* Table of MSP430-specific attributes.  */
+-const struct attribute_spec msp430_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (msp430_attribute_table,
+   {
+     /* { name, min_num_args, max_num_args, decl_req, type_req, fn_type_req,
+ 	 affects_type_identity, handler, exclude } */
+@@ -2073,10 +2073,8 @@ const struct attribute_spec msp430_attribute_table[] =
+     { ATTR_UPPER,       0, 0, true,  false, false, false, msp430_section_attr,
+       attr_upper_exclusions },
+     { ATTR_EITHER,      0, 0, true,  false, false, false, msp430_section_attr,
+-      attr_either_exclusions },
+-
+-    { NULL,		0, 0, false, false, false, false, NULL,  NULL }
+-  };
++      attr_either_exclusions }
++  });
+ 
+ #undef TARGET_HANDLE_GENERIC_ATTRIBUTE
+ #define TARGET_HANDLE_GENERIC_ATTRIBUTE msp430_handle_generic_attribute
+diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc
+index 27530495f..519b11e4c 100644
+--- a/gcc/config/nds32/nds32.cc
++++ b/gcc/config/nds32/nds32.cc
+@@ -288,7 +288,7 @@ static const int nds32_reg_alloc_order_for_speed[] =
+ };
+ 
+ /* Defining target-specific uses of __attribute__.  */
+-static const struct attribute_spec nds32_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (nds32_attribute_table,
+ {
+   /* Syntax: { name, min_len, max_len, decl_required, type_required,
+ 	       function_type_required, affects_type_identity, handler,
+@@ -326,11 +326,8 @@ static const struct attribute_spec nds32_attribute_table[] =
+ 
+   /* FOR BACKWARD COMPATIBILITY,
+      this attribute also tells no prologue/epilogue.  */
+-  { "no_prologue",  0,  0, false, false, false, false, NULL, NULL },
+-
+-  /* The last attribute spec is set to be NULL.  */
+-  { NULL,           0,  0, false, false, false, false, NULL, NULL }
+-};
++  { "no_prologue",  0,  0, false, false, false, false, NULL, NULL }
++});
+ 
+ 
+ /* ------------------------------------------------------------------------ */
+diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
+index 7f2103ba6..9a3e418f4 100644
+--- a/gcc/config/nvptx/nvptx.cc
++++ b/gcc/config/nvptx/nvptx.cc
+@@ -5817,16 +5817,15 @@ nvptx_handle_shared_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ }
+ 
+ /* Table of valid machine attributes.  */
+-static const struct attribute_spec nvptx_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (nvptx_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "kernel", 0, 0, true, false,  false, false, nvptx_handle_kernel_attribute,
+     NULL },
+   { "shared", 0, 0, true, false,  false, false, nvptx_handle_shared_attribute,
+-    NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
+-};
++    NULL }
++});
+ 
+ /* Limit vector alignments to BIGGEST_ALIGNMENT.  */
+ 
+diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
+index 9cf79beba..f5a27bdc9 100644
+--- a/gcc/config/riscv/riscv.cc
++++ b/gcc/config/riscv/riscv.cc
+@@ -336,7 +336,7 @@ static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+ static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
+ 
+ /* Defining target-specific uses of __attribute__.  */
+-static const struct attribute_spec riscv_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (riscv_attribute_table,
+ {
+   /* Syntax: { name, min_len, max_len, decl_required, type_required,
+ 	       function_type_required, affects_type_identity, handler,
+@@ -347,11 +347,8 @@ static const struct attribute_spec riscv_attribute_table[] =
+     riscv_handle_fndecl_attribute, NULL },
+   /* This attribute generates prologue/epilogue for interrupt handlers.  */
+   { "interrupt", 0, 1, false, true, true, false,
+-    riscv_handle_type_attribute, NULL },
+-
+-  /* The last attribute spec is set to be NULL.  */
+-  { NULL,	0,  0, false, false, false, false, NULL, NULL }
+-};
++    riscv_handle_type_attribute, NULL }
++});
+ 
+ /* Order for the CLOBBERs/USEs of gpr_save.  */
+ static const unsigned gpr_save_reg_order[] = {
+diff --git a/gcc/config/rl78/rl78.cc b/gcc/config/rl78/rl78.cc
+index b3727c0a8..97386c7ea 100644
+--- a/gcc/config/rl78/rl78.cc
++++ b/gcc/config/rl78/rl78.cc
+@@ -898,7 +898,7 @@ rl78_handle_vector_attribute (tree * node,
+ #define TARGET_ATTRIBUTE_TABLE		rl78_attribute_table
+ 
+ /* Table of RL78-specific attributes.  */
+-const struct attribute_spec rl78_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (rl78_attribute_table,
+ {
+   /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
+      affects_type_identity, handler, exclude.  */
+@@ -911,9 +911,8 @@ const struct attribute_spec rl78_attribute_table[] =
+   { "saddr",          0, 0, true, false, false, false,
+     rl78_handle_saddr_attribute, NULL },
+   { "vector",         1, -1, true, false, false, false,
+-	rl78_handle_vector_attribute, NULL },
+-  { NULL,             0, 0, false, false, false, false, NULL, NULL }
+-};
++	rl78_handle_vector_attribute, NULL }
++});
+ 
+ 
+ 
+diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
+index 55d4ce751..46e3d1a12 100644
+--- a/gcc/config/rs6000/rs6000.cc
++++ b/gcc/config/rs6000/rs6000.cc
+@@ -1276,7 +1276,7 @@ static const char alt_reg_names[][8] =
+ 
+ /* Table of valid machine attributes.  */
+ 
+-static const struct attribute_spec rs6000_attribute_table[] =
++static const attribute_spec rs6000_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -1293,7 +1293,16 @@ static const struct attribute_spec rs6000_attribute_table[] =
+ #ifdef SUBTARGET_ATTRIBUTE_TABLE
+   SUBTARGET_ATTRIBUTE_TABLE,
+ #endif
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
++};
++
++static const scoped_attribute_specs rs6000_gnu_attribute_table =
++{
++  "gnu", rs6000_gnu_attributes
++};
++
++static const scoped_attribute_specs *const rs6000_attribute_table[] =
++{
++  &rs6000_gnu_attribute_table
+ };
+ 
+ #ifndef TARGET_PROFILE_KERNEL
+diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc
+index 412a3a354..2f1178b00 100644
+--- a/gcc/config/rx/rx.cc
++++ b/gcc/config/rx/rx.cc
+@@ -2759,7 +2759,7 @@ rx_handle_vector_attribute (tree * node,
+ }
+ 
+ /* Table of RX specific attributes.  */
+-const struct attribute_spec rx_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (rx_attribute_table,
+ {
+   /* Name, min_len, max_len, decl_req, type_req, fn_type_req,
+      affects_type_identity, handler, exclude.  */
+@@ -2770,9 +2770,8 @@ const struct attribute_spec rx_attribute_table[] =
+   { "naked",          0, 0, true, false, false, false,
+     rx_handle_func_attribute, NULL },
+   { "vector",         1, -1, true, false, false, false,
+-    rx_handle_vector_attribute, NULL },
+-  { NULL,             0, 0, false, false, false, false, NULL, NULL }
+-};
++    rx_handle_vector_attribute, NULL }
++});
+ 
+ /* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE.  */
+ 
+diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
+index f1599a5c5..dcdf7dad0 100644
+--- a/gcc/config/s390/s390.cc
++++ b/gcc/config/s390/s390.cc
+@@ -1247,7 +1247,7 @@ s390_handle_string_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
+   return NULL_TREE;
+ }
+ 
+-static const struct attribute_spec s390_attribute_table[] = {
++TARGET_GNU_ATTRIBUTES (s390_attribute_table, {
+   { "hotpatch", 2, 2, true, false, false, false,
+     s390_handle_hotpatch_attribute, NULL },
+   { "s390_vector_bool", 0, 0, false, true, false, true,
+@@ -1263,11 +1263,8 @@ static const struct attribute_spec s390_attribute_table[] = {
+   { "function_return_reg", 1, 1, true, false, false, false,
+     s390_handle_string_attribute, NULL },
+   { "function_return_mem", 1, 1, true, false, false, false,
+-    s390_handle_string_attribute, NULL },
+-
+-  /* End element.  */
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+-};
++    s390_handle_string_attribute, NULL }
++});
+ 
+ /* Return the alignment for LABEL.  We default to the -falign-labels
+    value except for the literal pool base label.  */
+diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
+index 74d61c43b..5717b7ab8 100644
+--- a/gcc/config/sh/sh.cc
++++ b/gcc/config/sh/sh.cc
+@@ -328,7 +328,7 @@ static bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
+ static bool sh_modes_tieable_p (machine_mode, machine_mode);
+ static bool sh_can_change_mode_class (machine_mode, machine_mode, reg_class_t);
+ 
+-static const struct attribute_spec sh_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (sh_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -347,9 +347,8 @@ static const struct attribute_spec sh_attribute_table[] =
+   { "resbank",           0, 0, true,  false, false, false,
+     sh_handle_resbank_handler_attribute, NULL },
+   { "function_vector",   1, 1, true,  false, false, false,
+-    sh2a_handle_function_vector_handler_attribute, NULL },
+-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
+-};
++    sh2a_handle_function_vector_handler_attribute, NULL }
++});
+ 
+ /* Initialize the GCC target structure.  */
+ #undef TARGET_ATTRIBUTE_TABLE
+diff --git a/gcc/config/sparc/sparc.cc b/gcc/config/sparc/sparc.cc
+index 27db12e6b..61bf302db 100644
+--- a/gcc/config/sparc/sparc.cc
++++ b/gcc/config/sparc/sparc.cc
+@@ -719,13 +719,12 @@ static HARD_REG_SET sparc_zero_call_used_regs (HARD_REG_SET);
+ 
+ #ifdef SUBTARGET_ATTRIBUTE_TABLE
+ /* Table of valid machine attributes.  */
+-static const struct attribute_spec sparc_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (sparc_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        do_diagnostic, handler, exclude } */
+-  SUBTARGET_ATTRIBUTE_TABLE,
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+-};
++  SUBTARGET_ATTRIBUTE_TABLE
++});
+ #endif
+ 
+ char sparc_hard_reg_printed[8];
+diff --git a/gcc/config/stormy16/stormy16.cc b/gcc/config/stormy16/stormy16.cc
+index fabf09ab9..3adc0212a 100644
+--- a/gcc/config/stormy16/stormy16.cc
++++ b/gcc/config/stormy16/stormy16.cc
+@@ -2202,7 +2202,7 @@ static tree xstormy16_handle_interrupt_attribute
+ static tree xstormy16_handle_below100_attribute
+   (tree *, tree, tree, int, bool *);
+ 
+-static const struct attribute_spec xstormy16_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (xstormy16_attribute_table,
+ {
+   /* name, min_len, max_len, decl_req, type_req, fn_type_req,
+      affects_type_identity, handler, exclude.  */
+@@ -2211,9 +2211,8 @@ static const struct attribute_spec xstormy16_attribute_table[] =
+   { "BELOW100",  0, 0, false, false, false, false,
+     xstormy16_handle_below100_attribute, NULL },
+   { "below100",  0, 0, false, false, false, false,
+-    xstormy16_handle_below100_attribute, NULL },
+-  { NULL,        0, 0, false, false, false, false, NULL, NULL }
+-};
++    xstormy16_handle_below100_attribute, NULL }
++});
+ 
+ /* Handle an "interrupt" attribute;
+    arguments as in struct attribute_spec.handler.  */
+diff --git a/gcc/config/v850/v850.cc b/gcc/config/v850/v850.cc
+index c7d432990..b7bbfb810 100644
+--- a/gcc/config/v850/v850.cc
++++ b/gcc/config/v850/v850.cc
+@@ -3114,7 +3114,7 @@ v850_adjust_insn_length (rtx_insn *insn, int length)
+ 
+ /* V850 specific attributes.  */
+ 
+-static const struct attribute_spec v850_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (v850_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -3127,9 +3127,8 @@ static const struct attribute_spec v850_attribute_table[] =
+   { "tda",               0, 0, true,  false, false, false,
+     v850_handle_data_area_attribute, NULL },
+   { "zda",               0, 0, true,  false, false, false,
+-    v850_handle_data_area_attribute, NULL },
+-  { NULL,                0, 0, false, false, false, false, NULL, NULL }
+-};
++    v850_handle_data_area_attribute, NULL }
++});
+ 
+ static void
+ v850_option_override (void)
+diff --git a/gcc/config/visium/visium.cc b/gcc/config/visium/visium.cc
+index 35b46ced9..b572603bb 100644
+--- a/gcc/config/visium/visium.cc
++++ b/gcc/config/visium/visium.cc
+@@ -145,14 +145,13 @@ static inline bool current_function_has_lr_slot (void);
+ 
+ /* Supported attributes:
+    interrupt -- specifies this function is an interrupt handler.   */
+-static const struct attribute_spec visium_attribute_table[] =
++TARGET_GNU_ATTRIBUTES (visium_attribute_table,
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "interrupt", 0, 0, true, false, false, false, visium_handle_interrupt_attr,
+-    NULL},
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL },
+-};
++    NULL}
++});
+ 
+ static struct machine_function *visium_init_machine_status (void);
+ 
+diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
+index 3c04e5c02..ff0d0883a 100644
+--- a/gcc/cp/cp-objcp-common.h
++++ b/gcc/cp/cp-objcp-common.h
+@@ -123,13 +123,16 @@ extern tree cxx_simulate_record_decl (location_t, const char *,
+ #undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
+ #define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
+ 
+-/* Attribute hooks.  */
+-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
++static const scoped_attribute_specs *const cp_objcp_attribute_table[] =
++{
++  &std_attribute_table,
++  &cxx_gnu_attribute_table,
++  &c_common_gnu_attribute_table,
++  &c_common_format_attribute_table
++};
++
+ #undef LANG_HOOKS_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_ATTRIBUTE_TABLE cxx_attribute_table
++#define LANG_HOOKS_ATTRIBUTE_TABLE cp_objcp_attribute_table
+ 
+ #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
+ #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p
+diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
+index 64b3196d1..52d19faa3 100644
+--- a/gcc/cp/cp-tree.h
++++ b/gcc/cp/cp-tree.h
+@@ -7897,7 +7897,8 @@ extern tree maybe_dummy_object			(tree, tree *);
+ extern bool is_dummy_object			(const_tree);
+ extern bool is_byte_access_type			(tree);
+ extern bool is_byte_access_type_not_plain_char	(tree);
+-extern const struct attribute_spec cxx_attribute_table[];
++extern const struct scoped_attribute_specs cxx_gnu_attribute_table;
++extern const struct scoped_attribute_specs std_attribute_table;
+ extern tree make_ptrmem_cst			(tree, tree);
+ extern tree cp_build_type_attribute_variant     (tree, tree);
+ extern tree cp_build_reference_type		(tree, bool);
+diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
+index a7933ad2c..6cfc7a2d7 100644
+--- a/gcc/cp/tree.cc
++++ b/gcc/cp/tree.cc
+@@ -5004,7 +5004,7 @@ handle_likeliness_attribute (tree *node, tree name, tree args,
+ }
+ 
+ /* Table of valid C++ attributes.  */
+-const struct attribute_spec cxx_attribute_table[] =
++static const attribute_spec cxx_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -5012,11 +5012,15 @@ const struct attribute_spec cxx_attribute_table[] =
+     handle_init_priority_attribute, NULL },
+   { "abi_tag", 1, -1, false, false, false, true,
+     handle_abi_tag_attribute, NULL },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
++};
++
++const scoped_attribute_specs cxx_gnu_attribute_table =
++{
++  "gnu", cxx_gnu_attributes
+ };
+ 
+ /* Table of C++ standard attributes.  */
+-const struct attribute_spec std_attribute_table[] =
++static const attribute_spec std_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -5031,10 +5035,11 @@ const struct attribute_spec std_attribute_table[] =
+   { "unlikely", 0, 0, false, false, false, false,
+     handle_likeliness_attribute, attr_cold_hot_exclusions },
+   { "noreturn", 0, 0, true, false, false, false,
+-    handle_noreturn_attribute, attr_noreturn_exclusions },
+-  { NULL, 0, 0, false, false, false, false, NULL, NULL }
++    handle_noreturn_attribute, attr_noreturn_exclusions }
+ };
+ 
++const scoped_attribute_specs std_attribute_table = { nullptr, std_attributes };
++
+ /* Handle an "init_priority" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ static tree
+@@ -5617,7 +5622,6 @@ void
+ init_tree (void)
+ {
+   list_hash_table = hash_table::create_ggc (61);
+-  register_scoped_attributes (std_attribute_table, NULL);
+ }
+ 
+ /* Returns the kind of special function that DECL (a FUNCTION_DECL)
+diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
+index c271de0c7..e402c0c11 100644
+--- a/gcc/d/d-attribs.cc
++++ b/gcc/d/d-attribs.cc
+@@ -157,7 +157,7 @@ extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
+ 
+ /* Table of machine-independent attributes.
+    For internal use (marking of built-ins) only.  */
+-const attribute_spec d_langhook_common_attribute_table[] =
++static const attribute_spec d_langhook_common_attributes[] =
+ {
+   ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
+ 	     handle_noreturn_attribute, attr_noreturn_exclusions),
+@@ -183,11 +183,15 @@ const attribute_spec d_langhook_common_attribute_table[] =
+ 	     handle_type_generic_attribute, NULL),
+   ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
+ 	     handle_fnspec_attribute, NULL),
+-  ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
++};
++
++const scoped_attribute_specs d_langhook_common_attribute_table =
++{
++  "gnu", d_langhook_common_attributes
+ };
+ 
+ /* Table of D language attributes exposed by `gcc.attribute' UDAs.  */
+-const attribute_spec d_langhook_attribute_table[] =
++static const attribute_spec d_langhook_gnu_attributes[] =
+ {
+   ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
+ 	     d_handle_noinline_attribute, attr_noinline_exclusions),
+@@ -223,9 +227,12 @@ const attribute_spec d_langhook_attribute_table[] =
+ 	     d_handle_restrict_attribute, NULL),
+   ATTR_SPEC ("used", 0, 0, true, false, false, false,
+ 	     d_handle_used_attribute, NULL),
+-  ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
+ };
+ 
++const scoped_attribute_specs d_langhook_gnu_attribute_table =
++{
++  "gnu", d_langhook_gnu_attributes
++};
+ 
+ /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
+    Returns a new variant of the original type declaration.  */
+@@ -270,20 +277,14 @@ uda_attribute_p (const char *name)
+ 
+   /* Search both our language, and target attribute tables.
+      Common and format attributes are kept internal.  */
+-  for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
+-    {
+-      if (get_identifier (p->name) == ident)
+-	return true;
+-    }
++  for (const attribute_spec &p : d_langhook_gnu_attributes)
++    if (get_identifier (p.name) == ident)
++      return true;
+ 
+-  if (targetm.attribute_table)
+-    {
+-      for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
+-	{
+-	  if (get_identifier (p->name) == ident)
+-	    return true;
+-	}
+-    }
++  for (auto scoped_attributes : targetm.attribute_table)
++    for (const attribute_spec &p : scoped_attributes->attributes)
++      if (get_identifier (p.name) == ident)
++	return true;
+ 
+   return false;
+ }
+diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
+index f078f24fc..da9d6d4a2 100644
+--- a/gcc/d/d-lang.cc
++++ b/gcc/d/d-lang.cc
+@@ -1938,6 +1938,12 @@ d_enum_underlying_base_type (const_tree type)
+   return TREE_TYPE (type);
+ }
+ 
++const scoped_attribute_specs *const d_langhook_attribute_table[] =
++{
++  &d_langhook_gnu_attribute_table,
++  &d_langhook_common_attribute_table,
++};
++
+ /* Definitions for our language-specific hooks.  */
+ 
+ #undef LANG_HOOKS_NAME
+@@ -1949,7 +1955,6 @@ d_enum_underlying_base_type (const_tree type)
+ #undef LANG_HOOKS_HANDLE_OPTION
+ #undef LANG_HOOKS_POST_OPTIONS
+ #undef LANG_HOOKS_PARSE_FILE
+-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+ #undef LANG_HOOKS_ATTRIBUTE_TABLE
+ #undef LANG_HOOKS_GET_ALIAS_SET
+ #undef LANG_HOOKS_TYPES_COMPATIBLE_P
+@@ -1981,7 +1986,6 @@ d_enum_underlying_base_type (const_tree type)
+ #define LANG_HOOKS_HANDLE_OPTION	    d_handle_option
+ #define LANG_HOOKS_POST_OPTIONS		    d_post_options
+ #define LANG_HOOKS_PARSE_FILE		    d_parse_file
+-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE   d_langhook_common_attribute_table
+ #define LANG_HOOKS_ATTRIBUTE_TABLE	    d_langhook_attribute_table
+ #define LANG_HOOKS_GET_ALIAS_SET	    d_get_alias_set
+ #define LANG_HOOKS_TYPES_COMPATIBLE_P	    d_types_compatible_p
+diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
+index aedbdd80a..d4245b63b 100644
+--- a/gcc/d/d-tree.h
++++ b/gcc/d/d-tree.h
+@@ -496,8 +496,8 @@ extern tree insert_decl_attribute (tree, const char *, tree = NULL_TREE);
+ extern void apply_user_attributes (Dsymbol *, tree);
+ 
+ /* In d-builtins.cc.  */
+-extern const attribute_spec d_langhook_attribute_table[];
+-extern const attribute_spec d_langhook_common_attribute_table[];
++extern const struct scoped_attribute_specs d_langhook_gnu_attribute_table;
++extern const struct scoped_attribute_specs d_langhook_common_attribute_table;
+ extern Type *build_frontend_type (tree);
+ 
+ extern tree d_builtin_function (tree);
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 4f93facf7..95d96ce1b 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10427,12 +10427,33 @@ Target-specific attributes may be defined for functions, data and types.
+ These are described using the following target hooks; they also need to
+ be documented in @file{extend.texi}.
+ 
+-@deftypevr {Target Hook} {const struct attribute_spec *} TARGET_ATTRIBUTE_TABLE
+-If defined, this target hook points to an array of @samp{struct
+-attribute_spec} (defined in @file{tree-core.h}) specifying the machine
+-specific attributes for this target and some of the restrictions on the
+-entities to which these attributes are applied and the arguments they
+-take.
++@deftypevr {Target Hook} {array_slice} TARGET_ATTRIBUTE_TABLE
++If defined, this target hook provides an array of
++@samp{scoped_attribute_spec}s (defined in @file{attribs.h}) that specify the
++machine-specific attributes for this target.  The information includes some
++of the restrictions on the entities to which these attributes are applied
++and the arguments that the attributes take.
++
++In C and C++, these attributes are associated with two syntaxes:
++the traditional GNU @code{__attribute__} syntax and the standard
++@samp{[[]]} syntax.  Attributes that support the GNU syntax must be
++placed in the @code{gnu} namespace.  Such attributes can then also be
++written @samp{[[gnu::@dots{}]]}.  Attributes that use only the standard
++syntax should be placed in whichever namespace the attribute specification
++requires.  For example, a target might choose to support vendor-specific
++@samp{[[]]} attributes that the vendor places in their own namespace.
++
++Targets that only define attributes in the @code{gnu} namespace
++can uase the following shorthand to define the table:
++
++@smallexample
++TARGET_GNU_ATTRIBUTES (@var{cpu_attribute_table}, @{
++  @{ "@var{attribute1}", @dots{} @},
++  @{ "@var{attribute2}", @dots{} @},
++  @dots{},
++  @{ "@var{attributen}", @dots{} @},
++@});
++@end smallexample
+ @end deftypevr
+ 
+ @deftypefn {Target Hook} bool TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P (const_tree @var{name})
+diff --git a/gcc/fortran/f95-lang.cc b/gcc/fortran/f95-lang.cc
+index 468a0b7e3..27ffc7511 100644
+--- a/gcc/fortran/f95-lang.cc
++++ b/gcc/fortran/f95-lang.cc
+@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "cpp.h"
+ #include "trans-types.h"
+ #include "trans-const.h"
++#include "attribs.h"
+ 
+ /* Language-dependent contents of an identifier.  */
+ 
+@@ -87,7 +88,7 @@ gfc_handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
+ }
+ 
+ /* Table of valid Fortran attributes.  */
+-static const struct attribute_spec gfc_attribute_table[] =
++static const attribute_spec gfc_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -97,7 +98,16 @@ static const struct attribute_spec gfc_attribute_table[] =
+     gfc_handle_omp_declare_target_attribute, NULL },
+   { "oacc function", 0, -1, true,  false, false, false,
+     gfc_handle_omp_declare_target_attribute, NULL },
+-  { NULL,		  0, 0, false, false, false, false, NULL, NULL }
++};
++
++static const scoped_attribute_specs gfc_gnu_attribute_table =
++{
++  "gnu", gfc_gnu_attributes
++};
++
++static const scoped_attribute_specs *const gfc_attribute_table[] =
++{
++  &gfc_gnu_attribute_table
+ };
+ 
+ #undef LANG_HOOKS_NAME
+diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc
+index 84ff359bf..5f9f5336c 100644
+--- a/gcc/jit/dummy-frontend.cc
++++ b/gcc/jit/dummy-frontend.cc
+@@ -87,7 +87,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
+ };
+ 
+ /* Table of machine-independent attributes supported in libgccjit.  */
+-const struct attribute_spec jit_attribute_table[] =
++static const attribute_spec jit_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -128,22 +128,36 @@ const struct attribute_spec jit_attribute_table[] =
+   /* For internal use only.  The leading '*' both prevents its usage in
+      source code and signals that it may be overridden by machine tables.  */
+   { "*tm regparm",            0, 0, false, true, true, false,
+-			      ignore_attribute, NULL },
+-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
++			      ignore_attribute, NULL }
++};
++
++static const scoped_attribute_specs jit_gnu_attribute_table =
++{
++  "gnu", jit_gnu_attributes
+ };
+ 
+ /* Give the specifications for the format attributes, used by C and all
+    descendants.  */
+ 
+-const struct attribute_spec jit_format_attribute_table[] =
++static const attribute_spec jit_format_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+   { "format",                 3, 3, false, true,  true, false,
+ 			      handle_format_attribute, NULL },
+   { "format_arg",             1, 1, false, true,  true, false,
+-			      handle_format_arg_attribute, NULL },
+-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
++			      handle_format_arg_attribute, NULL }
++};
++
++static const scoped_attribute_specs jit_format_attribute_table =
++{
++  "gnu", jit_format_attributes
++};
++
++static const scoped_attribute_specs *const jit_attribute_table[] =
++{
++  &jit_gnu_attribute_table,
++  &jit_format_attribute_table
+ };
+ 
+ /* Attribute handlers.  */
+@@ -722,10 +736,8 @@ jit_langhook_getdecls (void)
+ #define LANG_HOOKS_GETDECLS		jit_langhook_getdecls
+ 
+ /* Attribute hooks.  */
+-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE jit_attribute_table
+-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE jit_format_attribute_table
++#undef LANG_HOOKS_ATTRIBUTE_TABLE
++#define LANG_HOOKS_ATTRIBUTE_TABLE jit_attribute_table
+ 
+ #undef  LANG_HOOKS_DEEP_UNSHARING
+ #define LANG_HOOKS_DEEP_UNSHARING	true
+diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
+index e22639517..11998e40f 100644
+--- a/gcc/langhooks-def.h
++++ b/gcc/langhooks-def.h
+@@ -151,9 +151,7 @@ extern void lhd_finalize_early_debug (void);
+ #define LANG_HOOKS_FINALIZE_EARLY_DEBUG lhd_finalize_early_debug
+ 
+ /* Attribute hooks.  */
+-#define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
+-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE	NULL
+-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE	NULL
++#define LANG_HOOKS_ATTRIBUTE_TABLE		{}
+ 
+ /* Tree inlining hooks.  */
+ #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
+@@ -365,8 +363,6 @@ extern void lhd_end_section (void);
+   LANG_HOOKS_PRINT_ERROR_FUNCTION, \
+   LANG_HOOKS_TO_TARGET_CHARSET, \
+   LANG_HOOKS_ATTRIBUTE_TABLE, \
+-  LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
+-  LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
+   LANG_HOOKS_TREE_INLINING_INITIALIZER, \
+   LANG_HOOKS_TREE_DUMP_INITIALIZER, \
+   LANG_HOOKS_DECLS, \
+diff --git a/gcc/langhooks.h b/gcc/langhooks.h
+index 4731f089a..5954f58e8 100644
+--- a/gcc/langhooks.h
++++ b/gcc/langhooks.h
+@@ -530,9 +530,7 @@ struct lang_hooks
+      table of attributes specific to the language, a table of
+      attributes common to two or more languages (to allow easy
+      sharing), and a table of attributes for checking formats.  */
+-  const struct attribute_spec *attribute_table;
+-  const struct attribute_spec *common_attribute_table;
+-  const struct attribute_spec *format_attribute_table;
++  array_slice attribute_table;
+ 
+   struct lang_hooks_for_tree_inlining tree_inlining;
+ 
+diff --git a/gcc/lto/lto-lang.cc b/gcc/lto/lto-lang.cc
+index 8d58d924d..601e92e86 100644
+--- a/gcc/lto/lto-lang.cc
++++ b/gcc/lto/lto-lang.cc
+@@ -94,7 +94,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
+ };
+ 
+ /* Table of machine-independent attributes supported in GIMPLE.  */
+-const struct attribute_spec lto_attribute_table[] =
++static const attribute_spec lto_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -135,14 +135,18 @@ const struct attribute_spec lto_attribute_table[] =
+   /* For internal use only.  The leading '*' both prevents its usage in
+      source code and signals that it may be overridden by machine tables.  */
+   { "*tm regparm",            0, 0, false, true, true, false,
+-			      ignore_attribute, NULL },
+-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
++			      ignore_attribute, NULL }
++};
++
++static const scoped_attribute_specs lto_gnu_attribute_table =
++{
++  "gnu", lto_gnu_attributes
+ };
+ 
+ /* Give the specifications for the format attributes, used by C and all
+    descendants.  */
+ 
+-const struct attribute_spec lto_format_attribute_table[] =
++static const attribute_spec lto_format_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -150,7 +154,17 @@ const struct attribute_spec lto_format_attribute_table[] =
+ 			      handle_format_attribute, NULL },
+   { "format_arg",             1, 1, false, true,  true, false,
+ 			      handle_format_arg_attribute, NULL },
+-  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
++};
++
++static const scoped_attribute_specs lto_format_attribute_table =
++{
++  "gnu", lto_format_attributes
++};
++
++static const scoped_attribute_specs *const lto_attribute_table[] =
++{
++  <o_gnu_attribute_table,
++  <o_format_attribute_table
+ };
+ 
+ enum built_in_attribute
+@@ -1453,10 +1467,8 @@ static void lto_init_ts (void)
+ #define LANG_HOOKS_EH_PERSONALITY lto_eh_personality
+ 
+ /* Attribute hooks.  */
+-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lto_attribute_table
+-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE lto_format_attribute_table
++#undef LANG_HOOKS_ATTRIBUTE_TABLE
++#define LANG_HOOKS_ATTRIBUTE_TABLE lto_attribute_table
+ 
+ #undef LANG_HOOKS_BEGIN_SECTION
+ #define LANG_HOOKS_BEGIN_SECTION lto_obj_begin_section
+diff --git a/gcc/plugin.h b/gcc/plugin.h
+index ff999c405..e29651d35 100644
+--- a/gcc/plugin.h
++++ b/gcc/plugin.h
+@@ -198,8 +198,7 @@ invoke_plugin_callbacks (int event ATTRIBUTE_UNUSED,
+ 
+ extern void register_attribute (const struct attribute_spec *attr);
+ /* The default argument for the third parameter is given in attribs.h.  */
+-extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
+-							     const char *,
++extern struct scoped_attributes* register_scoped_attributes (const struct scoped_attribute_spec &,
+ 							     bool);
+ 
+ #endif /* PLUGIN_H */
+diff --git a/gcc/target-def.h b/gcc/target-def.h
+index f81f8fe3b..70fb393f3 100644
+--- a/gcc/target-def.h
++++ b/gcc/target-def.h
+@@ -114,6 +114,20 @@
+ #define TARGET_FUNCTION_INCOMING_ARG TARGET_FUNCTION_ARG
+ #endif
+ 
++/* Declare a target attribute table called NAME that only has GNU attributes.
++   There should be no null trailing element.  E.g.:
++
++     TARGET_GNU_ATTRIBUTES (aarch64_attribute_table,
++     {
++       { "aarch64_vector_pcs", ... },
++       ...
++     });  */
++
++#define TARGET_GNU_ATTRIBUTES(NAME, ...) \
++  static const attribute_spec NAME##_2[] = __VA_ARGS__; \
++  static const scoped_attribute_specs NAME##_1 = { "gnu", NAME##_2 }; \
++  static const scoped_attribute_specs *const NAME[] = { &NAME##_1 }
++
+ #include "target-hooks-def.h"
+ 
+ #include "hooks.h"
+diff --git a/gcc/target.def b/gcc/target.def
+index 60096c60c..6cdc09fc2 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -2199,15 +2199,36 @@ merging.",
+  merge_type_attributes)
+ 
+ /* Table of machine attributes and functions to handle them.
+-   Ignored if NULL.  */
++   Ignored if empty.  */
+ DEFHOOKPOD
+ (attribute_table,
+- "If defined, this target hook points to an array of @samp{struct\n\
+-attribute_spec} (defined in @file{tree-core.h}) specifying the machine\n\
+-specific attributes for this target and some of the restrictions on the\n\
+-entities to which these attributes are applied and the arguments they\n\
+-take.",
+- const struct attribute_spec *, NULL)
++ "If defined, this target hook provides an array of\n\
++@samp{scoped_attribute_spec}s (defined in @file{attribs.h}) that specify the\n\
++machine-specific attributes for this target.  The information includes some\n\
++of the restrictions on the entities to which these attributes are applied\n\
++and the arguments that the attributes take.\n\
++\n\
++In C and C++, these attributes are associated with two syntaxes:\n\
++the traditional GNU @code{__attribute__} syntax and the standard\n\
++@samp{[[]]} syntax.  Attributes that support the GNU syntax must be\n\
++placed in the @code{gnu} namespace.  Such attributes can then also be\n\
++written @samp{[[gnu::@dots{}]]}.  Attributes that use only the standard\n\
++syntax should be placed in whichever namespace the attribute specification\n\
++requires.  For example, a target might choose to support vendor-specific\n\
++@samp{[[]]} attributes that the vendor places in their own namespace.\n\
++\n\
++Targets that only define attributes in the @code{gnu} namespace\n\
++can uase the following shorthand to define the table:\n\
++\n\
++@smallexample\n\
++TARGET_GNU_ATTRIBUTES (@var{cpu_attribute_table}, @{\n\
++  @{ \"@var{attribute1}\", @dots{} @},\n\
++  @{ \"@var{attribute2}\", @dots{} @},\n\
++  @dots{},\n\
++  @{ \"@var{attributen}\", @dots{} @},\n\
++@});\n\
++@end smallexample",
++ array_slice, {})
+ 
+ /* Return true iff attribute NAME expects a plain identifier as its first
+    argument.  */
+diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
+index f50dbbc52..67879c2c8 100644
+--- a/gcc/tree-inline.cc
++++ b/gcc/tree-inline.cc
+@@ -4105,17 +4105,16 @@ inline_forbidden_p (tree fndecl)
+ static bool
+ function_attribute_inlinable_p (const_tree fndecl)
+ {
+-  if (targetm.attribute_table)
++  for (auto scoped_attributes : targetm.attribute_table)
+     {
+       const_tree a;
+ 
+       for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
+ 	{
+ 	  const_tree name = get_attribute_name (a);
+-	  int i;
+ 
+-	  for (i = 0; targetm.attribute_table[i].name != NULL; i++)
+-	    if (is_attribute_p (targetm.attribute_table[i].name, name))
++	  for (const attribute_spec &attribute : scoped_attributes->attributes)
++	    if (is_attribute_p (attribute.name, name))
+ 	      return targetm.function_attribute_inlinable_p (fndecl);
+ 	}
+     }
+-- 
+2.33.0
+
diff --git a/0173-Backport-SME-aarch64-Fix-plugin-header-install.patch b/0173-Backport-SME-aarch64-Fix-plugin-header-install.patch
new file mode 100644
index 0000000..4bea8a5
--- /dev/null
+++ b/0173-Backport-SME-aarch64-Fix-plugin-header-install.patch
@@ -0,0 +1,64 @@
+From b1025ef48bff0622e54822dc0974f38748e9109f Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Thu, 22 Dec 2022 11:15:47 +0100
+Subject: [PATCH 074/157] [Backport][SME] aarch64: Fix plugin header install
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5b30e9bc211fede06cf85b54e466012540bef14d
+
+The r13-2943-g11a113d501ff64 made aarch64.h include
+aarch64-option-extensions.def, but that file isn't installed
+for building plugins.
+
+On Wed, Dec 21, 2022 at 09:56:33AM +0000, Richard Sandiford wrote:
+> Should this (and aarch64-fusion-pairs.def and aarch64-tuning-flags.def)
+> be in TM_H instead?  The first two OPTIONS_H_EXTRA entries seem to be
+> for aarch64-opt.h (included via aarch64.opt).
+>
+> I guess TM_H should also have aarch64-arches.def, since it's included
+> for aarch64_feature.
+
+gcc/Makefile.in has
+TM_H      = $(GTM_H) insn-flags.h $(OPTIONS_H)
+and
+OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
+which means that adding something into TM_H when it is already in
+OPTIONS_H_EXTRA is a unnecessary.
+It is true that aarch64-fusion-pairs.def (included by aarch64-protos.h)
+and aarch64-tuning-flags.def (ditto) and aarch64-option-extensions.def
+(included by aarch64.h) aren't needed for options.h, so I think the
+right patch would be following.
+
+2022-12-22  Jakub Jelinek  
+
+	* config/aarch64/t-aarch64 (TM_H): Don't add aarch64-cores.def,
+	add aarch64-fusion-pairs.def, aarch64-tuning-flags.def and
+	aarch64-option-extensions.def.
+	(OPTIONS_H_EXTRA): Don't add aarch64-fusion-pairs.def nor
+	aarch64-tuning-flags.def.
+---
+ gcc/config/aarch64/t-aarch64 | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
+index ba74abc0a..6a21a248f 100644
+--- a/gcc/config/aarch64/t-aarch64
++++ b/gcc/config/aarch64/t-aarch64
+@@ -18,11 +18,11 @@
+ #  along with GCC; see the file COPYING3.  If not see
+ #  .
+ 
+-TM_H += $(srcdir)/config/aarch64/aarch64-cores.def
++TM_H += $(srcdir)/config/aarch64/aarch64-fusion-pairs.def \
++	$(srcdir)/config/aarch64/aarch64-tuning-flags.def \
++	$(srcdir)/config/aarch64/aarch64-option-extensions.def
+ OPTIONS_H_EXTRA += $(srcdir)/config/aarch64/aarch64-cores.def \
+-		   $(srcdir)/config/aarch64/aarch64-arches.def \
+-		   $(srcdir)/config/aarch64/aarch64-fusion-pairs.def \
+-		   $(srcdir)/config/aarch64/aarch64-tuning-flags.def
++		   $(srcdir)/config/aarch64/aarch64-arches.def
+ 
+ $(srcdir)/config/aarch64/aarch64-tune.md: s-aarch64-tune-md; @true
+ s-aarch64-tune-md: $(srcdir)/config/aarch64/gentune.sh \
+-- 
+2.33.0
+
diff --git a/0174-Backport-SME-aarch64-Add-arm_streaming-_compatible-a.patch b/0174-Backport-SME-aarch64-Add-arm_streaming-_compatible-a.patch
new file mode 100644
index 0000000..381f4ce
--- /dev/null
+++ b/0174-Backport-SME-aarch64-Add-arm_streaming-_compatible-a.patch
@@ -0,0 +1,1178 @@
+From 70b732b4518dd0e44b9e6bfaaad78492b8db8f29 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:23 +0000
+Subject: [PATCH 075/157] [Backport][SME] aarch64: Add
+ arm_streaming(_compatible) attributes
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2c9a54b4238308b127c3b60b01a591363131e7db
+
+This patch adds support for recognising the SME arm::streaming
+and arm::streaming_compatible attributes.  These attributes
+respectively describe whether the processor is definitely in
+"streaming mode" (PSTATE.SM==1), whether the processor is
+definitely not in streaming mode (PSTATE.SM==0), or whether
+we don't know at compile time either way.
+
+As far as the compiler is concerned, this effectively creates three
+ISA submodes: streaming mode enables things that are not available
+in non-streaming mode, non-streaming mode enables things that not
+available in streaming mode, and streaming-compatible mode has to stick
+to the common subset.  This means that some instructions are conditional
+on PSTATE.SM==1 and some are conditional on PSTATE.SM==0.
+
+I wondered about recording the streaming state in a new variable.
+However, the set of available instructions is also influenced by
+PSTATE.ZA (added later), so I think it makes sense to view this
+as an instance of a more general mechanism.  Also, keeping the
+PSTATE.SM state in the same flag variable as the other ISA
+features makes it possible to sum up the requirements of an
+ACLE function in a single value.
+
+The patch therefore adds a new set of feature flags called "ISA modes".
+Unlike the other two sets of flags (optional features and architecture-
+level features), these ISA modes are not controlled directly by
+command-line parameters or "target" attributes.
+
+arm::streaming and arm::streaming_compatible are function type attributes
+rather than function declaration attributes.  This means that we need
+to find somewhere to copy the type information across to a function's
+target options.  The patch does this in aarch64_set_current_function.
+
+We also need to record which ISA mode a callee expects/requires
+to be active on entry.  (The same mode is then active on return.)
+The patch extends the current UNSPEC_CALLEE_ABI cookie to include
+this information, as well as the PCS variant that it recorded
+previously.
+
+The attributes can also be written __arm_streaming and
+__arm_streaming_compatible.  This has two advantages: it triggers
+an error on compilers that don't understand the attributes, and it
+eases use on C, where [[...]] attributes were only added in C23.
+
+gcc/
+	* config/aarch64/aarch64-isa-modes.def: New file.
+	* config/aarch64/aarch64.h: Include it in the feature enumerations.
+	(AARCH64_FL_SM_STATE, AARCH64_FL_ISA_MODES): New constants.
+	(AARCH64_FL_DEFAULT_ISA_MODE): Likewise.
+	(AARCH64_ISA_MODE): New macro.
+	(CUMULATIVE_ARGS): Add an isa_mode field.
+	* config/aarch64/aarch64-protos.h (aarch64_gen_callee_cookie): Declare.
+	(aarch64_tlsdesc_abi_id): Return an arm_pcs.
+	* config/aarch64/aarch64.cc (attr_streaming_exclusions)
+	(aarch64_gnu_attributes, aarch64_gnu_attribute_table)
+	(aarch64_arm_attributes, aarch64_arm_attribute_table): New tables.
+	(aarch64_attribute_table): Redefine to include the gnu and arm
+	attributes.
+	(aarch64_fntype_pstate_sm, aarch64_fntype_isa_mode): New functions.
+	(aarch64_fndecl_pstate_sm, aarch64_fndecl_isa_mode): Likewise.
+	(aarch64_gen_callee_cookie, aarch64_callee_abi): Likewise.
+	(aarch64_insn_callee_cookie, aarch64_insn_callee_abi): Use them.
+	(aarch64_function_arg, aarch64_output_mi_thunk): Likewise.
+	(aarch64_init_cumulative_args): Initialize the isa_mode field.
+	(aarch64_output_mi_thunk): Use aarch64_gen_callee_cookie to get
+	the ABI cookie.
+	(aarch64_override_options): Add the ISA mode to the feature set.
+	(aarch64_temporary_target::copy_from_fndecl): Likewise.
+	(aarch64_fndecl_options, aarch64_handle_attr_arch): Likewise.
+	(aarch64_set_current_function): Maintain the correct ISA mode.
+	(aarch64_tlsdesc_abi_id): Return an arm_pcs.
+	(aarch64_comp_type_attributes): Handle arm::streaming and
+	arm::streaming_compatible.
+	* config/aarch64/aarch64-c.cc (aarch64_define_unconditional_macros):
+	Define __arm_streaming and __arm_streaming_compatible.
+	* config/aarch64/aarch64.md (tlsdesc_small_): Use
+	aarch64_gen_callee_cookie to get the ABI cookie.
+	* config/aarch64/t-aarch64 (TM_H): Add all feature-related .def files.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/aarch64-sme.exp: New harness.
+	* gcc.target/aarch64/sme/streaming_mode_1.c: New test.
+	* gcc.target/aarch64/sme/streaming_mode_2.c: Likewise.
+	* gcc.target/aarch64/sme/keyword_macros_1.c: Likewise.
+	* g++.target/aarch64/sme/aarch64-sme.exp: New harness.
+	* g++.target/aarch64/sme/streaming_mode_1.C: New test.
+	* g++.target/aarch64/sme/streaming_mode_2.C: Likewise.
+	* g++.target/aarch64/sme/keyword_macros_1.C: Likewise.
+	* gcc.target/aarch64/auto-init-1.c: Only expect the call insn
+	to contain 1 (const_int 0), not 2.
+---
+ gcc/config/aarch64/aarch64-c.cc               |  14 ++
+ gcc/config/aarch64/aarch64-isa-modes.def      |  35 +++
+ gcc/config/aarch64/aarch64-protos.h           |   3 +-
+ gcc/config/aarch64/aarch64.cc                 | 233 +++++++++++++++---
+ gcc/config/aarch64/aarch64.h                  |  24 +-
+ gcc/config/aarch64/aarch64.md                 |   3 +-
+ gcc/config/aarch64/t-aarch64                  |   5 +-
+ .../g++.target/aarch64/sme/aarch64-sme.exp    |  40 +++
+ .../g++.target/aarch64/sme/keyword_macros_1.C |   4 +
+ .../g++.target/aarch64/sme/streaming_mode_1.C | 142 +++++++++++
+ .../g++.target/aarch64/sme/streaming_mode_2.C |  25 ++
+ .../gcc.target/aarch64/auto-init-1.c          |   3 +-
+ .../gcc.target/aarch64/sme/aarch64-sme.exp    |  40 +++
+ .../gcc.target/aarch64/sme/keyword_macros_1.c |   4 +
+ .../gcc.target/aarch64/sme/streaming_mode_1.c | 130 ++++++++++
+ .../gcc.target/aarch64/sme/streaming_mode_2.c |  25 ++
+ 16 files changed, 685 insertions(+), 45 deletions(-)
+ create mode 100644 gcc/config/aarch64/aarch64-isa-modes.def
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 4085ad840..397745fbd 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -72,6 +72,20 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
+   builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8);
+ 
+   builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
++
++  /* Define keyword attributes like __arm_streaming as macros that expand
++     to the associated [[...]] attribute.  Use __extension__ in the attribute
++     for C, since the [[...]] syntax was only added in C23.  */
++#define DEFINE_ARM_KEYWORD_MACRO(NAME) \
++  builtin_define_with_value ("__arm_" NAME, \
++			     lang_GNU_CXX () \
++			     ? "[[arm::" NAME "]]" \
++			     : "[[__extension__ arm::" NAME "]]", 0);
++
++  DEFINE_ARM_KEYWORD_MACRO ("streaming");
++  DEFINE_ARM_KEYWORD_MACRO ("streaming_compatible");
++
++#undef DEFINE_ARM_KEYWORD_MACRO
+ }
+ 
+ /* Undefine/redefine macros that depend on the current backend state and may
+diff --git a/gcc/config/aarch64/aarch64-isa-modes.def b/gcc/config/aarch64/aarch64-isa-modes.def
+new file mode 100644
+index 000000000..5915c98a8
+--- /dev/null
++++ b/gcc/config/aarch64/aarch64-isa-modes.def
+@@ -0,0 +1,35 @@
++/* Copyright (C) 2023 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
++   .  */
++
++/* This file defines a set of "ISA modes"; in other words, it defines
++   various bits of runtime state that control the set of available
++   instructions or that affect the semantics of instructions in some way.
++
++   Before using #include to read this file, define a macro:
++
++      DEF_AARCH64_ISA_MODE(NAME)
++
++   where NAME is the name of the mode.  */
++
++/* Indicates that PSTATE.SM is known to be 1 or 0 respectively.  These
++   modes are mutually exclusive.  If neither mode is active then the state
++   of PSTATE.SM is not known at compile time.  */
++DEF_AARCH64_ISA_MODE(SM_ON)
++DEF_AARCH64_ISA_MODE(SM_OFF)
++
++#undef DEF_AARCH64_ISA_MODE
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 14a568140..9b03410dc 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -772,6 +772,7 @@ bool aarch64_constant_address_p (rtx);
+ bool aarch64_emit_approx_div (rtx, rtx, rtx);
+ bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
+ tree aarch64_vector_load_decl (tree);
++rtx aarch64_gen_callee_cookie (aarch64_feature_flags, arm_pcs);
+ void aarch64_expand_call (rtx, rtx, rtx, bool);
+ bool aarch64_expand_cpymem (rtx *);
+ bool aarch64_expand_setmem (rtx *);
+@@ -851,7 +852,7 @@ bool aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT);
+ bool aarch64_use_return_insn_p (void);
+ const char *aarch64_output_casesi (rtx *);
+ 
+-unsigned int aarch64_tlsdesc_abi_id ();
++arm_pcs aarch64_tlsdesc_abi_id ();
+ enum aarch64_symbol_type aarch64_classify_symbol (rtx, HOST_WIDE_INT);
+ enum aarch64_symbol_type aarch64_classify_tls_symbol (rtx);
+ enum reg_class aarch64_regno_regclass (unsigned);
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 114252a3c..904166b21 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -2985,8 +2985,18 @@ handle_aarch64_vector_pcs_attribute (tree *node, tree name, tree,
+   gcc_unreachable ();
+ }
+ 
++/* Mutually-exclusive function type attributes for controlling PSTATE.SM.  */
++static const struct attribute_spec::exclusions attr_streaming_exclusions[] =
++{
++  /* Attribute name     exclusion applies to:
++			function, type, variable */
++  { "streaming", false, true, false },
++  { "streaming_compatible", false, true, false },
++  { NULL, false, false, false }
++};
++
+ /* Table of machine attributes.  */
+-TARGET_GNU_ATTRIBUTES (aarch64_attribute_table,
++static const attribute_spec aarch64_gnu_attributes[] =
+ {
+   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+        affects_type_identity, handler, exclude } */
+@@ -2998,7 +3008,31 @@ TARGET_GNU_ATTRIBUTES (aarch64_attribute_table,
+   { "Advanced SIMD type", 1, 1, false, true,  false, true,  NULL, NULL },
+   { "SVE type",		  3, 3, false, true,  false, true,  NULL, NULL },
+   { "SVE sizeless type",  0, 0, false, true,  false, true,  NULL, NULL }
+-});
++};
++
++static const scoped_attribute_specs aarch64_gnu_attribute_table =
++{
++  "gnu", aarch64_gnu_attributes
++};
++
++static const attribute_spec aarch64_arm_attributes[] =
++{
++  { "streaming",	  0, 0, false, true,  true,  true,
++			  NULL, attr_streaming_exclusions },
++  { "streaming_compatible", 0, 0, false, true,  true,  true,
++			  NULL, attr_streaming_exclusions },
++};
++
++static const scoped_attribute_specs aarch64_arm_attribute_table =
++{
++  "arm", aarch64_arm_attributes
++};
++
++static const scoped_attribute_specs *const aarch64_attribute_table[] =
++{
++  &aarch64_gnu_attribute_table,
++  &aarch64_arm_attribute_table
++};
+ 
+ /* An ISA extension in the co-processor and main instruction set space.  */
+ struct aarch64_option_extension
+@@ -4301,6 +4335,48 @@ aarch64_fntype_abi (const_tree fntype)
+   return default_function_abi;
+ }
+ 
++/* Return the state of PSTATE.SM on entry to functions of type FNTYPE.  */
++
++static aarch64_feature_flags
++aarch64_fntype_pstate_sm (const_tree fntype)
++{
++  if (lookup_attribute ("arm", "streaming", TYPE_ATTRIBUTES (fntype)))
++    return AARCH64_FL_SM_ON;
++
++  if (lookup_attribute ("arm", "streaming_compatible",
++			TYPE_ATTRIBUTES (fntype)))
++    return 0;
++
++  return AARCH64_FL_SM_OFF;
++}
++
++/* Return the ISA mode on entry to functions of type FNTYPE.  */
++
++static aarch64_feature_flags
++aarch64_fntype_isa_mode (const_tree fntype)
++{
++  return aarch64_fntype_pstate_sm (fntype);
++}
++
++/* Return the state of PSTATE.SM when compiling the body of
++   function FNDECL.  This might be different from the state of
++   PSTATE.SM on entry.  */
++
++static aarch64_feature_flags
++aarch64_fndecl_pstate_sm (const_tree fndecl)
++{
++  return aarch64_fntype_pstate_sm (TREE_TYPE (fndecl));
++}
++
++/* Return the ISA mode that should be used to compile the body of
++   function FNDECL.  */
++
++static aarch64_feature_flags
++aarch64_fndecl_isa_mode (const_tree fndecl)
++{
++  return aarch64_fndecl_pstate_sm (fndecl);
++}
++
+ /* Implement TARGET_COMPATIBLE_VECTOR_TYPES_P.  */
+ 
+ static bool
+@@ -4363,17 +4439,46 @@ aarch64_reg_save_mode (unsigned int regno)
+   gcc_unreachable ();
+ }
+ 
+-/* Implement TARGET_INSN_CALLEE_ABI.  */
++/* Given the ISA mode on entry to a callee and the ABI of the callee,
++   return the CONST_INT that should be placed in an UNSPEC_CALLEE_ABI rtx.  */
+ 
+-const predefined_function_abi &
+-aarch64_insn_callee_abi (const rtx_insn *insn)
++rtx
++aarch64_gen_callee_cookie (aarch64_feature_flags isa_mode, arm_pcs pcs_variant)
++{
++  return gen_int_mode ((unsigned int) isa_mode
++		       | (unsigned int) pcs_variant << AARCH64_NUM_ISA_MODES,
++		       DImode);
++}
++
++/* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx.  Return the
++   callee's ABI.  */
++
++static const predefined_function_abi &
++aarch64_callee_abi (rtx cookie)
++{
++  return function_abis[UINTVAL (cookie) >> AARCH64_NUM_ISA_MODES];
++}
++
++/* INSN is a call instruction.  Return the CONST_INT stored in its
++   UNSPEC_CALLEE_ABI rtx.  */
++
++static rtx
++aarch64_insn_callee_cookie (const rtx_insn *insn)
+ {
+   rtx pat = PATTERN (insn);
+   gcc_assert (GET_CODE (pat) == PARALLEL);
+   rtx unspec = XVECEXP (pat, 0, 1);
+   gcc_assert (GET_CODE (unspec) == UNSPEC
+ 	      && XINT (unspec, 1) == UNSPEC_CALLEE_ABI);
+-  return function_abis[INTVAL (XVECEXP (unspec, 0, 0))];
++  return XVECEXP (unspec, 0, 0);
++}
++
++/* Implement TARGET_INSN_CALLEE_ABI.  */
++
++const predefined_function_abi &
++aarch64_insn_callee_abi (const rtx_insn *insn)
++{
++  return aarch64_callee_abi (aarch64_insn_callee_cookie (insn));
+ }
+ 
+ /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The callee only saves
+@@ -8117,7 +8222,7 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
+ 	      || pcum->pcs_variant == ARM_PCS_SVE);
+ 
+   if (arg.end_marker_p ())
+-    return gen_int_mode (pcum->pcs_variant, DImode);
++    return aarch64_gen_callee_cookie (pcum->isa_mode, pcum->pcs_variant);
+ 
+   aarch64_layout_arg (pcum_v, arg);
+   return pcum->aapcs_reg;
+@@ -8138,9 +8243,15 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum,
+   pcum->aapcs_nextnvrn = 0;
+   pcum->aapcs_nextnprn = 0;
+   if (fntype)
+-    pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id ();
++    {
++      pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id ();
++      pcum->isa_mode = aarch64_fntype_isa_mode (fntype);
++    }
+   else
+-    pcum->pcs_variant = ARM_PCS_AAPCS64;
++    {
++      pcum->pcs_variant = ARM_PCS_AAPCS64;
++      pcum->isa_mode = AARCH64_FL_DEFAULT_ISA_MODE;
++    }
+   pcum->aapcs_reg = NULL_RTX;
+   pcum->aapcs_arg_processed = false;
+   pcum->aapcs_stack_words = 0;
+@@ -10627,7 +10738,9 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+     }
+   funexp = XEXP (DECL_RTL (function), 0);
+   funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
+-  rtx callee_abi = gen_int_mode (fndecl_abi (function).id (), DImode);
++  auto isa_mode = aarch64_fntype_isa_mode (TREE_TYPE (function));
++  auto pcs_variant = arm_pcs (fndecl_abi (function).id ());
++  rtx callee_abi = aarch64_gen_callee_cookie (isa_mode, pcs_variant);
+   insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi));
+   SIBLING_CALL_P (insn) = 1;
+ 
+@@ -18618,6 +18731,7 @@ aarch64_override_options (void)
+   SUBTARGET_OVERRIDE_OPTIONS;
+ #endif
+ 
++  auto isa_mode = AARCH64_FL_DEFAULT_ISA_MODE;
+   if (cpu && arch)
+     {
+       /* If both -mcpu and -march are specified, warn if they are not
+@@ -18630,25 +18744,25 @@ aarch64_override_options (void)
+ 	}
+ 
+       selected_arch = arch->arch;
+-      aarch64_set_asm_isa_flags (arch_isa);
++      aarch64_set_asm_isa_flags (arch_isa | isa_mode);
+     }
+   else if (cpu)
+     {
+       selected_arch = cpu->arch;
+-      aarch64_set_asm_isa_flags (cpu_isa);
++      aarch64_set_asm_isa_flags (cpu_isa | isa_mode);
+     }
+   else if (arch)
+     {
+       cpu = &all_cores[arch->ident];
+       selected_arch = arch->arch;
+-      aarch64_set_asm_isa_flags (arch_isa);
++      aarch64_set_asm_isa_flags (arch_isa | isa_mode);
+     }
+   else
+     {
+       /* No -mcpu or -march specified, so use the default CPU.  */
+       cpu = &all_cores[TARGET_CPU_DEFAULT];
+       selected_arch = cpu->arch;
+-      aarch64_set_asm_isa_flags (cpu->flags);
++      aarch64_set_asm_isa_flags (cpu->flags | isa_mode);
+     }
+ 
+   selected_tune = tune ? tune->ident : cpu->ident;
+@@ -18821,6 +18935,21 @@ aarch64_save_restore_target_globals (tree new_tree)
+     TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts ();
+ }
+ 
++/* Return the target_option_node for FNDECL, or the current options
++   if FNDECL is null.  */
++
++static tree
++aarch64_fndecl_options (tree fndecl)
++{
++  if (!fndecl)
++    return target_option_current_node;
++
++  if (tree options = DECL_FUNCTION_SPECIFIC_TARGET (fndecl))
++    return options;
++
++  return target_option_default_node;
++}
++
+ /* Implement TARGET_SET_CURRENT_FUNCTION.  Unpack the codegen decisions
+    like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET
+    of the function, if such exists.  This function may be called multiple
+@@ -18830,25 +18959,24 @@ aarch64_save_restore_target_globals (tree new_tree)
+ static void
+ aarch64_set_current_function (tree fndecl)
+ {
+-  if (!fndecl || fndecl == aarch64_previous_fndecl)
+-    return;
+-
+-  tree old_tree = (aarch64_previous_fndecl
+-		   ? DECL_FUNCTION_SPECIFIC_TARGET (aarch64_previous_fndecl)
+-		   : NULL_TREE);
+-
+-  tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
++  tree old_tree = aarch64_fndecl_options (aarch64_previous_fndecl);
++  tree new_tree = aarch64_fndecl_options (fndecl);
+ 
+-  /* If current function has no attributes but the previous one did,
+-     use the default node.  */
+-  if (!new_tree && old_tree)
+-    new_tree = target_option_default_node;
++  auto new_isa_mode = (fndecl
++		       ? aarch64_fndecl_isa_mode (fndecl)
++		       : AARCH64_FL_DEFAULT_ISA_MODE);
++  auto isa_flags = TREE_TARGET_OPTION (new_tree)->x_aarch64_isa_flags;
+ 
+   /* If nothing to do, return.  #pragma GCC reset or #pragma GCC pop to
+      the default have been handled by aarch64_save_restore_target_globals from
+      aarch64_pragma_target_parse.  */
+-  if (old_tree == new_tree)
+-    return;
++  if (old_tree == new_tree
++      && (!fndecl || aarch64_previous_fndecl)
++      && (isa_flags & AARCH64_FL_ISA_MODES) == new_isa_mode)
++    {
++      gcc_assert (AARCH64_ISA_MODE == new_isa_mode);
++      return;
++    }
+ 
+   aarch64_previous_fndecl = fndecl;
+ 
+@@ -18856,7 +18984,28 @@ aarch64_set_current_function (tree fndecl)
+   cl_target_option_restore (&global_options, &global_options_set,
+ 			    TREE_TARGET_OPTION (new_tree));
+ 
++  /* The ISA mode can vary based on function type attributes and
++     function declaration attributes.  Make sure that the target
++     options correctly reflect these attributes.  */
++  if ((isa_flags & AARCH64_FL_ISA_MODES) != new_isa_mode)
++    {
++      auto base_flags = (aarch64_asm_isa_flags & ~AARCH64_FL_ISA_MODES);
++      aarch64_set_asm_isa_flags (base_flags | new_isa_mode);
++
++      aarch64_override_options_internal (&global_options);
++      new_tree = build_target_option_node (&global_options,
++					   &global_options_set);
++      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_tree;
++
++      tree new_optimize = build_optimization_node (&global_options,
++						   &global_options_set);
++      if (new_optimize != optimization_default_node)
++	DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
++    }
++
+   aarch64_save_restore_target_globals (new_tree);
++
++  gcc_assert (AARCH64_ISA_MODE == new_isa_mode);
+ }
+ 
+ /* Enum describing the various ways we can handle attributes.
+@@ -18906,7 +19055,7 @@ aarch64_handle_attr_arch (const char *str)
+     {
+       gcc_assert (tmp_arch);
+       selected_arch = tmp_arch->arch;
+-      aarch64_set_asm_isa_flags (tmp_flags);
++      aarch64_set_asm_isa_flags (tmp_flags | AARCH64_ISA_MODE);
+       return true;
+     }
+ 
+@@ -18947,7 +19096,7 @@ aarch64_handle_attr_cpu (const char *str)
+       gcc_assert (tmp_cpu);
+       selected_tune = tmp_cpu->ident;
+       selected_arch = tmp_cpu->arch;
+-      aarch64_set_asm_isa_flags (tmp_flags);
++      aarch64_set_asm_isa_flags (tmp_flags | AARCH64_ISA_MODE);
+       return true;
+     }
+ 
+@@ -19047,7 +19196,7 @@ aarch64_handle_attr_isa_flags (char *str)
+      features if the user wants to handpick specific features.  */
+   if (strncmp ("+nothing", str, 8) == 0)
+     {
+-      isa_flags = 0;
++      isa_flags = AARCH64_ISA_MODE;
+       str += 8;
+     }
+ 
+@@ -19552,7 +19701,7 @@ aarch64_can_inline_p (tree caller, tree callee)
+ /* Return the ID of the TLDESC ABI, initializing the descriptor if hasn't
+    been already.  */
+ 
+-unsigned int
++arm_pcs
+ aarch64_tlsdesc_abi_id ()
+ {
+   predefined_function_abi &tlsdesc_abi = function_abis[ARM_PCS_TLSDESC];
+@@ -19566,7 +19715,7 @@ aarch64_tlsdesc_abi_id ()
+ 	SET_HARD_REG_BIT (full_reg_clobbers, regno);
+       tlsdesc_abi.initialize (ARM_PCS_TLSDESC, full_reg_clobbers);
+     }
+-  return tlsdesc_abi.id ();
++  return ARM_PCS_TLSDESC;
+ }
+ 
+ /* Return true if SYMBOL_REF X binds locally.  */
+@@ -27270,22 +27419,26 @@ aarch64_simd_clone_usable (struct cgraph_node *node)
+ static int
+ aarch64_comp_type_attributes (const_tree type1, const_tree type2)
+ {
+-  auto check_attr = [&](const char *name) {
+-    tree attr1 = lookup_attribute (name, TYPE_ATTRIBUTES (type1));
+-    tree attr2 = lookup_attribute (name, TYPE_ATTRIBUTES (type2));
++  auto check_attr = [&](const char *ns, const char *name) {
++    tree attr1 = lookup_attribute (ns, name, TYPE_ATTRIBUTES (type1));
++    tree attr2 = lookup_attribute (ns, name, TYPE_ATTRIBUTES (type2));
+     if (!attr1 && !attr2)
+       return true;
+ 
+     return attr1 && attr2 && attribute_value_equal (attr1, attr2);
+   };
+ 
+-  if (!check_attr ("aarch64_vector_pcs"))
++  if (!check_attr ("gnu", "aarch64_vector_pcs"))
++    return 0;
++  if (!check_attr ("gnu", "Advanced SIMD type"))
++    return 0;
++  if (!check_attr ("gnu", "SVE type"))
+     return 0;
+-  if (!check_attr ("Advanced SIMD type"))
++  if (!check_attr ("gnu", "SVE sizeless type"))
+     return 0;
+-  if (!check_attr ("SVE type"))
++  if (!check_attr ("arm", "streaming"))
+     return 0;
+-  if (!check_attr ("SVE sizeless type"))
++  if (!check_attr ("arm", "streaming_compatible"))
+     return 0;
+   return 1;
+ }
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 19b82b4f3..84215c8c3 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -157,10 +157,13 @@
+ 
+ #ifndef USED_FOR_TARGET
+ 
+-/* Define an enum of all features (architectures and extensions).  */
++/* Define an enum of all features (ISA modes, architectures and extensions).
++   The ISA modes must come first.  */
+ enum class aarch64_feature : unsigned char {
++#define DEF_AARCH64_ISA_MODE(IDENT) IDENT,
+ #define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) IDENT,
+ #define AARCH64_ARCH(A, B, IDENT, D, E) IDENT,
++#include "aarch64-isa-modes.def"
+ #include "aarch64-option-extensions.def"
+ #include "aarch64-arches.def"
+ };
+@@ -169,16 +172,34 @@ enum class aarch64_feature : unsigned char {
+ #define HANDLE(IDENT) \
+   constexpr auto AARCH64_FL_##IDENT \
+     = aarch64_feature_flags (1) << int (aarch64_feature::IDENT);
++#define DEF_AARCH64_ISA_MODE(IDENT) HANDLE (IDENT)
+ #define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F) HANDLE (IDENT)
+ #define AARCH64_ARCH(A, B, IDENT, D, E) HANDLE (IDENT)
++#include "aarch64-isa-modes.def"
+ #include "aarch64-option-extensions.def"
+ #include "aarch64-arches.def"
+ #undef HANDLE
+ 
++constexpr auto AARCH64_FL_SM_STATE = AARCH64_FL_SM_ON | AARCH64_FL_SM_OFF;
++
++constexpr unsigned int AARCH64_NUM_ISA_MODES = (0
++#define DEF_AARCH64_ISA_MODE(IDENT) + 1
++#include "aarch64-isa-modes.def"
++);
++
++/* The mask of all ISA modes.  */
++constexpr auto AARCH64_FL_ISA_MODES
++  = (aarch64_feature_flags (1) << AARCH64_NUM_ISA_MODES) - 1;
++
++/* The default ISA mode, for functions with no attributes that specify
++   something to the contrary.  */
++constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
++
+ #endif
+ 
+ /* Macros to test ISA flags.  */
+ 
++#define AARCH64_ISA_MODE           (aarch64_isa_flags & AARCH64_FL_ISA_MODES)
+ #define AARCH64_ISA_CRC            (aarch64_isa_flags & AARCH64_FL_CRC)
+ #define AARCH64_ISA_CRYPTO         (aarch64_isa_flags & AARCH64_FL_CRYPTO)
+ #define AARCH64_ISA_FP             (aarch64_isa_flags & AARCH64_FL_FP)
+@@ -904,6 +925,7 @@ enum arm_pcs
+ typedef struct
+ {
+   enum arm_pcs pcs_variant;
++  aarch64_feature_flags isa_mode;
+   int aapcs_arg_processed;	/* No need to lay out this argument again.  */
+   int aapcs_ncrn;		/* Next Core register number.  */
+   int aapcs_nextncrn;		/* Next next core register number.  */
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index c0977a3da..29a665e45 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -7017,7 +7017,8 @@
+   {
+     if (TARGET_SVE)
+       {
+-	rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode);
++	rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE,
++					     aarch64_tlsdesc_abi_id ());
+ 	rtx_insn *call
+ 	  = emit_call_insn (gen_tlsdesc_small_sve_ (operands[0], abi));
+ 	RTL_CONST_CALL_P (call) = 1;
+diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
+index 6a21a248f..10cd8f093 100644
+--- a/gcc/config/aarch64/t-aarch64
++++ b/gcc/config/aarch64/t-aarch64
+@@ -20,7 +20,10 @@
+ 
+ TM_H += $(srcdir)/config/aarch64/aarch64-fusion-pairs.def \
+ 	$(srcdir)/config/aarch64/aarch64-tuning-flags.def \
+-	$(srcdir)/config/aarch64/aarch64-option-extensions.def
++	$(srcdir)/config/aarch64/aarch64-option-extensions.def \
++	$(srcdir)/config/aarch64/aarch64-cores.def \
++	$(srcdir)/config/aarch64/aarch64-isa-modes.def \
++	$(srcdir)/config/aarch64/aarch64-arches.def
+ OPTIONS_H_EXTRA += $(srcdir)/config/aarch64/aarch64-cores.def \
+ 		   $(srcdir)/config/aarch64/aarch64-arches.def
+ 
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp
+new file mode 100644
+index 000000000..72fcd0bd9
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp
+@@ -0,0 +1,40 @@
++#  Specific regression driver for AArch64 SME.
++#  Copyright (C) 2009-2023 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
++#  .  */
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Exit immediately if this isn't an AArch64 target.
++if {![istarget aarch64*-*-*] } {
++    return
++}
++
++# Load support procs.
++load_lib g++-dg.exp
++
++# Initialize `dg'.
++dg-init
++
++aarch64-with-arch-dg-options "" {
++    # Main loop.
++    dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
++	"" ""
++}
++
++# All done.
++dg-finish
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+new file mode 100644
+index 000000000..032485adf
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+@@ -0,0 +1,4 @@
++/* { dg-options "-std=c++11 -pedantic-errors" } */
++
++void f1 () __arm_streaming;
++void f2 () __arm_streaming_compatible;
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C
+new file mode 100644
+index 000000000..c3de726e7
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_1.C
+@@ -0,0 +1,142 @@
++// { dg-options "" }
++
++void sc_a () [[arm::streaming_compatible]];
++void sc_a (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } }
++
++void sc_b ();
++void sc_b () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" }
++
++void sc_c () [[arm::streaming_compatible]];
++void sc_c () {} // Inherits attribute from declaration (confusingly).
++
++void sc_d ();
++void sc_d () [[arm::streaming_compatible]] {} // { dg-error "ambiguating new declaration" }
++
++void sc_e () [[arm::streaming_compatible]] {}
++void sc_e (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } }
++
++void sc_f () {}
++void sc_f () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" }
++
++extern void (*sc_g) ();
++extern void (*sc_g) () [[arm::streaming_compatible]]; // { dg-error "conflicting declaration" }
++
++extern void (*sc_h) () [[arm::streaming_compatible]];
++extern void (*sc_h) (); // { dg-error "conflicting declaration" }
++
++//----------------------------------------------------------------------------
++
++void s_a () [[arm::streaming]];
++void s_a (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } }
++
++void s_b ();
++void s_b () [[arm::streaming]]; // { dg-error "ambiguating new declaration" }
++
++void s_c () [[arm::streaming]];
++void s_c () {} // Inherits attribute from declaration (confusingly).
++
++void s_d ();
++void s_d () [[arm::streaming]] {} // { dg-error "ambiguating new declaration" }
++
++void s_e () [[arm::streaming]] {}
++void s_e (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } }
++
++void s_f () {}
++void s_f () [[arm::streaming]]; // { dg-error "ambiguating new declaration" }
++
++extern void (*s_g) ();
++extern void (*s_g) () [[arm::streaming]]; // { dg-error "conflicting declaration" }
++
++extern void (*s_h) () [[arm::streaming]];
++extern void (*s_h) (); // { dg-error "conflicting declaration" }
++
++//----------------------------------------------------------------------------
++
++void mixed_a () [[arm::streaming]];
++void mixed_a () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" }
++
++void mixed_b () [[arm::streaming_compatible]];
++void mixed_b () [[arm::streaming]]; // { dg-error "ambiguating new declaration" }
++
++void mixed_c () [[arm::streaming]];
++void mixed_c () [[arm::streaming_compatible]] {} // { dg-error "ambiguating new declaration" }
++
++void mixed_d () [[arm::streaming_compatible]];
++void mixed_d () [[arm::streaming]] {} // { dg-error "ambiguating new declaration" }
++
++void mixed_e () [[arm::streaming]] {}
++void mixed_e () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" }
++
++void mixed_f () [[arm::streaming_compatible]] {}
++void mixed_f () [[arm::streaming]]; // { dg-error "ambiguating new declaration" }
++
++extern void (*mixed_g) () [[arm::streaming_compatible]];
++extern void (*mixed_g) () [[arm::streaming]]; // { dg-error "conflicting declaration" }
++
++extern void (*mixed_h) () [[arm::streaming]];
++extern void (*mixed_h) () [[arm::streaming_compatible]]; // { dg-error "conflicting declaration" }
++
++//----------------------------------------------------------------------------
++
++void contradiction_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++void contradiction_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++
++int [[arm::streaming_compatible]] int_attr; // { dg-warning "attribute ignored" }
++void [[arm::streaming_compatible]] ret_attr (); // { dg-warning "attribute ignored" }
++void *[[arm::streaming]] ptr_attr; // { dg-warning "only applies to function types" }
++
++typedef void s_callback () [[arm::streaming]];
++typedef void sc_callback () [[arm::streaming_compatible]];
++
++typedef void contradiction_callback_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++typedef void contradiction_callback_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++
++void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++
++struct s {
++  void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++  void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++};
++
++//----------------------------------------------------------------------------
++
++void keyword_ok_1 () __arm_streaming;
++void keyword_ok_1 () __arm_streaming;
++
++void keyword_ok_2 () __arm_streaming;
++void keyword_ok_2 () [[arm::streaming]];
++
++void keyword_ok_3 () [[arm::streaming]];
++void keyword_ok_3 () __arm_streaming;
++
++void keyword_ok_4 () __arm_streaming [[arm::streaming]];
++
++void keyword_ok_5 () __arm_streaming_compatible;
++void keyword_ok_5 () [[arm::streaming_compatible]];
++
++//----------------------------------------------------------------------------
++
++void keyword_contradiction_1 () __arm_streaming;
++void keyword_contradiction_1 (); // { dg-error "ambiguating new declaration" "" { xfail *-*-* } }
++
++void keyword_contradiction_2 ();
++void keyword_contradiction_2 () __arm_streaming; // { dg-error "ambiguating new declaration" }
++
++void keyword_contradiction_3 () __arm_streaming;
++void keyword_contradiction_3 () [[arm::streaming_compatible]]; // { dg-error "ambiguating new declaration" }
++
++void keyword_contradiction_4 () [[arm::streaming_compatible]];
++void keyword_contradiction_4 () __arm_streaming; // { dg-error "ambiguating new declaration" }
++
++//----------------------------------------------------------------------------
++
++struct s1
++{
++  virtual void f () [[arm::streaming]];
++};
++
++struct s2 : public s1
++{
++  void f () override; // { dg-error "conflicting type attributes" }
++};
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C
+new file mode 100644
+index 000000000..f2dd2db9b
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/streaming_mode_2.C
+@@ -0,0 +1,25 @@
++// { dg-options "" }
++
++void sc_fn () [[arm::streaming_compatible]];
++void s_fn () [[arm::streaming]];
++void ns_fn ();
++
++void (*sc_fn_ptr) () [[arm::streaming_compatible]];
++void (*s_fn_ptr) () [[arm::streaming]];
++void (*ns_fn_ptr) ();
++
++void
++f ()
++{
++  sc_fn_ptr = sc_fn;
++  sc_fn_ptr = s_fn; // { dg-error "invalid conversion" }
++  sc_fn_ptr = ns_fn; // { dg-error "invalid conversion" }
++
++  s_fn_ptr = sc_fn; // { dg-error "invalid conversion" }
++  s_fn_ptr = s_fn;
++  s_fn_ptr = ns_fn; // { dg-error "invalid conversion" }
++
++  ns_fn_ptr = sc_fn; // { dg-error "invalid conversion" }
++  ns_fn_ptr = s_fn; // { dg-error "invalid conversion" }
++  ns_fn_ptr = ns_fn;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
+index 0fa470880..45bb02561 100644
+--- a/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
++++ b/gcc/testsuite/gcc.target/aarch64/auto-init-1.c
+@@ -29,4 +29,5 @@ void foo()
+   return;
+ }
+ 
+-/* { dg-final { scan-rtl-dump-times "const_int 0" 11 "expand" } } */
++/* Includes 1 for the call instruction and 1 for a nop.  */
++/* { dg-final { scan-rtl-dump-times "const_int 0" 10 "expand" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp
+new file mode 100644
+index 000000000..c990e5924
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp
+@@ -0,0 +1,40 @@
++#  Specific regression driver for AArch64 SME.
++#  Copyright (C) 2009-2023 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
++#  .  */
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Exit immediately if this isn't an AArch64 target.
++if {![istarget aarch64*-*-*] } {
++    return
++}
++
++# Load support procs.
++load_lib gcc-dg.exp
++
++# Initialize `dg'.
++dg-init
++
++aarch64-with-arch-dg-options "" {
++    # Main loop.
++    dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
++	"" ""
++}
++
++# All done.
++dg-finish
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+new file mode 100644
+index 000000000..8f1b83676
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+@@ -0,0 +1,4 @@
++/* { dg-options "-std=c90 -pedantic-errors" } */
++
++void f1 () __arm_streaming;
++void f2 () __arm_streaming_compatible;
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c
+new file mode 100644
+index 000000000..8874b05b8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_1.c
+@@ -0,0 +1,130 @@
++// { dg-options "" }
++
++void sc_a () [[arm::streaming_compatible]];
++void sc_a (); // { dg-error "conflicting types" }
++
++void sc_b ();
++void sc_b () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++void sc_c () [[arm::streaming_compatible]];
++void sc_c () {} // Inherits attribute from declaration (confusingly).
++
++void sc_d ();
++void sc_d () [[arm::streaming_compatible]] {} // { dg-error "conflicting types" }
++
++void sc_e () [[arm::streaming_compatible]] {}
++void sc_e (); // { dg-error "conflicting types" }
++
++void sc_f () {}
++void sc_f () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++extern void (*sc_g) ();
++extern void (*sc_g) () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++extern void (*sc_h) () [[arm::streaming_compatible]];
++extern void (*sc_h) (); // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++void s_a () [[arm::streaming]];
++void s_a (); // { dg-error "conflicting types" }
++
++void s_b ();
++void s_b () [[arm::streaming]]; // { dg-error "conflicting types" }
++
++void s_c () [[arm::streaming]];
++void s_c () {} // Inherits attribute from declaration (confusingly).
++
++void s_d ();
++void s_d () [[arm::streaming]] {} // { dg-error "conflicting types" }
++
++void s_e () [[arm::streaming]] {}
++void s_e (); // { dg-error "conflicting types" }
++
++void s_f () {}
++void s_f () [[arm::streaming]]; // { dg-error "conflicting types" }
++
++extern void (*s_g) ();
++extern void (*s_g) () [[arm::streaming]]; // { dg-error "conflicting types" }
++
++extern void (*s_h) () [[arm::streaming]];
++extern void (*s_h) (); // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++void mixed_a () [[arm::streaming]];
++void mixed_a () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++void mixed_b () [[arm::streaming_compatible]];
++void mixed_b () [[arm::streaming]]; // { dg-error "conflicting types" }
++
++void mixed_c () [[arm::streaming]];
++void mixed_c () [[arm::streaming_compatible]] {} // { dg-error "conflicting types" }
++
++void mixed_d () [[arm::streaming_compatible]];
++void mixed_d () [[arm::streaming]] {} // { dg-error "conflicting types" }
++
++void mixed_e () [[arm::streaming]] {}
++void mixed_e () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++void mixed_f () [[arm::streaming_compatible]] {}
++void mixed_f () [[arm::streaming]]; // { dg-error "conflicting types" }
++
++extern void (*mixed_g) () [[arm::streaming_compatible]];
++extern void (*mixed_g) () [[arm::streaming]]; // { dg-error "conflicting types" }
++
++extern void (*mixed_h) () [[arm::streaming]];
++extern void (*mixed_h) () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++void contradiction_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++void contradiction_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++
++int [[arm::streaming_compatible]] int_attr; // { dg-warning "only applies to function types" }
++void [[arm::streaming_compatible]] ret_attr (); // { dg-warning "only applies to function types" }
++void *[[arm::streaming]] ptr_attr; // { dg-warning "only applies to function types" }
++
++typedef void s_callback () [[arm::streaming]];
++typedef void sc_callback () [[arm::streaming_compatible]];
++
++typedef void contradiction_callback_1 () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++typedef void contradiction_callback_2 () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++
++void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++
++struct s {
++  void (*contradiction_callback_ptr_1) () [[arm::streaming, arm::streaming_compatible]]; // { dg-warning "conflicts with attribute" }
++  void (*contradiction_callback_ptr_2) () [[arm::streaming_compatible, arm::streaming]]; // { dg-warning "conflicts with attribute" }
++};
++
++//----------------------------------------------------------------------------
++
++void keyword_ok_1 () __arm_streaming;
++void keyword_ok_1 () __arm_streaming;
++
++void keyword_ok_2 () __arm_streaming;
++void keyword_ok_2 () [[arm::streaming]];
++
++void keyword_ok_3 () [[arm::streaming]];
++void keyword_ok_3 () __arm_streaming;
++
++void keyword_ok_4 () __arm_streaming [[arm::streaming]];
++
++void keyword_ok_5 () __arm_streaming_compatible;
++void keyword_ok_5 () [[arm::streaming_compatible]];
++
++//----------------------------------------------------------------------------
++
++void keyword_contradiction_1 () __arm_streaming;
++void keyword_contradiction_1 (); // { dg-error "conflicting types" }
++
++void keyword_contradiction_2 ();
++void keyword_contradiction_2 () __arm_streaming; // { dg-error "conflicting types" }
++
++void keyword_contradiction_3 () __arm_streaming;
++void keyword_contradiction_3 () [[arm::streaming_compatible]]; // { dg-error "conflicting types" }
++
++void keyword_contradiction_4 () [[arm::streaming_compatible]];
++void keyword_contradiction_4 () __arm_streaming; // { dg-error "conflicting types" }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c
+new file mode 100644
+index 000000000..e8be0f821
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c
+@@ -0,0 +1,25 @@
++// { dg-options "" }
++
++void sc_fn () [[arm::streaming_compatible]];
++void s_fn () [[arm::streaming]];
++void ns_fn ();
++
++void (*sc_fn_ptr) () [[arm::streaming_compatible]];
++void (*s_fn_ptr) () [[arm::streaming]];
++void (*ns_fn_ptr) ();
++
++void
++f ()
++{
++  sc_fn_ptr = sc_fn;
++  sc_fn_ptr = s_fn; // { dg-error "incompatible pointer type" }
++  sc_fn_ptr = ns_fn; // { dg-error "incompatible pointer type" }
++
++  s_fn_ptr = sc_fn; // { dg-error "incompatible pointer type" }
++  s_fn_ptr = s_fn;
++  s_fn_ptr = ns_fn; // { dg-error "incompatible pointer type" }
++
++  ns_fn_ptr = sc_fn; // { dg-error "incompatible pointer type" }
++  ns_fn_ptr = s_fn; // { dg-error "incompatible pointer type" }
++  ns_fn_ptr = ns_fn;
++}
+-- 
+2.33.0
+
diff --git a/0175-Backport-SME-aarch64-Add-sme.patch b/0175-Backport-SME-aarch64-Add-sme.patch
new file mode 100644
index 0000000..fc3ef34
--- /dev/null
+++ b/0175-Backport-SME-aarch64-Add-sme.patch
@@ -0,0 +1,330 @@
+From c097d9ffc7dd8f90f78eb3b994f3691f4c8f812d Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:23 +0000
+Subject: [PATCH 076/157] [Backport][SME] aarch64: Add +sme
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7e04bd1fadf3410c3d24b56f650a52ff53d01a3c
+
+This patch adds the +sme ISA feature and requires it to be present
+when compiling arm_streaming code.  (arm_streaming_compatible code
+does not necessarily assume the presence of SME.  It just has to
+work when SME is present and streaming mode is enabled.)
+
+gcc/
+	* doc/invoke.texi: Document SME.
+	* doc/sourcebuild.texi: Document aarch64_sve.
+	* config/aarch64/aarch64-option-extensions.def (sme): Define.
+	* config/aarch64/aarch64.h (AARCH64_ISA_SME): New macro.
+	(TARGET_SME): Likewise.
+	* config/aarch64/aarch64.cc (aarch64_override_options_internal):
+	Ensure that SME is present when compiling streaming code.
+
+gcc/testsuite/
+	* lib/target-supports.exp (check_effective_target_aarch64_sme): New
+	target test.
+	* gcc.target/aarch64/sme/aarch64-sme.exp: Force SME to be enabled
+	if it isn't by default.
+	* g++.target/aarch64/sme/aarch64-sme.exp: Likewise.
+	* gcc.target/aarch64/sme/streaming_mode_3.c: New test.
+---
+ .../aarch64/aarch64-option-extensions.def     |  2 +
+ gcc/config/aarch64/aarch64.cc                 | 33 ++++++++++
+ gcc/config/aarch64/aarch64.h                  |  5 ++
+ gcc/doc/invoke.texi                           |  2 +
+ gcc/doc/sourcebuild.texi                      |  2 +
+ .../g++.target/aarch64/sme/aarch64-sme.exp    | 10 ++-
+ .../gcc.target/aarch64/sme/aarch64-sme.exp    | 10 ++-
+ .../gcc.target/aarch64/sme/streaming_mode_3.c | 63 +++++++++++++++++++
+ .../gcc.target/aarch64/sme/streaming_mode_4.c | 22 +++++++
+ gcc/testsuite/lib/target-supports.exp         | 12 ++++
+ 10 files changed, 157 insertions(+), 4 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_4.c
+
+diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
+index bdf4baf30..faee64a79 100644
+--- a/gcc/config/aarch64/aarch64-option-extensions.def
++++ b/gcc/config/aarch64/aarch64-option-extensions.def
+@@ -149,4 +149,6 @@ AARCH64_OPT_EXTENSION("ls64", LS64, (), (), (), "")
+ 
+ AARCH64_OPT_EXTENSION("mops", MOPS, (), (), (), "")
+ 
++AARCH64_OPT_EXTENSION("sme", SME, (BF16, SVE2), (), (), "sme")
++
+ #undef AARCH64_OPT_EXTENSION
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 904166b21..8f8395201 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -11648,6 +11648,23 @@ aarch64_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+   return true;
+ }
+ 
++/* Implement TARGET_START_CALL_ARGS.  */
++
++static void
++aarch64_start_call_args (cumulative_args_t ca_v)
++{
++  CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
++
++  if (!TARGET_SME && (ca->isa_mode & AARCH64_FL_SM_ON))
++    {
++      error ("calling a streaming function requires the ISA extension %qs",
++	     "sme");
++      inform (input_location, "you can enable %qs using the command-line"
++	      " option %<-march%>, or by using the %"
++	      " attribute or pragma", "sme");
++    }
++}
++
+ /* This function is used by the call expanders of the machine description.
+    RESULT is the register in which the result is returned.  It's NULL for
+    "call" and "sibcall".
+@@ -18194,6 +18211,19 @@ aarch64_override_options_internal (struct gcc_options *opts)
+       && !fixed_regs[R18_REGNUM])
+     error ("%<-fsanitize=shadow-call-stack%> requires %<-ffixed-x18%>");
+ 
++  if ((opts->x_aarch64_isa_flags & AARCH64_FL_SM_ON)
++      && !(opts->x_aarch64_isa_flags & AARCH64_FL_SME))
++    {
++      error ("streaming functions require the ISA extension %qs", "sme");
++      inform (input_location, "you can enable %qs using the command-line"
++	      " option %<-march%>, or by using the %"
++	      " attribute or pragma", "sme");
++      opts->x_target_flags &= ~MASK_GENERAL_REGS_ONLY;
++      auto new_flags = (opts->x_aarch64_asm_isa_flags
++			| feature_deps::SME ().enable);
++      aarch64_set_asm_isa_flags (opts, new_flags);
++    }
++
+   initialize_aarch64_code_model (opts);
+   initialize_aarch64_tls_size (opts);
+ 
+@@ -28159,6 +28189,9 @@ aarch64_get_v16qi_mode ()
+ #undef TARGET_FUNCTION_VALUE_REGNO_P
+ #define TARGET_FUNCTION_VALUE_REGNO_P aarch64_function_value_regno_p
+ 
++#undef TARGET_START_CALL_ARGS
++#define TARGET_START_CALL_ARGS aarch64_start_call_args
++
+ #undef TARGET_GIMPLE_FOLD_BUILTIN
+ #define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 84215c8c3..dd2de4e88 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -214,6 +214,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ #define AARCH64_ISA_SVE2_BITPERM  (aarch64_isa_flags & AARCH64_FL_SVE2_BITPERM)
+ #define AARCH64_ISA_SVE2_SHA3	   (aarch64_isa_flags & AARCH64_FL_SVE2_SHA3)
+ #define AARCH64_ISA_SVE2_SM4	   (aarch64_isa_flags & AARCH64_FL_SVE2_SM4)
++#define AARCH64_ISA_SME		   (aarch64_isa_flags & AARCH64_FL_SME)
+ #define AARCH64_ISA_V8_3A	   (aarch64_isa_flags & AARCH64_FL_V8_3A)
+ #define AARCH64_ISA_DOTPROD	   (aarch64_isa_flags & AARCH64_FL_DOTPROD)
+ #define AARCH64_ISA_AES	           (aarch64_isa_flags & AARCH64_FL_AES)
+@@ -292,6 +293,10 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ /* SVE2 SM4 instructions, enabled through +sve2-sm4.  */
+ #define TARGET_SVE2_SM4 (AARCH64_ISA_SVE2_SM4)
+ 
++/* SME instructions, enabled through +sme.  Note that this does not
++   imply anything about the state of PSTATE.SM.  */
++#define TARGET_SME (AARCH64_ISA_SME)
++
+ /* ARMv8.3-A features.  */
+ #define TARGET_ARMV8_3	(AARCH64_ISA_V8_3A)
+ 
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 53709b246..2420b05d9 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -19478,6 +19478,8 @@ Enable the instructions to accelerate memory operations like @code{memcpy},
+ Enable the Flag Manipulation instructions Extension.
+ @item pauth
+ Enable the Pointer Authentication Extension.
++@item sme
++Enable the Scalable Matrix Extension.
+ 
+ @end table
+ 
+diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
+index 454fae11a..80936a0eb 100644
+--- a/gcc/doc/sourcebuild.texi
++++ b/gcc/doc/sourcebuild.texi
+@@ -2277,6 +2277,8 @@ AArch64 target which generates instruction sequences for big endian.
+ @item aarch64_small_fpic
+ Binutils installed on test system supports relocation types required by -fpic
+ for AArch64 small memory model.
++@item aarch64_sme
++AArch64 target that generates instructions for SME.
+ @item aarch64_sve_hw
+ AArch64 target that is able to generate and execute SVE code (regardless of
+ whether it does so by default).
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp
+index 72fcd0bd9..1c3e69cde 100644
+--- a/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp
++++ b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme.exp
+@@ -30,10 +30,16 @@ load_lib g++-dg.exp
+ # Initialize `dg'.
+ dg-init
+ 
+-aarch64-with-arch-dg-options "" {
++if { [check_effective_target_aarch64_sme] } {
++    set sme_flags ""
++} else {
++    set sme_flags "-march=armv9-a+sme"
++}
++
++aarch64-with-arch-dg-options $sme_flags {
+     # Main loop.
+     dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+-	"" ""
++	"" $sme_flags
+ }
+ 
+ # All done.
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp
+index c990e5924..011310e80 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp
++++ b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp
+@@ -30,10 +30,16 @@ load_lib gcc-dg.exp
+ # Initialize `dg'.
+ dg-init
+ 
+-aarch64-with-arch-dg-options "" {
++if { [check_effective_target_aarch64_sme] } {
++    set sme_flags ""
++} else {
++    set sme_flags "-march=armv9-a+sme"
++}
++
++aarch64-with-arch-dg-options $sme_flags {
+     # Main loop.
+     dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+-	"" ""
++	"" $sme_flags
+ }
+ 
+ # All done.
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_3.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_3.c
+new file mode 100644
+index 000000000..45ec92321
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_3.c
+@@ -0,0 +1,63 @@
++// { dg-options "" }
++
++#pragma GCC target "+nosme"
++
++void sc_a () [[arm::streaming_compatible]] {}
++void s_a () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++void ns_a () {}
++
++void sc_b () [[arm::streaming_compatible]] {}
++void ns_b () {}
++void s_b () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++
++void sc_c () [[arm::streaming_compatible]] {}
++void sc_d () [[arm::streaming_compatible]] {}
++
++void s_c () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++void s_d () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++
++void ns_c () {}
++void ns_d () {}
++
++void sc_e () [[arm::streaming_compatible]];
++void s_e () [[arm::streaming]];
++void ns_e ();
++
++#pragma GCC target "+sme"
++
++void sc_f () [[arm::streaming_compatible]] {}
++void s_f () [[arm::streaming]] {}
++void ns_f () {}
++
++void sc_g () [[arm::streaming_compatible]] {}
++void ns_g () {}
++void s_g () [[arm::streaming]] {}
++
++void sc_h () [[arm::streaming_compatible]] {}
++void sc_i () [[arm::streaming_compatible]] {}
++
++void s_h () [[arm::streaming]] {}
++void s_i () [[arm::streaming]] {}
++
++void ns_h () {}
++void ns_i () {}
++
++void sc_j () [[arm::streaming_compatible]];
++void s_j () [[arm::streaming]];
++void ns_j ();
++
++#pragma GCC target "+sme"
++
++void sc_k () [[arm::streaming_compatible]] {}
++
++#pragma GCC target "+nosme"
++#pragma GCC target "+sme"
++
++void s_k () [[arm::streaming]] {}
++
++#pragma GCC target "+nosme"
++#pragma GCC target "+sme"
++
++void ns_k () {}
++
++#pragma GCC target "+nosme"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_4.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_4.c
+new file mode 100644
+index 000000000..50e92f2e1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_4.c
+@@ -0,0 +1,22 @@
++// { dg-options "-mgeneral-regs-only" }
++
++void sc_a () [[arm::streaming_compatible]] {}
++void s_a () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++void ns_a () {}
++
++void sc_b () [[arm::streaming_compatible]] {}
++void ns_b () {}
++void s_b () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++
++void sc_c () [[arm::streaming_compatible]] {}
++void sc_d () [[arm::streaming_compatible]] {}
++
++void s_c () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++void s_d () [[arm::streaming]] {} // { dg-error "streaming functions require the ISA extension 'sme'" }
++
++void ns_c () {}
++void ns_d () {}
++
++void sc_e () [[arm::streaming_compatible]];
++void s_e () [[arm::streaming]];
++void ns_e ();
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index bd89d4f52..e2a9ef5fa 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -3887,6 +3887,18 @@ proc aarch64_sve_bits { } {
+     }]
+ }
+ 
++# Return 1 if this is an AArch64 target that generates instructions for SME.
++proc check_effective_target_aarch64_sme { } {
++    if { ![istarget aarch64*-*-*] } {
++	return 0
++    }
++    return [check_no_compiler_messages aarch64_sme assembly {
++	#if !defined (__ARM_FEATURE_SME)
++	#error FOO
++	#endif
++    }]
++}
++
+ # Return 1 if this is a compiler supporting ARC atomic operations
+ proc check_effective_target_arc_atomic { } {
+     return [check_no_compiler_messages arc_atomic assembly {
+-- 
+2.33.0
+
diff --git a/0176-Backport-SME-aarch64-Add-r-m-and-m-r-alternatives-to.patch b/0176-Backport-SME-aarch64-Add-r-m-and-m-r-alternatives-to.patch
new file mode 100644
index 0000000..3bd87e9
--- /dev/null
+++ b/0176-Backport-SME-aarch64-Add-r-m-and-m-r-alternatives-to.patch
@@ -0,0 +1,168 @@
+From d8233e19aae2272c4863de5e8d61d49d3147e807 Mon Sep 17 00:00:00 2001
+From: Kyrylo Tkachov 
+Date: Thu, 1 Jun 2023 09:37:06 +0100
+Subject: [PATCH 077/157] [Backport][SME] aarch64: Add =r,m and =m,r
+ alternatives to 64-bit vector move patterns
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=12e71b593ea0c64d919df525cd75ea10b7be8a4b
+
+We can use the X registers to load and store 64-bit vector modes, we just need to add the alternatives
+to the mov patterns. This straightforward patch does that and for the pair variants too.
+For the testcase in the code we now generate the optimal assembly without any superfluous
+GP<->SIMD moves.
+
+Bootstrapped and tested on aarch64-none-linux-gnu and aarch64_be-none-elf.
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64-simd.md (*aarch64_simd_mov):
+	Add =r,m and =r,m alternatives.
+	(load_pair): Likewise.
+	(vec_store_pair): Likewise.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/aarch64/xreg-vec-modes_1.c: New test.
+---
+ gcc/config/aarch64/aarch64-simd.md            | 40 ++++++++++--------
+ .../gcc.target/aarch64/xreg-vec-modes_1.c     | 42 +++++++++++++++++++
+ 2 files changed, 65 insertions(+), 17 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/xreg-vec-modes_1.c
+
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index 2d688edf5..b5c52ba16 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -116,26 +116,28 @@
+ 
+ (define_insn "*aarch64_simd_mov"
+   [(set (match_operand:VDMOV 0 "nonimmediate_operand"
+-		"=w, m,  m,  w, ?r, ?w, ?r,  w,  w")
++		"=w, r, m,  m, m,  w, ?r, ?w, ?r,  w,  w")
+ 	(match_operand:VDMOV 1 "general_operand"
+-		"m,  Dz, w,  w,  w,  r,  r, Dn, Dz"))]
++		"m,  m, Dz, w, r,  w,  w,  r,  r, Dn, Dz"))]
+   "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+   "@
+    ldr\t%d0, %1
++   ldr\t%x0, %1
+    str\txzr, %0
+    str\t%d1, %0
++   str\t%x1, %0
+    * return TARGET_SIMD ? \"mov\t%0., %1.\" : \"fmov\t%d0, %d1\";
+    * return TARGET_SIMD ? \"umov\t%0, %1.d[0]\" : \"fmov\t%x0, %d1\";
+    fmov\t%d0, %1
+    mov\t%0, %1
+    * return aarch64_output_simd_mov_immediate (operands[1], 64);
+    fmov\t%d0, xzr"
+-  [(set_attr "type" "neon_load1_1reg, store_8, neon_store1_1reg,\
+-		     neon_logic, neon_to_gp, f_mcr,\
++  [(set_attr "type" "neon_load1_1reg, load_8, store_8, neon_store1_1reg,\
++		     store_8, neon_logic, neon_to_gp, f_mcr,\
+ 		     mov_reg, neon_move, f_mcr")
+-   (set_attr "arch" "*,*,*,*,*,*,*,simd,*")]
++   (set_attr "arch" "*,*,*,*,*,*,*,*,*,simd,*")]
+ )
+ 
+ (define_insn "*aarch64_simd_mov"
+@@ -177,31 +179,35 @@
+ )
+ 
+ (define_insn "load_pair"
+-  [(set (match_operand:DREG 0 "register_operand" "=w")
+-	(match_operand:DREG 1 "aarch64_mem_pair_operand" "Ump"))
+-   (set (match_operand:DREG2 2 "register_operand" "=w")
+-	(match_operand:DREG2 3 "memory_operand" "m"))]
++  [(set (match_operand:DREG 0 "register_operand" "=w,r")
++	(match_operand:DREG 1 "aarch64_mem_pair_operand" "Ump,Ump"))
++   (set (match_operand:DREG2 2 "register_operand" "=w,r")
++	(match_operand:DREG2 3 "memory_operand" "m,m"))]
+   "TARGET_FLOAT
+    && rtx_equal_p (XEXP (operands[3], 0),
+ 		   plus_constant (Pmode,
+ 				  XEXP (operands[1], 0),
+ 				  GET_MODE_SIZE (mode)))"
+-  "ldp\\t%d0, %d2, %z1"
+-  [(set_attr "type" "neon_ldp")]
++  "@
++   ldp\t%d0, %d2, %z1
++   ldp\t%x0, %x2, %z1"
++  [(set_attr "type" "neon_ldp,load_16")]
+ )
+ 
+ (define_insn "vec_store_pair"
+-  [(set (match_operand:DREG 0 "aarch64_mem_pair_operand" "=Ump")
+-	(match_operand:DREG 1 "register_operand" "w"))
+-   (set (match_operand:DREG2 2 "memory_operand" "=m")
+-	(match_operand:DREG2 3 "register_operand" "w"))]
++  [(set (match_operand:DREG 0 "aarch64_mem_pair_operand" "=Ump,Ump")
++	(match_operand:DREG 1 "register_operand" "w,r"))
++   (set (match_operand:DREG2 2 "memory_operand" "=m,m")
++	(match_operand:DREG2 3 "register_operand" "w,r"))]
+   "TARGET_FLOAT
+    && rtx_equal_p (XEXP (operands[2], 0),
+ 		   plus_constant (Pmode,
+ 				  XEXP (operands[0], 0),
+ 				  GET_MODE_SIZE (mode)))"
+-  "stp\\t%d1, %d3, %z0"
+-  [(set_attr "type" "neon_stp")]
++  "@
++   stp\t%d1, %d3, %z0
++   stp\t%x1, %x3, %z0"
++  [(set_attr "type" "neon_stp,store_16")]
+ )
+ 
+ (define_insn "load_pair"
+diff --git a/gcc/testsuite/gcc.target/aarch64/xreg-vec-modes_1.c b/gcc/testsuite/gcc.target/aarch64/xreg-vec-modes_1.c
+new file mode 100644
+index 000000000..fc4dcb1ad
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/xreg-vec-modes_1.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O2" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++typedef unsigned int v2si  __attribute__((vector_size (8)));
++
++#define force_gp(V1)   asm volatile (""				\
++           : "=r"(V1)                                           \
++           : "r"(V1)                                            \
++           : /* No clobbers */);
++
++/*
++** foo:
++**	ldr	(x[0-9]+), \[x1\]
++**	str	\1, \[x0\]
++**	ret
++*/
++
++void
++foo (v2si *a, v2si *b)
++{
++  v2si tmp = *b;
++  force_gp (tmp);
++  *a = tmp;
++}
++
++/*
++** foo2:
++**	ldp	(x[0-9]+), (x[0-9]+), \[x0\]
++**	stp	\1, \2, \[x1\]
++**	ret
++*/
++void
++foo2 (v2si *a, v2si *b)
++{
++  v2si t1 = *a;
++  v2si t2 = a[1];
++  force_gp (t1);
++  force_gp (t2);
++  *b = t1;
++  b[1] = t2;
++}
+-- 
+2.33.0
+
diff --git a/0177-Backport-SME-AArch64-Rewrite-simd-move-immediate-pat.patch b/0177-Backport-SME-AArch64-Rewrite-simd-move-immediate-pat.patch
new file mode 100644
index 0000000..1e89f07
--- /dev/null
+++ b/0177-Backport-SME-AArch64-Rewrite-simd-move-immediate-pat.patch
@@ -0,0 +1,167 @@
+From 7d40978965ff893871a79f5f624f54ae02a34a8b Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Wed, 18 Oct 2023 09:34:01 +0100
+Subject: [PATCH 078/157] [Backport][SME] AArch64: Rewrite simd move immediate
+ patterns to new syntax
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=04227acbe9e6c60d1e314a6b4f2d949c07f30baa
+
+This rewrites the simd MOV patterns to use the new compact syntax.
+No change in semantics is expected.  This will be needed in follow on patches.
+
+This also merges the splits into the define_insn which will also be needed soon.
+
+gcc/ChangeLog:
+
+	PR tree-optimization/109154
+	* config/aarch64/aarch64-simd.md (*aarch64_simd_mov):
+	Rewrite to new syntax.
+	(*aarch64_simd_mov"
+-  [(set (match_operand:VDMOV 0 "nonimmediate_operand"
+-		"=w, r, m,  m, m,  w, ?r, ?w, ?r,  w,  w")
+-	(match_operand:VDMOV 1 "general_operand"
+-		"m,  m, Dz, w, r,  w,  w,  r,  r, Dn, Dz"))]
++  [(set (match_operand:VDMOV 0 "nonimmediate_operand")
++	(match_operand:VDMOV 1 "general_operand"))]
+   "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+-  "@
+-   ldr\t%d0, %1
+-   ldr\t%x0, %1
+-   str\txzr, %0
+-   str\t%d1, %0
+-   str\t%x1, %0
+-   * return TARGET_SIMD ? \"mov\t%0., %1.\" : \"fmov\t%d0, %d1\";
+-   * return TARGET_SIMD ? \"umov\t%0, %1.d[0]\" : \"fmov\t%x0, %d1\";
+-   fmov\t%d0, %1
+-   mov\t%0, %1
+-   * return aarch64_output_simd_mov_immediate (operands[1], 64);
+-   fmov\t%d0, xzr"
+-  [(set_attr "type" "neon_load1_1reg, load_8, store_8, neon_store1_1reg,\
+-		     store_8, neon_logic, neon_to_gp, f_mcr,\
+-		     mov_reg, neon_move, f_mcr")
+-   (set_attr "arch" "*,*,*,*,*,*,*,*,*,simd,*")]
+-)
+-
+-(define_insn "*aarch64_simd_mov"
+-  [(set (match_operand:VQMOV 0 "nonimmediate_operand"
+-		"=w, Umn,  m,  w, ?r, ?w, ?r, w,  w")
+-	(match_operand:VQMOV 1 "general_operand"
+-		"m,  Dz, w,  w,  w,  r,  r, Dn, Dz"))]
++  {@ [cons: =0, 1; attrs: type, arch]
++     [w , m ; neon_load1_1reg , *   ] ldr\t%d0, %1
++     [r , m ; load_8             , *   ] ldr\t%x0, %1
++     [m , Dz; store_8            , *   ] str\txzr, %0
++     [m , w ; neon_store1_1reg, *   ] str\t%d1, %0
++     [m , r ; store_8            , *   ] str\t%x1, %0
++     [w , w ; neon_logic      , simd] mov\t%0., %1.
++     [w , w ; neon_logic      , *   ] fmov\t%d0, %d1
++     [?r, w ; neon_to_gp      , simd] umov\t%0, %1.d[0]
++     [?r, w ; neon_to_gp      , *   ] fmov\t%x0, %d1
++     [?w, r ; f_mcr              , *   ] fmov\t%d0, %1
++     [?r, r ; mov_reg            , *   ] mov\t%0, %1
++     [w , Dn; neon_move       , simd] << aarch64_output_simd_mov_immediate (operands[1], 64);
++     [w , Dz; f_mcr              , *   ] fmov\t%d0, xzr
++  }
++)
++
++(define_insn_and_split "*aarch64_simd_mov"
++  [(set (match_operand:VQMOV 0 "nonimmediate_operand")
++	(match_operand:VQMOV 1 "general_operand"))]
+   "TARGET_FLOAT
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+-  "@
+-   ldr\t%q0, %1
+-   stp\txzr, xzr, %0
+-   str\t%q1, %0
+-   mov\t%0., %1.
+-   #
+-   #
+-   #
+-   * return aarch64_output_simd_mov_immediate (operands[1], 128);
+-   fmov\t%d0, xzr"
+-  [(set_attr "type" "neon_load1_1reg, store_16, neon_store1_1reg,\
+-		     neon_logic, multiple, multiple,\
+-		     multiple, neon_move, fmov")
+-   (set_attr "length" "4,4,4,4,8,8,8,4,4")
+-   (set_attr "arch" "*,*,*,simd,*,*,*,simd,*")]
++  {@ [cons: =0, 1; attrs: type, arch, length]
++     [w  , m ; neon_load1_1reg , *   , 4] ldr\t%q0, %1
++     [Umn, Dz; store_16           , *   , 4] stp\txzr, xzr, %0
++     [m  , w ; neon_store1_1reg, *   , 4] str\t%q1, %0
++     [w  , w ; neon_logic      , simd, 4] mov\t%0., %1.
++     [?r , w ; multiple           , *   , 8] #
++     [?w , r ; multiple           , *   , 8] #
++     [?r , r ; multiple           , *   , 8] #
++     [w  , Dn; neon_move       , simd, 4] << aarch64_output_simd_mov_immediate (operands[1], 128);
++     [w  , Dz; fmov               , *   , 4] fmov\t%d0, xzr
++  }
++  "&& reload_completed
++   && (REG_P (operands[0])
++	&& REG_P (operands[1])
++	&& !(FP_REGNUM_P (REGNO (operands[0]))
++	     && FP_REGNUM_P (REGNO (operands[1]))))"
++  [(const_int 0)]
++  {
++    if (GP_REGNUM_P (REGNO (operands[0]))
++	&& GP_REGNUM_P (REGNO (operands[1])))
++      aarch64_simd_emit_reg_reg_move (operands, DImode, 2);
++    else
++      aarch64_split_simd_move (operands[0], operands[1]);
++    DONE;
++  }
+ )
+ 
+ ;; When storing lane zero we can use the normal STR and its more permissive
+@@ -238,33 +243,6 @@
+   [(set_attr "type" "neon_stp_q")]
+ )
+ 
+-
+-(define_split
+-  [(set (match_operand:VQMOV 0 "register_operand" "")
+-	(match_operand:VQMOV 1 "register_operand" ""))]
+-  "TARGET_FLOAT
+-   && reload_completed
+-   && GP_REGNUM_P (REGNO (operands[0]))
+-   && GP_REGNUM_P (REGNO (operands[1]))"
+-  [(const_int 0)]
+-{
+-  aarch64_simd_emit_reg_reg_move (operands, DImode, 2);
+-  DONE;
+-})
+-
+-(define_split
+-  [(set (match_operand:VQMOV 0 "register_operand" "")
+-        (match_operand:VQMOV 1 "register_operand" ""))]
+-  "TARGET_FLOAT
+-   && reload_completed
+-   && ((FP_REGNUM_P (REGNO (operands[0])) && GP_REGNUM_P (REGNO (operands[1])))
+-       || (GP_REGNUM_P (REGNO (operands[0])) && FP_REGNUM_P (REGNO (operands[1]))))"
+-  [(const_int 0)]
+-{
+-  aarch64_split_simd_move (operands[0], operands[1]);
+-  DONE;
+-})
+-
+ (define_expand "@aarch64_split_simd_mov"
+   [(set (match_operand:VQMOV 0)
+ 	(match_operand:VQMOV 1))]
+-- 
+2.33.0
+
diff --git a/0178-Backport-SME-AArch64-remove-test-comment-from-mov-mo.patch b/0178-Backport-SME-AArch64-remove-test-comment-from-mov-mo.patch
new file mode 100644
index 0000000..95f88fc
--- /dev/null
+++ b/0178-Backport-SME-AArch64-remove-test-comment-from-mov-mo.patch
@@ -0,0 +1,34 @@
+From 883af5a13e648e74cb8d8722be6d4980e8bc8f48 Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Tue, 20 Jun 2023 08:54:42 +0100
+Subject: [PATCH 079/157] [Backport][SME] AArch64: remove test comment from
+ *mov_aarch64
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=36de416df8b3f109353e309011061fa66e872e3a
+
+I accidentally left a test comment in the final version of the patch.
+This removes the comment.
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64.md (*mov_aarch64): Drop test comment.
+---
+ gcc/config/aarch64/aarch64.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 29a665e45..1ec23fae8 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1213,7 +1213,7 @@
+      [m, r Z  ; store_4        , *     ] str\\t%w1, %0
+      [m, w    ; store_4        , *     ] str\t%1, %0
+      [r, w    ; neon_to_gp  , simd  ] umov\t%w0, %1.[0]
+-     [r, w    ; neon_to_gp  , nosimd] fmov\t%w0, %s1 /*foo */
++     [r, w    ; neon_to_gp  , nosimd] fmov\t%w0, %s1
+      [w, r Z  ; neon_from_gp, simd  ] dup\t%0., %w1
+      [w, r Z  ; neon_from_gp, nosimd] fmov\t%s0, %w1
+      [w, w    ; neon_dup       , simd  ] dup\t%0, %1.[0]
+-- 
+2.33.0
+
diff --git a/0179-Backport-SME-aarch64-Distinguish-streaming-compatibl.patch b/0179-Backport-SME-aarch64-Distinguish-streaming-compatibl.patch
new file mode 100644
index 0000000..f99b246
--- /dev/null
+++ b/0179-Backport-SME-aarch64-Distinguish-streaming-compatibl.patch
@@ -0,0 +1,1552 @@
+From 4a0e91dc27b30ae673ba132bf2be17a74bc89f31 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:24 +0000
+Subject: [PATCH 080/157] [Backport][SME] aarch64: Distinguish
+ streaming-compatible AdvSIMD insns
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c86ee4f683e05e5809597d96b5eeb261c9c92cac
+
+The vast majority of Advanced SIMD instructions are not
+available in streaming mode, but some of the load/store/move
+instructions are.  This patch adds a new target feature macro
+called TARGET_BASE_SIMD for this streaming-compatible subset.
+
+The vector-to-vector move instructions are not streaming-compatible,
+so we need to use the SVE move instructions where enabled, or fall
+back to the nofp16 handling otherwise.
+
+I haven't found a good way of testing the SVE EXT alternative
+in aarch64_simd_mov_from_high, but I'd rather provide it
+than not.
+
+gcc/
+	* config/aarch64/aarch64.h (TARGET_BASE_SIMD): New macro.
+	(TARGET_SIMD): Require PSTATE.SM to be 0.
+	(AARCH64_ISA_SM_OFF): New macro.
+	* config/aarch64/aarch64.cc (aarch64_array_mode_supported_p):
+	Allow Advanced SIMD structure modes for TARGET_BASE_SIMD.
+	(aarch64_print_operand): Support '%Z'.
+	(aarch64_secondary_reload): Expect SVE moves to be used for
+	Advanced SIMD modes if SVE is enabled and non-streaming
+	Advanced SIMD isn't.
+	(aarch64_register_move_cost): Likewise.
+	(aarch64_simd_container_mode): Extend Advanced SIMD mode
+	handling to TARGET_BASE_SIMD.
+	(aarch64_expand_cpymem): Expand commentary.
+	* config/aarch64/aarch64.md (arches): Add base_simd and nobase_simd.
+	(arch_enabled): Handle it.
+	(*mov_aarch64): Extend UMOV alternative to TARGET_BASE_SIMD.
+	(*movti_aarch64): Use an SVE move instruction if non-streaming
+	SIMD isn't available.
+	(*mov_aarch64): Likewise.
+	(load_pair_dw_tftf): Extend to TARGET_BASE_SIMD.
+	(store_pair_dw_tftf): Likewise.
+	(loadwb_pair_): Likewise.
+	(storewb_pair_): Likewise.
+	* config/aarch64/aarch64-simd.md (*aarch64_simd_mov):
+	Allow UMOV in streaming mode.
+	(*aarch64_simd_mov): Use an SVE move instruction
+	if non-streaming SIMD isn't available.
+	(aarch64_store_lane0): Depend on TARGET_FLOAT rather than
+	TARGET_SIMD.
+	(aarch64_simd_mov_from_low): Likewise.  Use fmov if
+	Advanced SIMD is completely disabled.
+	(aarch64_simd_mov_from_high): Use SVE EXT instructions if
+	non-streaming SIMD isn't available.
+
+gcc/testsuite/
+	* gcc.target/aarch64/movdf_2.c: New test.
+	* gcc.target/aarch64/movdi_3.c: Likewise.
+	* gcc.target/aarch64/movhf_2.c: Likewise.
+	* gcc.target/aarch64/movhi_2.c: Likewise.
+	* gcc.target/aarch64/movqi_2.c: Likewise.
+	* gcc.target/aarch64/movsf_2.c: Likewise.
+	* gcc.target/aarch64/movsi_2.c: Likewise.
+	* gcc.target/aarch64/movtf_3.c: Likewise.
+	* gcc.target/aarch64/movtf_4.c: Likewise.
+	* gcc.target/aarch64/movti_3.c: Likewise.
+	* gcc.target/aarch64/movti_4.c: Likewise.
+	* gcc.target/aarch64/movv16qi_4.c: Likewise.
+	* gcc.target/aarch64/movv16qi_5.c: Likewise.
+	* gcc.target/aarch64/movv8qi_4.c: Likewise.
+	* gcc.target/aarch64/sme/arm_neon_1.c: Likewise.
+	* gcc.target/aarch64/sme/arm_neon_2.c: Likewise.
+	* gcc.target/aarch64/sme/arm_neon_3.c: Likewise.
+---
+ gcc/config/aarch64/aarch64-simd.md            | 50 ++++++-----
+ gcc/config/aarch64/aarch64.cc                 | 16 ++--
+ gcc/config/aarch64/aarch64.h                  | 12 ++-
+ gcc/config/aarch64/aarch64.md                 | 77 +++++++++--------
+ gcc/testsuite/gcc.target/aarch64/movdf_2.c    | 51 +++++++++++
+ gcc/testsuite/gcc.target/aarch64/movdi_3.c    | 59 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movhf_2.c    | 53 ++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movhi_2.c    | 61 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movqi_2.c    | 59 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movsf_2.c    | 51 +++++++++++
+ gcc/testsuite/gcc.target/aarch64/movsi_2.c    | 59 +++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movtf_3.c    | 81 +++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movtf_4.c    | 78 +++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movti_3.c    | 86 +++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movti_4.c    | 83 ++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movv16qi_4.c | 82 ++++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movv16qi_5.c | 79 +++++++++++++++++
+ gcc/testsuite/gcc.target/aarch64/movv8qi_4.c  | 55 ++++++++++++
+ .../gcc.target/aarch64/sme/arm_neon_1.c       | 13 +++
+ .../gcc.target/aarch64/sme/arm_neon_2.c       | 11 +++
+ .../gcc.target/aarch64/sme/arm_neon_3.c       | 11 +++
+ 21 files changed, 1062 insertions(+), 65 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movdf_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movdi_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movhf_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movhi_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movqi_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movsf_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movsi_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movtf_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movtf_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movti_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movti_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv16qi_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv16qi_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/movv8qi_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/arm_neon_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/arm_neon_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/arm_neon_3.c
+
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index 1f4b30642..62493cdfa 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -121,19 +121,19 @@
+    && (register_operand (operands[0], mode)
+        || aarch64_simd_reg_or_zero (operands[1], mode))"
+   {@ [cons: =0, 1; attrs: type, arch]
+-     [w , m ; neon_load1_1reg , *   ] ldr\t%d0, %1
+-     [r , m ; load_8             , *   ] ldr\t%x0, %1
+-     [m , Dz; store_8            , *   ] str\txzr, %0
+-     [m , w ; neon_store1_1reg, *   ] str\t%d1, %0
+-     [m , r ; store_8            , *   ] str\t%x1, %0
+-     [w , w ; neon_logic      , simd] mov\t%0., %1.
+-     [w , w ; neon_logic      , *   ] fmov\t%d0, %d1
+-     [?r, w ; neon_to_gp      , simd] umov\t%0, %1.d[0]
+-     [?r, w ; neon_to_gp      , *   ] fmov\t%x0, %d1
+-     [?w, r ; f_mcr              , *   ] fmov\t%d0, %1
+-     [?r, r ; mov_reg            , *   ] mov\t%0, %1
+-     [w , Dn; neon_move       , simd] << aarch64_output_simd_mov_immediate (operands[1], 64);
+-     [w , Dz; f_mcr              , *   ] fmov\t%d0, xzr
++     [w , m ; neon_load1_1reg , *        ] ldr\t%d0, %1
++     [r , m ; load_8             , *        ] ldr\t%x0, %1
++     [m , Dz; store_8            , *        ] str\txzr, %0
++     [m , w ; neon_store1_1reg, *        ] str\t%d1, %0
++     [m , r ; store_8            , *        ] str\t%x1, %0
++     [w , w ; neon_logic      , simd     ] mov\t%0., %1.
++     [w , w ; neon_logic      , *        ] fmov\t%d0, %d1
++     [?r, w ; neon_to_gp      , base_simd] umov\t%0, %1.d[0]
++     [?r, w ; neon_to_gp      , *        ] fmov\t%x0, %d1
++     [?w, r ; f_mcr              , *        ] fmov\t%d0, %1
++     [?r, r ; mov_reg            , *        ] mov\t%0, %1
++     [w , Dn; neon_move       , simd     ] << aarch64_output_simd_mov_immediate (operands[1], 64);
++     [w , Dz; f_mcr              , *        ] fmov\t%d0, xzr
+   }
+ )
+ 
+@@ -148,6 +148,7 @@
+      [Umn, Dz; store_16           , *   , 4] stp\txzr, xzr, %0
+      [m  , w ; neon_store1_1reg, *   , 4] str\t%q1, %0
+      [w  , w ; neon_logic      , simd, 4] mov\t%0., %1.
++     [w  , w ; *                  , sve , 4] mov\t%Z0.d, %Z1.d
+      [?r , w ; multiple           , *   , 8] #
+      [?w , r ; multiple           , *   , 8] #
+      [?r , r ; multiple           , *   , 8] #
+@@ -177,7 +178,7 @@
+   [(set (match_operand: 0 "memory_operand" "=m")
+ 	(vec_select: (match_operand:VALL_F16 1 "register_operand" "w")
+ 			(parallel [(match_operand 2 "const_int_operand" "n")])))]
+-  "TARGET_SIMD
++  "TARGET_FLOAT
+    && ENDIAN_LANE_N (, INTVAL (operands[2])) == 0"
+   "str\\t%1, %0"
+   [(set_attr "type" "neon_store1_1reg")]
+@@ -312,35 +313,38 @@
+ )
+ 
+ (define_insn_and_split "aarch64_simd_mov_from_low"
+-  [(set (match_operand: 0 "register_operand" "=w,?r")
++  [(set (match_operand: 0 "register_operand" "=w,?r,?r")
+         (vec_select:
+-          (match_operand:VQMOV_NO2E 1 "register_operand" "w,w")
++          (match_operand:VQMOV_NO2E 1 "register_operand" "w,w,w")
+           (match_operand:VQMOV_NO2E 2 "vect_par_cnst_lo_half" "")))]
+-  "TARGET_SIMD"
++  "TARGET_FLOAT"
+   "@
+    #
+-   umov\t%0, %1.d[0]"
++   umov\t%0, %1.d[0]
++   fmov\t%0, %d1"
+   "&& reload_completed && aarch64_simd_register (operands[0], mode)"
+   [(set (match_dup 0) (match_dup 1))]
+   {
+     operands[1] = aarch64_replace_reg_mode (operands[1], mode);
+   }
+-  [(set_attr "type" "mov_reg,neon_to_gp")
++  [(set_attr "type" "mov_reg,neon_to_gp,f_mrc")
++   (set_attr "arch" "simd,base_simd,*")
+    (set_attr "length" "4")]
+ )
+ 
+ (define_insn "aarch64_simd_mov_from_high"
+-  [(set (match_operand: 0 "register_operand" "=w,?r,?r")
++  [(set (match_operand: 0 "register_operand" "=w,w,?r,?r")
+         (vec_select:
+-          (match_operand:VQMOV_NO2E 1 "register_operand" "w,w,w")
++          (match_operand:VQMOV_NO2E 1 "register_operand" "w,w,w,w")
+           (match_operand:VQMOV_NO2E 2 "vect_par_cnst_hi_half" "")))]
+   "TARGET_FLOAT"
+   "@
+    dup\t%d0, %1.d[1]
++   ext\t%Z0.b, %Z0.b, %Z0.b, #8
+    umov\t%0, %1.d[1]
+    fmov\t%0, %1.d[1]"
+-  [(set_attr "type" "neon_dup,neon_to_gp,f_mrc")
+-   (set_attr "arch" "simd,simd,*")
++  [(set_attr "type" "neon_dup,*,neon_to_gp,f_mrc")
++   (set_attr "arch" "simd,sve,simd,*")
+    (set_attr "length" "4")]
+ )
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 8f8395201..08a98f8ba 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -3999,7 +3999,7 @@ static bool
+ aarch64_array_mode_supported_p (machine_mode mode,
+ 				unsigned HOST_WIDE_INT nelems)
+ {
+-  if (TARGET_SIMD
++  if (TARGET_BASE_SIMD
+       && (AARCH64_VALID_SIMD_QREG_MODE (mode)
+ 	  || AARCH64_VALID_SIMD_DREG_MODE (mode))
+       && (nelems >= 2 && nelems <= 4))
+@@ -12955,8 +12955,8 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
+       return NO_REGS;
+     }
+ 
+-  /* Without the TARGET_SIMD instructions we cannot move a Q register
+-     to a Q register directly.  We need a scratch.  */
++  /* Without the TARGET_SIMD or TARGET_SVE instructions we cannot move a
++     Q register to a Q register directly.  We need a scratch.  */
+   if (REG_P (x)
+       && (mode == TFmode
+ 	  || mode == TImode
+@@ -15540,7 +15540,7 @@ aarch64_register_move_cost (machine_mode mode,
+ 	 secondary reload.  A general register is used as a scratch to move
+ 	 the upper DI value and the lower DI value is moved directly,
+ 	 hence the cost is the sum of three moves. */
+-      if (! TARGET_SIMD)
++      if (!TARGET_SIMD && !TARGET_SVE)
+ 	return regmove_cost->GP2FP + regmove_cost->FP2GP + regmove_cost->FP2FP;
+ 
+       return regmove_cost->FP2FP;
+@@ -21107,7 +21107,7 @@ aarch64_simd_container_mode (scalar_mode mode, poly_int64 width)
+     return aarch64_full_sve_mode (mode).else_mode (word_mode);
+ 
+   gcc_assert (known_eq (width, 64) || known_eq (width, 128));
+-  if (TARGET_SIMD)
++  if (TARGET_BASE_SIMD)
+     {
+       if (known_eq (width, 128))
+ 	return aarch64_vq_mode (mode).else_mode (word_mode);
+@@ -25221,7 +25221,11 @@ aarch64_expand_cpymem (rtx *operands)
+   int copy_bits = 256;
+ 
+   /* Default to 256-bit LDP/STP on large copies, however small copies, no SIMD
+-     support or slow 256-bit LDP/STP fall back to 128-bit chunks.  */
++     support or slow 256-bit LDP/STP fall back to 128-bit chunks.
++
++     ??? Although it would be possible to use LDP/STP Qn in streaming mode
++     (so using TARGET_BASE_SIMD instead of TARGET_SIMD), it isn't clear
++     whether that would improve performance.  */
+   if (size <= 24
+       || !TARGET_SIMD
+       || (aarch64_tune_params.extra_tuning_flags
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index dd2de4e88..a3c83a3b1 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -61,8 +61,15 @@
+ #define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
+ 
+ /* AdvSIMD is supported in the default configuration, unless disabled by
+-   -mgeneral-regs-only or by the +nosimd extension.  */
+-#define TARGET_SIMD (AARCH64_ISA_SIMD)
++   -mgeneral-regs-only or by the +nosimd extension.  The set of available
++   instructions is then subdivided into:
++
++   - the "base" set, available both in SME streaming mode and in
++     non-streaming mode
++
++   - the full set, available only in non-streaming mode.  */
++#define TARGET_BASE_SIMD (AARCH64_ISA_SIMD)
++#define TARGET_SIMD (AARCH64_ISA_SIMD && AARCH64_ISA_SM_OFF)
+ #define TARGET_FLOAT (AARCH64_ISA_FP)
+ 
+ #define UNITS_PER_WORD		8
+@@ -199,6 +206,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ 
+ /* Macros to test ISA flags.  */
+ 
++#define AARCH64_ISA_SM_OFF         (aarch64_isa_flags & AARCH64_FL_SM_OFF)
+ #define AARCH64_ISA_MODE           (aarch64_isa_flags & AARCH64_FL_ISA_MODES)
+ #define AARCH64_ISA_CRC            (aarch64_isa_flags & AARCH64_FL_CRC)
+ #define AARCH64_ISA_CRYPTO         (aarch64_isa_flags & AARCH64_FL_CRYPTO)
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 1ec23fae8..079c8a3f9 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -378,7 +378,8 @@
+ ;; As a convenience, "fp_q" means "fp" + the ability to move between
+ ;; Q registers and is equivalent to "simd".
+ 
+-(define_enum "arches" [ any rcpc8_4 fp fp_q simd nosimd sve fp16])
++(define_enum "arches" [any rcpc8_4 fp fp_q base_simd nobase_simd
++		       simd nosimd sve fp16])
+ 
+ (define_enum_attr "arch" "arches" (const_string "any"))
+ 
+@@ -406,6 +407,12 @@
+ 	(and (eq_attr "arch" "fp")
+ 	     (match_test "TARGET_FLOAT"))
+ 
++	(and (eq_attr "arch" "base_simd")
++	     (match_test "TARGET_BASE_SIMD"))
++
++	(and (eq_attr "arch" "nobase_simd")
++	     (match_test "!TARGET_BASE_SIMD"))
++
+ 	(and (eq_attr "arch" "fp_q, simd")
+ 	     (match_test "TARGET_SIMD"))
+ 
+@@ -1202,22 +1209,22 @@
+   "(register_operand (operands[0], mode)
+     || aarch64_reg_or_zero (operands[1], mode))"
+   {@ [cons: =0, 1; attrs: type, arch]
+-     [r, r    ; mov_reg        , *     ] mov\t%w0, %w1
+-     [r, M    ; mov_imm        , *     ] mov\t%w0, %1
+-     [w, D; neon_move      , simd  ] << aarch64_output_scalar_simd_mov_immediate (operands[1], mode);
++     [r, r    ; mov_reg        , *          ] mov\t%w0, %w1
++     [r, M    ; mov_imm        , *          ] mov\t%w0, %1
++     [w, D; neon_move      , simd       ] << aarch64_output_scalar_simd_mov_immediate (operands[1], mode);
+      /* The "mov_imm" type for CNT is just a placeholder.  */
+-     [r, Usv  ; mov_imm        , sve   ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
+-     [r, Usr  ; mov_imm        , sve   ] << aarch64_output_sve_rdvl (operands[1]);
+-     [r, m    ; load_4         , *     ] ldr\t%w0, %1
+-     [w, m    ; load_4         , *     ] ldr\t%0, %1
+-     [m, r Z  ; store_4        , *     ] str\\t%w1, %0
+-     [m, w    ; store_4        , *     ] str\t%1, %0
+-     [r, w    ; neon_to_gp  , simd  ] umov\t%w0, %1.[0]
+-     [r, w    ; neon_to_gp  , nosimd] fmov\t%w0, %s1
+-     [w, r Z  ; neon_from_gp, simd  ] dup\t%0., %w1
+-     [w, r Z  ; neon_from_gp, nosimd] fmov\t%s0, %w1
+-     [w, w    ; neon_dup       , simd  ] dup\t%0, %1.[0]
+-     [w, w    ; neon_dup       , nosimd] fmov\t%s0, %s1
++     [r, Usv  ; mov_imm        , sve        ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
++     [r, Usr  ; mov_imm        , sve        ] << aarch64_output_sve_rdvl (operands[1]);
++     [r, m    ; load_4         , *          ] ldr\t%w0, %1
++     [w, m    ; load_4         , *          ] ldr\t%0, %1
++     [m, r Z  ; store_4        , *          ] str\\t%w1, %0
++     [m, w    ; store_4        , *          ] str\t%1, %0
++     [r, w    ; neon_to_gp  , base_simd  ] umov\t%w0, %1.[0]
++     [r, w    ; neon_to_gp  , nobase_simd] fmov\t%w0, %s1
++     [w, r Z  ; neon_from_gp, simd       ] dup\t%0., %w1
++     [w, r Z  ; neon_from_gp, nosimd     ] fmov\t%s0, %w1
++     [w, w    ; neon_dup       , simd       ] dup\t%0, %1.[0]
++     [w, w    ; neon_dup       , nosimd     ] fmov\t%s0, %s1
+   }
+ )
+ 
+@@ -1372,9 +1379,9 @@
+ 
+ (define_insn "*movti_aarch64"
+   [(set (match_operand:TI 0
+-	 "nonimmediate_operand"  "=   r,w,w,w, r,w,r,m,m,w,m")
++	 "nonimmediate_operand"  "=   r,w,w,w, r,w,w,r,m,m,w,m")
+ 	(match_operand:TI 1
+-	 "aarch64_movti_operand" " rUti,Z,Z,r, w,w,m,r,Z,m,w"))]
++	 "aarch64_movti_operand" " rUti,Z,Z,r, w,w,w,m,r,Z,m,w"))]
+   "(register_operand (operands[0], TImode)
+     || aarch64_reg_or_zero (operands[1], TImode))"
+   "@
+@@ -1384,16 +1391,17 @@
+    #
+    #
+    mov\\t%0.16b, %1.16b
++   mov\\t%Z0.d, %Z1.d
+    ldp\\t%0, %H0, %1
+    stp\\t%1, %H1, %0
+    stp\\txzr, xzr, %0
+    ldr\\t%q0, %1
+    str\\t%q1, %0"
+-  [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q, \
++  [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q,*,\
+ 		             load_16,store_16,store_16,\
+                              load_16,store_16")
+-   (set_attr "length" "8,4,4,8,8,4,4,4,4,4,4")
+-   (set_attr "arch" "*,simd,*,*,*,simd,*,*,*,fp,fp")]
++   (set_attr "length" "8,4,4,8,8,4,4,4,4,4,4,4")
++   (set_attr "arch" "*,simd,*,*,*,simd,sve,*,*,*,fp,fp")]
+ )
+ 
+ ;; Split a TImode register-register or register-immediate move into
+@@ -1529,13 +1537,14 @@
+ 
+ (define_insn "*mov_aarch64"
+   [(set (match_operand:TFD 0
+-	 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
++	 "nonimmediate_operand" "=w,w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
+ 	(match_operand:TFD 1
+-	 "general_operand"      " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
++	 "general_operand"      " w,w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
+   "TARGET_FLOAT && (register_operand (operands[0], mode)
+     || aarch64_reg_or_fp_zero (operands[1], mode))"
+   "@
+    mov\\t%0.16b, %1.16b
++   mov\\t%Z0.d, %Z1.d
+    #
+    #
+    #
+@@ -1546,10 +1555,10 @@
+    ldp\\t%0, %H0, %1
+    stp\\t%1, %H1, %0
+    stp\\txzr, xzr, %0"
+-  [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
++  [(set_attr "type" "logic_reg,*,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
+                      f_loadd,f_stored,load_16,store_16,store_16")
+-   (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
+-   (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
++   (set_attr "length" "4,4,8,8,8,4,4,4,4,4,4,4")
++   (set_attr "arch" "simd,sve,*,*,*,simd,*,*,*,*,*,*")]
+ )
+ 
+ (define_split
+@@ -1738,7 +1747,7 @@
+ 	(match_operand:TF 1 "aarch64_mem_pair_operand" "Ump"))
+    (set (match_operand:TF 2 "register_operand" "=w")
+ 	(match_operand:TF 3 "memory_operand" "m"))]
+-   "TARGET_SIMD
++   "TARGET_BASE_SIMD
+     && rtx_equal_p (XEXP (operands[3], 0),
+ 		    plus_constant (Pmode,
+ 				   XEXP (operands[1], 0),
+@@ -1788,11 +1797,11 @@
+ 	(match_operand:TF 1 "register_operand" "w"))
+    (set (match_operand:TF 2 "memory_operand" "=m")
+ 	(match_operand:TF 3 "register_operand" "w"))]
+-   "TARGET_SIMD &&
+-    rtx_equal_p (XEXP (operands[2], 0),
+-		 plus_constant (Pmode,
+-				XEXP (operands[0], 0),
+-				GET_MODE_SIZE (TFmode)))"
++   "TARGET_BASE_SIMD
++    && rtx_equal_p (XEXP (operands[2], 0),
++		    plus_constant (Pmode,
++				   XEXP (operands[0], 0),
++				   GET_MODE_SIZE (TFmode)))"
+   "stp\\t%q1, %q3, %z0"
+   [(set_attr "type" "neon_stp_q")
+    (set_attr "fp" "yes")]
+@@ -1840,7 +1849,7 @@
+      (set (match_operand:TX 3 "register_operand" "=w")
+           (mem:TX (plus:P (match_dup 1)
+ 			  (match_operand:P 5 "const_int_operand" "n"))))])]
+-  "TARGET_SIMD && INTVAL (operands[5]) == GET_MODE_SIZE (mode)"
++  "TARGET_BASE_SIMD && INTVAL (operands[5]) == GET_MODE_SIZE (mode)"
+   "ldp\\t%q2, %q3, [%1], %4"
+   [(set_attr "type" "neon_ldp_q")]
+ )
+@@ -1890,7 +1899,7 @@
+      (set (mem:TX (plus:P (match_dup 0)
+ 			  (match_operand:P 5 "const_int_operand" "n")))
+           (match_operand:TX 3 "register_operand" "w"))])]
+-  "TARGET_SIMD
++  "TARGET_BASE_SIMD
+    && INTVAL (operands[5])
+       == INTVAL (operands[4]) + GET_MODE_SIZE (mode)"
+   "stp\\t%q2, %q3, [%0, %4]!"
+diff --git a/gcc/testsuite/gcc.target/aarch64/movdf_2.c b/gcc/testsuite/gcc.target/aarch64/movdf_2.c
+new file mode 100644
+index 000000000..0d459d317
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movdf_2.c
+@@ -0,0 +1,51 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** fpr_to_fpr:
++**	fmov	d0, d1
++**	ret
++*/
++double
++fpr_to_fpr (double q0, double q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	d0, x0
++**	ret
++*/
++double
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register double x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++double
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	x0, d0
++**	ret
++*/
++void
++fpr_to_gpr (double q0) [[arm::streaming_compatible]]
++{
++  register double x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movdi_3.c b/gcc/testsuite/gcc.target/aarch64/movdi_3.c
+new file mode 100644
+index 000000000..31b2cbbae
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movdi_3.c
+@@ -0,0 +1,59 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	d0, d1
++**	ret
++*/
++void
++fpr_to_fpr (void) [[arm::streaming_compatible]]
++{
++  register uint64_t q0 asm ("q0");
++  register uint64_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	d0, x0
++**	ret
++*/
++void
++gpr_to_fpr (uint64_t x0) [[arm::streaming_compatible]]
++{
++  register uint64_t q0 asm ("q0");
++  q0 = x0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++void
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  register uint64_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	x0, d0
++**	ret
++*/
++uint64_t
++fpr_to_gpr () [[arm::streaming_compatible]]
++{
++  register uint64_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movhf_2.c b/gcc/testsuite/gcc.target/aarch64/movhf_2.c
+new file mode 100644
+index 000000000..3292b0de8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movhf_2.c
+@@ -0,0 +1,53 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+simd"
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++_Float16
++fpr_to_fpr (_Float16 q0, _Float16 q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++_Float16
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register _Float16 w0 asm ("w0");
++  asm volatile ("" : "=r" (w0));
++  return w0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++_Float16
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++void
++fpr_to_gpr (_Float16 q0) [[arm::streaming_compatible]]
++{
++  register _Float16 w0 asm ("w0");
++  w0 = q0;
++  asm volatile ("" :: "r" (w0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movhi_2.c b/gcc/testsuite/gcc.target/aarch64/movhi_2.c
+new file mode 100644
+index 000000000..dbbf3486f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movhi_2.c
+@@ -0,0 +1,61 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nothing+simd"
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++void
++fpr_to_fpr (void) [[arm::streaming_compatible]]
++{
++  register uint16_t q0 asm ("q0");
++  register uint16_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++void
++gpr_to_fpr (uint16_t w0) [[arm::streaming_compatible]]
++{
++  register uint16_t q0 asm ("q0");
++  q0 = w0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++void
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  register uint16_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	umov	w0, v0.h\[0\]
++**	ret
++*/
++uint16_t
++fpr_to_gpr () [[arm::streaming_compatible]]
++{
++  register uint16_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movqi_2.c b/gcc/testsuite/gcc.target/aarch64/movqi_2.c
+new file mode 100644
+index 000000000..aec087e4e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movqi_2.c
+@@ -0,0 +1,59 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++void
++fpr_to_fpr (void) [[arm::streaming_compatible]]
++{
++  register uint8_t q0 asm ("q0");
++  register uint8_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++void
++gpr_to_fpr (uint8_t w0) [[arm::streaming_compatible]]
++{
++  register uint8_t q0 asm ("q0");
++  q0 = w0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++void
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  register uint8_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	umov	w0, v0.b\[0\]
++**	ret
++*/
++uint8_t
++fpr_to_gpr () [[arm::streaming_compatible]]
++{
++  register uint8_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movsf_2.c b/gcc/testsuite/gcc.target/aarch64/movsf_2.c
+new file mode 100644
+index 000000000..7fed4b22f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movsf_2.c
+@@ -0,0 +1,51 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++float
++fpr_to_fpr (float q0, float q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++float
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register float w0 asm ("w0");
++  asm volatile ("" : "=r" (w0));
++  return w0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++float
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++void
++fpr_to_gpr (float q0) [[arm::streaming_compatible]]
++{
++  register float w0 asm ("w0");
++  w0 = q0;
++  asm volatile ("" :: "r" (w0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movsi_2.c b/gcc/testsuite/gcc.target/aarch64/movsi_2.c
+new file mode 100644
+index 000000000..c14d2468a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movsi_2.c
+@@ -0,0 +1,59 @@
++/* { dg-do assemble } */
++/* { dg-options "-O --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#include 
++
++/*
++** fpr_to_fpr:
++**	fmov	s0, s1
++**	ret
++*/
++void
++fpr_to_fpr (void) [[arm::streaming_compatible]]
++{
++  register uint32_t q0 asm ("q0");
++  register uint32_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	s0, w0
++**	ret
++*/
++void
++gpr_to_fpr (uint32_t w0) [[arm::streaming_compatible]]
++{
++  register uint32_t q0 asm ("q0");
++  q0 = w0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++void
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  register uint32_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:
++**	fmov	w0, s0
++**	ret
++*/
++uint32_t
++fpr_to_gpr () [[arm::streaming_compatible]]
++{
++  register uint32_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movtf_3.c b/gcc/testsuite/gcc.target/aarch64/movtf_3.c
+new file mode 100644
+index 000000000..dd164a418
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movtf_3.c
+@@ -0,0 +1,81 @@
++/* { dg-do assemble } */
++/* { dg-require-effective-target large_long_double } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nosve"
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++long double
++fpr_to_fpr (long double q0, long double q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++long double
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register long double x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++long double
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++void
++fpr_to_gpr (long double q0) [[arm::streaming_compatible]]
++{
++  register long double x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movtf_4.c b/gcc/testsuite/gcc.target/aarch64/movtf_4.c
+new file mode 100644
+index 000000000..faf9703e2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movtf_4.c
+@@ -0,0 +1,78 @@
++/* { dg-do assemble } */
++/* { dg-require-effective-target large_long_double } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+sve"
++
++/*
++** fpr_to_fpr:
++**	mov	z0.d, z1.d
++**	ret
++*/
++long double
++fpr_to_fpr (long double q0, long double q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++long double
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register long double x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	s0, wzr
++**	ret
++*/
++long double
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return 0;
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++void
++fpr_to_gpr (long double q0) [[arm::streaming_compatible]]
++{
++  register long double x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movti_3.c b/gcc/testsuite/gcc.target/aarch64/movti_3.c
+new file mode 100644
+index 000000000..243109181
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movti_3.c
+@@ -0,0 +1,86 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nosve"
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++void
++fpr_to_fpr (void) [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  register __int128_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++void
++gpr_to_fpr (__int128_t x0) [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  q0 = x0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++void
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++__int128_t
++fpr_to_gpr () [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movti_4.c b/gcc/testsuite/gcc.target/aarch64/movti_4.c
+new file mode 100644
+index 000000000..a70feccb0
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movti_4.c
+@@ -0,0 +1,83 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+sve"
++
++/*
++** fpr_to_fpr:
++**	mov	z0\.d, z1\.d
++**	ret
++*/
++void
++fpr_to_fpr (void) [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  register __int128_t q1 asm ("q1");
++  asm volatile ("" : "=w" (q1));
++  q0 = q1;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++void
++gpr_to_fpr (__int128_t x0) [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  q0 = x0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++void
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  q0 = 0;
++  asm volatile ("" :: "w" (q0));
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	fmov	x0, d0
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	fmov	x0, d0
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	fmov	x1, d0
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	fmov	x1, d0
++** )
++**	ret
++*/
++__int128_t
++fpr_to_gpr () [[arm::streaming_compatible]]
++{
++  register __int128_t q0 asm ("q0");
++  asm volatile ("" : "=w" (q0));
++  return q0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv16qi_4.c b/gcc/testsuite/gcc.target/aarch64/movv16qi_4.c
+new file mode 100644
+index 000000000..7bec888b7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv16qi_4.c
+@@ -0,0 +1,82 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nosve"
++
++typedef unsigned char v16qi __attribute__((vector_size(16)));
++
++/*
++** fpr_to_fpr:
++**	sub	sp, sp, #16
++**	str	q1, \[sp\]
++**	ldr	q0, \[sp\]
++**	add	sp, sp, #?16
++**	ret
++*/
++v16qi
++fpr_to_fpr (v16qi q0, v16qi q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++v16qi
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register v16qi x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++v16qi
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return (v16qi) {};
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	umov	x0, v0.d\[0\]
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	umov	x0, v0.d\[0\]
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	umov	x1, v0.d\[0\]
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	umov	x1, v0.d\[0\]
++** )
++**	ret
++*/
++void
++fpr_to_gpr (v16qi q0) [[arm::streaming_compatible]]
++{
++  register v16qi x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv16qi_5.c b/gcc/testsuite/gcc.target/aarch64/movv16qi_5.c
+new file mode 100644
+index 000000000..2d36342b3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv16qi_5.c
+@@ -0,0 +1,79 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+sve"
++
++typedef unsigned char v16qi __attribute__((vector_size(16)));
++
++/*
++** fpr_to_fpr:
++**	mov	z0.d, z1.d
++**	ret
++*/
++v16qi
++fpr_to_fpr (v16qi q0, v16qi q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:	{ target aarch64_little_endian }
++**	fmov	d0, x0
++**	fmov	v0.d\[1\], x1
++**	ret
++*/
++/*
++** gpr_to_fpr:	{ target aarch64_big_endian }
++**	fmov	d0, x1
++**	fmov	v0.d\[1\], x0
++**	ret
++*/
++v16qi
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register v16qi x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++v16qi
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return (v16qi) {};
++}
++
++/*
++** fpr_to_gpr:	{ target aarch64_little_endian }
++** (
++**	umov	x0, v0.d\[0\]
++**	fmov	x1, v0.d\[1\]
++** |
++**	fmov	x1, v0.d\[1\]
++**	umov	x0, v0.d\[0\]
++** )
++**	ret
++*/
++/*
++** fpr_to_gpr:	{ target aarch64_big_endian }
++** (
++**	umov	x1, v0.d\[0\]
++**	fmov	x0, v0.d\[1\]
++** |
++**	fmov	x0, v0.d\[1\]
++**	umov	x1, v0.d\[0\]
++** )
++**	ret
++*/
++void
++fpr_to_gpr (v16qi q0) [[arm::streaming_compatible]]
++{
++  register v16qi x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/movv8qi_4.c b/gcc/testsuite/gcc.target/aarch64/movv8qi_4.c
+new file mode 100644
+index 000000000..12ae25a3a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/movv8qi_4.c
+@@ -0,0 +1,55 @@
++/* { dg-do assemble } */
++/* { dg-options "-O -mtune=neoverse-v1 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#pragma GCC target "+nosve"
++
++typedef unsigned char v8qi __attribute__((vector_size(8)));
++
++/*
++** fpr_to_fpr:
++**	fmov	d0, d1
++**	ret
++*/
++v8qi
++fpr_to_fpr (v8qi q0, v8qi q1) [[arm::streaming_compatible]]
++{
++  return q1;
++}
++
++/*
++** gpr_to_fpr:
++**	fmov	d0, x0
++**	ret
++*/
++v8qi
++gpr_to_fpr () [[arm::streaming_compatible]]
++{
++  register v8qi x0 asm ("x0");
++  asm volatile ("" : "=r" (x0));
++  return x0;
++}
++
++/*
++** zero_to_fpr:
++**	fmov	d0, xzr
++**	ret
++*/
++v8qi
++zero_to_fpr () [[arm::streaming_compatible]]
++{
++  return (v8qi) {};
++}
++
++/*
++** fpr_to_gpr:
++**	umov	x0, v0\.d\[0\]
++**	ret
++*/
++void
++fpr_to_gpr (v8qi q0) [[arm::streaming_compatible]]
++{
++  register v8qi x0 asm ("x0");
++  x0 = q0;
++  asm volatile ("" :: "r" (x0));
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_1.c b/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_1.c
+new file mode 100644
+index 000000000..5b5346cf4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_1.c
+@@ -0,0 +1,13 @@
++// { dg-options "" }
++
++#include 
++
++#pragma GCC target "+nosme"
++
++// { dg-error {inlining failed.*'vhaddq_s32'} "" { target *-*-* } 0 }
++
++int32x4_t
++foo (int32x4_t x, int32x4_t y) [[arm::streaming_compatible]]
++{
++  return vhaddq_s32 (x, y);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_2.c b/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_2.c
+new file mode 100644
+index 000000000..2092c4471
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_2.c
+@@ -0,0 +1,11 @@
++// { dg-options "" }
++
++#include 
++
++// { dg-error {inlining failed.*'vhaddq_s32'} "" { target *-*-* } 0 }
++
++int32x4_t
++foo (int32x4_t x, int32x4_t y) [[arm::streaming_compatible]]
++{
++  return vhaddq_s32 (x, y);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_3.c b/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_3.c
+new file mode 100644
+index 000000000..36794e5b0
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/arm_neon_3.c
+@@ -0,0 +1,11 @@
++// { dg-options "" }
++
++#include 
++
++// { dg-error {inlining failed.*'vhaddq_s32'} "" { target *-*-* } 0 }
++
++int32x4_t
++foo (int32x4_t x, int32x4_t y) [[arm::streaming]]
++{
++  return vhaddq_s32 (x, y);
++}
+-- 
+2.33.0
+
diff --git a/0180-Backport-SME-aarch64-Mark-relevant-SVE-instructions-.patch b/0180-Backport-SME-aarch64-Mark-relevant-SVE-instructions-.patch
new file mode 100644
index 0000000..679e26e
--- /dev/null
+++ b/0180-Backport-SME-aarch64-Mark-relevant-SVE-instructions-.patch
@@ -0,0 +1,4506 @@
+From 0404dfa43633a35460aba1b96d04f62cc7d6103b Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:24 +0000
+Subject: [PATCH 081/157] [Backport][SME] aarch64: Mark relevant SVE
+ instructions as non-streaming
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=983b4365028e9a059b5fb1eef85a297bea19fc8e
+
+Following on from the previous Advanced SIMD patch, this one
+divides SVE instructions into non-streaming and streaming-
+compatible groups.
+
+gcc/
+	* config/aarch64/aarch64.h (TARGET_NON_STREAMING): New macro.
+	(TARGET_SVE2_AES, TARGET_SVE2_BITPERM): Use it.
+	(TARGET_SVE2_SHA3, TARGET_SVE2_SM4): Likewise.
+	* config/aarch64/aarch64-sve-builtins-base.def: Separate out
+	the functions that require PSTATE.SM to be 0 and guard them
+	with AARCH64_FL_SM_OFF.
+	* config/aarch64/aarch64-sve-builtins-sve2.def: Likewise.
+	* config/aarch64/aarch64-sve-builtins.cc (check_required_extensions):
+	Enforce AARCH64_FL_SM_OFF requirements.
+	* config/aarch64/aarch64-sve.md (aarch64_wrffr): Require
+	TARGET_NON_STREAMING
+	(aarch64_rdffr, aarch64_rdffr_z, *aarch64_rdffr_z_ptest): Likewise.
+	(*aarch64_rdffr_ptest, *aarch64_rdffr_z_cc, *aarch64_rdffr_cc)
+	(@aarch64_ldf1): Likewise.
+	(@aarch64_ldf1_)
+	(gather_load): Likewise
+	(mask_gather_load): Likewise.
+	(mask_gather_load): Likewise.
+	(*mask_gather_load_xtw_unpacked): Likewise.
+	(*mask_gather_load_sxtw): Likewise.
+	(*mask_gather_load_uxtw): Likewise.
+	(@aarch64_gather_load_)
+	(@aarch64_gather_load_
+	): Likewise.
+	(*aarch64_gather_load_
+	_xtw_unpacked)
+	(*aarch64_gather_load_
+	_sxtw): Likewise.
+	(*aarch64_gather_load_
+	_uxtw): Likewise.
+	(@aarch64_ldff1_gather, @aarch64_ldff1_gather): Likewise.
+	(*aarch64_ldff1_gather_sxtw): Likewise.
+	(*aarch64_ldff1_gather_uxtw): Likewise.
+	(@aarch64_ldff1_gather_
+	): Likewise.
+	(@aarch64_ldff1_gather_
+	): Likewise.
+	(*aarch64_ldff1_gather_
+	_sxtw): Likewise.
+	(*aarch64_ldff1_gather_
+	_uxtw): Likewise.
+	(@aarch64_sve_gather_prefetch)
+	(@aarch64_sve_gather_prefetch)
+	(*aarch64_sve_gather_prefetch_sxtw)
+	(*aarch64_sve_gather_prefetch_uxtw)
+	(scatter_store): Likewise.
+	(mask_scatter_store): Likewise.
+	(*mask_scatter_store_xtw_unpacked)
+	(*mask_scatter_store_sxtw): Likewise.
+	(*mask_scatter_store_uxtw): Likewise.
+	(@aarch64_scatter_store_trunc)
+	(@aarch64_scatter_store_trunc)
+	(*aarch64_scatter_store_trunc_sxtw)
+	(*aarch64_scatter_store_trunc_uxtw)
+	(@aarch64_sve_ld1ro, @aarch64_adr): Likewise.
+	(*aarch64_adr_sxtw, *aarch64_adr_uxtw_unspec): Likewise.
+	(*aarch64_adr_uxtw_and, @aarch64_adr_shift): Likewise.
+	(*aarch64_adr_shift, *aarch64_adr_shift_sxtw): Likewise.
+	(*aarch64_adr_shift_uxtw, @aarch64_sve_add_): Likewise.
+	(@aarch64_sve_, fold_left_plus_): Likewise.
+	(mask_fold_left_plus_, @aarch64_sve_compact): Likewise.
+	* config/aarch64/aarch64-sve2.md (@aarch64_gather_ldnt)
+	(@aarch64_gather_ldnt_
+	): Likewise.
+	(@aarch64_sve2_histcnt, @aarch64_sve2_histseg): Likewise.
+	(@aarch64_pred_): Likewise.
+	(*aarch64_pred__cc): Likewise.
+	(*aarch64_pred__ptest): Likewise.
+	* config/aarch64/iterators.md (SVE_FP_UNARY_INT): Make FEXPA
+	depend on TARGET_NON_STREAMING.
+	(SVE_BFLOAT_TERNARY_LONG): Likewise BFMMLA.
+
+gcc/testsuite/
+	* g++.target/aarch64/sve/aarch64-ssve.exp: New harness.
+	* g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp: Add
+	-DSTREAMING_COMPATIBLE to the list of options.
+	* g++.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp: Likewise.
+	* gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp: Likewise.
+	* gcc.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp: Likewise.
+	Fix pasto in variable name.
+	* gcc.target/aarch64/sve/acle/asm/test_sve_acle.h: Mark functions
+	as streaming-compatible if STREAMING_COMPATIBLE is defined.
+	* gcc.target/aarch64/sve/acle/asm/adda_f16.c: Disable for
+	streaming-compatible code.
+	* gcc.target/aarch64/sve/acle/asm/adda_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/adda_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/adrb.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/adrd.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/adrh.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/adrw.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/bfmmla_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/compact_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/compact_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/compact_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/compact_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/compact_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/compact_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/expa_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/expa_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/expa_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1_gather_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1_gather_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_bf16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sw_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1sw_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1uw_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ld1uw_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_bf16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_gather_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_gather_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_s8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1_u8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sb_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sh_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sw_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1sw_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1ub_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uh_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uw_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldff1uw_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_bf16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_s8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1_u8.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sb_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sb_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sb_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sb_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sb_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sb_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sh_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sh_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sh_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sh_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sw_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1sw_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1ub_s16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1ub_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1ub_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1ub_u16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1ub_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1ub_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1uh_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1uh_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1uh_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1uh_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1uw_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/ldnf1uw_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/mmla_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/mmla_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/mmla_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/mmla_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfb_gather.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfd_gather.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfh_gather.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/prfw_gather.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/rdffr_1.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1_scatter_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1_scatter_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1_scatter_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1_scatter_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1b_scatter_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1b_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1b_scatter_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1b_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1h_scatter_s32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1h_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1h_scatter_u32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1h_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1w_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/st1w_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tmad_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tmad_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tmad_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tsmul_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tsmul_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tsmul_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tssel_f16.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tssel_f32.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/tssel_f64.c: Likewise.
+	* gcc.target/aarch64/sve/acle/asm/usmmla_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/aesd_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/aese_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/aesimc_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/aesmc_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bdep_u16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bdep_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bdep_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bdep_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bext_u16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bext_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bext_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bext_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bgrp_u16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bgrp_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bgrp_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/bgrp_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/histcnt_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/histcnt_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/histcnt_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/histcnt_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/histseg_s8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/histseg_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/match_s16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/match_s8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/match_u16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/match_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/nmatch_s16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/nmatch_s8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/nmatch_u16.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/nmatch_u8.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/pmullb_pair_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/pmullt_pair_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/rax1_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/rax1_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/sm4e_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/sm4ekey_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u32.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_s64.c: Likewise.
+	* gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_u64.c: Likewise.
+---
+ .../aarch64/aarch64-sve-builtins-base.def     | 158 +++++----
+ .../aarch64/aarch64-sve-builtins-sve2.def     |  63 ++--
+ gcc/config/aarch64/aarch64-sve-builtins.cc    |   7 +
+ gcc/config/aarch64/aarch64-sve.md             | 124 +++----
+ gcc/config/aarch64/aarch64-sve2.md            |  14 +-
+ gcc/config/aarch64/aarch64.h                  |  11 +-
+ gcc/config/aarch64/iterators.md               |   4 +-
+ .../g++.target/aarch64/sve/aarch64-ssve.exp   | 308 ++++++++++++++++++
+ .../aarch64/sve/acle/aarch64-sve-acle-asm.exp |   1 +
+ .../sve2/acle/aarch64-sve2-acle-asm.exp       |   1 +
+ .../aarch64/sve/acle/aarch64-sve-acle-asm.exp |   1 +
+ .../aarch64/sve/acle/asm/adda_f16.c           |   1 +
+ .../aarch64/sve/acle/asm/adda_f32.c           |   1 +
+ .../aarch64/sve/acle/asm/adda_f64.c           |   1 +
+ .../gcc.target/aarch64/sve/acle/asm/adrb.c    |   1 +
+ .../gcc.target/aarch64/sve/acle/asm/adrd.c    |   1 +
+ .../gcc.target/aarch64/sve/acle/asm/adrh.c    |   1 +
+ .../gcc.target/aarch64/sve/acle/asm/adrw.c    |   1 +
+ .../aarch64/sve/acle/asm/bfmmla_f32.c         |   1 +
+ .../aarch64/sve/acle/asm/compact_f32.c        |   1 +
+ .../aarch64/sve/acle/asm/compact_f64.c        |   1 +
+ .../aarch64/sve/acle/asm/compact_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/compact_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/compact_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/compact_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/expa_f16.c           |   1 +
+ .../aarch64/sve/acle/asm/expa_f32.c           |   1 +
+ .../aarch64/sve/acle/asm/expa_f64.c           |   1 +
+ .../aarch64/sve/acle/asm/ld1_gather_f32.c     |   1 +
+ .../aarch64/sve/acle/asm/ld1_gather_f64.c     |   1 +
+ .../aarch64/sve/acle/asm/ld1_gather_s32.c     |   1 +
+ .../aarch64/sve/acle/asm/ld1_gather_s64.c     |   1 +
+ .../aarch64/sve/acle/asm/ld1_gather_u32.c     |   1 +
+ .../aarch64/sve/acle/asm/ld1_gather_u64.c     |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_bf16.c         |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_f16.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_f32.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_f64.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_s16.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_s32.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_s64.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_s8.c           |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_u16.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_u32.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_u64.c          |   1 +
+ .../aarch64/sve/acle/asm/ld1ro_u8.c           |   1 +
+ .../aarch64/sve/acle/asm/ld1sb_gather_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sb_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sb_gather_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sb_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sh_gather_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sh_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sh_gather_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sh_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sw_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1sw_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1ub_gather_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1ub_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1ub_gather_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1ub_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1uh_gather_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1uh_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1uh_gather_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1uh_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1uw_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ld1uw_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_bf16.c         |   1 +
+ .../aarch64/sve/acle/asm/ldff1_f16.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_f32.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_f64.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_gather_f32.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_gather_f64.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_gather_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_gather_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_gather_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_gather_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/ldff1_s16.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_s32.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_s64.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_s8.c           |   1 +
+ .../aarch64/sve/acle/asm/ldff1_u16.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_u32.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_u64.c          |   1 +
+ .../aarch64/sve/acle/asm/ldff1_u8.c           |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_gather_s32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_gather_s64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_gather_u32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_gather_u64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_s16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_u16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sb_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_gather_s32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_gather_s64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_gather_u32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_gather_u64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sh_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sw_gather_s64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sw_gather_u64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1sw_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1sw_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_gather_s32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_gather_s64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_gather_u32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_gather_u64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_s16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_u16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1ub_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_gather_s32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_gather_s64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_gather_u32.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_gather_u64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1uh_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1uw_gather_s64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1uw_gather_u64.c |   1 +
+ .../aarch64/sve/acle/asm/ldff1uw_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldff1uw_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_bf16.c         |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_f16.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_f32.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_f64.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_s16.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_s32.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_s64.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_s8.c           |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_u16.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_u32.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_u64.c          |   1 +
+ .../aarch64/sve/acle/asm/ldnf1_u8.c           |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sb_s16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sb_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sb_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sb_u16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sb_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sb_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sh_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sh_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sh_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sh_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sw_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1sw_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1ub_s16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1ub_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1ub_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1ub_u16.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1ub_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1ub_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1uh_s32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1uh_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1uh_u32.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1uh_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1uw_s64.c        |   1 +
+ .../aarch64/sve/acle/asm/ldnf1uw_u64.c        |   1 +
+ .../aarch64/sve/acle/asm/mmla_f32.c           |   1 +
+ .../aarch64/sve/acle/asm/mmla_f64.c           |   1 +
+ .../aarch64/sve/acle/asm/mmla_s32.c           |   1 +
+ .../aarch64/sve/acle/asm/mmla_u32.c           |   1 +
+ .../aarch64/sve/acle/asm/prfb_gather.c        |   1 +
+ .../aarch64/sve/acle/asm/prfd_gather.c        |   1 +
+ .../aarch64/sve/acle/asm/prfh_gather.c        |   1 +
+ .../aarch64/sve/acle/asm/prfw_gather.c        |   1 +
+ .../gcc.target/aarch64/sve/acle/asm/rdffr_1.c |   1 +
+ .../aarch64/sve/acle/asm/st1_scatter_f32.c    |   1 +
+ .../aarch64/sve/acle/asm/st1_scatter_f64.c    |   1 +
+ .../aarch64/sve/acle/asm/st1_scatter_s32.c    |   1 +
+ .../aarch64/sve/acle/asm/st1_scatter_s64.c    |   1 +
+ .../aarch64/sve/acle/asm/st1_scatter_u32.c    |   1 +
+ .../aarch64/sve/acle/asm/st1_scatter_u64.c    |   1 +
+ .../aarch64/sve/acle/asm/st1b_scatter_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/st1b_scatter_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/st1b_scatter_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/st1b_scatter_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/st1h_scatter_s32.c   |   1 +
+ .../aarch64/sve/acle/asm/st1h_scatter_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/st1h_scatter_u32.c   |   1 +
+ .../aarch64/sve/acle/asm/st1h_scatter_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/st1w_scatter_s64.c   |   1 +
+ .../aarch64/sve/acle/asm/st1w_scatter_u64.c   |   1 +
+ .../aarch64/sve/acle/asm/test_sve_acle.h      |  11 +-
+ .../aarch64/sve/acle/asm/tmad_f16.c           |   1 +
+ .../aarch64/sve/acle/asm/tmad_f32.c           |   1 +
+ .../aarch64/sve/acle/asm/tmad_f64.c           |   1 +
+ .../aarch64/sve/acle/asm/tsmul_f16.c          |   1 +
+ .../aarch64/sve/acle/asm/tsmul_f32.c          |   1 +
+ .../aarch64/sve/acle/asm/tsmul_f64.c          |   1 +
+ .../aarch64/sve/acle/asm/tssel_f16.c          |   1 +
+ .../aarch64/sve/acle/asm/tssel_f32.c          |   1 +
+ .../aarch64/sve/acle/asm/tssel_f64.c          |   1 +
+ .../aarch64/sve/acle/asm/usmmla_s32.c         |   1 +
+ .../sve2/acle/aarch64-sve2-acle-asm.exp       |   1 +
+ .../aarch64/sve2/acle/asm/aesd_u8.c           |   1 +
+ .../aarch64/sve2/acle/asm/aese_u8.c           |   1 +
+ .../aarch64/sve2/acle/asm/aesimc_u8.c         |   1 +
+ .../aarch64/sve2/acle/asm/aesmc_u8.c          |   1 +
+ .../aarch64/sve2/acle/asm/bdep_u16.c          |   1 +
+ .../aarch64/sve2/acle/asm/bdep_u32.c          |   1 +
+ .../aarch64/sve2/acle/asm/bdep_u64.c          |   1 +
+ .../aarch64/sve2/acle/asm/bdep_u8.c           |   1 +
+ .../aarch64/sve2/acle/asm/bext_u16.c          |   1 +
+ .../aarch64/sve2/acle/asm/bext_u32.c          |   1 +
+ .../aarch64/sve2/acle/asm/bext_u64.c          |   1 +
+ .../aarch64/sve2/acle/asm/bext_u8.c           |   1 +
+ .../aarch64/sve2/acle/asm/bgrp_u16.c          |   1 +
+ .../aarch64/sve2/acle/asm/bgrp_u32.c          |   1 +
+ .../aarch64/sve2/acle/asm/bgrp_u64.c          |   1 +
+ .../aarch64/sve2/acle/asm/bgrp_u8.c           |   1 +
+ .../aarch64/sve2/acle/asm/histcnt_s32.c       |   1 +
+ .../aarch64/sve2/acle/asm/histcnt_s64.c       |   1 +
+ .../aarch64/sve2/acle/asm/histcnt_u32.c       |   1 +
+ .../aarch64/sve2/acle/asm/histcnt_u64.c       |   1 +
+ .../aarch64/sve2/acle/asm/histseg_s8.c        |   1 +
+ .../aarch64/sve2/acle/asm/histseg_u8.c        |   1 +
+ .../aarch64/sve2/acle/asm/ldnt1_gather_f32.c  |   1 +
+ .../aarch64/sve2/acle/asm/ldnt1_gather_f64.c  |   1 +
+ .../aarch64/sve2/acle/asm/ldnt1_gather_s32.c  |   1 +
+ .../aarch64/sve2/acle/asm/ldnt1_gather_s64.c  |   1 +
+ .../aarch64/sve2/acle/asm/ldnt1_gather_u32.c  |   1 +
+ .../aarch64/sve2/acle/asm/ldnt1_gather_u64.c  |   1 +
+ .../sve2/acle/asm/ldnt1sb_gather_s32.c        |   1 +
+ .../sve2/acle/asm/ldnt1sb_gather_s64.c        |   1 +
+ .../sve2/acle/asm/ldnt1sb_gather_u32.c        |   1 +
+ .../sve2/acle/asm/ldnt1sb_gather_u64.c        |   1 +
+ .../sve2/acle/asm/ldnt1sh_gather_s32.c        |   1 +
+ .../sve2/acle/asm/ldnt1sh_gather_s64.c        |   1 +
+ .../sve2/acle/asm/ldnt1sh_gather_u32.c        |   1 +
+ .../sve2/acle/asm/ldnt1sh_gather_u64.c        |   1 +
+ .../sve2/acle/asm/ldnt1sw_gather_s64.c        |   1 +
+ .../sve2/acle/asm/ldnt1sw_gather_u64.c        |   1 +
+ .../sve2/acle/asm/ldnt1ub_gather_s32.c        |   1 +
+ .../sve2/acle/asm/ldnt1ub_gather_s64.c        |   1 +
+ .../sve2/acle/asm/ldnt1ub_gather_u32.c        |   1 +
+ .../sve2/acle/asm/ldnt1ub_gather_u64.c        |   1 +
+ .../sve2/acle/asm/ldnt1uh_gather_s32.c        |   1 +
+ .../sve2/acle/asm/ldnt1uh_gather_s64.c        |   1 +
+ .../sve2/acle/asm/ldnt1uh_gather_u32.c        |   1 +
+ .../sve2/acle/asm/ldnt1uh_gather_u64.c        |   1 +
+ .../sve2/acle/asm/ldnt1uw_gather_s64.c        |   1 +
+ .../sve2/acle/asm/ldnt1uw_gather_u64.c        |   1 +
+ .../aarch64/sve2/acle/asm/match_s16.c         |   1 +
+ .../aarch64/sve2/acle/asm/match_s8.c          |   1 +
+ .../aarch64/sve2/acle/asm/match_u16.c         |   1 +
+ .../aarch64/sve2/acle/asm/match_u8.c          |   1 +
+ .../aarch64/sve2/acle/asm/nmatch_s16.c        |   1 +
+ .../aarch64/sve2/acle/asm/nmatch_s8.c         |   1 +
+ .../aarch64/sve2/acle/asm/nmatch_u16.c        |   1 +
+ .../aarch64/sve2/acle/asm/nmatch_u8.c         |   1 +
+ .../aarch64/sve2/acle/asm/pmullb_pair_u64.c   |   1 +
+ .../aarch64/sve2/acle/asm/pmullt_pair_u64.c   |   1 +
+ .../aarch64/sve2/acle/asm/rax1_s64.c          |   1 +
+ .../aarch64/sve2/acle/asm/rax1_u64.c          |   1 +
+ .../aarch64/sve2/acle/asm/sm4e_u32.c          |   1 +
+ .../aarch64/sve2/acle/asm/sm4ekey_u32.c       |   1 +
+ .../aarch64/sve2/acle/asm/stnt1_scatter_f32.c |   1 +
+ .../aarch64/sve2/acle/asm/stnt1_scatter_f64.c |   1 +
+ .../aarch64/sve2/acle/asm/stnt1_scatter_s32.c |   1 +
+ .../aarch64/sve2/acle/asm/stnt1_scatter_s64.c |   1 +
+ .../aarch64/sve2/acle/asm/stnt1_scatter_u32.c |   1 +
+ .../aarch64/sve2/acle/asm/stnt1_scatter_u64.c |   1 +
+ .../sve2/acle/asm/stnt1b_scatter_s32.c        |   1 +
+ .../sve2/acle/asm/stnt1b_scatter_s64.c        |   1 +
+ .../sve2/acle/asm/stnt1b_scatter_u32.c        |   1 +
+ .../sve2/acle/asm/stnt1b_scatter_u64.c        |   1 +
+ .../sve2/acle/asm/stnt1h_scatter_s32.c        |   1 +
+ .../sve2/acle/asm/stnt1h_scatter_s64.c        |   1 +
+ .../sve2/acle/asm/stnt1h_scatter_u32.c        |   1 +
+ .../sve2/acle/asm/stnt1h_scatter_u64.c        |   1 +
+ .../sve2/acle/asm/stnt1w_scatter_s64.c        |   1 +
+ .../sve2/acle/asm/stnt1w_scatter_u64.c        |   1 +
+ 279 files changed, 805 insertions(+), 165 deletions(-)
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sve/aarch64-ssve.exp
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.def b/gcc/config/aarch64/aarch64-sve-builtins-base.def
+index 756469959..e732b4792 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-base.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins-base.def
+@@ -25,12 +25,7 @@ DEF_SVE_FUNCTION (svacgt, compare_opt_n, all_float, implicit)
+ DEF_SVE_FUNCTION (svacle, compare_opt_n, all_float, implicit)
+ DEF_SVE_FUNCTION (svaclt, compare_opt_n, all_float, implicit)
+ DEF_SVE_FUNCTION (svadd, binary_opt_n, all_arith, mxz)
+-DEF_SVE_FUNCTION (svadda, fold_left, all_float, implicit)
+ DEF_SVE_FUNCTION (svaddv, reduction_wide, all_arith, implicit)
+-DEF_SVE_FUNCTION (svadrb, adr_offset, none, none)
+-DEF_SVE_FUNCTION (svadrd, adr_index, none, none)
+-DEF_SVE_FUNCTION (svadrh, adr_index, none, none)
+-DEF_SVE_FUNCTION (svadrw, adr_index, none, none)
+ DEF_SVE_FUNCTION (svand, binary_opt_n, all_integer, mxz)
+ DEF_SVE_FUNCTION (svand, binary_opt_n, b, z)
+ DEF_SVE_FUNCTION (svandv, reduction, all_integer, implicit)
+@@ -75,7 +70,6 @@ DEF_SVE_FUNCTION (svcnth_pat, count_pat, none, none)
+ DEF_SVE_FUNCTION (svcntp, count_pred, all_pred, implicit)
+ DEF_SVE_FUNCTION (svcntw, count_inherent, none, none)
+ DEF_SVE_FUNCTION (svcntw_pat, count_pat, none, none)
+-DEF_SVE_FUNCTION (svcompact, unary, sd_data, implicit)
+ DEF_SVE_FUNCTION (svcreate2, create, all_data, none)
+ DEF_SVE_FUNCTION (svcreate3, create, all_data, none)
+ DEF_SVE_FUNCTION (svcreate4, create, all_data, none)
+@@ -93,7 +87,6 @@ DEF_SVE_FUNCTION (svdupq_lane, binary_uint64_n, all_data, none)
+ DEF_SVE_FUNCTION (sveor, binary_opt_n, all_integer, mxz)
+ DEF_SVE_FUNCTION (sveor, binary_opt_n, b, z)
+ DEF_SVE_FUNCTION (sveorv, reduction, all_integer, implicit)
+-DEF_SVE_FUNCTION (svexpa, unary_uint, all_float, none)
+ DEF_SVE_FUNCTION (svext, ext, all_data, none)
+ DEF_SVE_FUNCTION (svextb, unary, hsd_integer, mxz)
+ DEF_SVE_FUNCTION (svexth, unary, sd_integer, mxz)
+@@ -106,51 +99,13 @@ DEF_SVE_FUNCTION (svinsr, binary_n, all_data, none)
+ DEF_SVE_FUNCTION (svlasta, reduction, all_data, implicit)
+ DEF_SVE_FUNCTION (svlastb, reduction, all_data, implicit)
+ DEF_SVE_FUNCTION (svld1, load, all_data, implicit)
+-DEF_SVE_FUNCTION (svld1_gather, load_gather_sv, sd_data, implicit)
+-DEF_SVE_FUNCTION (svld1_gather, load_gather_vs, sd_data, implicit)
+ DEF_SVE_FUNCTION (svld1rq, load_replicate, all_data, implicit)
+ DEF_SVE_FUNCTION (svld1sb, load_ext, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svld1sb_gather, load_ext_gather_offset, sd_integer, implicit)
+ DEF_SVE_FUNCTION (svld1sh, load_ext, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_offset, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_index, sd_integer, implicit)
+ DEF_SVE_FUNCTION (svld1sw, load_ext, d_integer, implicit)
+-DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_offset, d_integer, implicit)
+-DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_index, d_integer, implicit)
+ DEF_SVE_FUNCTION (svld1ub, load_ext, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svld1ub_gather, load_ext_gather_offset, sd_integer, implicit)
+ DEF_SVE_FUNCTION (svld1uh, load_ext, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_offset, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_index, sd_integer, implicit)
+ DEF_SVE_FUNCTION (svld1uw, load_ext, d_integer, implicit)
+-DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_offset, d_integer, implicit)
+-DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_index, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1, load, all_data, implicit)
+-DEF_SVE_FUNCTION (svldff1_gather, load_gather_sv, sd_data, implicit)
+-DEF_SVE_FUNCTION (svldff1_gather, load_gather_vs, sd_data, implicit)
+-DEF_SVE_FUNCTION (svldff1sb, load_ext, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sb_gather, load_ext_gather_offset, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sh, load_ext, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_offset, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_index, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sw, load_ext, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_offset, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_index, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1ub, load_ext, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1ub_gather, load_ext_gather_offset, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1uh, load_ext, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_offset, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_index, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1uw, load_ext, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_offset, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_index, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldnf1, load, all_data, implicit)
+-DEF_SVE_FUNCTION (svldnf1sb, load_ext, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnf1sh, load_ext, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnf1sw, load_ext, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldnf1ub, load_ext, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnf1uh, load_ext, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnf1uw, load_ext, d_integer, implicit)
+ DEF_SVE_FUNCTION (svldnt1, load, all_data, implicit)
+ DEF_SVE_FUNCTION (svld2, load, all_data, implicit)
+ DEF_SVE_FUNCTION (svld3, load, all_data, implicit)
+@@ -173,7 +128,6 @@ DEF_SVE_FUNCTION (svmla, ternary_opt_n, all_arith, mxz)
+ DEF_SVE_FUNCTION (svmla_lane, ternary_lane, all_float, none)
+ DEF_SVE_FUNCTION (svmls, ternary_opt_n, all_arith, mxz)
+ DEF_SVE_FUNCTION (svmls_lane, ternary_lane, all_float, none)
+-DEF_SVE_FUNCTION (svmmla, mmla, none, none)
+ DEF_SVE_FUNCTION (svmov, unary, b, z)
+ DEF_SVE_FUNCTION (svmsb, ternary_opt_n, all_arith, mxz)
+ DEF_SVE_FUNCTION (svmul, binary_opt_n, all_arith, mxz)
+@@ -197,13 +151,9 @@ DEF_SVE_FUNCTION (svpfalse, inherent_b, b, none)
+ DEF_SVE_FUNCTION (svpfirst, unary, b, implicit)
+ DEF_SVE_FUNCTION (svpnext, unary_pred, all_pred, implicit)
+ DEF_SVE_FUNCTION (svprfb, prefetch, none, implicit)
+-DEF_SVE_FUNCTION (svprfb_gather, prefetch_gather_offset, none, implicit)
+ DEF_SVE_FUNCTION (svprfd, prefetch, none, implicit)
+-DEF_SVE_FUNCTION (svprfd_gather, prefetch_gather_index, none, implicit)
+ DEF_SVE_FUNCTION (svprfh, prefetch, none, implicit)
+-DEF_SVE_FUNCTION (svprfh_gather, prefetch_gather_index, none, implicit)
+ DEF_SVE_FUNCTION (svprfw, prefetch, none, implicit)
+-DEF_SVE_FUNCTION (svprfw_gather, prefetch_gather_index, none, implicit)
+ DEF_SVE_FUNCTION (svptest_any, ptest, none, implicit)
+ DEF_SVE_FUNCTION (svptest_first, ptest, none, implicit)
+ DEF_SVE_FUNCTION (svptest_last, ptest, none, implicit)
+@@ -244,7 +194,6 @@ DEF_SVE_FUNCTION (svqincw_pat, inc_dec_pat, s_integer, none)
+ DEF_SVE_FUNCTION (svqincw_pat, inc_dec_pat, sd_integer, none)
+ DEF_SVE_FUNCTION (svqsub, binary_opt_n, all_integer, none)
+ DEF_SVE_FUNCTION (svrbit, unary, all_integer, mxz)
+-DEF_SVE_FUNCTION (svrdffr, rdffr, none, z_or_none)
+ DEF_SVE_FUNCTION (svrecpe, unary, all_float, none)
+ DEF_SVE_FUNCTION (svrecps, binary, all_float, none)
+ DEF_SVE_FUNCTION (svrecpx, unary, all_float, mxz)
+@@ -269,20 +218,12 @@ DEF_SVE_FUNCTION (svsel, binary, b, implicit)
+ DEF_SVE_FUNCTION (svset2, set, all_data, none)
+ DEF_SVE_FUNCTION (svset3, set, all_data, none)
+ DEF_SVE_FUNCTION (svset4, set, all_data, none)
+-DEF_SVE_FUNCTION (svsetffr, setffr, none, none)
+ DEF_SVE_FUNCTION (svsplice, binary, all_data, implicit)
+ DEF_SVE_FUNCTION (svsqrt, unary, all_float, mxz)
+ DEF_SVE_FUNCTION (svst1, store, all_data, implicit)
+-DEF_SVE_FUNCTION (svst1_scatter, store_scatter_index, sd_data, implicit)
+-DEF_SVE_FUNCTION (svst1_scatter, store_scatter_offset, sd_data, implicit)
+ DEF_SVE_FUNCTION (svst1b, store, hsd_integer, implicit)
+-DEF_SVE_FUNCTION (svst1b_scatter, store_scatter_offset, sd_integer, implicit)
+ DEF_SVE_FUNCTION (svst1h, store, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_index, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_offset, sd_integer, implicit)
+ DEF_SVE_FUNCTION (svst1w, store, d_integer, implicit)
+-DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_index, d_integer, implicit)
+-DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_offset, d_integer, implicit)
+ DEF_SVE_FUNCTION (svst2, store, all_data, implicit)
+ DEF_SVE_FUNCTION (svst3, store, all_data, implicit)
+ DEF_SVE_FUNCTION (svst4, store, all_data, implicit)
+@@ -290,13 +231,10 @@ DEF_SVE_FUNCTION (svstnt1, store, all_data, implicit)
+ DEF_SVE_FUNCTION (svsub, binary_opt_n, all_arith, mxz)
+ DEF_SVE_FUNCTION (svsubr, binary_opt_n, all_arith, mxz)
+ DEF_SVE_FUNCTION (svtbl, binary_uint, all_data, none)
+-DEF_SVE_FUNCTION (svtmad, tmad, all_float, none)
+ DEF_SVE_FUNCTION (svtrn1, binary, all_data, none)
+ DEF_SVE_FUNCTION (svtrn1, binary_pred, all_pred, none)
+ DEF_SVE_FUNCTION (svtrn2, binary, all_data, none)
+ DEF_SVE_FUNCTION (svtrn2, binary_pred, all_pred, none)
+-DEF_SVE_FUNCTION (svtsmul, binary_uint, all_float, none)
+-DEF_SVE_FUNCTION (svtssel, binary_uint, all_float, none)
+ DEF_SVE_FUNCTION (svundef, inherent, all_data, none)
+ DEF_SVE_FUNCTION (svundef2, inherent, all_data, none)
+ DEF_SVE_FUNCTION (svundef3, inherent, all_data, none)
+@@ -311,13 +249,78 @@ DEF_SVE_FUNCTION (svuzp2, binary, all_data, none)
+ DEF_SVE_FUNCTION (svuzp2, binary_pred, all_pred, none)
+ DEF_SVE_FUNCTION (svwhilele, compare_scalar, while, none)
+ DEF_SVE_FUNCTION (svwhilelt, compare_scalar, while, none)
+-DEF_SVE_FUNCTION (svwrffr, setffr, none, implicit)
+ DEF_SVE_FUNCTION (svzip1, binary, all_data, none)
+ DEF_SVE_FUNCTION (svzip1, binary_pred, all_pred, none)
+ DEF_SVE_FUNCTION (svzip2, binary, all_data, none)
+ DEF_SVE_FUNCTION (svzip2, binary_pred, all_pred, none)
+ #undef REQUIRED_EXTENSIONS
+ 
++#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_SM_OFF
++DEF_SVE_FUNCTION (svadda, fold_left, all_float, implicit)
++DEF_SVE_FUNCTION (svadrb, adr_offset, none, none)
++DEF_SVE_FUNCTION (svadrd, adr_index, none, none)
++DEF_SVE_FUNCTION (svadrh, adr_index, none, none)
++DEF_SVE_FUNCTION (svadrw, adr_index, none, none)
++DEF_SVE_FUNCTION (svcompact, unary, sd_data, implicit)
++DEF_SVE_FUNCTION (svexpa, unary_uint, all_float, none)
++DEF_SVE_FUNCTION (svld1_gather, load_gather_sv, sd_data, implicit)
++DEF_SVE_FUNCTION (svld1_gather, load_gather_vs, sd_data, implicit)
++DEF_SVE_FUNCTION (svld1sb_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_index, sd_integer, implicit)
++DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_offset, d_integer, implicit)
++DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_index, d_integer, implicit)
++DEF_SVE_FUNCTION (svld1ub_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_index, sd_integer, implicit)
++DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_offset, d_integer, implicit)
++DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_index, d_integer, implicit)
++DEF_SVE_FUNCTION (svldff1, load, all_data, implicit)
++DEF_SVE_FUNCTION (svldff1_gather, load_gather_sv, sd_data, implicit)
++DEF_SVE_FUNCTION (svldff1_gather, load_gather_vs, sd_data, implicit)
++DEF_SVE_FUNCTION (svldff1sb, load_ext, hsd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sb_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sh, load_ext, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_index, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sw, load_ext, d_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_offset, d_integer, implicit)
++DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_index, d_integer, implicit)
++DEF_SVE_FUNCTION (svldff1ub, load_ext, hsd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1ub_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1uh, load_ext, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_index, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldff1uw, load_ext, d_integer, implicit)
++DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_offset, d_integer, implicit)
++DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_index, d_integer, implicit)
++DEF_SVE_FUNCTION (svldnf1, load, all_data, implicit)
++DEF_SVE_FUNCTION (svldnf1sb, load_ext, hsd_integer, implicit)
++DEF_SVE_FUNCTION (svldnf1sh, load_ext, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnf1sw, load_ext, d_integer, implicit)
++DEF_SVE_FUNCTION (svldnf1ub, load_ext, hsd_integer, implicit)
++DEF_SVE_FUNCTION (svldnf1uh, load_ext, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnf1uw, load_ext, d_integer, implicit)
++DEF_SVE_FUNCTION (svmmla, mmla, none, none)
++DEF_SVE_FUNCTION (svprfb_gather, prefetch_gather_offset, none, implicit)
++DEF_SVE_FUNCTION (svprfd_gather, prefetch_gather_index, none, implicit)
++DEF_SVE_FUNCTION (svprfh_gather, prefetch_gather_index, none, implicit)
++DEF_SVE_FUNCTION (svprfw_gather, prefetch_gather_index, none, implicit)
++DEF_SVE_FUNCTION (svrdffr, rdffr, none, z_or_none)
++DEF_SVE_FUNCTION (svsetffr, setffr, none, none)
++DEF_SVE_FUNCTION (svst1_scatter, store_scatter_index, sd_data, implicit)
++DEF_SVE_FUNCTION (svst1_scatter, store_scatter_offset, sd_data, implicit)
++DEF_SVE_FUNCTION (svst1b_scatter, store_scatter_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_index, sd_integer, implicit)
++DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_offset, sd_integer, implicit)
++DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_index, d_integer, implicit)
++DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_offset, d_integer, implicit)
++DEF_SVE_FUNCTION (svtmad, tmad, all_float, none)
++DEF_SVE_FUNCTION (svtsmul, binary_uint, all_float, none)
++DEF_SVE_FUNCTION (svtssel, binary_uint, all_float, none)
++DEF_SVE_FUNCTION (svwrffr, setffr, none, implicit)
++#undef REQUIRED_EXTENSIONS
++
+ #define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_BF16
+ DEF_SVE_FUNCTION (svbfdot, ternary_bfloat_opt_n, s_float, none)
+ DEF_SVE_FUNCTION (svbfdot_lane, ternary_bfloat_lanex2, s_float, none)
+@@ -325,27 +328,37 @@ DEF_SVE_FUNCTION (svbfmlalb, ternary_bfloat_opt_n, s_float, none)
+ DEF_SVE_FUNCTION (svbfmlalb_lane, ternary_bfloat_lane, s_float, none)
+ DEF_SVE_FUNCTION (svbfmlalt, ternary_bfloat_opt_n, s_float, none)
+ DEF_SVE_FUNCTION (svbfmlalt_lane, ternary_bfloat_lane, s_float, none)
+-DEF_SVE_FUNCTION (svbfmmla, ternary_bfloat, s_float, none)
+ DEF_SVE_FUNCTION (svcvt, unary_convert, cvt_bfloat, mxz)
+ DEF_SVE_FUNCTION (svcvtnt, unary_convert_narrowt, cvt_bfloat, mx)
+ #undef REQUIRED_EXTENSIONS
+ 
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_BF16 \
++			     | AARCH64_FL_SM_OFF)
++DEF_SVE_FUNCTION (svbfmmla, ternary_bfloat, s_float, none)
++#undef REQUIRED_EXTENSIONS
++
+ #define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_I8MM
+-DEF_SVE_FUNCTION (svmmla, mmla, s_integer, none)
+-DEF_SVE_FUNCTION (svusmmla, ternary_uintq_intq, s_signed, none)
+ DEF_SVE_FUNCTION (svsudot, ternary_intq_uintq_opt_n, s_signed, none)
+ DEF_SVE_FUNCTION (svsudot_lane, ternary_intq_uintq_lane, s_signed, none)
+ DEF_SVE_FUNCTION (svusdot, ternary_uintq_intq_opt_n, s_signed, none)
+ DEF_SVE_FUNCTION (svusdot_lane, ternary_uintq_intq_lane, s_signed, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+-#define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_F32MM
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_I8MM \
++			     | AARCH64_FL_SM_OFF)
++DEF_SVE_FUNCTION (svmmla, mmla, s_integer, none)
++DEF_SVE_FUNCTION (svusmmla, ternary_uintq_intq, s_signed, none)
++#undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_F32MM \
++			     | AARCH64_FL_SM_OFF)
+ DEF_SVE_FUNCTION (svmmla, mmla, s_float, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+ #define REQUIRED_EXTENSIONS AARCH64_FL_SVE | AARCH64_FL_F64MM
+-DEF_SVE_FUNCTION (svld1ro, load_replicate, all_data, implicit)
+-DEF_SVE_FUNCTION (svmmla, mmla, d_float, none)
+ DEF_SVE_FUNCTION (svtrn1q, binary, all_data, none)
+ DEF_SVE_FUNCTION (svtrn2q, binary, all_data, none)
+ DEF_SVE_FUNCTION (svuzp1q, binary, all_data, none)
+@@ -353,3 +366,10 @@ DEF_SVE_FUNCTION (svuzp2q, binary, all_data, none)
+ DEF_SVE_FUNCTION (svzip1q, binary, all_data, none)
+ DEF_SVE_FUNCTION (svzip2q, binary, all_data, none)
+ #undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_F64MM \
++			     | AARCH64_FL_SM_OFF)
++DEF_SVE_FUNCTION (svld1ro, load_replicate, all_data, implicit)
++DEF_SVE_FUNCTION (svmmla, mmla, d_float, none)
++#undef REQUIRED_EXTENSIONS
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
+index d5f23a887..3c0a0e072 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
+@@ -51,24 +51,9 @@ DEF_SVE_FUNCTION (sveor3, ternary_opt_n, all_integer, none)
+ DEF_SVE_FUNCTION (sveorbt, ternary_opt_n, all_integer, none)
+ DEF_SVE_FUNCTION (sveortb, ternary_opt_n, all_integer, none)
+ DEF_SVE_FUNCTION (svhadd, binary_opt_n, all_integer, mxz)
+-DEF_SVE_FUNCTION (svhistcnt, binary_to_uint, sd_integer, z)
+-DEF_SVE_FUNCTION (svhistseg, binary_to_uint, b_integer, none)
+ DEF_SVE_FUNCTION (svhsub, binary_opt_n, all_integer, mxz)
+ DEF_SVE_FUNCTION (svhsubr, binary_opt_n, all_integer, mxz)
+-DEF_SVE_FUNCTION (svldnt1_gather, load_gather_sv_restricted, sd_data, implicit)
+-DEF_SVE_FUNCTION (svldnt1_gather, load_gather_vs, sd_data, implicit)
+-DEF_SVE_FUNCTION (svldnt1sb_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1sh_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1sh_gather, load_ext_gather_index_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1sw_gather, load_ext_gather_offset_restricted, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1sw_gather, load_ext_gather_index_restricted, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1ub_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1uh_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1uh_gather, load_ext_gather_index_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1uw_gather, load_ext_gather_offset_restricted, d_integer, implicit)
+-DEF_SVE_FUNCTION (svldnt1uw_gather, load_ext_gather_index_restricted, d_integer, implicit)
+ DEF_SVE_FUNCTION (svlogb, unary_to_int, all_float, mxz)
+-DEF_SVE_FUNCTION (svmatch, compare, bh_integer, implicit)
+ DEF_SVE_FUNCTION (svmaxp, binary, all_arith, mx)
+ DEF_SVE_FUNCTION (svmaxnmp, binary, all_float, mx)
+ DEF_SVE_FUNCTION (svmla_lane, ternary_lane, hsd_integer, none)
+@@ -91,7 +76,6 @@ DEF_SVE_FUNCTION (svmullb_lane, binary_long_lane, sd_integer, none)
+ DEF_SVE_FUNCTION (svmullt, binary_long_opt_n, hsd_integer, none)
+ DEF_SVE_FUNCTION (svmullt_lane, binary_long_lane, sd_integer, none)
+ DEF_SVE_FUNCTION (svnbsl, ternary_opt_n, all_integer, none)
+-DEF_SVE_FUNCTION (svnmatch, compare, bh_integer, implicit)
+ DEF_SVE_FUNCTION (svpmul, binary_opt_n, b_unsigned, none)
+ DEF_SVE_FUNCTION (svpmullb, binary_long_opt_n, hd_unsigned, none)
+ DEF_SVE_FUNCTION (svpmullb_pair, binary_opt_n, bs_unsigned, none)
+@@ -164,13 +148,6 @@ DEF_SVE_FUNCTION (svsli, ternary_shift_left_imm, all_integer, none)
+ DEF_SVE_FUNCTION (svsqadd, binary_int_opt_n, all_unsigned, mxz)
+ DEF_SVE_FUNCTION (svsra, ternary_shift_right_imm, all_integer, none)
+ DEF_SVE_FUNCTION (svsri, ternary_shift_right_imm, all_integer, none)
+-DEF_SVE_FUNCTION (svstnt1_scatter, store_scatter_index_restricted, sd_data, implicit)
+-DEF_SVE_FUNCTION (svstnt1_scatter, store_scatter_offset_restricted, sd_data, implicit)
+-DEF_SVE_FUNCTION (svstnt1b_scatter, store_scatter_offset_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svstnt1h_scatter, store_scatter_index_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svstnt1h_scatter, store_scatter_offset_restricted, sd_integer, implicit)
+-DEF_SVE_FUNCTION (svstnt1w_scatter, store_scatter_index_restricted, d_integer, implicit)
+-DEF_SVE_FUNCTION (svstnt1w_scatter, store_scatter_offset_restricted, d_integer, implicit)
+ DEF_SVE_FUNCTION (svsubhnb, binary_narrowb_opt_n, hsd_integer, none)
+ DEF_SVE_FUNCTION (svsubhnt, binary_narrowt_opt_n, hsd_integer, none)
+ DEF_SVE_FUNCTION (svsublb, binary_long_opt_n, hsd_integer, none)
+@@ -191,7 +168,36 @@ DEF_SVE_FUNCTION (svxar, ternary_shift_right_imm, all_integer, none)
+ 
+ #define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
+ 			     | AARCH64_FL_SVE2 \
+-			     | AARCH64_FL_SVE2_AES)
++			     | AARCH64_FL_SM_OFF)
++DEF_SVE_FUNCTION (svhistcnt, binary_to_uint, sd_integer, z)
++DEF_SVE_FUNCTION (svhistseg, binary_to_uint, b_integer, none)
++DEF_SVE_FUNCTION (svldnt1_gather, load_gather_sv_restricted, sd_data, implicit)
++DEF_SVE_FUNCTION (svldnt1_gather, load_gather_vs, sd_data, implicit)
++DEF_SVE_FUNCTION (svldnt1sb_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1sh_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1sh_gather, load_ext_gather_index_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1sw_gather, load_ext_gather_offset_restricted, d_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1sw_gather, load_ext_gather_index_restricted, d_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1ub_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1uh_gather, load_ext_gather_offset_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1uh_gather, load_ext_gather_index_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1uw_gather, load_ext_gather_offset_restricted, d_integer, implicit)
++DEF_SVE_FUNCTION (svldnt1uw_gather, load_ext_gather_index_restricted, d_integer, implicit)
++DEF_SVE_FUNCTION (svmatch, compare, bh_integer, implicit)
++DEF_SVE_FUNCTION (svnmatch, compare, bh_integer, implicit)
++DEF_SVE_FUNCTION (svstnt1_scatter, store_scatter_index_restricted, sd_data, implicit)
++DEF_SVE_FUNCTION (svstnt1_scatter, store_scatter_offset_restricted, sd_data, implicit)
++DEF_SVE_FUNCTION (svstnt1b_scatter, store_scatter_offset_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svstnt1h_scatter, store_scatter_index_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svstnt1h_scatter, store_scatter_offset_restricted, sd_integer, implicit)
++DEF_SVE_FUNCTION (svstnt1w_scatter, store_scatter_index_restricted, d_integer, implicit)
++DEF_SVE_FUNCTION (svstnt1w_scatter, store_scatter_offset_restricted, d_integer, implicit)
++#undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
++			     | AARCH64_FL_SVE2 \
++			     | AARCH64_FL_SVE2_AES \
++			     | AARCH64_FL_SM_OFF)
+ DEF_SVE_FUNCTION (svaesd, binary, b_unsigned, none)
+ DEF_SVE_FUNCTION (svaese, binary, b_unsigned, none)
+ DEF_SVE_FUNCTION (svaesmc, unary, b_unsigned, none)
+@@ -202,7 +208,8 @@ DEF_SVE_FUNCTION (svpmullt_pair, binary_opt_n, d_unsigned, none)
+ 
+ #define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
+ 			     | AARCH64_FL_SVE2 \
+-			     | AARCH64_FL_SVE2_BITPERM)
++			     | AARCH64_FL_SVE2_BITPERM \
++			     | AARCH64_FL_SM_OFF)
+ DEF_SVE_FUNCTION (svbdep, binary_opt_n, all_unsigned, none)
+ DEF_SVE_FUNCTION (svbext, binary_opt_n, all_unsigned, none)
+ DEF_SVE_FUNCTION (svbgrp, binary_opt_n, all_unsigned, none)
+@@ -210,13 +217,15 @@ DEF_SVE_FUNCTION (svbgrp, binary_opt_n, all_unsigned, none)
+ 
+ #define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
+ 			     | AARCH64_FL_SVE2 \
+-			     | AARCH64_FL_SVE2_SHA3)
++			     | AARCH64_FL_SVE2_SHA3 \
++			     | AARCH64_FL_SM_OFF)
+ DEF_SVE_FUNCTION (svrax1, binary, d_integer, none)
+ #undef REQUIRED_EXTENSIONS
+ 
+ #define REQUIRED_EXTENSIONS (AARCH64_FL_SVE \
+ 			     | AARCH64_FL_SVE2 \
+-			     | AARCH64_FL_SVE2_SM4)
++			     | AARCH64_FL_SVE2_SM4 \
++			     | AARCH64_FL_SM_OFF)
+ DEF_SVE_FUNCTION (svsm4e, binary, s_unsigned, none)
+ DEF_SVE_FUNCTION (svsm4ekey, binary, s_unsigned, none)
+ #undef REQUIRED_EXTENSIONS
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index c439f2e8a..5f3a2baea 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -738,6 +738,13 @@ check_required_extensions (location_t location, tree fndecl,
+   if (missing_extensions == 0)
+     return check_required_registers (location, fndecl);
+ 
++  if (missing_extensions & AARCH64_FL_SM_OFF)
++    {
++      error_at (location, "ACLE function %qD cannot be called when"
++		" SME streaming mode is enabled", fndecl);
++      return false;
++    }
++
+   static const struct {
+     aarch64_feature_flags flag;
+     const char *name;
+diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
+index 28b73d807..a8a5dc3a2 100644
+--- a/gcc/config/aarch64/aarch64-sve.md
++++ b/gcc/config/aarch64/aarch64-sve.md
+@@ -1082,7 +1082,7 @@
+ 	(match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one" "Dm, Upa"))
+    (set (reg:VNx16BI FFRT_REGNUM)
+ 	(unspec:VNx16BI [(match_dup 0)] UNSPEC_WRFFR))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    setffr
+    wrffr\t%0.b"
+@@ -1123,7 +1123,7 @@
+ (define_insn "aarch64_rdffr"
+   [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ 	(reg:VNx16BI FFRT_REGNUM))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "rdffr\t%0.b"
+ )
+ 
+@@ -1133,7 +1133,7 @@
+ 	(and:VNx16BI
+ 	  (reg:VNx16BI FFRT_REGNUM)
+ 	  (match_operand:VNx16BI 1 "register_operand" "Upa")))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "rdffr\t%0.b, %1/z"
+ )
+ 
+@@ -1149,7 +1149,7 @@
+ 	     (match_dup 1))]
+ 	  UNSPEC_PTEST))
+    (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "rdffrs\t%0.b, %1/z"
+ )
+ 
+@@ -1163,7 +1163,7 @@
+ 	   (reg:VNx16BI FFRT_REGNUM)]
+ 	  UNSPEC_PTEST))
+    (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "rdffrs\t%0.b, %1/z"
+ )
+ 
+@@ -1182,7 +1182,7 @@
+ 	(and:VNx16BI
+ 	  (reg:VNx16BI FFRT_REGNUM)
+ 	  (match_dup 1)))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "rdffrs\t%0.b, %1/z"
+ )
+ 
+@@ -1197,7 +1197,7 @@
+ 	  UNSPEC_PTEST))
+    (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ 	(reg:VNx16BI FFRT_REGNUM))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "rdffrs\t%0.b, %1/z"
+ )
+ 
+@@ -1327,7 +1327,7 @@
+ 	   (match_operand:SVE_FULL 1 "aarch64_sve_ldf1_operand" "Ut")
+ 	   (reg:VNx16BI FFRT_REGNUM)]
+ 	  SVE_LDFF1_LDNF1))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "ldf1\t%0., %2/z, %1"
+ )
+ 
+@@ -1361,7 +1361,9 @@
+ 		(reg:VNx16BI FFRT_REGNUM)]
+ 	       SVE_LDFF1_LDNF1))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE && (~ & ) == 0"
++  "TARGET_SVE
++   && TARGET_NON_STREAMING
++   && (~ & ) == 0"
+   "ldf1\t%0., %2/z, %1"
+   "&& !CONSTANT_P (operands[3])"
+   {
+@@ -1409,7 +1411,7 @@
+ 	   (match_operand:DI 4 "aarch64_gather_scale_operand_")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LD1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     operands[5] = aarch64_ptrue_reg (mode);
+   }
+@@ -1427,7 +1429,7 @@
+ 	   (match_operand:DI 4 "aarch64_gather_scale_operand_" "Ui1, Ui1, Ui1, Ui1, i, i")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LD1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ld1\t%0.s, %5/z, [%2.s]
+    ld1\t%0.s, %5/z, [%2.s, #%1]
+@@ -1449,7 +1451,7 @@
+ 	   (match_operand:DI 4 "aarch64_gather_scale_operand_" "Ui1, Ui1, Ui1, i")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LD1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ld1\t%0.d, %5/z, [%2.d]
+    ld1\t%0.d, %5/z, [%2.d, #%1]
+@@ -1472,7 +1474,7 @@
+ 	   (match_operand:DI 4 "aarch64_gather_scale_operand_" "Ui1, i")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LD1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ld1\t%0.d, %5/z, [%1, %2.d, xtw]
+    ld1\t%0.d, %5/z, [%1, %2.d, xtw %p4]"
+@@ -1499,7 +1501,7 @@
+ 	   (match_operand:DI 4 "aarch64_gather_scale_operand_" "Ui1, i")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LD1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ld1\t%0.d, %5/z, [%1, %2.d, sxtw]
+    ld1\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+@@ -1523,7 +1525,7 @@
+ 	   (match_operand:DI 4 "aarch64_gather_scale_operand_" "Ui1, i")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LD1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ld1\t%0.d, %5/z, [%1, %2.d, uxtw]
+    ld1\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+@@ -1557,7 +1559,9 @@
+ 		(mem:BLK (scratch))]
+ 	       UNSPEC_LD1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE && (~ & ) == 0"
++  "TARGET_SVE
++   && TARGET_NON_STREAMING
++   && (~ & ) == 0"
+   "@
+    ld1\t%0.s, %5/z, [%2.s]
+    ld1\t%0.s, %5/z, [%2.s, #%1]
+@@ -1587,7 +1591,9 @@
+ 		(mem:BLK (scratch))]
+ 	       UNSPEC_LD1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE && (~ & ) == 0"
++  "TARGET_SVE
++   && TARGET_NON_STREAMING
++   && (~ & ) == 0"
+   "@
+    ld1\t%0.d, %5/z, [%2.d]
+    ld1\t%0.d, %5/z, [%2.d, #%1]
+@@ -1618,7 +1624,9 @@
+ 		(mem:BLK (scratch))]
+ 	       UNSPEC_LD1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE && (~ & ) == 0"
++  "TARGET_SVE
++   && TARGET_NON_STREAMING
++   && (~ & ) == 0"
+   "@
+    ld1\t%0.d, %5/z, [%1, %2.d, xtw]
+    ld1\t%0.d, %5/z, [%1, %2.d, xtw %p4]"
+@@ -1650,7 +1658,9 @@
+ 		(mem:BLK (scratch))]
+ 	       UNSPEC_LD1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE && (~ & ) == 0"
++  "TARGET_SVE
++   && TARGET_NON_STREAMING
++   && (~ & ) == 0"
+   "@
+    ld1\t%0.d, %5/z, [%1, %2.d, sxtw]
+    ld1\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+@@ -1679,7 +1689,9 @@
+ 		(mem:BLK (scratch))]
+ 	       UNSPEC_LD1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE && (~ & ) == 0"
++  "TARGET_SVE
++   && TARGET_NON_STREAMING
++   && (~ & ) == 0"
+   "@
+    ld1\t%0.d, %5/z, [%1, %2.d, uxtw]
+    ld1\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+@@ -1710,7 +1722,7 @@
+ 	   (mem:BLK (scratch))
+ 	   (reg:VNx16BI FFRT_REGNUM)]
+ 	  UNSPEC_LDFF1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1w\t%0.s, %5/z, [%2.s]
+    ldff1w\t%0.s, %5/z, [%2.s, #%1]
+@@ -1733,7 +1745,7 @@
+ 	   (mem:BLK (scratch))
+ 	   (reg:VNx16BI FFRT_REGNUM)]
+ 	  UNSPEC_LDFF1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1d\t%0.d, %5/z, [%2.d]
+    ldff1d\t%0.d, %5/z, [%2.d, #%1]
+@@ -1758,7 +1770,7 @@
+ 	   (mem:BLK (scratch))
+ 	   (reg:VNx16BI FFRT_REGNUM)]
+ 	  UNSPEC_LDFF1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1d\t%0.d, %5/z, [%1, %2.d, sxtw]
+    ldff1d\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+@@ -1782,7 +1794,7 @@
+ 	   (mem:BLK (scratch))
+ 	   (reg:VNx16BI FFRT_REGNUM)]
+ 	  UNSPEC_LDFF1_GATHER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw]
+    ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+@@ -1817,7 +1829,7 @@
+ 		(reg:VNx16BI FFRT_REGNUM)]
+ 	       UNSPEC_LDFF1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1\t%0.s, %5/z, [%2.s]
+    ldff1\t%0.s, %5/z, [%2.s, #%1]
+@@ -1848,7 +1860,7 @@
+ 		(reg:VNx16BI FFRT_REGNUM)]
+ 	       UNSPEC_LDFF1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1\t%0.d, %5/z, [%2.d]
+    ldff1\t%0.d, %5/z, [%2.d, #%1]
+@@ -1881,7 +1893,7 @@
+ 		(reg:VNx16BI FFRT_REGNUM)]
+ 	       UNSPEC_LDFF1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1\t%0.d, %5/z, [%1, %2.d, sxtw]
+    ldff1\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+@@ -1910,7 +1922,7 @@
+ 		(reg:VNx16BI FFRT_REGNUM)]
+ 	       UNSPEC_LDFF1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    ldff1\t%0.d, %5/z, [%1, %2.d, uxtw]
+    ldff1\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+@@ -1985,7 +1997,7 @@
+ 	       UNSPEC_SVE_PREFETCH_GATHER)
+ 	     (match_operand:DI 7 "const_int_operand")
+ 	     (match_operand:DI 8 "const_int_operand"))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     static const char *const insns[][2] = {
+       "prf", "%0, [%2.s]",
+@@ -2014,7 +2026,7 @@
+ 	       UNSPEC_SVE_PREFETCH_GATHER)
+ 	     (match_operand:DI 7 "const_int_operand")
+ 	     (match_operand:DI 8 "const_int_operand"))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     static const char *const insns[][2] = {
+       "prf", "%0, [%2.d]",
+@@ -2045,7 +2057,7 @@
+ 	       UNSPEC_SVE_PREFETCH_GATHER)
+ 	     (match_operand:DI 7 "const_int_operand")
+ 	     (match_operand:DI 8 "const_int_operand"))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     static const char *const insns[][2] = {
+       "prfb", "%0, [%1, %2.d, sxtw]",
+@@ -2075,7 +2087,7 @@
+ 	       UNSPEC_SVE_PREFETCH_GATHER)
+ 	     (match_operand:DI 7 "const_int_operand")
+ 	     (match_operand:DI 8 "const_int_operand"))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     static const char *const insns[][2] = {
+       "prfb", "%0, [%1, %2.d, uxtw]",
+@@ -2242,7 +2254,7 @@
+ 	   (match_operand:DI 3 "aarch64_gather_scale_operand_")
+ 	   (match_operand:SVE_24 4 "register_operand")]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     operands[5] = aarch64_ptrue_reg (mode);
+   }
+@@ -2260,7 +2272,7 @@
+ 	   (match_operand:DI 3 "aarch64_gather_scale_operand_" "Ui1, Ui1, Ui1, Ui1, i, i")
+ 	   (match_operand:SVE_4 4 "register_operand" "w, w, w, w, w, w")]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.s, %5, [%1.s]
+    st1\t%4.s, %5, [%1.s, #%0]
+@@ -2282,7 +2294,7 @@
+ 	   (match_operand:DI 3 "aarch64_gather_scale_operand_" "Ui1, Ui1, Ui1, i")
+ 	   (match_operand:SVE_2 4 "register_operand" "w, w, w, w")]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%1.d]
+    st1\t%4.d, %5, [%1.d, #%0]
+@@ -2305,7 +2317,7 @@
+ 	   (match_operand:DI 3 "aarch64_gather_scale_operand_" "Ui1, i")
+ 	   (match_operand:SVE_2 4 "register_operand" "w, w")]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%0, %1.d, xtw]
+    st1\t%4.d, %5, [%0, %1.d, xtw %p3]"
+@@ -2332,7 +2344,7 @@
+ 	   (match_operand:DI 3 "aarch64_gather_scale_operand_" "Ui1, i")
+ 	   (match_operand:SVE_2 4 "register_operand" "w, w")]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%0, %1.d, sxtw]
+    st1\t%4.d, %5, [%0, %1.d, sxtw %p3]"
+@@ -2356,7 +2368,7 @@
+ 	   (match_operand:DI 3 "aarch64_gather_scale_operand_" "Ui1, i")
+ 	   (match_operand:SVE_2 4 "register_operand" "w, w")]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%0, %1.d, uxtw]
+    st1\t%4.d, %5, [%0, %1.d, uxtw %p3]"
+@@ -2384,7 +2396,7 @@
+ 	   (truncate:VNx4_NARROW
+ 	     (match_operand:VNx4_WIDE 4 "register_operand" "w, w, w, w, w, w"))]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.s, %5, [%1.s]
+    st1\t%4.s, %5, [%1.s, #%0]
+@@ -2407,7 +2419,7 @@
+ 	   (truncate:VNx2_NARROW
+ 	     (match_operand:VNx2_WIDE 4 "register_operand" "w, w, w, w"))]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%1.d]
+    st1\t%4.d, %5, [%1.d, #%0]
+@@ -2432,7 +2444,7 @@
+ 	   (truncate:VNx2_NARROW
+ 	     (match_operand:VNx2_WIDE 4 "register_operand" "w, w"))]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%0, %1.d, sxtw]
+    st1\t%4.d, %5, [%0, %1.d, sxtw %p3]"
+@@ -2456,7 +2468,7 @@
+ 	   (truncate:VNx2_NARROW
+ 	     (match_operand:VNx2_WIDE 4 "register_operand" "w, w"))]
+ 	  UNSPEC_ST1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    st1\t%4.d, %5, [%0, %1.d, uxtw]
+    st1\t%4.d, %5, [%0, %1.d, uxtw %p3]"
+@@ -2602,7 +2614,7 @@
+ 	   (match_operand:OI 1 "aarch64_sve_ld1ro_operand_"
+ 			       "UO")]
+ 	  UNSPEC_LD1RO))]
+-  "TARGET_SVE_F64MM"
++  "TARGET_SVE_F64MM && TARGET_NON_STREAMING"
+   {
+     operands[1] = gen_rtx_MEM (mode, XEXP (operands[1], 0));
+     return "ld1ro\t%0., %2/z, %1";
+@@ -3834,7 +3846,7 @@
+ 	  [(match_operand:SVE_FULL_SDI 1 "register_operand" "w")
+ 	   (match_operand:SVE_FULL_SDI 2 "register_operand" "w")]
+ 	  UNSPEC_ADR))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0., [%1., %2.]"
+ )
+ 
+@@ -3850,7 +3862,7 @@
+ 		  (match_operand:VNx2DI 2 "register_operand" "w")))]
+ 	     UNSPEC_PRED_X)]
+ 	  UNSPEC_ADR))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0.d, [%1.d, %2.d, sxtw]"
+   "&& !CONSTANT_P (operands[3])"
+   {
+@@ -3867,7 +3879,7 @@
+ 	     (match_operand:VNx2DI 2 "register_operand" "w")
+ 	     (match_operand:VNx2DI 3 "aarch64_sve_uxtw_immediate"))]
+ 	  UNSPEC_ADR))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0.d, [%1.d, %2.d, uxtw]"
+ )
+ 
+@@ -3879,7 +3891,7 @@
+ 	    (match_operand:VNx2DI 2 "register_operand" "w")
+ 	    (match_operand:VNx2DI 3 "aarch64_sve_uxtw_immediate"))
+ 	  (match_operand:VNx2DI 1 "register_operand" "w")))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0.d, [%1.d, %2.d, uxtw]"
+ )
+ 
+@@ -3894,7 +3906,7 @@
+ 	       (match_operand:SVE_FULL_SDI 3 "const_1_to_3_operand"))]
+ 	    UNSPEC_PRED_X)
+ 	  (match_operand:SVE_FULL_SDI 1 "register_operand")))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     operands[4] = CONSTM1_RTX (mode);
+   }
+@@ -3910,7 +3922,7 @@
+ 	       (match_operand:SVE_24I 3 "const_1_to_3_operand"))]
+ 	    UNSPEC_PRED_X)
+ 	  (match_operand:SVE_24I 1 "register_operand" "w")))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0., [%1., %2., lsl %3]"
+   "&& !CONSTANT_P (operands[4])"
+   {
+@@ -3934,7 +3946,7 @@
+ 	       (match_operand:VNx2DI 3 "const_1_to_3_operand"))]
+ 	    UNSPEC_PRED_X)
+ 	  (match_operand:VNx2DI 1 "register_operand" "w")))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0.d, [%1.d, %2.d, sxtw %3]"
+   "&& (!CONSTANT_P (operands[4]) || !CONSTANT_P (operands[5]))"
+   {
+@@ -3955,7 +3967,7 @@
+ 	       (match_operand:VNx2DI 3 "const_1_to_3_operand"))]
+ 	    UNSPEC_PRED_X)
+ 	  (match_operand:VNx2DI 1 "register_operand" "w")))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "adr\t%0.d, [%1.d, %2.d, uxtw %3]"
+   "&& !CONSTANT_P (operands[5])"
+   {
+@@ -6967,7 +6979,7 @@
+ 	     (match_operand: 3 "register_operand" "w, w")]
+ 	    MATMUL)
+ 	  (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")))]
+-  "TARGET_SVE_I8MM"
++  "TARGET_SVE_I8MM && TARGET_NON_STREAMING"
+   "@
+    mmla\\t%0.s, %2.b, %3.b
+    movprfx\t%0, %1\;mmla\\t%0.s, %2.b, %3.b"
+@@ -7538,7 +7550,7 @@
+ 	   (match_operand:SVE_MATMULF 3 "register_operand" "w, w")
+ 	   (match_operand:SVE_MATMULF 1 "register_operand" "0, w")]
+ 	  FMMLA))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    \\t%0., %2., %3.
+    movprfx\t%0, %1\;\\t%0., %2., %3."
+@@ -8601,7 +8613,7 @@
+ 		       (match_operand: 1 "register_operand")
+ 		       (match_operand:SVE_FULL_F 2 "register_operand")]
+ 		      UNSPEC_FADDA))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   {
+     operands[3] = aarch64_ptrue_reg (mode);
+   }
+@@ -8614,7 +8626,7 @@
+ 		       (match_operand: 1 "register_operand" "0")
+ 		       (match_operand:SVE_FULL_F 2 "register_operand" "w")]
+ 		      UNSPEC_FADDA))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "fadda\t%0, %3, %0, %2."
+ )
+ 
+@@ -8668,7 +8680,7 @@
+ 	  [(match_operand: 1 "register_operand" "Upl")
+ 	   (match_operand:SVE_FULL_SD 2 "register_operand" "w")]
+ 	  UNSPEC_SVE_COMPACT))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "compact\t%0., %1, %2."
+ )
+ 
+diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md
+index f138f4be4..36555f65c 100644
+--- a/gcc/config/aarch64/aarch64-sve2.md
++++ b/gcc/config/aarch64/aarch64-sve2.md
+@@ -109,7 +109,7 @@
+ 	   (match_operand: 3 "register_operand" "w, w")
+ 	   (mem:BLK (scratch))]
+ 	  UNSPEC_LDNT1_GATHER))]
+-  "TARGET_SVE2"
++  "TARGET_SVE2 && TARGET_NON_STREAMING"
+   "@
+    ldnt1\t%0., %1/z, [%3.]
+    ldnt1\t%0., %1/z, [%3., %2]"
+@@ -129,6 +129,7 @@
+ 	       UNSPEC_LDNT1_GATHER))]
+ 	  UNSPEC_PRED_X))]
+   "TARGET_SVE2
++   && TARGET_NON_STREAMING
+    && (~ & ) == 0"
+   "@
+    ldnt1\t%0., %1/z, [%3.]
+@@ -159,7 +160,7 @@
+ 	   (match_operand:SVE_FULL_SD 3 "register_operand" "w, w")]
+ 
+ 	  UNSPEC_STNT1_SCATTER))]
+-  "TARGET_SVE"
++  "TARGET_SVE && TARGET_NON_STREAMING"
+   "@
+    stnt1\t%3., %0, [%2.]
+    stnt1\t%3., %0, [%2., %1]"
+@@ -176,6 +177,7 @@
+ 	     (match_operand:SVE_FULL_SDI 3 "register_operand" "w, w"))]
+ 	  UNSPEC_STNT1_SCATTER))]
+   "TARGET_SVE2
++   && TARGET_NON_STREAMING
+    && (~ & ) == 0"
+   "@
+    stnt1\t%3., %0, [%2.]
+@@ -2426,7 +2428,7 @@
+ 	   (match_operand:SVE_FULL_SDI 2 "register_operand" "w")
+ 	   (match_operand:SVE_FULL_SDI 3 "register_operand" "w")]
+ 	  UNSPEC_HISTCNT))]
+-  "TARGET_SVE2"
++  "TARGET_SVE2 && TARGET_NON_STREAMING"
+   "histcnt\t%0., %1/z, %2., %3."
+ )
+ 
+@@ -2436,7 +2438,7 @@
+ 	  [(match_operand:VNx16QI_ONLY 1 "register_operand" "w")
+ 	   (match_operand:VNx16QI_ONLY 2 "register_operand" "w")]
+ 	  UNSPEC_HISTSEG))]
+-  "TARGET_SVE2"
++  "TARGET_SVE2 && TARGET_NON_STREAMING"
+   "histseg\t%0., %1., %2."
+ )
+ 
+@@ -2460,7 +2462,7 @@
+ 	     SVE2_MATCH)]
+ 	  UNSPEC_PRED_Z))
+    (clobber (reg:CC_NZC CC_REGNUM))]
+-  "TARGET_SVE2"
++  "TARGET_SVE2 && TARGET_NON_STREAMING"
+   "\t%0., %1/z, %3., %4."
+ )
+ 
+@@ -2491,6 +2493,7 @@
+ 	     SVE2_MATCH)]
+ 	  UNSPEC_PRED_Z))]
+   "TARGET_SVE2
++   && TARGET_NON_STREAMING
+    && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+   "\t%0., %1/z, %2., %3."
+   "&& !rtx_equal_p (operands[4], operands[6])"
+@@ -2518,6 +2521,7 @@
+ 	  UNSPEC_PTEST))
+    (clobber (match_scratch: 0 "=Upa"))]
+   "TARGET_SVE2
++   && TARGET_NON_STREAMING
+    && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+   "\t%0., %1/z, %2., %3."
+   "&& !rtx_equal_p (operands[4], operands[6])"
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index a3c83a3b1..8f0ac2cde 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -252,6 +252,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ #define AARCH64_ISA_MOPS	   (aarch64_isa_flags & AARCH64_FL_MOPS)
+ #define AARCH64_ISA_LS64	   (aarch64_isa_flags & AARCH64_FL_LS64)
+ 
++/* The current function is a normal non-streaming function.  */
++#define TARGET_NON_STREAMING (AARCH64_ISA_SM_OFF)
++
+ /* Crypto is an optional extension to AdvSIMD.  */
+ #define TARGET_CRYPTO (AARCH64_ISA_CRYPTO)
+ 
+@@ -290,16 +293,16 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ #define TARGET_SVE2 (AARCH64_ISA_SVE2)
+ 
+ /* SVE2 AES instructions, enabled through +sve2-aes.  */
+-#define TARGET_SVE2_AES (AARCH64_ISA_SVE2_AES)
++#define TARGET_SVE2_AES (AARCH64_ISA_SVE2_AES && TARGET_NON_STREAMING)
+ 
+ /* SVE2 BITPERM instructions, enabled through +sve2-bitperm.  */
+-#define TARGET_SVE2_BITPERM (AARCH64_ISA_SVE2_BITPERM)
++#define TARGET_SVE2_BITPERM (AARCH64_ISA_SVE2_BITPERM && TARGET_NON_STREAMING)
+ 
+ /* SVE2 SHA3 instructions, enabled through +sve2-sha3.  */
+-#define TARGET_SVE2_SHA3 (AARCH64_ISA_SVE2_SHA3)
++#define TARGET_SVE2_SHA3 (AARCH64_ISA_SVE2_SHA3 && TARGET_NON_STREAMING)
+ 
+ /* SVE2 SM4 instructions, enabled through +sve2-sm4.  */
+-#define TARGET_SVE2_SM4 (AARCH64_ISA_SVE2_SM4)
++#define TARGET_SVE2_SM4 (AARCH64_ISA_SVE2_SM4 && TARGET_NON_STREAMING)
+ 
+ /* SME instructions, enabled through +sme.  Note that this does not
+    imply anything about the state of PSTATE.SM.  */
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index 8dd2035bc..226dea48a 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -2706,7 +2706,7 @@
+ 
+ (define_int_iterator SVE_FP_UNARY [UNSPEC_FRECPE UNSPEC_RSQRTE])
+ 
+-(define_int_iterator SVE_FP_UNARY_INT [UNSPEC_FEXPA])
++(define_int_iterator SVE_FP_UNARY_INT [(UNSPEC_FEXPA "TARGET_NON_STREAMING")])
+ 
+ (define_int_iterator SVE_INT_SHIFT_IMM [UNSPEC_ASRD
+ 					(UNSPEC_SQSHLU "TARGET_SVE2")
+@@ -2720,7 +2720,7 @@
+ (define_int_iterator SVE_BFLOAT_TERNARY_LONG [UNSPEC_BFDOT
+ 					      UNSPEC_BFMLALB
+ 					      UNSPEC_BFMLALT
+-					      UNSPEC_BFMMLA])
++					      (UNSPEC_BFMMLA "TARGET_NON_STREAMING")])
+ 
+ (define_int_iterator SVE_BFLOAT_TERNARY_LONG_LANE [UNSPEC_BFDOT
+ 						   UNSPEC_BFMLALB
+diff --git a/gcc/testsuite/g++.target/aarch64/sve/aarch64-ssve.exp b/gcc/testsuite/g++.target/aarch64/sve/aarch64-ssve.exp
+new file mode 100644
+index 000000000..d6a5a561a
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sve/aarch64-ssve.exp
+@@ -0,0 +1,308 @@
++#  Specific regression driver for AArch64 SME.
++#  Copyright (C) 2009-2023 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
++#  .  */
++
++# Test whether certain SVE instructions are accepted or rejected in
++# SME streaming mode.
++
++# Exit immediately if this isn't an AArch64 target.
++if {![istarget aarch64*-*-*] } {
++    return
++}
++
++load_lib gcc-defs.exp
++
++gcc_parallel_test_enable 0
++
++# Code shared by all tests.
++set preamble {
++#include 
++
++#pragma GCC target "+i8mm+f32mm+f64mm+sve2+sve2-bitperm+sve2-sm4+sve2-aes+sve2-sha3+sme"
++
++extern svbool_t &pred;
++
++extern svint8_t &s8;
++extern svint32_t &s32;
++
++extern svuint8_t &u8;
++extern svuint16_t &u16;
++extern svuint32_t &u32;
++extern svuint64_t &u64;
++
++extern svbfloat16_t &bf16;
++extern svfloat32_t &f32;
++
++extern void *void_ptr;
++
++extern int8_t *s8_ptr;
++extern int16_t *s16_ptr;
++extern int32_t *s32_ptr;
++
++extern uint8_t *u8_ptr;
++extern uint16_t *u16_ptr;
++extern uint32_t *u32_ptr;
++extern uint64_t *u64_ptr;
++
++extern uint64_t indx;
++}
++
++# Wrap a standalone call in a streaming-compatible function.
++set sc_harness {
++void
++foo () [[arm::streaming_compatible]]
++{
++  $CALL;
++}
++}
++
++# HARNESS is some source code that should be appended to the preamble
++# variable defined above.  It includes the string "$CALL", which should be
++# replaced by the function call in CALL.  The result after both steps is
++# a complete C++ translation unit.
++#
++# Try compiling the C++ code and see what output GCC produces.
++# The expected output is either:
++#
++# - empty, if SHOULD_PASS is true
++# - a message rejecting CALL in streaming mode, if SHOULD_PASS is false
++#
++# CALL is simple enough that it can be used in test names.
++proc check_ssve_call { harness name call should_pass } {
++    global preamble
++
++    set filename test-[pid]
++    set fd [open $filename.cc w]
++    puts $fd $preamble
++    puts -nonewline $fd [string map [list {$CALL} $call] $harness]
++    close $fd
++    remote_download host $filename.cc
++
++    set test "streaming SVE call $name"
++
++    set gcc_output [g++_target_compile $filename.cc $filename.s assembly ""]
++    remote_file build delete $filename.cc $filename.s
++
++    if { [string equal $gcc_output ""] } {
++	if { $should_pass } {
++	    pass $test
++	} else {
++	    fail $test
++	}
++	return
++    }
++
++    set lines [split $gcc_output "\n"]
++    set error_text "cannot be called when SME streaming mode is enabled"
++    if { [llength $lines] == 3
++	 && [string first "In function" [lindex $lines 0]] >= 0
++	 && [string first $error_text [lindex $lines 1]] >= 0
++	 && [string equal [lindex $lines 2] ""] } {
++	if { $should_pass } {
++	    fail $test
++	} else {
++	    pass $test
++	}
++	return
++    }
++
++    verbose -log "$test: unexpected output"
++    fail $test
++}
++
++# Apply check_ssve_call to each line in CALLS.  The other arguments are
++# as for check_ssve_call.
++proc check_ssve_calls { harness calls should_pass } {
++    foreach line [split $calls "\n"] {
++	set call [string trim $line]
++	if { [string equal $call ""] } {
++	    continue
++	}
++	check_ssve_call $harness "$call" $call $should_pass
++    }
++}
++
++# A small selection of things that are valid in streaming mode.
++set streaming_ok {
++    s8 = svadd_x (pred, s8, s8)
++    s8 = svld1 (pred, s8_ptr)
++}
++
++# This order follows the list in the SME manual.
++set nonstreaming_only {
++    u32 = svadrb_offset (u32, u32)
++    u64 = svadrb_offset (u64, u64)
++    u32 = svadrh_index (u32, u32)
++    u64 = svadrh_index (u64, u64)
++    u32 = svadrw_index (u32, u32)
++    u64 = svadrw_index (u64, u64)
++    u32 = svadrd_index (u32, u32)
++    u64 = svadrd_index (u64, u64)
++    u8 = svaesd (u8, u8)
++    u8 = svaese (u8, u8)
++    u8 = svaesimc (u8)
++    u8 = svaesmc (u8)
++    u8 = svbdep (u8, u8)
++    u8 = svbext (u8, u8)
++    f32 = svbfmmla (f32, bf16, bf16)
++    u8 = svbgrp (u8, u8)
++    u32 = svcompact (pred, u32)
++    f32 = svadda (pred, 1.0f, f32)
++    f32 = svexpa (u32)
++    f32 = svmmla (f32, f32, f32)
++    f32 = svtmad (f32, f32, 0)
++    f32 = svtsmul (f32, u32)
++    f32 = svtssel (f32, u32)
++    u32 = svhistcnt_z (pred, u32, u32)
++    u8 = svhistseg (u8, u8)
++    u32 = svld1ub_gather_offset_u32 (pred, u8_ptr, u32)
++    u32 = svld1ub_gather_offset_u32 (pred, u32, 1)
++    u64 = svld1_gather_index (pred, u64_ptr, u64)
++    u64 = svld1_gather_index_u64 (pred, u64, 1)
++    u32 = svld1uh_gather_index_u32 (pred, u16_ptr, u32)
++    u32 = svld1uh_gather_index_u32 (pred, u32, 1)
++    u8 = svld1ro (pred, u8_ptr + indx)
++    u8 = svld1ro (pred, u8_ptr + 1)
++    u16 = svld1ro (pred, u16_ptr + indx)
++    u16 = svld1ro (pred, u16_ptr + 1)
++    u32 = svld1ro (pred, u32_ptr + indx)
++    u32 = svld1ro (pred, u32_ptr + 1)
++    u64 = svld1ro (pred, u64_ptr + indx)
++    u64 = svld1ro (pred, u64_ptr + 1)
++    u32 = svld1sb_gather_offset_u32 (pred, s8_ptr, u32)
++    u32 = svld1sb_gather_offset_u32 (pred, u32, 1)
++    u32 = svld1sh_gather_index_u32 (pred, s16_ptr, u32)
++    u32 = svld1sh_gather_index_u32 (pred, u32, 1)
++    u64 = svld1sw_gather_index_u64 (pred, s32_ptr, u64)
++    u64 = svld1sw_gather_index_u64 (pred, u64, 1)
++    u64 = svld1uw_gather_index_u64 (pred, u32_ptr, u64)
++    u64 = svld1uw_gather_index_u64 (pred, u64, 1)
++    u32 = svld1_gather_index (pred, u32_ptr, u32)
++    u32 = svld1_gather_index_u32 (pred, u32, 1)
++    u8 = svldff1(pred, u8_ptr)
++    u16 = svldff1ub_u16(pred, u8_ptr)
++    u32 = svldff1ub_u32(pred, u8_ptr)
++    u64 = svldff1ub_u64(pred, u8_ptr)
++    u32 = svldff1ub_gather_offset_u32 (pred, u8_ptr, u32)
++    u32 = svldff1ub_gather_offset_u32 (pred, u32, 1)
++    u64 = svldff1(pred, u64_ptr)
++    u64 = svldff1_gather_index (pred, u64_ptr, u64)
++    u64 = svldff1_gather_index_u64 (pred, u64, 1)
++    u16 = svldff1(pred, u16_ptr)
++    u32 = svldff1uh_u32(pred, u16_ptr)
++    u64 = svldff1uh_u64(pred, u16_ptr)
++    u32 = svldff1uh_gather_offset_u32 (pred, u16_ptr, u32)
++    u32 = svldff1uh_gather_offset_u32 (pred, u32, 1)
++    u16 = svldff1sb_u16(pred, s8_ptr)
++    u32 = svldff1sb_u32(pred, s8_ptr)
++    u64 = svldff1sb_u64(pred, s8_ptr)
++    u32 = svldff1sb_gather_offset_u32 (pred, s8_ptr, u32)
++    u32 = svldff1sb_gather_offset_u32 (pred, u32, 1)
++    u32 = svldff1sh_u32(pred, s16_ptr)
++    u64 = svldff1sh_u64(pred, s16_ptr)
++    u32 = svldff1sh_gather_offset_u32 (pred, s16_ptr, u32)
++    u32 = svldff1sh_gather_offset_u32 (pred, u32, 1)
++    u64 = svldff1sw_u64(pred, s32_ptr)
++    u64 = svldff1sw_gather_offset_u64 (pred, s32_ptr, u64)
++    u64 = svldff1sw_gather_offset_u64 (pred, u64, 1)
++    u32 = svldff1(pred, u32_ptr)
++    u32 = svldff1_gather_index (pred, u32_ptr, u32)
++    u32 = svldff1_gather_index_u32 (pred, u32, 1)
++    u64 = svldff1uw_u64(pred, u32_ptr)
++    u64 = svldff1uw_gather_offset_u64 (pred, u32_ptr, u64)
++    u64 = svldff1uw_gather_offset_u64 (pred, u64, 1)
++    u8 = svldnf1(pred, u8_ptr)
++    u16 = svldnf1ub_u16(pred, u8_ptr)
++    u32 = svldnf1ub_u32(pred, u8_ptr)
++    u64 = svldnf1ub_u64(pred, u8_ptr)
++    u64 = svldnf1(pred, u64_ptr)
++    u16 = svldnf1(pred, u16_ptr)
++    u32 = svldnf1uh_u32(pred, u16_ptr)
++    u64 = svldnf1uh_u64(pred, u16_ptr)
++    u16 = svldnf1sb_u16(pred, s8_ptr)
++    u32 = svldnf1sb_u32(pred, s8_ptr)
++    u64 = svldnf1sb_u64(pred, s8_ptr)
++    u32 = svldnf1sh_u32(pred, s16_ptr)
++    u64 = svldnf1sh_u64(pred, s16_ptr)
++    u64 = svldnf1sw_u64(pred, s32_ptr)
++    u32 = svldnf1(pred, u32_ptr)
++    u64 = svldnf1uw_u64(pred, u32_ptr)
++    u32 = svldnt1ub_gather_offset_u32 (pred, u8_ptr, u32)
++    u32 = svldnt1ub_gather_offset_u32 (pred, u32, 1)
++    u64 = svldnt1_gather_index (pred, u64_ptr, u64)
++    u64 = svldnt1_gather_index_u64 (pred, u64, 1)
++    u32 = svldnt1uh_gather_offset_u32 (pred, u16_ptr, u32)
++    u32 = svldnt1uh_gather_offset_u32 (pred, u32, 1)
++    u32 = svldnt1sb_gather_offset_u32 (pred, s8_ptr, u32)
++    u32 = svldnt1sb_gather_offset_u32 (pred, u32, 1)
++    u32 = svldnt1sh_gather_offset_u32 (pred, s16_ptr, u32)
++    u32 = svldnt1sh_gather_offset_u32 (pred, u32, 1)
++    u64 = svldnt1sw_gather_offset_u64 (pred, s32_ptr, u64)
++    u64 = svldnt1sw_gather_offset_u64 (pred, u64, 1)
++    u64 = svldnt1uw_gather_offset_u64 (pred, u32_ptr, u64)
++    u64 = svldnt1uw_gather_offset_u64 (pred, u64, 1)
++    u32 = svldnt1_gather_offset (pred, u32_ptr, u32)
++    u32 = svldnt1_gather_offset_u32 (pred, u32, 1)
++    pred = svmatch (pred, u8, u8)
++    pred = svnmatch (pred, u8, u8)
++    u64 = svpmullb_pair (u64, u64)
++    u64 = svpmullt_pair (u64, u64)
++    svprfb_gather_offset (pred, void_ptr, u64, SV_PLDL1KEEP)
++    svprfb_gather_offset (pred, u64, 1, SV_PLDL1KEEP)
++    svprfd_gather_index (pred, void_ptr, u64, SV_PLDL1KEEP)
++    svprfd_gather_index (pred, u64, 1, SV_PLDL1KEEP)
++    svprfh_gather_index (pred, void_ptr, u64, SV_PLDL1KEEP)
++    svprfh_gather_index (pred, u64, 1, SV_PLDL1KEEP)
++    svprfw_gather_index (pred, void_ptr, u64, SV_PLDL1KEEP)
++    svprfw_gather_index (pred, u64, 1, SV_PLDL1KEEP)
++    u64 = svrax1 (u64, u64)
++    pred = svrdffr ()
++    pred = svrdffr_z (pred)
++    svsetffr ()
++    u32 = svsm4e (u32, u32)
++    u32 = svsm4ekey (u32, u32)
++    s32 = svmmla (s32, s8, s8)
++    svst1b_scatter_offset (pred, u8_ptr, u32, u32)
++    svst1b_scatter_offset (pred, u32, 1, u32)
++    svst1_scatter_index (pred, u64_ptr, u64, u64)
++    svst1_scatter_index (pred, u64, 1, u64)
++    svst1h_scatter_index (pred, u16_ptr, u32, u32)
++    svst1h_scatter_index (pred, u32, 1, u32)
++    svst1w_scatter_index (pred, u32_ptr, u64, u64)
++    svst1w_scatter_index (pred, u64, 1, u64)
++    svst1_scatter_index (pred, u32_ptr, u32, u32)
++    svst1_scatter_index (pred, u32, 1, u32)
++    svstnt1b_scatter_offset (pred, u8_ptr, u32, u32)
++    svstnt1b_scatter_offset (pred, u32, 1, u32)
++    svstnt1_scatter_offset (pred, u64_ptr, u64, u64)
++    svstnt1_scatter_offset (pred, u64, 1, u64)
++    svstnt1h_scatter_offset (pred, u16_ptr, u32, u32)
++    svstnt1h_scatter_offset (pred, u32, 1, u32)
++    svstnt1w_scatter_offset (pred, u32_ptr, u64, u64)
++    svstnt1w_scatter_offset (pred, u64, 1, u64)
++    svstnt1_scatter_offset (pred, u32_ptr, u32, u32)
++    svstnt1_scatter_offset (pred, u32, 1, u32)
++    u32 = svmmla (u32, u8, u8)
++    s32 = svusmmla (s32, u8, s8)
++    svwrffr (pred)
++}
++
++check_ssve_calls $sc_harness $streaming_ok 1
++check_ssve_calls $sc_harness $nonstreaming_only 0
++
++gcc_parallel_test_enable 1
+diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp b/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp
+index 38140413a..45270be60 100644
+--- a/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp
++++ b/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp
+@@ -50,6 +50,7 @@ if { [info exists gcc_runtest_parallelize_limit_minor] } {
+ torture-init
+ set-torture-options {
+     "-std=c++98 -O0 -g"
++    "-std=c++11 -O0 -DSTREAMING_COMPATIBLE"
+     "-std=c++98 -O1 -g"
+     "-std=c++11 -O2 -g"
+     "-std=c++14 -O3 -g"
+diff --git a/gcc/testsuite/g++.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp b/gcc/testsuite/g++.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
+index 78e8ecae7..0a7151220 100644
+--- a/gcc/testsuite/g++.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
++++ b/gcc/testsuite/g++.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
+@@ -53,6 +53,7 @@ if { [info exists gcc_runtest_parallelize_limit_minor] } {
+ torture-init
+ set-torture-options {
+     "-std=c++98 -O0 -g"
++    "-std=c++11 -O0 -DSTREAMING_COMPATIBLE"
+     "-std=c++98 -O1 -g"
+     "-std=c++11 -O2 -g"
+     "-std=c++14 -O3 -g"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp
+index a271f1793..8cb2b9bb4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp
+@@ -50,6 +50,7 @@ if { [info exists gcc_runtest_parallelize_limit_minor] } {
+ torture-init
+ set-torture-options {
+     "-std=c90 -O0 -g"
++    "-std=c90 -O0 -DSTREAMING_COMPATIBLE"
+     "-std=c90 -O1 -g"
+     "-std=c99 -O2 -g"
+     "-std=c11 -O3 -g"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f16.c
+index 6c6bfa1c2..4d6ec2d65 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f32.c
+index 8b2a1dd1c..04afbcee6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f64.c
+index 90a56420a..8b4c7d1ff 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adda_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrb.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrb.c
+index a61eec971..5dcdc54b0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrb.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrb.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrd.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrd.c
+index 970485bd6..d9d16ce3f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrd.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrd.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrh.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrh.c
+index d06f51fe3..a358c2403 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrh.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrh.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrw.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrw.c
+index b23f25a11..bd1e9af0a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrw.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/adrw.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/bfmmla_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/bfmmla_f32.c
+index b1d98fbf5..4bb2912a4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/bfmmla_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/bfmmla_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-additional-options "-march=armv8.2-a+sve+bf16" } */
+ /* { dg-require-effective-target aarch64_asm_bf16_ok }  */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f32.c
+index 2e80d6830..d261ec00b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f64.c
+index e0bc33efe..024b0510f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s32.c
+index e4634982b..0b32dfb60 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s64.c
+index 71cb97b8a..38688dbca 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u32.c
+index 954329a0b..a3e89cc97 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u64.c
+index ec664845f..602ab048c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/compact_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f16.c
+index 5a5411e46..87c26e6ea 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f32.c
+index 4ded1c575..5e9839537 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f64.c
+index c31f9ccb5..b117df2a4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/expa_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f32.c
+index 00b68ff29..8b972f61b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f64.c
+index 47127960c..413d4d62d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s32.c
+index 9b6335547..b3df7d154 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s64.c
+index c9cea3ad8..0da1e5296 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u32.c
+index 2cccc8d49..a3304c419 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u64.c
+index 6ee1d48ab..73ef94805 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_bf16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_bf16.c
+index cb1801778..fe909b666 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_bf16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_bf16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
+index 86081edbd..30ba30639 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c
+index c8df00f8a..cf62fada9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c
+index 2fb9d5b74..b9fde4dac 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
+index 3cd211b16..35b7dd1d2 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c
+index 44b16ed5f..57b6a6567 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c
+index 3aa9a15ee..bd7e28478 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c
+index 49aff5146..143800003 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_s8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c
+index 00bf9e129..145b0b7f3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c
+index 9e9b3290a..9f150631b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c
+index 64ec62871..8dd75d136 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c
+index 22701320b..f15454586 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ro_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ /* { dg-additional-options "-march=armv8.6-a+f64mm" } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok }  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s32.c
+index 16a5316a9..06249ad4c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s64.c
+index 3f953247e..8d141e133 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u32.c
+index 424de65a6..77836cbf6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u64.c
+index aa375bea2..f4b24ab41 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sb_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s32.c
+index ed07b4dfc..1b9782368 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s64.c
+index 20ca42720..2009dec81 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u32.c
+index e3a85a23f..0e1d48966 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u64.c
+index 3a0094fba..115d7d3a9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sh_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_s64.c
+index 4d076b486..5dc44421c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_u64.c
+index ffa85eb3e..fac4ec41c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1sw_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s32.c
+index a9c418265..f57df4226 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s64.c
+index 99af86ddf..0c069fa4f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u32.c
+index 77c7e0a2d..98102e013 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u64.c
+index b605f8b67..f86a34d12 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1ub_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s32.c
+index 84fb5c335..139371878 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s64.c
+index 447001793..f0338aae6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u32.c
+index 09d3cc8c2..5810bc0ac 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u64.c
+index f3dcf03cd..52e95abb9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uh_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_s64.c
+index f4e9d5db9..0889eefdd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_u64.c
+index 854d19233..fb144d756 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ld1uw_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_bf16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_bf16.c
+index 80f646870..1f997480e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_bf16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_bf16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f16.c
+index 13ce863c9..60405d0a0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f32.c
+index 2fcc63390..225e9969d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f64.c
+index cc15b927a..366e36afd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f32.c
+index 7e330c042..b84b9bcdd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f64.c
+index d0e47f0bf..e779b0712 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s32.c
+index 66bf0f746..17e0f9aa2 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s64.c
+index faf71bf9d..030f187b1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u32.c
+index 41c7dc9cf..fb8653016 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u64.c
+index 8b53ce94f..5be30a2d8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s16.c
+index 1d5fde0e6..61d242c07 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s32.c
+index 97a36e884..afe748ef9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s64.c
+index c018a4c1c..bee222855 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s8.c
+index cf620d1f4..ccaac2ca4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_s8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u16.c
+index 1fa819296..c8416f99d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u32.c
+index 5224ec40a..ec26a82ca 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u64.c
+index 18e87f2b8..e211f1794 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u8.c
+index 83883fca4..24dfe452f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s32.c
+index c2a676807..f7e3977bf 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s64.c
+index 2f2a04d24..7f2a829a8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u32.c
+index e3e83a205..685f62808 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u64.c
+index 769f2c266..49a7a8536 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s16.c
+index e0a748c6a..1d30c7ba6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s32.c
+index 86716da9b..c2b3f42cb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s64.c
+index e7a4aa6e9..585a6241e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u16.c
+index 69ba96d52..ebb2f0f66 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u32.c
+index e1a1873f0..f4ea96cf9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u64.c
+index 0a49cbcc0..e3735239c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sb_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s32.c
+index b633335dc..67e70361b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s64.c
+index 32a4309b6..5755c79bc 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u32.c
+index 73a9be892..a58489995 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u64.c
+index 94ea73b63..b18751209 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s32.c
+index 81b64e836..bffac9365 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s64.c
+index 453b3ff24..a4acb1e5e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u32.c
+index bbbed79dc..828288cd8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u64.c
+index 5430e256b..e3432c46c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sh_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_s64.c
+index e5da8a83d..78aa34ec0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_u64.c
+index 411428756..9dad1212c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_s64.c
+index d795ace63..33b6c10dd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_u64.c
+index 6caf2f504..e8c9c845f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1sw_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s32.c
+index af0be08d2..b1c9c8135 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s64.c
+index 43124dd89..9ab776a21 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u32.c
+index 90c4e58a2..745740dfa 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u64.c
+index 302623a40..3a7bd6a43 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s16.c
+index 88ad2d1dc..ade0704f7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s32.c
+index e8e06411f..5d3e0ce95 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s64.c
+index 21d02ddb7..08ae802ee 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u16.c
+index 904cb027e..d8dc5e157 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u32.c
+index a40012318..042ae5a9f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u64.c
+index a9a98a683..d0844fa51 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1ub_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s32.c
+index d02e44342..12460105d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s64.c
+index 663a73d27..536331371 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u32.c
+index 5e0ef067f..602e6a686 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u64.c
+index 1cfae1b95..4b307b341 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s32.c
+index abb3d769a..db205b1ef 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s64.c
+index 6e330e8e8..0eac877eb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u32.c
+index 4eb5323e9..266ecf167 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u64.c
+index ebac26e7d..bdd725e4a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uh_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_s64.c
+index 6c0daea52..ab2c79da7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_u64.c
+index 0e400c679..361d7de05 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_s64.c
+index ac9779899..8adcec3d5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_u64.c
+index c7ab06171..781fc1a9c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldff1uw_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_bf16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_bf16.c
+index 947a896e7..93b4425ec 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_bf16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_bf16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f16.c
+index cf0178688..d47d748c7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f32.c
+index 83b73ec8e..e390d6857 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f64.c
+index 778096e82..97a0e39e7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s16.c
+index 592c8237d..21008d7f9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s32.c
+index 634092af8..8a3d795b3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s64.c
+index 4a03f6676..c0b57a2f3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s8.c
+index 162ee176a..6714152d9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_s8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u16.c
+index e920ac43b..3df404d77 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u32.c
+index 65e28c5c2..e899a4a6f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u64.c
+index 70d3f27d8..ab69656cf 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u8.c
+index 5c29f1d19..5d7b07497 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s16.c
+index e04b9a788..5b53c885d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s32.c
+index 0553fc98d..992eba7cc 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s64.c
+index 61a474fdf..99e0f8bd0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u16.c
+index be63d8bf9..fe23913f2 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u32.c
+index 4f52490b4..6deb39770 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u64.c
+index 73f50d182..e76457da6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sb_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s32.c
+index 08c7dc6dd..e49a7f8ed 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s64.c
+index 6a41bc26b..00b40281c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u32.c
+index 2f7718730..41560af33 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u64.c
+index d7f1a68a4..0acf4b349 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sh_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_s64.c
+index 5b483e4aa..578212898 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_u64.c
+index 62121ce0a..8249c4c3f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1sw_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s16.c
+index 8fe13411f..e59c451f7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s32.c
+index 50122e3b7..d788576e2 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s64.c
+index d7cce11b6..b21fdb964 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u16.c
+index 7bf82c3b6..1ae41b002 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u32.c
+index e2fef064b..e3d8fb3b5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u64.c
+index 57c61e122..df9a0c07f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1ub_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s32.c
+index ed9686c4e..c3467d846 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s64.c
+index a3107f562..bf3355e99 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u32.c
+index 93d5abaf7..bcc3eb3fd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u64.c
+index 32d36a84c..4c01c13ac 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uh_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_s64.c
+index 373922791..3c6556591 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_u64.c
+index b3c3be1d0..b222a0dc6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/ldnf1uw_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f32.c
+index f66dbf397..e1c7f47dc 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-require-effective-target aarch64_asm_f32mm_ok } */
+ /* { dg-additional-options "-march=armv8.2-a+f32mm" } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f64.c
+index 49dc0607c..c45caa700 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-require-effective-target aarch64_asm_f64mm_ok } */
+ /* { dg-additional-options "-march=armv8.2-a+f64mm" } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_s32.c
+index e7ce009ac..dc155461c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-require-effective-target aarch64_asm_i8mm_ok } */
+ /* { dg-additional-options "-march=armv8.2-a+sve+i8mm" } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_u32.c
+index 81f5166fb..43d601a47 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/mmla_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-require-effective-target aarch64_asm_i8mm_ok } */
+ /* { dg-additional-options "-march=armv8.2-a+sve+i8mm" } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb_gather.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb_gather.c
+index c4bfbbbf7..f32cfbfcb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb_gather.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfb_gather.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd_gather.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd_gather.c
+index a84acb1a1..8a4293b62 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd_gather.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfd_gather.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh_gather.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh_gather.c
+index 04b7a1575..6beca4b8e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh_gather.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfh_gather.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw_gather.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw_gather.c
+index 2bbae1b9e..6af44ac82 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw_gather.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/prfw_gather.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rdffr_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rdffr_1.c
+index 5564e967f..7e28ef641 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rdffr_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/rdffr_1.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f32.c
+index cb6774ad0..1efd43445 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f64.c
+index fe978bbe5..f50c43e83 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s32.c
+index d244e701a..bb6fb10b8 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s64.c
+index 5c4ebf440..19ec78e9e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u32.c
+index fe3f7259f..57fbb91b0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u64.c
+index 232123566..60018be5b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s32.c
+index d59033356..fb1bb29db 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s64.c
+index c7a35f1b4..65ee9a071 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u32.c
+index e098cb9b7..ceec61939 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u64.c
+index 058d1313f..aeedbc6d7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1b_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s32.c
+index 2a23d41f3..2d69d085b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s64.c
+index 6a1adb056..3e5733ef9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u32.c
+index 12197315d..5cd330a3d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u64.c
+index 7021ea68f..0ee9948cb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1h_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_s64.c
+index 2363f592b..f18bedce1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_u64.c
+index 767c009b4..6850865ec 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/st1w_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
+index 2da61ff5c..d8916809b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
+@@ -11,10 +11,17 @@
+ #error "Please define -DTEST_OVERLOADS or -DTEST_FULL"
+ #endif
+ 
++#ifdef STREAMING_COMPATIBLE
++#define ATTR __arm_streaming_compatible
++#else
++#define ATTR
++#endif
++
+ #ifdef __cplusplus
+-#define PROTO(NAME, RET, ARGS) extern "C" RET NAME ARGS; RET NAME ARGS
++#define PROTO(NAME, RET, ARGS) \
++  extern "C" RET NAME ARGS ATTR; RET NAME ARGS ATTR
+ #else
+-#define PROTO(NAME, RET, ARGS) RET NAME ARGS
++#define PROTO(NAME, RET, ARGS) RET NAME ARGS ATTR
+ #endif
+ 
+ #define TEST_UNIFORM_Z(NAME, TYPE, CODE1, CODE2)		\
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f16.c
+index 3a00716e3..c0b03a0d3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f32.c
+index b73d420fb..8eef8a12c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f64.c
+index fc31928a6..5c96c5579 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tmad_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f16.c
+index 94bc696eb..9deed667f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f32.c
+index d0ec91882..749ea8664 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f64.c
+index 23e0da3f7..053abcb26 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tsmul_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f16.c
+index e7c3ea03b..3ab251fe0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f32.c
+index 022573a19..6c6471c5e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f64.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f64.c
+index ffcdf4224..9559e0f35 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/tssel_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/usmmla_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/usmmla_s32.c
+index 9440f3fd9..a0dd7e334 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/usmmla_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/usmmla_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-require-effective-target aarch64_asm_i8mm_ok } */
+ /* { dg-additional-options "-march=armv8.2-a+sve+i8mm" } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp b/gcc/testsuite/gcc.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
+index e08cd6121..2fb27fb5e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/aarch64-sve2-acle-asm.exp
+@@ -52,6 +52,7 @@ if { [info exists gcc_runtest_parallelize_limit_minor] } {
+ torture-init
+ set-torture-options {
+     "-std=c90 -O0 -g"
++    "-std=c90 -O0 -DSTREAMING_COMPATIBLE"
+     "-std=c90 -O1 -g"
+     "-std=c99 -O2 -g"
+     "-std=c11 -O3 -g"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_u8.c
+index 622f5cf46..484f7251f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_u8.c
+index 6555bbb1d..6869bbd05 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesimc_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesimc_u8.c
+index 4630595ff..534ffe06f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesimc_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesimc_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesmc_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesmc_u8.c
+index 6e8acf48f..1660a8eaf 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesmc_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesmc_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u16.c
+index 14230850f..c1a4e1061 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u32.c
+index 7f08df4ba..4f14cc4c4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u64.c
+index 7f7cbbeeb..091253ec6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u8.c
+index b420323b9..deb1ad27d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bdep_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u16.c
+index 50a647918..9efa501ef 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u32.c
+index 9f98b843c..18963da5b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u64.c
+index 9dbaec1b7..91591f93b 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u8.c
+index 81ed5a463..1211587ef 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bext_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u16.c
+index 70aeae3f3..72868bea7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u32.c
+index 6e19e38d8..c8923816f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u64.c
+index 27fa40f47..86989529f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u8.c
+index b667e03e3..5cd941a7a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/bgrp_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s32.c
+index 7bf783a7c..53d6c5c56 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s64.c
+index 001f5f0f1..c6d9862e3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u32.c
+index d93091adc..cb11a0026 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u64.c
+index 3b8898023..0bb06cdb4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histcnt_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_s8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_s8.c
+index 380ccdf85..ce3458e5e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_s8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_u8.c
+index f43292f0c..7b1eff811 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/histseg_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f32.c
+index 102810e25..17e3673a4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f64.c
+index a0ed71227..8ce32e9f9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s32.c
+index 94c64971c..b7e1d7a99 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s64.c
+index a0aa6703f..b0789ad21 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u32.c
+index e1479684e..df09eaa76 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u64.c
+index 77cdcfeba..5f185ea82 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s32.c
+index bb729483f..71fece575 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s64.c
+index de5b69314..1183e72f0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u32.c
+index d01ec18e4..4d5e6e771 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u64.c
+index b96e94353..ed329a23f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sb_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s32.c
+index 1dcfbc0fb..6dbd6cea0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s64.c
+index 4166ed0a6..4ea3335a2 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u32.c
+index 7680344da..d55451519 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u64.c
+index 2427c83ab..18c8ca44e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sh_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_s64.c
+index 2f538e847..41bff31d0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_u64.c
+index ace1c2f2f..30b8f6948 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1sw_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s32.c
+index d3b29eb19..8750d11af 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s64.c
+index 3bc406620..f7981991a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u32.c
+index 0af4b40b8..4d5ee4ef4 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u64.c
+index fe28d78ed..005c29c06 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1ub_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s32.c
+index 985432615..92613b166 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s64.c
+index 3c5baeee6..be2e6d126 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u32.c
+index 4d945e9f9..4d122059f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u64.c
+index 680238ac4..e3bc1044c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uh_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_s64.c
+index 787ae9def..9efa4b2cb 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_u64.c
+index 4810bc3c4..4ded4454d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/ldnt1uw_gather_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s16.c
+index baebc7693..d0ce81294 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s8.c
+index f35a75379..03473906a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_s8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u16.c
+index 0bdf4462f..2a8b4d250 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u8.c
+index 6d78692bd..8409276d9 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/match_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s16.c
+index 935b19a10..044ba1de3 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s8.c
+index 8a00b30f3..6c2d890fa 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_s8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u16.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u16.c
+index 868c20a11..863e31054 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u16.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u16.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u8.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u8.c
+index af6b58165..a62783db7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/nmatch_u8.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullb_pair_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullb_pair_u64.c
+index 944609214..1fd85e0ce 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullb_pair_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullb_pair_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullt_pair_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullt_pair_u64.c
+index 90e2e991f..300d885ab 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullt_pair_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmullt_pair_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_s64.c
+index ea80d40db..9dbc71839 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_u64.c
+index b237c7edd..5caa2a544 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/rax1_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4e_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4e_u32.c
+index 0ff5746d8..14194eef6 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4e_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4e_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4ekey_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4ekey_u32.c
+index 58ad33c5d..e72384108 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4ekey_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/sm4ekey_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f32.c
+index 3f928e20e..75539f692 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f64.c
+index 8a35c76b9..c0d47d0c1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_f64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s32.c
+index bd6002682..80fb3e869 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s64.c
+index 0bfa2616e..edd2bc418 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u32.c
+index fbfa008c1..a6e5059de 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u64.c
+index c283135c4..067e5b109 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s32.c
+index bf6ba5973..498fe82e5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s64.c
+index a24d0c89c..614f5fb1a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u32.c
+index 2b05a7720..ce2c482af 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u64.c
+index a13c5f5bb..593dc1939 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1b_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s32.c
+index 4e012f61f..b9d06c1c5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s64.c
+index e934a708d..006e0e24d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u32.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u32.c
+index db21821eb..8cd7cb86a 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u32.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u32.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u64.c
+index 53f930da1..972ee3689 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1h_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_s64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_s64.c
+index ec6c837d9..368a17c47 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_s64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_s64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_u64.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_u64.c
+index 3c5d96de4..57d60a350 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_u64.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/stnt1w_scatter_u64.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "" { *-*-* } { "-DSTREAMING_COMPATIBLE" } { "" } } */
+ /* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" { target { ! ilp32 } } } } */
+ 
+ #include "test_sve_acle.h"
+-- 
+2.33.0
+
diff --git a/0181-Backport-SME-AArch64-Support-new-tbranch-optab.patch b/0181-Backport-SME-AArch64-Support-new-tbranch-optab.patch
new file mode 100644
index 0000000..77f70f4
--- /dev/null
+++ b/0181-Backport-SME-AArch64-Support-new-tbranch-optab.patch
@@ -0,0 +1,250 @@
+From da06b276b6ae281efad2ec3b982e09b1f4015917 Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Mon, 12 Dec 2022 15:18:56 +0000
+Subject: [PATCH 082/157] [Backport][SME] AArch64: Support new tbranch optab.
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=17ae956c0fa6baac3d22764019d5dd5ebf5c2b11
+
+This implements the new tbranch optab for AArch64.
+
+we cannot emit one big RTL for the final instruction immediately.
+The reason that all comparisons in the AArch64 backend expand to separate CC
+compares, and separate testing of the operands is for ifcvt.
+
+The separate CC compare is needed so ifcvt can produce csel, cset etc from the
+compares.  Unlike say combine, ifcvt can not do recog on a parallel with a
+clobber.  Should we emit the instruction directly then ifcvt will not be able
+to say, make a csel, because we have no patterns which handle zero_extract and
+compare. (unlike combine ifcvt cannot transform the extract into an AND).
+
+While you could provide various patterns for this (and I did try) you end up
+with broken patterns because you can't add the clobber to the CC register.  If
+you do, ifcvt recog fails.
+
+i.e.
+
+int
+f1 (int x)
+{
+  if (x & 1)
+    return 1;
+  return x;
+}
+
+We lose csel here.
+
+Secondly the reason the compare with an explicit CC mode is needed is so that
+ifcvt can transform the operation into a version that doesn't require the flags
+to be set.  But it only does so if it know the explicit usage of the CC reg.
+
+For instance
+
+int
+foo (int a, int b)
+{
+  return ((a & (1 << 25)) ? 5 : 4);
+}
+
+Doesn't require a comparison, the optimal form is:
+
+foo(int, int):
+        ubfx    x0, x0, 25, 1
+        add     w0, w0, 4
+        ret
+
+and no compare is actually needed.  If you represent the instruction using an
+ANDS instead of a zero_extract then you get close, but you end up with an ands
+followed by an add, which is a slower operation.
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64.md (*tb1): Rename to...
+	(*tb1): ... this.
+	(tbranch_4): New.
+	* config/aarch64/iterators.md(ZEROM, zerom): New.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/aarch64/tbz_1.c: New test.
+---
+ gcc/config/aarch64/aarch64.md            | 33 ++++++--
+ gcc/config/aarch64/iterators.md          |  2 +
+ gcc/testsuite/gcc.target/aarch64/tbz_1.c | 95 ++++++++++++++++++++++++
+ 3 files changed, 122 insertions(+), 8 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/tbz_1.c
+
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 079c8a3f9..2becc888e 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -953,12 +953,29 @@
+ 		      (const_int 1)))]
+ )
+ 
+-(define_insn "*tb1"
++(define_expand "tbranch_3"
+   [(set (pc) (if_then_else
+-	      (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
+-				    (const_int 1)
+-				    (match_operand 1
+-				      "aarch64_simd_shift_imm_" "n"))
++              (EQL (match_operand:ALLI 0 "register_operand")
++                   (match_operand 1 "aarch64_simd_shift_imm_"))
++              (label_ref (match_operand 2 ""))
++              (pc)))]
++  ""
++{
++  rtx bitvalue = gen_reg_rtx (mode);
++  rtx reg = gen_lowpart (mode, operands[0]);
++  rtx val = GEN_INT (1UL << UINTVAL (operands[1]));
++  emit_insn (gen_and3 (bitvalue, reg, val));
++  operands[1] = const0_rtx;
++  operands[0] = aarch64_gen_compare_reg (, bitvalue,
++					 operands[1]);
++})
++
++(define_insn "*tb1"
++  [(set (pc) (if_then_else
++	      (EQL (zero_extract:GPI (match_operand:ALLI 0 "register_operand" "r")
++				     (const_int 1)
++				     (match_operand 1
++				       "aarch64_simd_shift_imm_" "n"))
+ 		   (const_int 0))
+ 	     (label_ref (match_operand 2 "" ""))
+ 	     (pc)))
+@@ -969,15 +986,15 @@
+       {
+ 	if (get_attr_far_branch (insn) == 1)
+ 	  return aarch64_gen_far_branch (operands, 2, "Ltb",
+-					 "\\t%0, %1, ");
++					 "\\t%0, %1, ");
+ 	else
+ 	  {
+ 	    operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
+-	    return "tst\t%0, %1\;\t%l2";
++	    return "tst\t%0, %1\;\t%l2";
+ 	  }
+       }
+     else
+-      return "\t%0, %1, %l2";
++      return "\t%0, %1, %l2";
+   }
+   [(set_attr "type" "branch")
+    (set (attr "length")
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index 226dea48a..b616f5c9a 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -1104,6 +1104,8 @@
+ 
+ ;; Give the number of bits in the mode
+ (define_mode_attr sizen [(QI "8") (HI "16") (SI "32") (DI "64")])
++(define_mode_attr ZEROM [(QI "SI") (HI "SI") (SI "SI") (DI "DI")])
++(define_mode_attr zerom [(QI "si") (HI "si") (SI "si") (DI "di")])
+ 
+ ;; Give the ordinal of the MSB in the mode
+ (define_mode_attr sizem1 [(QI "#7") (HI "#15") (SI "#31") (DI "#63")
+diff --git a/gcc/testsuite/gcc.target/aarch64/tbz_1.c b/gcc/testsuite/gcc.target/aarch64/tbz_1.c
+new file mode 100644
+index 000000000..39deb58e2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/tbz_1.c
+@@ -0,0 +1,95 @@
++/* { dg-do compile } */
++/* { dg-additional-options "-O2 -std=c99  -fno-unwind-tables -fno-asynchronous-unwind-tables" } */
++/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
++
++#include 
++
++void h(void);
++
++/*
++** g1:
++** 	tbnz	w[0-9]+, #?0, .L([0-9]+)
++** 	ret
++**	...
++*/
++void g1(bool x)
++{
++  if (__builtin_expect (x, 0))
++    h ();
++}
++
++/*
++** g2:
++** 	tbz	w[0-9]+, #?0, .L([0-9]+)
++** 	b	h
++**	...
++*/
++void g2(bool x)
++{
++  if (__builtin_expect (x, 1))
++    h ();
++}
++
++/*
++** g3_ge:
++** 	tbnz	w[0-9]+, #?31, .L[0-9]+
++** 	b	h
++**	...
++*/
++void g3_ge(int x)
++{
++  if (__builtin_expect (x >= 0, 1))
++    h ();
++}
++
++/*
++** g3_gt:
++** 	cmp	w[0-9]+, 0
++** 	ble	.L[0-9]+
++** 	b	h
++**	...
++*/
++void g3_gt(int x)
++{
++  if (__builtin_expect (x > 0, 1))
++    h ();
++}
++
++/*
++** g3_lt:
++** 	tbz	w[0-9]+, #?31, .L[0-9]+
++** 	b	h
++**	...
++*/
++void g3_lt(int x)
++{
++  if (__builtin_expect (x < 0, 1))
++    h ();
++}
++
++/*
++** g3_le:
++** 	cmp	w[0-9]+, 0
++** 	bgt	.L[0-9]+
++** 	b	h
++**	...
++*/
++void g3_le(int x)
++{
++  if (__builtin_expect (x <= 0, 1))
++    h ();
++}
++
++/*
++** g5:
++** 	mov	w[0-9]+, 65279
++** 	tst	w[0-9]+, w[0-9]+
++** 	beq	.L[0-9]+
++** 	b	h
++**	...
++*/ 
++void g5(int x)
++{
++  if (__builtin_expect (x & 0xfeff, 1))
++    h ();
++}
+-- 
+2.33.0
+
diff --git a/0182-Backport-SME-aarch64-Use-local-frame-vars-in-shrink-.patch b/0182-Backport-SME-aarch64-Use-local-frame-vars-in-shrink-.patch
new file mode 100644
index 0000000..257cdb3
--- /dev/null
+++ b/0182-Backport-SME-aarch64-Use-local-frame-vars-in-shrink-.patch
@@ -0,0 +1,381 @@
+From 755f67b1abd70b3c3ea20076fe60c1d303bf1e0c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:04 +0100
+Subject: [PATCH 083/157] [Backport][SME] aarch64: Use local frame vars in
+ shrink-wrapping code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=76d89da25af3064e80c9b7b584c678ff72b1f0bd
+
+aarch64_layout_frame uses a shorthand for referring to
+cfun->machine->frame:
+
+  aarch64_frame &frame = cfun->machine->frame;
+
+This patch does the same for some other heavy users of the structure.
+No functional change intended.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_save_callee_saves): Use
+	a local shorthand for cfun->machine->frame.
+	(aarch64_restore_callee_saves, aarch64_get_separate_components):
+	(aarch64_process_components): Likewise.
+	(aarch64_allocate_and_probe_stack_space): Likewise.
+	(aarch64_expand_prologue, aarch64_expand_epilogue): Likewise.
+	(aarch64_layout_frame): Use existing shorthand for one more case.
+---
+ gcc/config/aarch64/aarch64.cc | 123 ++++++++++++++++++----------------
+ 1 file changed, 64 insertions(+), 59 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 08a98f8ba..b7da1d0be 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8951,7 +8951,7 @@ aarch64_layout_frame (void)
+   frame.is_scs_enabled
+     = (!crtl->calls_eh_return
+        && sanitize_flags_p (SANITIZE_SHADOW_CALL_STACK)
+-       && known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0));
++       && known_ge (frame.reg_offset[LR_REGNUM], 0));
+ 
+   /* When shadow call stack is enabled, the scs_pop in the epilogue will
+      restore x30, and we don't need to pop x30 again in the traditional
+@@ -9363,6 +9363,7 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+ 			   unsigned start, unsigned limit, bool skip_wb,
+ 			   bool hard_fp_valid_p)
+ {
++  aarch64_frame &frame = cfun->machine->frame;
+   rtx_insn *insn;
+   unsigned regno;
+   unsigned regno2;
+@@ -9377,8 +9378,8 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+       bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno);
+ 
+       if (skip_wb
+-	  && (regno == cfun->machine->frame.wb_push_candidate1
+-	      || regno == cfun->machine->frame.wb_push_candidate2))
++	  && (regno == frame.wb_push_candidate1
++	      || regno == frame.wb_push_candidate2))
+ 	continue;
+ 
+       if (cfun->machine->reg_is_wrapped_separately[regno])
+@@ -9386,7 +9387,7 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       reg = gen_rtx_REG (mode, regno);
+-      offset = start_offset + cfun->machine->frame.reg_offset[regno];
++      offset = start_offset + frame.reg_offset[regno];
+       rtx base_rtx = stack_pointer_rtx;
+       poly_int64 sp_offset = offset;
+ 
+@@ -9399,7 +9400,7 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+ 	{
+ 	  gcc_assert (known_eq (start_offset, 0));
+ 	  poly_int64 fp_offset
+-	    = cfun->machine->frame.below_hard_fp_saved_regs_size;
++	    = frame.below_hard_fp_saved_regs_size;
+ 	  if (hard_fp_valid_p)
+ 	    base_rtx = hard_frame_pointer_rtx;
+ 	  else
+@@ -9421,8 +9422,7 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+ 	  && (regno2 = aarch64_next_callee_save (regno + 1, limit)) <= limit
+ 	  && !cfun->machine->reg_is_wrapped_separately[regno2]
+ 	  && known_eq (GET_MODE_SIZE (mode),
+-		       cfun->machine->frame.reg_offset[regno2]
+-		       - cfun->machine->frame.reg_offset[regno]))
++		       frame.reg_offset[regno2] - frame.reg_offset[regno]))
+ 	{
+ 	  rtx reg2 = gen_rtx_REG (mode, regno2);
+ 	  rtx mem2;
+@@ -9472,6 +9472,7 @@ static void
+ aarch64_restore_callee_saves (poly_int64 start_offset, unsigned start,
+ 			      unsigned limit, bool skip_wb, rtx *cfi_ops)
+ {
++  aarch64_frame &frame = cfun->machine->frame;
+   unsigned regno;
+   unsigned regno2;
+   poly_int64 offset;
+@@ -9488,13 +9489,13 @@ aarch64_restore_callee_saves (poly_int64 start_offset, unsigned start,
+       rtx reg, mem;
+ 
+       if (skip_wb
+-	  && (regno == cfun->machine->frame.wb_pop_candidate1
+-	      || regno == cfun->machine->frame.wb_pop_candidate2))
++	  && (regno == frame.wb_pop_candidate1
++	      || regno == frame.wb_pop_candidate2))
+ 	continue;
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       reg = gen_rtx_REG (mode, regno);
+-      offset = start_offset + cfun->machine->frame.reg_offset[regno];
++      offset = start_offset + frame.reg_offset[regno];
+       rtx base_rtx = stack_pointer_rtx;
+       if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg,
+@@ -9505,8 +9506,7 @@ aarch64_restore_callee_saves (poly_int64 start_offset, unsigned start,
+ 	  && (regno2 = aarch64_next_callee_save (regno + 1, limit)) <= limit
+ 	  && !cfun->machine->reg_is_wrapped_separately[regno2]
+ 	  && known_eq (GET_MODE_SIZE (mode),
+-		       cfun->machine->frame.reg_offset[regno2]
+-		       - cfun->machine->frame.reg_offset[regno]))
++		       frame.reg_offset[regno2] - frame.reg_offset[regno]))
+ 	{
+ 	  rtx reg2 = gen_rtx_REG (mode, regno2);
+ 	  rtx mem2;
+@@ -9611,6 +9611,7 @@ offset_12bit_unsigned_scaled_p (machine_mode mode, poly_int64 offset)
+ static sbitmap
+ aarch64_get_separate_components (void)
+ {
++  aarch64_frame &frame = cfun->machine->frame;
+   sbitmap components = sbitmap_alloc (LAST_SAVED_REGNUM + 1);
+   bitmap_clear (components);
+ 
+@@ -9627,18 +9628,18 @@ aarch64_get_separate_components (void)
+ 	if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	  continue;
+ 
+-	poly_int64 offset = cfun->machine->frame.reg_offset[regno];
++	poly_int64 offset = frame.reg_offset[regno];
+ 
+ 	/* If the register is saved in the first SVE save slot, we use
+ 	   it as a stack probe for -fstack-clash-protection.  */
+ 	if (flag_stack_clash_protection
+-	    && maybe_ne (cfun->machine->frame.below_hard_fp_saved_regs_size, 0)
++	    && maybe_ne (frame.below_hard_fp_saved_regs_size, 0)
+ 	    && known_eq (offset, 0))
+ 	  continue;
+ 
+ 	/* Get the offset relative to the register we'll use.  */
+ 	if (frame_pointer_needed)
+-	  offset -= cfun->machine->frame.below_hard_fp_saved_regs_size;
++	  offset -= frame.below_hard_fp_saved_regs_size;
+ 	else
+ 	  offset += crtl->outgoing_args_size;
+ 
+@@ -9657,11 +9658,11 @@ aarch64_get_separate_components (void)
+   /* If the spare predicate register used by big-endian SVE code
+      is call-preserved, it must be saved in the main prologue
+      before any saves that use it.  */
+-  if (cfun->machine->frame.spare_pred_reg != INVALID_REGNUM)
+-    bitmap_clear_bit (components, cfun->machine->frame.spare_pred_reg);
++  if (frame.spare_pred_reg != INVALID_REGNUM)
++    bitmap_clear_bit (components, frame.spare_pred_reg);
+ 
+-  unsigned reg1 = cfun->machine->frame.wb_push_candidate1;
+-  unsigned reg2 = cfun->machine->frame.wb_push_candidate2;
++  unsigned reg1 = frame.wb_push_candidate1;
++  unsigned reg2 = frame.wb_push_candidate2;
+   /* If registers have been chosen to be stored/restored with
+      writeback don't interfere with them to avoid having to output explicit
+      stack adjustment instructions.  */
+@@ -9770,6 +9771,7 @@ aarch64_get_next_set_bit (sbitmap bmp, unsigned int start)
+ static void
+ aarch64_process_components (sbitmap components, bool prologue_p)
+ {
++  aarch64_frame &frame = cfun->machine->frame;
+   rtx ptr_reg = gen_rtx_REG (Pmode, frame_pointer_needed
+ 			     ? HARD_FRAME_POINTER_REGNUM
+ 			     : STACK_POINTER_REGNUM);
+@@ -9784,9 +9786,9 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       
+       rtx reg = gen_rtx_REG (mode, regno);
+-      poly_int64 offset = cfun->machine->frame.reg_offset[regno];
++      poly_int64 offset = frame.reg_offset[regno];
+       if (frame_pointer_needed)
+-	offset -= cfun->machine->frame.below_hard_fp_saved_regs_size;
++	offset -= frame.below_hard_fp_saved_regs_size;
+       else
+ 	offset += crtl->outgoing_args_size;
+ 
+@@ -9811,14 +9813,14 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+ 	  break;
+ 	}
+ 
+-      poly_int64 offset2 = cfun->machine->frame.reg_offset[regno2];
++      poly_int64 offset2 = frame.reg_offset[regno2];
+       /* The next register is not of the same class or its offset is not
+ 	 mergeable with the current one into a pair.  */
+       if (aarch64_sve_mode_p (mode)
+ 	  || !satisfies_constraint_Ump (mem)
+ 	  || GP_REGNUM_P (regno) != GP_REGNUM_P (regno2)
+ 	  || (crtl->abi->id () == ARM_PCS_SIMD && FP_REGNUM_P (regno))
+-	  || maybe_ne ((offset2 - cfun->machine->frame.reg_offset[regno]),
++	  || maybe_ne ((offset2 - frame.reg_offset[regno]),
+ 		       GET_MODE_SIZE (mode)))
+ 	{
+ 	  insn = emit_insn (set);
+@@ -9840,7 +9842,7 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+       /* REGNO2 can be saved/restored in a pair with REGNO.  */
+       rtx reg2 = gen_rtx_REG (mode, regno2);
+       if (frame_pointer_needed)
+-	offset2 -= cfun->machine->frame.below_hard_fp_saved_regs_size;
++	offset2 -= frame.below_hard_fp_saved_regs_size;
+       else
+ 	offset2 += crtl->outgoing_args_size;
+       rtx addr2 = plus_constant (Pmode, ptr_reg, offset2);
+@@ -9935,6 +9937,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+ 					bool frame_related_p,
+ 					bool final_adjustment_p)
+ {
++  aarch64_frame &frame = cfun->machine->frame;
+   HOST_WIDE_INT guard_size
+     = 1 << param_stack_clash_protection_guard_size;
+   HOST_WIDE_INT guard_used_by_caller = STACK_CLASH_CALLER_GUARD;
+@@ -9955,25 +9958,25 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+        register as a probe.  We can't assume that LR was saved at position 0
+        though, so treat any space below it as unprobed.  */
+   if (final_adjustment_p
+-      && known_eq (cfun->machine->frame.below_hard_fp_saved_regs_size, 0))
++      && known_eq (frame.below_hard_fp_saved_regs_size, 0))
+     {
+-      poly_int64 lr_offset = cfun->machine->frame.reg_offset[LR_REGNUM];
++      poly_int64 lr_offset = frame.reg_offset[LR_REGNUM];
+       if (known_ge (lr_offset, 0))
+ 	min_probe_threshold -= lr_offset.to_constant ();
+       else
+ 	gcc_assert (!flag_stack_clash_protection || known_eq (poly_size, 0));
+     }
+ 
+-  poly_int64 frame_size = cfun->machine->frame.frame_size;
++  poly_int64 frame_size = frame.frame_size;
+ 
+   /* We should always have a positive probe threshold.  */
+   gcc_assert (min_probe_threshold > 0);
+ 
+   if (flag_stack_clash_protection && !final_adjustment_p)
+     {
+-      poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
+-      poly_int64 sve_callee_adjust = cfun->machine->frame.sve_callee_adjust;
+-      poly_int64 final_adjust = cfun->machine->frame.final_adjust;
++      poly_int64 initial_adjust = frame.initial_adjust;
++      poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
++      poly_int64 final_adjust = frame.final_adjust;
+ 
+       if (known_eq (frame_size, 0))
+ 	{
+@@ -10262,17 +10265,18 @@ aarch64_epilogue_uses (int regno)
+ void
+ aarch64_expand_prologue (void)
+ {
+-  poly_int64 frame_size = cfun->machine->frame.frame_size;
+-  poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
+-  HOST_WIDE_INT callee_adjust = cfun->machine->frame.callee_adjust;
+-  poly_int64 final_adjust = cfun->machine->frame.final_adjust;
+-  poly_int64 callee_offset = cfun->machine->frame.callee_offset;
+-  poly_int64 sve_callee_adjust = cfun->machine->frame.sve_callee_adjust;
++  aarch64_frame &frame = cfun->machine->frame;
++  poly_int64 frame_size = frame.frame_size;
++  poly_int64 initial_adjust = frame.initial_adjust;
++  HOST_WIDE_INT callee_adjust = frame.callee_adjust;
++  poly_int64 final_adjust = frame.final_adjust;
++  poly_int64 callee_offset = frame.callee_offset;
++  poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
+   poly_int64 below_hard_fp_saved_regs_size
+-    = cfun->machine->frame.below_hard_fp_saved_regs_size;
+-  unsigned reg1 = cfun->machine->frame.wb_push_candidate1;
+-  unsigned reg2 = cfun->machine->frame.wb_push_candidate2;
+-  bool emit_frame_chain = cfun->machine->frame.emit_frame_chain;
++    = frame.below_hard_fp_saved_regs_size;
++  unsigned reg1 = frame.wb_push_candidate1;
++  unsigned reg2 = frame.wb_push_candidate2;
++  bool emit_frame_chain = frame.emit_frame_chain;
+   rtx_insn *insn;
+ 
+   if (flag_stack_clash_protection && known_eq (callee_adjust, 0))
+@@ -10303,7 +10307,7 @@ aarch64_expand_prologue (void)
+     }
+ 
+   /* Push return address to shadow call stack.  */
+-  if (cfun->machine->frame.is_scs_enabled)
++  if (frame.is_scs_enabled)
+     emit_insn (gen_scs_push ());
+ 
+   if (flag_stack_usage_info)
+@@ -10342,7 +10346,7 @@ aarch64_expand_prologue (void)
+ 
+   /* The offset of the frame chain record (if any) from the current SP.  */
+   poly_int64 chain_offset = (initial_adjust + callee_adjust
+-			     - cfun->machine->frame.hard_fp_offset);
++			     - frame.hard_fp_offset);
+   gcc_assert (known_ge (chain_offset, 0));
+ 
+   /* The offset of the bottom of the save area from the current SP.  */
+@@ -10445,16 +10449,17 @@ aarch64_use_return_insn_p (void)
+ void
+ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ {
+-  poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
+-  HOST_WIDE_INT callee_adjust = cfun->machine->frame.callee_adjust;
+-  poly_int64 final_adjust = cfun->machine->frame.final_adjust;
+-  poly_int64 callee_offset = cfun->machine->frame.callee_offset;
+-  poly_int64 sve_callee_adjust = cfun->machine->frame.sve_callee_adjust;
++  aarch64_frame &frame = cfun->machine->frame;
++  poly_int64 initial_adjust = frame.initial_adjust;
++  HOST_WIDE_INT callee_adjust = frame.callee_adjust;
++  poly_int64 final_adjust = frame.final_adjust;
++  poly_int64 callee_offset = frame.callee_offset;
++  poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
+   poly_int64 below_hard_fp_saved_regs_size
+-    = cfun->machine->frame.below_hard_fp_saved_regs_size;
+-  unsigned reg1 = cfun->machine->frame.wb_pop_candidate1;
+-  unsigned reg2 = cfun->machine->frame.wb_pop_candidate2;
+-  unsigned int last_gpr = (cfun->machine->frame.is_scs_enabled
++    = frame.below_hard_fp_saved_regs_size;
++  unsigned reg1 = frame.wb_pop_candidate1;
++  unsigned reg2 = frame.wb_pop_candidate2;
++  unsigned int last_gpr = (frame.is_scs_enabled
+ 			   ? R29_REGNUM : R30_REGNUM);
+   rtx cfi_ops = NULL;
+   rtx_insn *insn;
+@@ -10488,7 +10493,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+   /* We need to add memory barrier to prevent read from deallocated stack.  */
+   bool need_barrier_p
+     = maybe_ne (get_frame_size ()
+-		+ cfun->machine->frame.saved_varargs_size, 0);
++		+ frame.saved_varargs_size, 0);
+ 
+   /* Emit a barrier to prevent loads from a deallocated stack.  */
+   if (maybe_gt (final_adjust, crtl->outgoing_args_size)
+@@ -10569,7 +10574,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+     }
+ 
+   /* Pop return address from shadow call stack.  */
+-  if (cfun->machine->frame.is_scs_enabled)
++  if (frame.is_scs_enabled)
+     {
+       machine_mode mode = aarch64_reg_save_mode (R30_REGNUM);
+       rtx reg = gen_rtx_REG (mode, R30_REGNUM);
+@@ -13023,24 +13028,24 @@ aarch64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+ poly_int64
+ aarch64_initial_elimination_offset (unsigned from, unsigned to)
+ {
++  aarch64_frame &frame = cfun->machine->frame;
++
+   if (to == HARD_FRAME_POINTER_REGNUM)
+     {
+       if (from == ARG_POINTER_REGNUM)
+-	return cfun->machine->frame.hard_fp_offset;
++	return frame.hard_fp_offset;
+ 
+       if (from == FRAME_POINTER_REGNUM)
+-	return cfun->machine->frame.hard_fp_offset
+-	       - cfun->machine->frame.locals_offset;
++	return frame.hard_fp_offset - frame.locals_offset;
+     }
+ 
+   if (to == STACK_POINTER_REGNUM)
+     {
+       if (from == FRAME_POINTER_REGNUM)
+-	  return cfun->machine->frame.frame_size
+-		 - cfun->machine->frame.locals_offset;
++	return frame.frame_size - frame.locals_offset;
+     }
+ 
+-  return cfun->machine->frame.frame_size;
++  return frame.frame_size;
+ }
+ 
+ 
+-- 
+2.33.0
+
diff --git a/0183-Backport-SME-aarch64-Avoid-a-use-of-callee_offset.patch b/0183-Backport-SME-aarch64-Avoid-a-use-of-callee_offset.patch
new file mode 100644
index 0000000..7a2c9e2
--- /dev/null
+++ b/0183-Backport-SME-aarch64-Avoid-a-use-of-callee_offset.patch
@@ -0,0 +1,103 @@
+From 54a6e52207703a8643fc406175377105f887ebef Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:04 +0100
+Subject: [PATCH] [Backport][SME] aarch64: Avoid a use of callee_offset
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f9ab771fa8cd747f34786c6f33deea32c2eb828b
+
+When we emit the frame chain, i.e. when we reach Here in this statement
+of aarch64_expand_prologue:
+
+  if (emit_frame_chain)
+    {
+      // Here
+      ...
+    }
+
+the stack is in one of two states:
+
+- We've allocated up to the frame chain, but no more.
+
+- We've allocated the whole frame, and the frame chain is within easy
+  reach of the new SP.
+
+The offset of the frame chain from the current SP is available
+in aarch64_frame as callee_offset.  It is also available as the
+chain_offset local variable, where the latter is calculated from other
+data.  (However, chain_offset is not always equal to callee_offset when
+!emit_frame_chain, so chain_offset isn't redundant.)
+
+In c600df9a4060da3c6121ff4d0b93f179eafd69d1 I switched to using
+chain_offset for the initialisation of the hard frame pointer:
+
+       aarch64_add_offset (Pmode, hard_frame_pointer_rtx,
+-                         stack_pointer_rtx, callee_offset,
++                         stack_pointer_rtx, chain_offset,
+                          tmp1_rtx, tmp0_rtx, frame_pointer_needed);
+
+But the later REG_CFA_ADJUST_CFA handling still used callee_offset.
+
+I think the difference is harmless, but it's more logical for the
+CFA note to be in sync, and it's more convenient for later patches
+if it uses chain_offset.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_expand_prologue): Use
+	chain_offset rather than callee_offset.
+---
+ gcc/config/aarch64/aarch64.cc | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index b7da1d0be..fbd7a079a 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -10263,21 +10263,20 @@ aarch64_epilogue_uses (int regno)
+    current FP is also set up if it is in use.  */
+ 
+ void
+ aarch64_expand_prologue (void)
+ {
+   aarch64_frame &frame = cfun->machine->frame;
+   poly_int64 frame_size = frame.frame_size;
+   poly_int64 initial_adjust = frame.initial_adjust;
+   HOST_WIDE_INT callee_adjust = frame.callee_adjust;
+   poly_int64 final_adjust = frame.final_adjust;
+-  poly_int64 callee_offset = frame.callee_offset;
+   poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
+   poly_int64 below_hard_fp_saved_regs_size
+     = frame.below_hard_fp_saved_regs_size;
+   unsigned reg1 = frame.wb_push_candidate1;
+   unsigned reg2 = frame.wb_push_candidate2;
+   bool emit_frame_chain = frame.emit_frame_chain;
+   rtx_insn *insn;
+ 
+   if (flag_stack_clash_protection && known_eq (callee_adjust, 0))
+     {
+@@ -10376,22 +10375,21 @@ aarch64_expand_prologue (void)
+ 	     the CFA based on the frame pointer.  We therefore need new
+ 	     DW_CFA_expressions to re-express the save slots with addresses
+ 	     based on the frame pointer.  */
+ 	  rtx_insn *insn = get_last_insn ();
+ 	  gcc_assert (RTX_FRAME_RELATED_P (insn));
+ 
+ 	  /* Add an explicit CFA definition if this was previously
+ 	     implicit.  */
+ 	  if (!find_reg_note (insn, REG_CFA_ADJUST_CFA, NULL_RTX))
+ 	    {
+-	      rtx src = plus_constant (Pmode, stack_pointer_rtx,
+-				       callee_offset);
++	      rtx src = plus_constant (Pmode, stack_pointer_rtx, chain_offset);
+ 	      add_reg_note (insn, REG_CFA_ADJUST_CFA,
+ 			    gen_rtx_SET (hard_frame_pointer_rtx, src));
+ 	    }
+ 
+ 	  /* Change the save slot expressions for the registers that
+ 	     we've already saved.  */
+ 	  aarch64_add_cfa_expression (insn, regno_reg_rtx[reg2],
+ 				      hard_frame_pointer_rtx, UNITS_PER_WORD);
+ 	  aarch64_add_cfa_expression (insn, regno_reg_rtx[reg1],
+ 				      hard_frame_pointer_rtx, 0);
+-- 
+2.38.1.windows.1
+
diff --git a/0184-Backport-SME-aarch64-Explicitly-handle-frames-with-n.patch b/0184-Backport-SME-aarch64-Explicitly-handle-frames-with-n.patch
new file mode 100644
index 0000000..3af28ed
--- /dev/null
+++ b/0184-Backport-SME-aarch64-Explicitly-handle-frames-with-n.patch
@@ -0,0 +1,51 @@
+From 82bbe6513987a7656150110164e25f44fe410796 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:05 +0100
+Subject: [PATCH 085/157] [Backport][SME] aarch64: Explicitly handle frames
+ with no saved registers
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c601c918c9ac01ef8315774a642ff924f77c85e5
+
+If a frame has no saved registers, it can be allocated in one go.
+There is no need to treat the areas below and above the saved
+registers as separate.
+
+And if we allocate the frame in one go, it should be allocated
+as the initial_adjust rather than the final_adjust.  This allows the
+frame size to grow to guard_size - guard_used_by_caller before a stack
+probe is needed.  (A frame with no register saves is necessarily a
+leaf frame.)
+
+This is a no-op as thing stand, since a leaf function will have
+no outgoing arguments, and so all the frame will be above where
+the saved registers normally go.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Explicitly
+	allocate the frame in one go if there are no saved registers.
+---
+ gcc/config/aarch64/aarch64.cc | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index fbd7a079a..c59af6b1c 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8978,9 +8978,11 @@ aarch64_layout_frame (void)
+ 
+   HOST_WIDE_INT const_size, const_outgoing_args_size, const_fp_offset;
+   HOST_WIDE_INT const_saved_regs_size;
+-  if (frame.frame_size.is_constant (&const_size)
+-      && const_size < max_push_offset
+-      && known_eq (frame.hard_fp_offset, const_size))
++  if (known_eq (frame.saved_regs_size, 0))
++    frame.initial_adjust = frame.frame_size;
++  else if (frame.frame_size.is_constant (&const_size)
++	   && const_size < max_push_offset
++	   && known_eq (frame.hard_fp_offset, const_size))
+     {
+       /* Simple, small frame with no outgoing arguments:
+ 
+-- 
+2.33.0
+
diff --git a/0185-Backport-SME-aarch64-Add-bytes_below_saved_regs-to-f.patch b/0185-Backport-SME-aarch64-Add-bytes_below_saved_regs-to-f.patch
new file mode 100644
index 0000000..f754f97
--- /dev/null
+++ b/0185-Backport-SME-aarch64-Add-bytes_below_saved_regs-to-f.patch
@@ -0,0 +1,236 @@
+From bf985fe08b6298218180666a7d20f4aa0b41326f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:05 +0100
+Subject: [PATCH 086/157] [Backport][SME] aarch64: Add bytes_below_saved_regs
+ to frame info
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7b792ecaa9414bc81520b3da552d40ad854be976
+
+The frame layout code currently hard-codes the assumption that
+the number of bytes below the saved registers is equal to the
+size of the outgoing arguments.  This patch abstracts that
+value into a new field of aarch64_frame.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::bytes_below_saved_regs): New
+	field.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Initialize it,
+	and use it instead of crtl->outgoing_args_size.
+	(aarch64_get_separate_components): Use bytes_below_saved_regs instead
+	of outgoing_args_size.
+	(aarch64_process_components): Likewise.
+---
+ gcc/config/aarch64/aarch64.cc | 71 ++++++++++++++++++-----------------
+ gcc/config/aarch64/aarch64.h  |  5 +++
+ 2 files changed, 41 insertions(+), 35 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index c59af6b1c..5533dd85b 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8817,6 +8817,8 @@ aarch64_layout_frame (void)
+   gcc_assert (crtl->is_leaf
+ 	      || maybe_ne (frame.reg_offset[R30_REGNUM], SLOT_NOT_REQUIRED));
+ 
++  frame.bytes_below_saved_regs = crtl->outgoing_args_size;
++
+   /* Now assign stack slots for the registers.  Start with the predicate
+      registers, since predicate LDR and STR have a relatively small
+      offset range.  These saves happen below the hard frame pointer.  */
+@@ -8921,18 +8923,18 @@ aarch64_layout_frame (void)
+ 
+   poly_int64 varargs_and_saved_regs_size = offset + frame.saved_varargs_size;
+ 
+-  poly_int64 above_outgoing_args
++  poly_int64 saved_regs_and_above
+     = aligned_upper_bound (varargs_and_saved_regs_size
+ 			   + get_frame_size (),
+ 			   STACK_BOUNDARY / BITS_PER_UNIT);
+ 
+   frame.hard_fp_offset
+-    = above_outgoing_args - frame.below_hard_fp_saved_regs_size;
++    = saved_regs_and_above - frame.below_hard_fp_saved_regs_size;
+ 
+   /* Both these values are already aligned.  */
+-  gcc_assert (multiple_p (crtl->outgoing_args_size,
++  gcc_assert (multiple_p (frame.bytes_below_saved_regs,
+ 			  STACK_BOUNDARY / BITS_PER_UNIT));
+-  frame.frame_size = above_outgoing_args + crtl->outgoing_args_size;
++  frame.frame_size = saved_regs_and_above + frame.bytes_below_saved_regs;
+ 
+   frame.locals_offset = frame.saved_varargs_size;
+ 
+@@ -8976,7 +8978,7 @@ aarch64_layout_frame (void)
+   else if (frame.wb_pop_candidate1 != INVALID_REGNUM)
+     max_push_offset = 256;
+ 
+-  HOST_WIDE_INT const_size, const_outgoing_args_size, const_fp_offset;
++  HOST_WIDE_INT const_size, const_below_saved_regs, const_fp_offset;
+   HOST_WIDE_INT const_saved_regs_size;
+   if (known_eq (frame.saved_regs_size, 0))
+     frame.initial_adjust = frame.frame_size;
+@@ -8984,31 +8986,31 @@ aarch64_layout_frame (void)
+ 	   && const_size < max_push_offset
+ 	   && known_eq (frame.hard_fp_offset, const_size))
+     {
+-      /* Simple, small frame with no outgoing arguments:
++      /* Simple, small frame with no data below the saved registers.
+ 
+ 	 stp reg1, reg2, [sp, -frame_size]!
+ 	 stp reg3, reg4, [sp, 16]  */
+       frame.callee_adjust = const_size;
+     }
+-  else if (crtl->outgoing_args_size.is_constant (&const_outgoing_args_size)
++  else if (frame.bytes_below_saved_regs.is_constant (&const_below_saved_regs)
+ 	   && frame.saved_regs_size.is_constant (&const_saved_regs_size)
+-	   && const_outgoing_args_size + const_saved_regs_size < 512
+-	   /* We could handle this case even with outgoing args, provided
+-	      that the number of args left us with valid offsets for all
+-	      predicate and vector save slots.  It's such a rare case that
+-	      it hardly seems worth the effort though.  */
+-	   && (!saves_below_hard_fp_p || const_outgoing_args_size == 0)
++	   && const_below_saved_regs + const_saved_regs_size < 512
++	   /* We could handle this case even with data below the saved
++	      registers, provided that that data left us with valid offsets
++	      for all predicate and vector save slots.  It's such a rare
++	      case that it hardly seems worth the effort though.  */
++	   && (!saves_below_hard_fp_p || const_below_saved_regs == 0)
+ 	   && !(cfun->calls_alloca
+ 		&& frame.hard_fp_offset.is_constant (&const_fp_offset)
+ 		&& const_fp_offset < max_push_offset))
+     {
+-      /* Frame with small outgoing arguments:
++      /* Frame with small area below the saved registers:
+ 
+ 	 sub sp, sp, frame_size
+-	 stp reg1, reg2, [sp, outgoing_args_size]
+-	 stp reg3, reg4, [sp, outgoing_args_size + 16]  */
++	 stp reg1, reg2, [sp, bytes_below_saved_regs]
++	 stp reg3, reg4, [sp, bytes_below_saved_regs + 16]  */
+       frame.initial_adjust = frame.frame_size;
+-      frame.callee_offset = const_outgoing_args_size;
++      frame.callee_offset = const_below_saved_regs;
+     }
+   else if (saves_below_hard_fp_p
+ 	   && known_eq (frame.saved_regs_size,
+@@ -9018,30 +9020,29 @@ aarch64_layout_frame (void)
+ 
+ 	 sub sp, sp, hard_fp_offset + below_hard_fp_saved_regs_size
+ 	 save SVE registers relative to SP
+-	 sub sp, sp, outgoing_args_size  */
++	 sub sp, sp, bytes_below_saved_regs  */
+       frame.initial_adjust = (frame.hard_fp_offset
+ 			      + frame.below_hard_fp_saved_regs_size);
+-      frame.final_adjust = crtl->outgoing_args_size;
++      frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+   else if (frame.hard_fp_offset.is_constant (&const_fp_offset)
+ 	   && const_fp_offset < max_push_offset)
+     {
+-      /* Frame with large outgoing arguments or SVE saves, but with
+-	 a small local area:
++      /* Frame with large area below the saved registers, or with SVE saves,
++	 but with a small area above:
+ 
+ 	 stp reg1, reg2, [sp, -hard_fp_offset]!
+ 	 stp reg3, reg4, [sp, 16]
+ 	 [sub sp, sp, below_hard_fp_saved_regs_size]
+ 	 [save SVE registers relative to SP]
+-	 sub sp, sp, outgoing_args_size  */
++	 sub sp, sp, bytes_below_saved_regs  */
+       frame.callee_adjust = const_fp_offset;
+       frame.sve_callee_adjust = frame.below_hard_fp_saved_regs_size;
+-      frame.final_adjust = crtl->outgoing_args_size;
++      frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+   else
+     {
+-      /* Frame with large local area and outgoing arguments or SVE saves,
+-	 using frame pointer:
++      /* General case:
+ 
+ 	 sub sp, sp, hard_fp_offset
+ 	 stp x29, x30, [sp, 0]
+@@ -9049,10 +9050,10 @@ aarch64_layout_frame (void)
+ 	 stp reg3, reg4, [sp, 16]
+ 	 [sub sp, sp, below_hard_fp_saved_regs_size]
+ 	 [save SVE registers relative to SP]
+-	 sub sp, sp, outgoing_args_size  */
++	 sub sp, sp, bytes_below_saved_regs  */
+       frame.initial_adjust = frame.hard_fp_offset;
+       frame.sve_callee_adjust = frame.below_hard_fp_saved_regs_size;
+-      frame.final_adjust = crtl->outgoing_args_size;
++      frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+ 
+   /* Make sure the individual adjustments add up to the full frame size.  */
+@@ -9643,7 +9644,7 @@ aarch64_get_separate_components (void)
+ 	if (frame_pointer_needed)
+ 	  offset -= frame.below_hard_fp_saved_regs_size;
+ 	else
+-	  offset += crtl->outgoing_args_size;
++	  offset += frame.bytes_below_saved_regs;
+ 
+ 	/* Check that we can access the stack slot of the register with one
+ 	   direct load with no adjustments needed.  */
+@@ -9792,7 +9793,7 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+       if (frame_pointer_needed)
+ 	offset -= frame.below_hard_fp_saved_regs_size;
+       else
+-	offset += crtl->outgoing_args_size;
++	offset += frame.bytes_below_saved_regs;
+ 
+       rtx addr = plus_constant (Pmode, ptr_reg, offset);
+       rtx mem = gen_frame_mem (mode, addr);
+@@ -9846,7 +9847,7 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+       if (frame_pointer_needed)
+ 	offset2 -= frame.below_hard_fp_saved_regs_size;
+       else
+-	offset2 += crtl->outgoing_args_size;
++	offset2 += frame.bytes_below_saved_regs;
+       rtx addr2 = plus_constant (Pmode, ptr_reg, offset2);
+       rtx mem2 = gen_frame_mem (mode, addr2);
+       rtx set2 = prologue_p ? gen_rtx_SET (mem2, reg2)
+@@ -9920,10 +9921,10 @@ aarch64_stack_clash_protection_alloca_probe_range (void)
+    registers.  If POLY_SIZE is not large enough to require a probe this function
+    will only adjust the stack.  When allocating the stack space
+    FRAME_RELATED_P is then used to indicate if the allocation is frame related.
+-   FINAL_ADJUSTMENT_P indicates whether we are allocating the outgoing
+-   arguments.  If we are then we ensure that any allocation larger than the ABI
+-   defined buffer needs a probe so that the invariant of having a 1KB buffer is
+-   maintained.
++   FINAL_ADJUSTMENT_P indicates whether we are allocating the area below
++   the saved registers.  If we are then we ensure that any allocation
++   larger than the ABI defined buffer needs a probe so that the
++   invariant of having a 1KB buffer is maintained.
+ 
+    We emit barriers after each stack adjustment to prevent optimizations from
+    breaking the invariant that we never drop the stack more than a page.  This
+@@ -10132,7 +10133,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+   /* Handle any residuals.  Residuals of at least MIN_PROBE_THRESHOLD have to
+      be probed.  This maintains the requirement that each page is probed at
+      least once.  For initial probing we probe only if the allocation is
+-     more than GUARD_SIZE - buffer, and for the outgoing arguments we probe
++     more than GUARD_SIZE - buffer, and below the saved registers we probe
+      if the amount is larger than buffer.  GUARD_SIZE - buffer + buffer ==
+      GUARD_SIZE.  This works that for any allocation that is large enough to
+      trigger a probe here, we'll have at least one, and if they're not large
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 8f0ac2cde..9e0ca380e 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -801,6 +801,11 @@ struct GTY (()) aarch64_frame
+   /* The size of the callee-save registers with a slot in REG_OFFSET.  */
+   poly_int64 saved_regs_size;
+ 
++  /* The number of bytes between the bottom of the static frame (the bottom
++     of the outgoing arguments) and the bottom of the register save area.
++     This value is always a multiple of STACK_BOUNDARY.  */
++  poly_int64 bytes_below_saved_regs;
++
+   /* The size of the callee-save registers with a slot in REG_OFFSET that
+      are saved below the hard frame pointer.  */
+   poly_int64 below_hard_fp_saved_regs_size;
+-- 
+2.33.0
+
diff --git a/0186-Backport-SME-aarch64-Add-bytes_below_hard_fp-to-fram.patch b/0186-Backport-SME-aarch64-Add-bytes_below_hard_fp-to-fram.patch
new file mode 100644
index 0000000..5eed26e
--- /dev/null
+++ b/0186-Backport-SME-aarch64-Add-bytes_below_hard_fp-to-fram.patch
@@ -0,0 +1,87 @@
+From bd5299017c233bcdf0fcc3dd7217eec1641411fe Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:06 +0100
+Subject: [PATCH 087/157] [Backport][SME] aarch64: Add bytes_below_hard_fp to
+ frame info
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=99305f306246079cc57d30dae7c32107f02ff3e8
+
+Following on from the previous bytes_below_saved_regs patch, this one
+records the number of bytes that are below the hard frame pointer.
+This eventually replaces below_hard_fp_saved_regs_size.
+
+If a frame pointer is not needed, the epilogue adds final_adjust
+to the stack pointer before restoring registers:
+
+     aarch64_add_sp (tmp1_rtx, tmp0_rtx, final_adjust, true);
+
+Therefore, if the epilogue needs to restore the stack pointer from
+the hard frame pointer, the directly corresponding offset is:
+
+     -bytes_below_hard_fp + final_adjust
+
+i.e. go from the hard frame pointer to the bottom of the frame,
+then add the same amount as if we were using the stack pointer
+from the outset.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::bytes_below_hard_fp): New
+	field.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Initialize it.
+	(aarch64_expand_epilogue): Use it instead of
+	below_hard_fp_saved_regs_size.
+---
+ gcc/config/aarch64/aarch64.cc | 6 +++---
+ gcc/config/aarch64/aarch64.h  | 5 +++++
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 5533dd85b..2bb49b9b0 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8869,6 +8869,7 @@ aarch64_layout_frame (void)
+      of the callee save area.  */
+   bool saves_below_hard_fp_p = maybe_ne (offset, 0);
+   frame.below_hard_fp_saved_regs_size = offset;
++  frame.bytes_below_hard_fp = offset + frame.bytes_below_saved_regs;
+   if (frame.emit_frame_chain)
+     {
+       /* FP and LR are placed in the linkage record.  */
+@@ -10456,8 +10457,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+   poly_int64 final_adjust = frame.final_adjust;
+   poly_int64 callee_offset = frame.callee_offset;
+   poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
+-  poly_int64 below_hard_fp_saved_regs_size
+-    = frame.below_hard_fp_saved_regs_size;
++  poly_int64 bytes_below_hard_fp = frame.bytes_below_hard_fp;
+   unsigned reg1 = frame.wb_pop_candidate1;
+   unsigned reg2 = frame.wb_pop_candidate2;
+   unsigned int last_gpr = (frame.is_scs_enabled
+@@ -10515,7 +10515,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+        is restored on the instruction doing the writeback.  */
+     aarch64_add_offset (Pmode, stack_pointer_rtx,
+ 			hard_frame_pointer_rtx,
+-			-callee_offset - below_hard_fp_saved_regs_size,
++			-bytes_below_hard_fp + final_adjust,
+ 			tmp1_rtx, tmp0_rtx, callee_adjust == 0);
+   else
+      /* The case where we need to re-use the register here is very rare, so
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 9e0ca380e..dedc5b32f 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -810,6 +810,11 @@ struct GTY (()) aarch64_frame
+      are saved below the hard frame pointer.  */
+   poly_int64 below_hard_fp_saved_regs_size;
+ 
++  /* The number of bytes between the bottom of the static frame (the bottom
++     of the outgoing arguments) and the hard frame pointer.  This value is
++     always a multiple of STACK_BOUNDARY.  */
++  poly_int64 bytes_below_hard_fp;
++
+   /* Offset from the base of the frame (incomming SP) to the
+      top of the locals area.  This value is always a multiple of
+      STACK_BOUNDARY.  */
+-- 
+2.33.0
+
diff --git a/0187-Backport-SME-aarch64-Robustify-stack-tie-handling.patch b/0187-Backport-SME-aarch64-Robustify-stack-tie-handling.patch
new file mode 100644
index 0000000..cc9f87c
--- /dev/null
+++ b/0187-Backport-SME-aarch64-Robustify-stack-tie-handling.patch
@@ -0,0 +1,126 @@
+From 4dc3e578d958ceb73f973483f42247c3d33210dc Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 20 Jun 2023 21:48:38 +0100
+Subject: [PATCH 088/157] [Backport][SME] aarch64: Robustify stack tie handling
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=580b74a79146e51268dd11192d3870645adb0bbb
+
+The SVE handling of stack clash protection copied the stack
+pointer to X11 before the probe and set up X11 as the CFA
+for unwind purposes:
+
+    /* This is done to provide unwinding information for the stack
+       adjustments we're about to do, however to prevent the optimizers
+       from removing the R11 move and leaving the CFA note (which would be
+       very wrong) we tie the old and new stack pointer together.
+       The tie will expand to nothing but the optimizers will not touch
+       the instruction.  */
+    rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM);
+    emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
+    emit_insn (gen_stack_tie (stack_ptr_copy, stack_pointer_rtx));
+
+    /* We want the CFA independent of the stack pointer for the
+       duration of the loop.  */
+    add_reg_note (insn, REG_CFA_DEF_CFA, stack_ptr_copy);
+    RTX_FRAME_RELATED_P (insn) = 1;
+
+-fcprop-registers is now smart enough to realise that X11 = SP,
+replace X11 with SP in the stack tie, and delete the instruction
+created above.
+
+This patch tries to prevent that by making stack_tie fussy about
+the register numbers.  It fixes failures in
+gcc.target/aarch64/sve/pcs/stack_clash*.c.
+
+gcc/
+	* config/aarch64/aarch64.md (stack_tie): Hard-code the first
+	register operand to the stack pointer.  Require the second register
+	operand to have the number specified in a separate const_int operand.
+	* config/aarch64/aarch64.cc (aarch64_emit_stack_tie): New function.
+	(aarch64_allocate_and_probe_stack_space): Use it.
+	(aarch64_expand_prologue, aarch64_expand_epilogue): Likewise.
+	(aarch64_expand_epilogue): Likewise.
+---
+ gcc/config/aarch64/aarch64.cc | 18 ++++++++++++++----
+ gcc/config/aarch64/aarch64.md |  7 ++++---
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 2bb49b9b0..4d505c6fc 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -9917,6 +9917,16 @@ aarch64_stack_clash_protection_alloca_probe_range (void)
+   return STACK_CLASH_CALLER_GUARD;
+ }
+ 
++/* Emit a stack tie that acts as a scheduling barrier for all previous and
++   subsequent memory accesses and that requires the stack pointer and REG
++   to have their current values.  REG can be stack_pointer_rtx if no
++   other register's value needs to be fixed.  */
++
++static void
++aarch64_emit_stack_tie (rtx reg)
++{
++  emit_insn (gen_stack_tie (reg, gen_int_mode (REGNO (reg), DImode)));
++}
+ 
+ /* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch
+    registers.  If POLY_SIZE is not large enough to require a probe this function
+@@ -10030,7 +10040,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+ 	     the instruction.  */
+ 	  rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM);
+ 	  emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
+-	  emit_insn (gen_stack_tie (stack_ptr_copy, stack_pointer_rtx));
++	  aarch64_emit_stack_tie (stack_ptr_copy);
+ 
+ 	  /* We want the CFA independent of the stack pointer for the
+ 	     duration of the loop.  */
+@@ -10398,7 +10408,7 @@ aarch64_expand_prologue (void)
+ 	  aarch64_add_cfa_expression (insn, regno_reg_rtx[reg1],
+ 				      hard_frame_pointer_rtx, 0);
+ 	}
+-      emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx));
++      aarch64_emit_stack_tie (hard_frame_pointer_rtx);
+     }
+ 
+   aarch64_save_callee_saves (saved_regs_offset, R0_REGNUM, R30_REGNUM,
+@@ -10501,7 +10511,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+       || cfun->calls_alloca
+       || crtl->calls_eh_return)
+     {
+-      emit_insn (gen_stack_tie (stack_pointer_rtx, stack_pointer_rtx));
++      aarch64_emit_stack_tie (stack_pointer_rtx);
+       need_barrier_p = false;
+     }
+ 
+@@ -10540,7 +10550,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ 				callee_adjust != 0, &cfi_ops);
+ 
+   if (need_barrier_p)
+-    emit_insn (gen_stack_tie (stack_pointer_rtx, stack_pointer_rtx));
++    aarch64_emit_stack_tie (stack_pointer_rtx);
+ 
+   if (callee_adjust != 0)
+     aarch64_pop_regs (reg1, reg2, callee_adjust, &cfi_ops);
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 2becc888e..2ce123255 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -7088,10 +7088,11 @@
+ 
+ (define_insn "stack_tie"
+   [(set (mem:BLK (scratch))
+-	(unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
+-		     (match_operand:DI 1 "register_operand" "rk")]
++	(unspec:BLK [(reg:DI SP_REGNUM)
++		     (match_operand:DI 0 "register_operand" "rk")
++		     (match_operand:DI 1 "const_int_operand")]
+ 		    UNSPEC_PRLG_STK))]
+-  ""
++  "REGNO (operands[0]) == INTVAL (operands[1])"
+   ""
+   [(set_attr "length" "0")]
+ )
+-- 
+2.33.0
+
diff --git a/0188-Backport-SME-aarch64-Tweak-aarch64_save-restore_call.patch b/0188-Backport-SME-aarch64-Tweak-aarch64_save-restore_call.patch
new file mode 100644
index 0000000..c302467
--- /dev/null
+++ b/0188-Backport-SME-aarch64-Tweak-aarch64_save-restore_call.patch
@@ -0,0 +1,228 @@
+From 8e010ea1a3e122a74696250d7c6ce5660a88b8f5 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:06 +0100
+Subject: [PATCH 089/157] [Backport][SME] aarch64: Tweak
+ aarch64_save/restore_callee_saves
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=38698967268c44991e02aa1e5a2ce9382d6de9db
+
+aarch64_save_callee_saves and aarch64_restore_callee_saves took
+a parameter called start_offset that gives the offset of the
+bottom of the saved register area from the current stack pointer.
+However, it's more convenient for later patches if we use the
+bottom of the entire frame as the reference point, rather than
+the bottom of the saved registers.
+
+Doing that removes the need for the callee_offset field.
+Other than that, this is not a win on its own.  It only really
+makes sense in combination with the follow-on patches.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::callee_offset): Delete.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Remove
+	callee_offset handling.
+	(aarch64_save_callee_saves): Replace the start_offset parameter
+	with a bytes_below_sp parameter.
+	(aarch64_restore_callee_saves): Likewise.
+	(aarch64_expand_prologue): Update accordingly.
+	(aarch64_expand_epilogue): Likewise.
+---
+ gcc/config/aarch64/aarch64.cc | 56 +++++++++++++++++------------------
+ gcc/config/aarch64/aarch64.h  |  4 ---
+ 2 files changed, 28 insertions(+), 32 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 4d505c6fc..a0a4c7ac3 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8943,7 +8943,6 @@ aarch64_layout_frame (void)
+   frame.final_adjust = 0;
+   frame.callee_adjust = 0;
+   frame.sve_callee_adjust = 0;
+-  frame.callee_offset = 0;
+ 
+   frame.wb_pop_candidate1 = frame.wb_push_candidate1;
+   frame.wb_pop_candidate2 = frame.wb_push_candidate2;
+@@ -9011,7 +9010,6 @@ aarch64_layout_frame (void)
+ 	 stp reg1, reg2, [sp, bytes_below_saved_regs]
+ 	 stp reg3, reg4, [sp, bytes_below_saved_regs + 16]  */
+       frame.initial_adjust = frame.frame_size;
+-      frame.callee_offset = const_below_saved_regs;
+     }
+   else if (saves_below_hard_fp_p
+ 	   && known_eq (frame.saved_regs_size,
+@@ -9358,12 +9356,13 @@ aarch64_add_cfa_expression (rtx_insn *insn, rtx reg,
+ }
+ 
+ /* Emit code to save the callee-saved registers from register number START
+-   to LIMIT to the stack at the location starting at offset START_OFFSET,
+-   skipping any write-back candidates if SKIP_WB is true.  HARD_FP_VALID_P
+-   is true if the hard frame pointer has been set up.  */
++   to LIMIT to the stack.  The stack pointer is currently BYTES_BELOW_SP
++   bytes above the bottom of the static frame.  Skip any write-back
++   candidates if SKIP_WB is true.  HARD_FP_VALID_P is true if the hard
++   frame pointer has been set up.  */
+ 
+ static void
+-aarch64_save_callee_saves (poly_int64 start_offset,
++aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 			   unsigned start, unsigned limit, bool skip_wb,
+ 			   bool hard_fp_valid_p)
+ {
+@@ -9391,7 +9390,9 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       reg = gen_rtx_REG (mode, regno);
+-      offset = start_offset + frame.reg_offset[regno];
++      offset = (frame.reg_offset[regno]
++		+ frame.bytes_below_saved_regs
++		- bytes_below_sp);
+       rtx base_rtx = stack_pointer_rtx;
+       poly_int64 sp_offset = offset;
+ 
+@@ -9402,9 +9403,7 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+       else if (GP_REGNUM_P (regno)
+ 	       && (!offset.is_constant (&const_offset) || const_offset >= 512))
+ 	{
+-	  gcc_assert (known_eq (start_offset, 0));
+-	  poly_int64 fp_offset
+-	    = frame.below_hard_fp_saved_regs_size;
++	  poly_int64 fp_offset = frame.bytes_below_hard_fp - bytes_below_sp;
+ 	  if (hard_fp_valid_p)
+ 	    base_rtx = hard_frame_pointer_rtx;
+ 	  else
+@@ -9468,12 +9467,13 @@ aarch64_save_callee_saves (poly_int64 start_offset,
+ }
+ 
+ /* Emit code to restore the callee registers from register number START
+-   up to and including LIMIT.  Restore from the stack offset START_OFFSET,
+-   skipping any write-back candidates if SKIP_WB is true.  Write the
+-   appropriate REG_CFA_RESTORE notes into CFI_OPS.  */
++   up to and including LIMIT.  The stack pointer is currently BYTES_BELOW_SP
++   bytes above the bottom of the static frame.  Skip any write-back
++   candidates if SKIP_WB is true.  Write the appropriate REG_CFA_RESTORE
++   notes into CFI_OPS.  */
+ 
+ static void
+-aarch64_restore_callee_saves (poly_int64 start_offset, unsigned start,
++aarch64_restore_callee_saves (poly_int64 bytes_below_sp, unsigned start,
+ 			      unsigned limit, bool skip_wb, rtx *cfi_ops)
+ {
+   aarch64_frame &frame = cfun->machine->frame;
+@@ -9499,7 +9499,9 @@ aarch64_restore_callee_saves (poly_int64 start_offset, unsigned start,
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       reg = gen_rtx_REG (mode, regno);
+-      offset = start_offset + frame.reg_offset[regno];
++      offset = (frame.reg_offset[regno]
++		+ frame.bytes_below_saved_regs
++		- bytes_below_sp);
+       rtx base_rtx = stack_pointer_rtx;
+       if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg,
+@@ -10285,8 +10287,6 @@ aarch64_expand_prologue (void)
+   HOST_WIDE_INT callee_adjust = frame.callee_adjust;
+   poly_int64 final_adjust = frame.final_adjust;
+   poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
+-  poly_int64 below_hard_fp_saved_regs_size
+-    = frame.below_hard_fp_saved_regs_size;
+   unsigned reg1 = frame.wb_push_candidate1;
+   unsigned reg2 = frame.wb_push_candidate2;
+   bool emit_frame_chain = frame.emit_frame_chain;
+@@ -10362,8 +10362,8 @@ aarch64_expand_prologue (void)
+ 			     - frame.hard_fp_offset);
+   gcc_assert (known_ge (chain_offset, 0));
+ 
+-  /* The offset of the bottom of the save area from the current SP.  */
+-  poly_int64 saved_regs_offset = chain_offset - below_hard_fp_saved_regs_size;
++  /* The offset of the current SP from the bottom of the static frame.  */
++  poly_int64 bytes_below_sp = frame_size - initial_adjust - callee_adjust;
+ 
+   if (emit_frame_chain)
+     {
+@@ -10371,7 +10371,7 @@ aarch64_expand_prologue (void)
+ 	{
+ 	  reg1 = R29_REGNUM;
+ 	  reg2 = R30_REGNUM;
+-	  aarch64_save_callee_saves (saved_regs_offset, reg1, reg2,
++	  aarch64_save_callee_saves (bytes_below_sp, reg1, reg2,
+ 				     false, false);
+ 	}
+       else
+@@ -10411,7 +10411,7 @@ aarch64_expand_prologue (void)
+       aarch64_emit_stack_tie (hard_frame_pointer_rtx);
+     }
+ 
+-  aarch64_save_callee_saves (saved_regs_offset, R0_REGNUM, R30_REGNUM,
++  aarch64_save_callee_saves (bytes_below_sp, R0_REGNUM, R30_REGNUM,
+ 			     callee_adjust != 0 || emit_frame_chain,
+ 			     emit_frame_chain);
+   if (maybe_ne (sve_callee_adjust, 0))
+@@ -10421,16 +10421,17 @@ aarch64_expand_prologue (void)
+       aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx,
+ 					      sve_callee_adjust,
+ 					      !frame_pointer_needed, false);
+-      saved_regs_offset += sve_callee_adjust;
++      bytes_below_sp -= sve_callee_adjust;
+     }
+-  aarch64_save_callee_saves (saved_regs_offset, P0_REGNUM, P15_REGNUM,
++  aarch64_save_callee_saves (bytes_below_sp, P0_REGNUM, P15_REGNUM,
+ 			     false, emit_frame_chain);
+-  aarch64_save_callee_saves (saved_regs_offset, V0_REGNUM, V31_REGNUM,
++  aarch64_save_callee_saves (bytes_below_sp, V0_REGNUM, V31_REGNUM,
+ 			     callee_adjust != 0 || emit_frame_chain,
+ 			     emit_frame_chain);
+ 
+   /* We may need to probe the final adjustment if it is larger than the guard
+      that is assumed by the called.  */
++  gcc_assert (known_eq (bytes_below_sp, final_adjust));
+   aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx, final_adjust,
+ 					  !frame_pointer_needed, true);
+ }
+@@ -10465,7 +10466,6 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+   poly_int64 initial_adjust = frame.initial_adjust;
+   HOST_WIDE_INT callee_adjust = frame.callee_adjust;
+   poly_int64 final_adjust = frame.final_adjust;
+-  poly_int64 callee_offset = frame.callee_offset;
+   poly_int64 sve_callee_adjust = frame.sve_callee_adjust;
+   poly_int64 bytes_below_hard_fp = frame.bytes_below_hard_fp;
+   unsigned reg1 = frame.wb_pop_candidate1;
+@@ -10535,9 +10535,9 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ 
+   /* Restore the vector registers before the predicate registers,
+      so that we can use P4 as a temporary for big-endian SVE frames.  */
+-  aarch64_restore_callee_saves (callee_offset, V0_REGNUM, V31_REGNUM,
++  aarch64_restore_callee_saves (final_adjust, V0_REGNUM, V31_REGNUM,
+ 				callee_adjust != 0, &cfi_ops);
+-  aarch64_restore_callee_saves (callee_offset, P0_REGNUM, P15_REGNUM,
++  aarch64_restore_callee_saves (final_adjust, P0_REGNUM, P15_REGNUM,
+ 				false, &cfi_ops);
+   if (maybe_ne (sve_callee_adjust, 0))
+     aarch64_add_sp (NULL_RTX, NULL_RTX, sve_callee_adjust, true);
+@@ -10545,7 +10545,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+   /* When shadow call stack is enabled, the scs_pop in the epilogue will
+      restore x30, we don't need to restore x30 again in the traditional
+      way.  */
+-  aarch64_restore_callee_saves (callee_offset - sve_callee_adjust,
++  aarch64_restore_callee_saves (final_adjust + sve_callee_adjust,
+ 				R0_REGNUM, last_gpr,
+ 				callee_adjust != 0, &cfi_ops);
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index dedc5b32f..a1db4f689 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -837,10 +837,6 @@ struct GTY (()) aarch64_frame
+      It is zero when no push is used.  */
+   HOST_WIDE_INT callee_adjust;
+ 
+-  /* The offset from SP to the callee-save registers after initial_adjust.
+-     It may be non-zero if no push is used (ie. callee_adjust == 0).  */
+-  poly_int64 callee_offset;
+-
+   /* The size of the stack adjustment before saving or after restoring
+      SVE registers.  */
+   poly_int64 sve_callee_adjust;
+-- 
+2.33.0
+
diff --git a/0189-Backport-SME-aarch64-Only-calculate-chain_offset-if-.patch b/0189-Backport-SME-aarch64-Only-calculate-chain_offset-if-.patch
new file mode 100644
index 0000000..267b3ab
--- /dev/null
+++ b/0189-Backport-SME-aarch64-Only-calculate-chain_offset-if-.patch
@@ -0,0 +1,47 @@
+From c8768dd861538817db8c1955dcce4b6d8ce17c48 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:07 +0100
+Subject: [PATCH 090/157] [Backport][SME] aarch64: Only calculate chain_offset
+ if there is a chain
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=aa8b57ee0206e8e5ac7078692ee67fb6ead05645
+
+After previous patches, it is no longer necessary to calculate
+a chain_offset in cases where there is no chain record.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_expand_prologue): Move the
+	calculation of chain_offset into the emit_frame_chain block.
+---
+ gcc/config/aarch64/aarch64.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index a0a4c7ac3..bef6a658b 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -10357,16 +10357,16 @@ aarch64_expand_prologue (void)
+   if (callee_adjust != 0)
+     aarch64_push_regs (reg1, reg2, callee_adjust);
+ 
+-  /* The offset of the frame chain record (if any) from the current SP.  */
+-  poly_int64 chain_offset = (initial_adjust + callee_adjust
+-			     - frame.hard_fp_offset);
+-  gcc_assert (known_ge (chain_offset, 0));
+-
+   /* The offset of the current SP from the bottom of the static frame.  */
+   poly_int64 bytes_below_sp = frame_size - initial_adjust - callee_adjust;
+ 
+   if (emit_frame_chain)
+     {
++      /* The offset of the frame chain record (if any) from the current SP.  */
++      poly_int64 chain_offset = (initial_adjust + callee_adjust
++				 - frame.hard_fp_offset);
++      gcc_assert (known_ge (chain_offset, 0));
++
+       if (callee_adjust == 0)
+ 	{
+ 	  reg1 = R29_REGNUM;
+-- 
+2.33.0
+
diff --git a/0190-Backport-SME-aarch64-Rename-locals_offset-to-bytes_a.patch b/0190-Backport-SME-aarch64-Rename-locals_offset-to-bytes_a.patch
new file mode 100644
index 0000000..8b44c65
--- /dev/null
+++ b/0190-Backport-SME-aarch64-Rename-locals_offset-to-bytes_a.patch
@@ -0,0 +1,94 @@
+From 43dc03de6d608e10d83cc7994d127e3764bfbcf7 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:07 +0100
+Subject: [PATCH 091/157] [Backport][SME] aarch64: Rename locals_offset to
+ bytes_above_locals
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=28034dbb5e32711d5f4d655576f2499e6f57f854
+
+locals_offset was described as:
+
+  /* Offset from the base of the frame (incomming SP) to the
+     top of the locals area.  This value is always a multiple of
+     STACK_BOUNDARY.  */
+
+This is implicitly an “upside down” view of the frame: the incoming
+SP is at offset 0, and anything N bytes below the incoming SP is at
+offset N (rather than -N).
+
+However, reg_offset instead uses a “right way up” view; that is,
+it views offsets in address terms.  Something above X is at a
+positive offset from X and something below X is at a negative
+offset from X.
+
+Also, even on FRAME_GROWS_DOWNWARD targets like AArch64,
+target-independent code views offsets in address terms too:
+locals are allocated at negative offsets to virtual_stack_vars.
+
+It seems confusing to have *_offset fields of the same structure
+using different polarities like this.  This patch tries to avoid
+that by renaming locals_offset to bytes_above_locals.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::locals_offset): Rename to...
+	(aarch64_frame::bytes_above_locals): ...this.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame)
+	(aarch64_initial_elimination_offset): Update accordingly.
+---
+ gcc/config/aarch64/aarch64.cc | 6 +++---
+ gcc/config/aarch64/aarch64.h  | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index bef6a658b..992f71bbd 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8937,7 +8937,7 @@ aarch64_layout_frame (void)
+ 			  STACK_BOUNDARY / BITS_PER_UNIT));
+   frame.frame_size = saved_regs_and_above + frame.bytes_below_saved_regs;
+ 
+-  frame.locals_offset = frame.saved_varargs_size;
++  frame.bytes_above_locals = frame.saved_varargs_size;
+ 
+   frame.initial_adjust = 0;
+   frame.final_adjust = 0;
+@@ -13047,13 +13047,13 @@ aarch64_initial_elimination_offset (unsigned from, unsigned to)
+ 	return frame.hard_fp_offset;
+ 
+       if (from == FRAME_POINTER_REGNUM)
+-	return frame.hard_fp_offset - frame.locals_offset;
++	return frame.hard_fp_offset - frame.bytes_above_locals;
+     }
+ 
+   if (to == STACK_POINTER_REGNUM)
+     {
+       if (from == FRAME_POINTER_REGNUM)
+-	return frame.frame_size - frame.locals_offset;
++	return frame.frame_size - frame.bytes_above_locals;
+     }
+ 
+   return frame.frame_size;
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index a1db4f689..2acff9a96 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -815,10 +815,10 @@ struct GTY (()) aarch64_frame
+      always a multiple of STACK_BOUNDARY.  */
+   poly_int64 bytes_below_hard_fp;
+ 
+-  /* Offset from the base of the frame (incomming SP) to the
+-     top of the locals area.  This value is always a multiple of
++  /* The number of bytes between the top of the locals area and the top
++     of the frame (the incomming SP).  This value is always a multiple of
+      STACK_BOUNDARY.  */
+-  poly_int64 locals_offset;
++  poly_int64 bytes_above_locals;
+ 
+   /* Offset from the base of the frame (incomming SP) to the
+      hard_frame_pointer.  This value is always a multiple of
+-- 
+2.33.0
+
diff --git a/0191-Backport-SME-aarch64-Rename-hard_fp_offset-to-bytes_.patch b/0191-Backport-SME-aarch64-Rename-hard_fp_offset-to-bytes_.patch
new file mode 100644
index 0000000..b02958e
--- /dev/null
+++ b/0191-Backport-SME-aarch64-Rename-hard_fp_offset-to-bytes_.patch
@@ -0,0 +1,151 @@
+From e33aa6e25334fd94e1e4f2d8b6c8247029657a54 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:08 +0100
+Subject: [PATCH 092/157] [Backport][SME] aarch64: Rename hard_fp_offset to
+ bytes_above_hard_fp
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ed61c87f044f5460109c197855b316641db3c6c6
+
+Similarly to the previous locals_offset patch, hard_fp_offset
+was described as:
+
+  /* Offset from the base of the frame (incomming SP) to the
+     hard_frame_pointer.  This value is always a multiple of
+     STACK_BOUNDARY.  */
+  poly_int64 hard_fp_offset;
+
+which again took an “upside-down” view: higher offsets meant lower
+addresses.  This patch renames the field to bytes_above_hard_fp instead.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::hard_fp_offset): Rename
+	to...
+	(aarch64_frame::bytes_above_hard_fp): ...this.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame)
+	(aarch64_expand_prologue): Update accordingly.
+	(aarch64_initial_elimination_offset): Likewise.
+---
+ gcc/config/aarch64/aarch64.cc | 26 +++++++++++++-------------
+ gcc/config/aarch64/aarch64.h  |  6 +++---
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 992f71bbd..67199a026 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8929,7 +8929,7 @@ aarch64_layout_frame (void)
+ 			   + get_frame_size (),
+ 			   STACK_BOUNDARY / BITS_PER_UNIT);
+ 
+-  frame.hard_fp_offset
++  frame.bytes_above_hard_fp
+     = saved_regs_and_above - frame.below_hard_fp_saved_regs_size;
+ 
+   /* Both these values are already aligned.  */
+@@ -8978,13 +8978,13 @@ aarch64_layout_frame (void)
+   else if (frame.wb_pop_candidate1 != INVALID_REGNUM)
+     max_push_offset = 256;
+ 
+-  HOST_WIDE_INT const_size, const_below_saved_regs, const_fp_offset;
++  HOST_WIDE_INT const_size, const_below_saved_regs, const_above_fp;
+   HOST_WIDE_INT const_saved_regs_size;
+   if (known_eq (frame.saved_regs_size, 0))
+     frame.initial_adjust = frame.frame_size;
+   else if (frame.frame_size.is_constant (&const_size)
+ 	   && const_size < max_push_offset
+-	   && known_eq (frame.hard_fp_offset, const_size))
++	   && known_eq (frame.bytes_above_hard_fp, const_size))
+     {
+       /* Simple, small frame with no data below the saved registers.
+ 
+@@ -9001,8 +9001,8 @@ aarch64_layout_frame (void)
+ 	      case that it hardly seems worth the effort though.  */
+ 	   && (!saves_below_hard_fp_p || const_below_saved_regs == 0)
+ 	   && !(cfun->calls_alloca
+-		&& frame.hard_fp_offset.is_constant (&const_fp_offset)
+-		&& const_fp_offset < max_push_offset))
++		&& frame.bytes_above_hard_fp.is_constant (&const_above_fp)
++		&& const_above_fp < max_push_offset))
+     {
+       /* Frame with small area below the saved registers:
+ 
+@@ -9020,12 +9020,12 @@ aarch64_layout_frame (void)
+ 	 sub sp, sp, hard_fp_offset + below_hard_fp_saved_regs_size
+ 	 save SVE registers relative to SP
+ 	 sub sp, sp, bytes_below_saved_regs  */
+-      frame.initial_adjust = (frame.hard_fp_offset
++      frame.initial_adjust = (frame.bytes_above_hard_fp
+ 			      + frame.below_hard_fp_saved_regs_size);
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+-  else if (frame.hard_fp_offset.is_constant (&const_fp_offset)
+-	   && const_fp_offset < max_push_offset)
++  else if (frame.bytes_above_hard_fp.is_constant (&const_above_fp)
++	   && const_above_fp < max_push_offset)
+     {
+       /* Frame with large area below the saved registers, or with SVE saves,
+ 	 but with a small area above:
+@@ -9035,7 +9035,7 @@ aarch64_layout_frame (void)
+ 	 [sub sp, sp, below_hard_fp_saved_regs_size]
+ 	 [save SVE registers relative to SP]
+ 	 sub sp, sp, bytes_below_saved_regs  */
+-      frame.callee_adjust = const_fp_offset;
++      frame.callee_adjust = const_above_fp;
+       frame.sve_callee_adjust = frame.below_hard_fp_saved_regs_size;
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+@@ -9050,7 +9050,7 @@ aarch64_layout_frame (void)
+ 	 [sub sp, sp, below_hard_fp_saved_regs_size]
+ 	 [save SVE registers relative to SP]
+ 	 sub sp, sp, bytes_below_saved_regs  */
+-      frame.initial_adjust = frame.hard_fp_offset;
++      frame.initial_adjust = frame.bytes_above_hard_fp;
+       frame.sve_callee_adjust = frame.below_hard_fp_saved_regs_size;
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+@@ -10364,7 +10364,7 @@ aarch64_expand_prologue (void)
+     {
+       /* The offset of the frame chain record (if any) from the current SP.  */
+       poly_int64 chain_offset = (initial_adjust + callee_adjust
+-				 - frame.hard_fp_offset);
++				 - frame.bytes_above_hard_fp);
+       gcc_assert (known_ge (chain_offset, 0));
+ 
+       if (callee_adjust == 0)
+@@ -13044,10 +13044,10 @@ aarch64_initial_elimination_offset (unsigned from, unsigned to)
+   if (to == HARD_FRAME_POINTER_REGNUM)
+     {
+       if (from == ARG_POINTER_REGNUM)
+-	return frame.hard_fp_offset;
++	return frame.bytes_above_hard_fp;
+ 
+       if (from == FRAME_POINTER_REGNUM)
+-	return frame.hard_fp_offset - frame.bytes_above_locals;
++	return frame.bytes_above_hard_fp - frame.bytes_above_locals;
+     }
+ 
+   if (to == STACK_POINTER_REGNUM)
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 2acff9a96..0f7822c3d 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -820,10 +820,10 @@ struct GTY (()) aarch64_frame
+      STACK_BOUNDARY.  */
+   poly_int64 bytes_above_locals;
+ 
+-  /* Offset from the base of the frame (incomming SP) to the
+-     hard_frame_pointer.  This value is always a multiple of
++  /* The number of bytes between the hard_frame_pointer and the top of
++     the frame (the incomming SP).  This value is always a multiple of
+      STACK_BOUNDARY.  */
+-  poly_int64 hard_fp_offset;
++  poly_int64 bytes_above_hard_fp;
+ 
+   /* The size of the frame.  This value is the offset from base of the
+      frame (incomming SP) to the stack_pointer.  This value is always
+-- 
+2.33.0
+
diff --git a/0192-Backport-SME-aarch64-Tweak-frame_size-comment.patch b/0192-Backport-SME-aarch64-Tweak-frame_size-comment.patch
new file mode 100644
index 0000000..def17bb
--- /dev/null
+++ b/0192-Backport-SME-aarch64-Tweak-frame_size-comment.patch
@@ -0,0 +1,37 @@
+From 6aa0db727b6e3a7fed95b014f25f3f022d1f46e2 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:08 +0100
+Subject: [PATCH 093/157] [Backport][SME] aarch64: Tweak frame_size comment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=492b60670e69b0a7f11345b69a3c922c20d5d8c3
+
+This patch fixes another case in which a value was described with
+an “upside-down” view.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::frame_size): Tweak comment.
+---
+ gcc/config/aarch64/aarch64.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 0f7822c3d..39abca051 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -825,8 +825,8 @@ struct GTY (()) aarch64_frame
+      STACK_BOUNDARY.  */
+   poly_int64 bytes_above_hard_fp;
+ 
+-  /* The size of the frame.  This value is the offset from base of the
+-     frame (incomming SP) to the stack_pointer.  This value is always
++  /* The size of the frame, i.e. the number of bytes between the bottom
++     of the outgoing arguments and the incoming SP.  This value is always
+      a multiple of STACK_BOUNDARY.  */
+   poly_int64 frame_size;
+ 
+-- 
+2.33.0
+
diff --git a/0193-Backport-SME-aarch64-Measure-reg_offset-from-the-bot.patch b/0193-Backport-SME-aarch64-Measure-reg_offset-from-the-bot.patch
new file mode 100644
index 0000000..c036731
--- /dev/null
+++ b/0193-Backport-SME-aarch64-Measure-reg_offset-from-the-bot.patch
@@ -0,0 +1,198 @@
+From 3b10711c6a5610bf8e2287b9491557268ee148da Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:09 +0100
+Subject: [PATCH 094/157] [Backport][SME] aarch64: Measure reg_offset from the
+ bottom of the frame
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=67a36b6f5d6be11d280081b461e72910aca2fc54
+
+reg_offset was measured from the bottom of the saved register area.
+This made perfect sense with the original layout, since the bottom
+of the saved register area was also the hard frame pointer address.
+It became slightly less obvious with SVE, since we save SVE
+registers below the hard frame pointer, but it still made sense.
+
+However, if we want to allow different frame layouts, it's more
+convenient and obvious to measure reg_offset from the bottom of
+the frame.  After previous patches, it's also a slight simplification
+in its own right.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame): Add comment above
+	reg_offset.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Walk offsets
+	from the bottom of the frame, rather than the bottom of the saved
+	register area.  Measure reg_offset from the bottom of the frame
+	rather than the bottom of the saved register area.
+	(aarch64_save_callee_saves): Update accordingly.
+	(aarch64_restore_callee_saves): Likewise.
+	(aarch64_get_separate_components): Likewise.
+	(aarch64_process_components): Likewise.
+---
+ gcc/config/aarch64/aarch64.cc | 53 ++++++++++++++++-------------------
+ gcc/config/aarch64/aarch64.h  |  3 ++
+ 2 files changed, 27 insertions(+), 29 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 67199a026..df8a83b04 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8739,7 +8739,6 @@ aarch64_needs_frame_chain (void)
+ static void
+ aarch64_layout_frame (void)
+ {
+-  poly_int64 offset = 0;
+   int regno, last_fp_reg = INVALID_REGNUM;
+   machine_mode vector_save_mode = aarch64_reg_save_mode (V8_REGNUM);
+   poly_int64 vector_save_size = GET_MODE_SIZE (vector_save_mode);
+@@ -8817,7 +8816,9 @@ aarch64_layout_frame (void)
+   gcc_assert (crtl->is_leaf
+ 	      || maybe_ne (frame.reg_offset[R30_REGNUM], SLOT_NOT_REQUIRED));
+ 
+-  frame.bytes_below_saved_regs = crtl->outgoing_args_size;
++  poly_int64 offset = crtl->outgoing_args_size;
++  gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT));
++  frame.bytes_below_saved_regs = offset;
+ 
+   /* Now assign stack slots for the registers.  Start with the predicate
+      registers, since predicate LDR and STR have a relatively small
+@@ -8829,7 +8830,8 @@ aarch64_layout_frame (void)
+ 	offset += BYTES_PER_SVE_PRED;
+       }
+ 
+-  if (maybe_ne (offset, 0))
++  poly_int64 saved_prs_size = offset - frame.bytes_below_saved_regs;
++  if (maybe_ne (saved_prs_size, 0))
+     {
+       /* If we have any vector registers to save above the predicate registers,
+ 	 the offset of the vector register save slots need to be a multiple
+@@ -8847,10 +8849,10 @@ aarch64_layout_frame (void)
+ 	offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+       else
+ 	{
+-	  if (known_le (offset, vector_save_size))
+-	    offset = vector_save_size;
+-	  else if (known_le (offset, vector_save_size * 2))
+-	    offset = vector_save_size * 2;
++	  if (known_le (saved_prs_size, vector_save_size))
++	    offset = frame.bytes_below_saved_regs + vector_save_size;
++	  else if (known_le (saved_prs_size, vector_save_size * 2))
++	    offset = frame.bytes_below_saved_regs + vector_save_size * 2;
+ 	  else
+ 	    gcc_unreachable ();
+ 	}
+@@ -8867,9 +8869,10 @@ aarch64_layout_frame (void)
+ 
+   /* OFFSET is now the offset of the hard frame pointer from the bottom
+      of the callee save area.  */
+-  bool saves_below_hard_fp_p = maybe_ne (offset, 0);
+-  frame.below_hard_fp_saved_regs_size = offset;
+-  frame.bytes_below_hard_fp = offset + frame.bytes_below_saved_regs;
++  frame.below_hard_fp_saved_regs_size = offset - frame.bytes_below_saved_regs;
++  bool saves_below_hard_fp_p
++    = maybe_ne (frame.below_hard_fp_saved_regs_size, 0);
++  frame.bytes_below_hard_fp = offset;
+   if (frame.emit_frame_chain)
+     {
+       /* FP and LR are placed in the linkage record.  */
+@@ -8920,9 +8923,10 @@ aarch64_layout_frame (void)
+ 
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+ 
+-  frame.saved_regs_size = offset;
++  frame.saved_regs_size = offset - frame.bytes_below_saved_regs;
+ 
+-  poly_int64 varargs_and_saved_regs_size = offset + frame.saved_varargs_size;
++  poly_int64 varargs_and_saved_regs_size
++    = frame.saved_regs_size + frame.saved_varargs_size;
+ 
+   poly_int64 saved_regs_and_above
+     = aligned_upper_bound (varargs_and_saved_regs_size
+@@ -9390,9 +9394,7 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       reg = gen_rtx_REG (mode, regno);
+-      offset = (frame.reg_offset[regno]
+-		+ frame.bytes_below_saved_regs
+-		- bytes_below_sp);
++      offset = frame.reg_offset[regno] - bytes_below_sp;
+       rtx base_rtx = stack_pointer_rtx;
+       poly_int64 sp_offset = offset;
+ 
+@@ -9499,9 +9501,7 @@ aarch64_restore_callee_saves (poly_int64 bytes_below_sp, unsigned start,
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       reg = gen_rtx_REG (mode, regno);
+-      offset = (frame.reg_offset[regno]
+-		+ frame.bytes_below_saved_regs
+-		- bytes_below_sp);
++      offset = frame.reg_offset[regno] - bytes_below_sp;
+       rtx base_rtx = stack_pointer_rtx;
+       if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg,
+@@ -9640,14 +9640,12 @@ aarch64_get_separate_components (void)
+ 	   it as a stack probe for -fstack-clash-protection.  */
+ 	if (flag_stack_clash_protection
+ 	    && maybe_ne (frame.below_hard_fp_saved_regs_size, 0)
+-	    && known_eq (offset, 0))
++	    && known_eq (offset, frame.bytes_below_saved_regs))
+ 	  continue;
+ 
+ 	/* Get the offset relative to the register we'll use.  */
+ 	if (frame_pointer_needed)
+-	  offset -= frame.below_hard_fp_saved_regs_size;
+-	else
+-	  offset += frame.bytes_below_saved_regs;
++	  offset -= frame.bytes_below_hard_fp;
+ 
+ 	/* Check that we can access the stack slot of the register with one
+ 	   direct load with no adjustments needed.  */
+@@ -9794,9 +9792,7 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+       rtx reg = gen_rtx_REG (mode, regno);
+       poly_int64 offset = frame.reg_offset[regno];
+       if (frame_pointer_needed)
+-	offset -= frame.below_hard_fp_saved_regs_size;
+-      else
+-	offset += frame.bytes_below_saved_regs;
++	offset -= frame.bytes_below_hard_fp;
+ 
+       rtx addr = plus_constant (Pmode, ptr_reg, offset);
+       rtx mem = gen_frame_mem (mode, addr);
+@@ -9848,9 +9844,7 @@ aarch64_process_components (sbitmap components, bool prologue_p)
+       /* REGNO2 can be saved/restored in a pair with REGNO.  */
+       rtx reg2 = gen_rtx_REG (mode, regno2);
+       if (frame_pointer_needed)
+-	offset2 -= frame.below_hard_fp_saved_regs_size;
+-      else
+-	offset2 += frame.bytes_below_saved_regs;
++	offset2 -= frame.bytes_below_hard_fp;
+       rtx addr2 = plus_constant (Pmode, ptr_reg, offset2);
+       rtx mem2 = gen_frame_mem (mode, addr2);
+       rtx set2 = prologue_p ? gen_rtx_SET (mem2, reg2)
+@@ -9976,7 +9970,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+   if (final_adjustment_p
+       && known_eq (frame.below_hard_fp_saved_regs_size, 0))
+     {
+-      poly_int64 lr_offset = frame.reg_offset[LR_REGNUM];
++      poly_int64 lr_offset = (frame.reg_offset[LR_REGNUM]
++			      - frame.bytes_below_saved_regs);
+       if (known_ge (lr_offset, 0))
+ 	min_probe_threshold -= lr_offset.to_constant ();
+       else
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 39abca051..f340237d0 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -790,6 +790,9 @@ extern enum aarch64_processor aarch64_tune;
+ #ifdef HAVE_POLY_INT_H
+ struct GTY (()) aarch64_frame
+ {
++  /* The offset from the bottom of the static frame (the bottom of the
++     outgoing arguments) of each register save slot, or -2 if no save is
++     needed.  */
+   poly_int64 reg_offset[LAST_SAVED_REGNUM + 1];
+ 
+   /* The number of extra stack bytes taken up by register varargs.
+-- 
+2.33.0
+
diff --git a/0194-Backport-SME-aarch64-Simplify-top-of-frame-allocatio.patch b/0194-Backport-SME-aarch64-Simplify-top-of-frame-allocatio.patch
new file mode 100644
index 0000000..f671841
--- /dev/null
+++ b/0194-Backport-SME-aarch64-Simplify-top-of-frame-allocatio.patch
@@ -0,0 +1,58 @@
+From 4b8f3f194e68d0d411eaa6692699d8e5e2b4217d Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:09 +0100
+Subject: [PATCH 095/157] [Backport][SME] aarch64: Simplify top of frame
+ allocation
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=bc9dcdde80915d7585a21daa2b69f4adf4a1e3c1
+
+After previous patches, it no longer really makes sense to allocate
+the top of the frame in terms of varargs_and_saved_regs_size and
+saved_regs_and_above.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Simplify
+	the allocation of the top of the frame.
+---
+ gcc/config/aarch64/aarch64.cc | 23 ++++++++---------------
+ 1 file changed, 8 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index df8a83b04..3329aa364 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8925,23 +8925,16 @@ aarch64_layout_frame (void)
+ 
+   frame.saved_regs_size = offset - frame.bytes_below_saved_regs;
+ 
+-  poly_int64 varargs_and_saved_regs_size
+-    = frame.saved_regs_size + frame.saved_varargs_size;
+-
+-  poly_int64 saved_regs_and_above
+-    = aligned_upper_bound (varargs_and_saved_regs_size
+-			   + get_frame_size (),
+-			   STACK_BOUNDARY / BITS_PER_UNIT);
+-
+-  frame.bytes_above_hard_fp
+-    = saved_regs_and_above - frame.below_hard_fp_saved_regs_size;
++  offset += get_frame_size ();
++  offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
++  auto top_of_locals = offset;
+ 
+-  /* Both these values are already aligned.  */
+-  gcc_assert (multiple_p (frame.bytes_below_saved_regs,
+-			  STACK_BOUNDARY / BITS_PER_UNIT));
+-  frame.frame_size = saved_regs_and_above + frame.bytes_below_saved_regs;
++  offset += frame.saved_varargs_size;
++  gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT));
++  frame.frame_size = offset;
+ 
+-  frame.bytes_above_locals = frame.saved_varargs_size;
++  frame.bytes_above_hard_fp = frame.frame_size - frame.bytes_below_hard_fp;
++  frame.bytes_above_locals = frame.frame_size - top_of_locals;
+ 
+   frame.initial_adjust = 0;
+   frame.final_adjust = 0;
+-- 
+2.33.0
+
diff --git a/0195-Backport-SME-aarch64-Minor-initial-adjustment-tweak.patch b/0195-Backport-SME-aarch64-Minor-initial-adjustment-tweak.patch
new file mode 100644
index 0000000..d962cb9
--- /dev/null
+++ b/0195-Backport-SME-aarch64-Minor-initial-adjustment-tweak.patch
@@ -0,0 +1,41 @@
+From 0ab484f5de7d28c0a7166439d403e0983834b120 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:10 +0100
+Subject: [PATCH 096/157] [Backport][SME] aarch64: Minor initial adjustment
+ tweak
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ee5466ff4faca2076cc61f1f120d0b5062c8111c
+
+This patch just changes a calculation of initial_adjust
+to one that makes it slightly more obvious that the total
+adjustment is frame.frame_size.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Tweak
+	calculation of initial_adjust for frames in which all saves
+	are SVE saves.
+---
+ gcc/config/aarch64/aarch64.cc | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 3329aa364..72604dd9d 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -9014,11 +9014,10 @@ aarch64_layout_frame (void)
+     {
+       /* Frame in which all saves are SVE saves:
+ 
+-	 sub sp, sp, hard_fp_offset + below_hard_fp_saved_regs_size
++	 sub sp, sp, frame_size - bytes_below_saved_regs
+ 	 save SVE registers relative to SP
+ 	 sub sp, sp, bytes_below_saved_regs  */
+-      frame.initial_adjust = (frame.bytes_above_hard_fp
+-			      + frame.below_hard_fp_saved_regs_size);
++      frame.initial_adjust = frame.frame_size - frame.bytes_below_saved_regs;
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+   else if (frame.bytes_above_hard_fp.is_constant (&const_above_fp)
+-- 
+2.33.0
+
diff --git a/0196-Backport-SME-aarch64-Tweak-stack-clash-boundary-cond.patch b/0196-Backport-SME-aarch64-Tweak-stack-clash-boundary-cond.patch
new file mode 100644
index 0000000..6199468
--- /dev/null
+++ b/0196-Backport-SME-aarch64-Tweak-stack-clash-boundary-cond.patch
@@ -0,0 +1,128 @@
+From b4581d1e6a7b94dfbd58871dad51d3f12889081f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:10 +0100
+Subject: [PATCH 097/157] [Backport][SME] aarch64: Tweak stack clash boundary
+ condition
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1785b8077cc03214ebd1db953c870172fcf15966
+
+The AArch64 ABI says that, when stack clash protection is used,
+there can be a maximum of 1KiB of unprobed space at sp on entry
+to a function.  Therefore, we need to probe when allocating
+>= guard_size - 1KiB of data (>= rather than >).  This is what
+GCC does.
+
+If an allocation is exactly guard_size bytes, it is enough to allocate
+those bytes and probe once at offset 1024.  It isn't possible to use a
+single probe at any other offset: higher would conmplicate later code,
+by leaving more unprobed space than usual, while lower would risk
+leaving an entire page unprobed.  For simplicity, the code probes all
+allocations at offset 1024.
+
+Some register saves also act as probes.  If we need to allocate
+more space below the last such register save probe, we need to
+probe the allocation if it is > 1KiB.  Again, this allocation is
+then sometimes (but not always) probed at offset 1024.  This sort of
+allocation is currently only used for outgoing arguments, which are
+rarely this big.
+
+However, the code also probed if this final outgoing-arguments
+allocation was == 1KiB, rather than just > 1KiB.  This isn't
+necessary, since the register save then probes at offset 1024
+as required.  Continuing to probe allocations of exactly 1KiB
+would complicate later patches.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_allocate_and_probe_stack_space):
+	Don't probe final allocations that are exactly 1KiB in size (after
+	unprobed space above the final allocation has been deducted).
+
+gcc/testsuite/
+	* gcc.target/aarch64/stack-check-prologue-17.c: New test.
+---
+ gcc/config/aarch64/aarch64.cc                 |  4 +-
+ .../aarch64/stack-check-prologue-17.c         | 55 +++++++++++++++++++
+ 2 files changed, 58 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 72604dd9d..ba92a23a7 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -9943,9 +9943,11 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+   HOST_WIDE_INT guard_size
+     = 1 << param_stack_clash_protection_guard_size;
+   HOST_WIDE_INT guard_used_by_caller = STACK_CLASH_CALLER_GUARD;
++  HOST_WIDE_INT byte_sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
++  gcc_assert (multiple_p (poly_size, byte_sp_alignment));
+   HOST_WIDE_INT min_probe_threshold
+     = (final_adjustment_p
+-       ? guard_used_by_caller
++       ? guard_used_by_caller + byte_sp_alignment
+        : guard_size - guard_used_by_caller);
+   /* When doing the final adjustment for the outgoing arguments, take into
+      account any unprobed space there is above the current SP.  There are
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c
+new file mode 100644
+index 000000000..0d8a25d73
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c
+@@ -0,0 +1,55 @@
++/* { dg-options "-O2 -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void f(int, ...);
++void g();
++
++/*
++** test1:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #1024
++**	cbnz	w0, .*
++**	bl	g
++**	...
++*/
++int test1(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x);
++    }
++  g();
++  return 1;
++}
++
++/*
++** test2:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #1040
++**	str	xzr, \[sp\]
++**	cbnz	w0, .*
++**	bl	g
++**	...
++*/
++int test2(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x);
++    }
++  g();
++  return 1;
++}
+-- 
+2.33.0
+
diff --git a/0197-Backport-SME-aarch64-Put-LR-save-probe-in-first-16-b.patch b/0197-Backport-SME-aarch64-Put-LR-save-probe-in-first-16-b.patch
new file mode 100644
index 0000000..c848e19
--- /dev/null
+++ b/0197-Backport-SME-aarch64-Put-LR-save-probe-in-first-16-b.patch
@@ -0,0 +1,409 @@
+From ffd483dc6a2a4af495d56cf5ebdbbb3b9ca58820 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:11 +0100
+Subject: [PATCH 098/157] [Backport][SME] aarch64: Put LR save probe in first
+ 16 bytes
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=fee0a18abfdd4874194abd149943fa7c77a29b7c
+
+-fstack-clash-protection uses the save of LR as a probe for the next
+allocation.  The next allocation could be:
+
+* another part of the static frame, e.g. when allocating SVE save slots
+  or outgoing arguments
+
+* an alloca in the same function
+
+* an allocation made by a callee function
+
+However, when -fomit-frame-pointer is used, the LR save slot is placed
+above the other GPR save slots.  It could therefore be up to 80 bytes
+above the base of the GPR save area (which is also the hard fp address).
+
+aarch64_allocate_and_probe_stack_space took this into account when
+deciding how much subsequent space could be allocated without needing
+a probe.  However, it interacted badly with:
+
+      /* If doing a small final adjustment, we always probe at offset 0.
+	 This is done to avoid issues when LR is not at position 0 or when
+	 the final adjustment is smaller than the probing offset.  */
+      else if (final_adjustment_p && rounded_size == 0)
+	residual_probe_offset = 0;
+
+which forces any allocation that is smaller than the guard page size
+to be probed at offset 0 rather than the usual offset 1024.  It was
+therefore possible to construct cases in which we had:
+
+* a probe using LR at SP + 80 bytes (or some other value >= 16)
+* an allocation of the guard page size - 16 bytes
+* a probe at SP + 0
+
+which allocates guard page size + 64 consecutive unprobed bytes.
+
+This patch requires the LR probe to be in the first 16 bytes of the
+save area when stack clash protection is active.  Doing it
+unconditionally would cause code-quality regressions.
+
+Putting LR before other registers prevents push/pop allocation
+when shadow call stacks are enabled, since LR is restored
+separately from the other callee-saved registers.
+
+The new comment doesn't say that the probe register is required
+to be LR, since a later patch removes that restriction.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Ensure that
+	the LR save slot is in the first 16 bytes of the register save area.
+	Only form STP/LDP push/pop candidates if both registers are valid.
+	(aarch64_allocate_and_probe_stack_space): Remove workaround for
+	when LR was not in the first 16 bytes.
+
+gcc/testsuite/
+	* gcc.target/aarch64/stack-check-prologue-18.c: New test.
+	* gcc.target/aarch64/stack-check-prologue-19.c: Likewise.
+	* gcc.target/aarch64/stack-check-prologue-20.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                 |  72 ++++++-------
+ .../aarch64/stack-check-prologue-18.c         | 100 ++++++++++++++++++
+ .../aarch64/stack-check-prologue-19.c         | 100 ++++++++++++++++++
+ .../aarch64/stack-check-prologue-20.c         |   3 +
+ 4 files changed, 233 insertions(+), 42 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-check-prologue-20.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index ba92a23a7..1ba4c2f89 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8873,26 +8873,34 @@ aarch64_layout_frame (void)
+   bool saves_below_hard_fp_p
+     = maybe_ne (frame.below_hard_fp_saved_regs_size, 0);
+   frame.bytes_below_hard_fp = offset;
++
++  auto allocate_gpr_slot = [&](unsigned int regno)
++    {
++      frame.reg_offset[regno] = offset;
++      if (frame.wb_push_candidate1 == INVALID_REGNUM)
++	frame.wb_push_candidate1 = regno;
++      else if (frame.wb_push_candidate2 == INVALID_REGNUM)
++	frame.wb_push_candidate2 = regno;
++      offset += UNITS_PER_WORD;
++    };
++
+   if (frame.emit_frame_chain)
+     {
+       /* FP and LR are placed in the linkage record.  */
+-      frame.reg_offset[R29_REGNUM] = offset;
+-      frame.wb_push_candidate1 = R29_REGNUM;
+-      frame.reg_offset[R30_REGNUM] = offset + UNITS_PER_WORD;
+-      frame.wb_push_candidate2 = R30_REGNUM;
+-      offset += 2 * UNITS_PER_WORD;
++      allocate_gpr_slot (R29_REGNUM);
++      allocate_gpr_slot (R30_REGNUM);
+     }
++  else if (flag_stack_clash_protection
++	   && known_eq (frame.reg_offset[R30_REGNUM], SLOT_REQUIRED))
++    /* Put the LR save slot first, since it makes a good choice of probe
++       for stack clash purposes.  The idea is that the link register usually
++       has to be saved before a call anyway, and so we lose little by
++       stopping it from being individually shrink-wrapped.  */
++    allocate_gpr_slot (R30_REGNUM);
+ 
+   for (regno = R0_REGNUM; regno <= R30_REGNUM; regno++)
+     if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+-      {
+-	frame.reg_offset[regno] = offset;
+-	if (frame.wb_push_candidate1 == INVALID_REGNUM)
+-	  frame.wb_push_candidate1 = regno;
+-	else if (frame.wb_push_candidate2 == INVALID_REGNUM)
+-	  frame.wb_push_candidate2 = regno;
+-	offset += UNITS_PER_WORD;
+-      }
++      allocate_gpr_slot (regno);
+ 
+   poly_int64 max_int_offset = offset;
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+@@ -8970,10 +8978,13 @@ aarch64_layout_frame (void)
+      max_push_offset to 0, because no registers are popped at this time,
+      so callee_adjust cannot be adjusted.  */
+   HOST_WIDE_INT max_push_offset = 0;
+-  if (frame.wb_pop_candidate2 != INVALID_REGNUM)
+-    max_push_offset = 512;
+-  else if (frame.wb_pop_candidate1 != INVALID_REGNUM)
+-    max_push_offset = 256;
++  if (frame.wb_pop_candidate1 != INVALID_REGNUM)
++    {
++      if (frame.wb_pop_candidate2 != INVALID_REGNUM)
++	max_push_offset = 512;
++      else
++	max_push_offset = 256;
++    }
+ 
+   HOST_WIDE_INT const_size, const_below_saved_regs, const_above_fp;
+   HOST_WIDE_INT const_saved_regs_size;
+@@ -9949,29 +9960,6 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+     = (final_adjustment_p
+        ? guard_used_by_caller + byte_sp_alignment
+        : guard_size - guard_used_by_caller);
+-  /* When doing the final adjustment for the outgoing arguments, take into
+-     account any unprobed space there is above the current SP.  There are
+-     two cases:
+-
+-     - When saving SVE registers below the hard frame pointer, we force
+-       the lowest save to take place in the prologue before doing the final
+-       adjustment (i.e. we don't allow the save to be shrink-wrapped).
+-       This acts as a probe at SP, so there is no unprobed space.
+-
+-     - When there are no SVE register saves, we use the store of the link
+-       register as a probe.  We can't assume that LR was saved at position 0
+-       though, so treat any space below it as unprobed.  */
+-  if (final_adjustment_p
+-      && known_eq (frame.below_hard_fp_saved_regs_size, 0))
+-    {
+-      poly_int64 lr_offset = (frame.reg_offset[LR_REGNUM]
+-			      - frame.bytes_below_saved_regs);
+-      if (known_ge (lr_offset, 0))
+-	min_probe_threshold -= lr_offset.to_constant ();
+-      else
+-	gcc_assert (!flag_stack_clash_protection || known_eq (poly_size, 0));
+-    }
+-
+   poly_int64 frame_size = frame.frame_size;
+ 
+   /* We should always have a positive probe threshold.  */
+@@ -10151,8 +10139,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+       if (final_adjustment_p && rounded_size != 0)
+ 	min_probe_threshold = 0;
+       /* If doing a small final adjustment, we always probe at offset 0.
+-	 This is done to avoid issues when LR is not at position 0 or when
+-	 the final adjustment is smaller than the probing offset.  */
++	 This is done to avoid issues when the final adjustment is smaller
++	 than the probing offset.  */
+       else if (final_adjustment_p && rounded_size == 0)
+ 	residual_probe_offset = 0;
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+new file mode 100644
+index 000000000..82447d20f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+@@ -0,0 +1,100 @@
++/* { dg-options "-O2 -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void f(int, ...);
++void g();
++
++/*
++** test1:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #4064
++**	str	xzr, \[sp\]
++**	cbnz	w0, .*
++**	bl	g
++**	...
++**	str	x26, \[sp, #?4128\]
++**	...
++*/
++int test1(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      asm volatile ("" :::
++		    "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26");
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x);
++    }
++  g();
++  return 1;
++}
++
++/*
++** test2:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #1040
++**	str	xzr, \[sp\]
++**	cbnz	w0, .*
++**	bl	g
++**	...
++*/
++int test2(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      asm volatile ("" :::
++		    "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26");
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x);
++    }
++  g();
++  return 1;
++}
++
++/*
++** test3:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #1024
++**	cbnz	w0, .*
++**	bl	g
++**	...
++*/
++int test3(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      asm volatile ("" :::
++		    "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26");
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x);
++    }
++  g();
++  return 1;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c
+new file mode 100644
+index 000000000..73ac3e4e4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c
+@@ -0,0 +1,100 @@
++/* { dg-options "-O2 -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12 -fsanitize=shadow-call-stack -ffixed-x18" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void f(int, ...);
++void g();
++
++/*
++** test1:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #4064
++**	str	xzr, \[sp\]
++**	cbnz	w0, .*
++**	bl	g
++**	...
++**	str	x26, \[sp, #?4128\]
++**	...
++*/
++int test1(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      asm volatile ("" :::
++		    "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26");
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x);
++    }
++  g();
++  return 1;
++}
++
++/*
++** test2:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #1040
++**	str	xzr, \[sp\]
++**	cbnz	w0, .*
++**	bl	g
++**	...
++*/
++int test2(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      asm volatile ("" :::
++		    "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26");
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x);
++    }
++  g();
++  return 1;
++}
++
++/*
++** test3:
++**	...
++**	str	x30, \[sp\]
++**	sub	sp, sp, #1024
++**	cbnz	w0, .*
++**	bl	g
++**	...
++*/
++int test3(int z) {
++  __uint128_t x = 0;
++  int y[0x400];
++  if (z)
++    {
++      asm volatile ("" :::
++		    "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26");
++      f(0, 0, 0, 0, 0, 0, 0, &y,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
++	x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x);
++    }
++  g();
++  return 1;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-20.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-20.c
+new file mode 100644
+index 000000000..690aae8df
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-20.c
+@@ -0,0 +1,3 @@
++/* { dg-options "-O2 -fstack-protector-all -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12 -fsanitize=shadow-call-stack -ffixed-x18" } */
++
++#include "stack-check-prologue-19.c"
+-- 
+2.33.0
+
diff --git a/0198-Backport-SME-aarch64-Simplify-probe-of-final-frame-a.patch b/0198-Backport-SME-aarch64-Simplify-probe-of-final-frame-a.patch
new file mode 100644
index 0000000..70cd64b
--- /dev/null
+++ b/0198-Backport-SME-aarch64-Simplify-probe-of-final-frame-a.patch
@@ -0,0 +1,126 @@
+From c12de24e57cbe26c224bab39698736fa4004f8ff Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:11 +0100
+Subject: [PATCH 099/157] [Backport][SME] aarch64: Simplify probe of final
+ frame allocation
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f87028a905059573ae7fdfe526d034fd70b3bcae
+
+Previous patches ensured that the final frame allocation only needs
+a probe when the size is strictly greater than 1KiB.  It's therefore
+safe to use the normal 1024 probe offset in all cases.
+
+The main motivation for doing this is to simplify the code and
+remove the number of special cases.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_allocate_and_probe_stack_space):
+	Always probe the residual allocation at offset 1024, asserting
+	that that is in range.
+
+gcc/testsuite/
+	* gcc.target/aarch64/stack-check-prologue-17.c: Expect the probe
+	to be at offset 1024 rather than offset 0.
+	* gcc.target/aarch64/stack-check-prologue-18.c: Likewise.
+	* gcc.target/aarch64/stack-check-prologue-19.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                        | 12 ++++--------
+ .../gcc.target/aarch64/stack-check-prologue-17.c     |  2 +-
+ .../gcc.target/aarch64/stack-check-prologue-18.c     |  4 ++--
+ .../gcc.target/aarch64/stack-check-prologue-19.c     |  4 ++--
+ 4 files changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 1ba4c2f89..6d835dc8f 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -10133,16 +10133,12 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+      are still safe.  */
+   if (residual)
+     {
+-      HOST_WIDE_INT residual_probe_offset = guard_used_by_caller;
++      gcc_assert (guard_used_by_caller + byte_sp_alignment <= size);
++
+       /* If we're doing final adjustments, and we've done any full page
+ 	 allocations then any residual needs to be probed.  */
+       if (final_adjustment_p && rounded_size != 0)
+ 	min_probe_threshold = 0;
+-      /* If doing a small final adjustment, we always probe at offset 0.
+-	 This is done to avoid issues when the final adjustment is smaller
+-	 than the probing offset.  */
+-      else if (final_adjustment_p && rounded_size == 0)
+-	residual_probe_offset = 0;
+ 
+       aarch64_sub_sp (temp1, temp2, residual, frame_related_p);
+       if (residual >= min_probe_threshold)
+@@ -10153,8 +10149,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+ 		     HOST_WIDE_INT_PRINT_DEC " bytes, probing will be required."
+ 		     "\n", residual);
+ 
+-	    emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+-					     residual_probe_offset));
++	  emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
++					   guard_used_by_caller));
+ 	  emit_insn (gen_blockage ());
+ 	}
+     }
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c
+index 0d8a25d73..f0ec13897 100644
+--- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c
+@@ -33,7 +33,7 @@ int test1(int z) {
+ **	...
+ **	str	x30, \[sp\]
+ **	sub	sp, sp, #1040
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+index 82447d20f..6383bec5e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c
+@@ -9,7 +9,7 @@ void g();
+ **	...
+ **	str	x30, \[sp\]
+ **	sub	sp, sp, #4064
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+@@ -50,7 +50,7 @@ int test1(int z) {
+ **	...
+ **	str	x30, \[sp\]
+ **	sub	sp, sp, #1040
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c
+index 73ac3e4e4..562039b5e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c
++++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c
+@@ -9,7 +9,7 @@ void g();
+ **	...
+ **	str	x30, \[sp\]
+ **	sub	sp, sp, #4064
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+@@ -50,7 +50,7 @@ int test1(int z) {
+ **	...
+ **	str	x30, \[sp\]
+ **	sub	sp, sp, #1040
+-**	str	xzr, \[sp\]
++**	str	xzr, \[sp, #?1024\]
+ **	cbnz	w0, .*
+ **	bl	g
+ **	...
+-- 
+2.33.0
+
diff --git a/0199-Backport-SME-aarch64-Explicitly-record-probe-registe.patch b/0199-Backport-SME-aarch64-Explicitly-record-probe-registe.patch
new file mode 100644
index 0000000..6fe7afa
--- /dev/null
+++ b/0199-Backport-SME-aarch64-Explicitly-record-probe-registe.patch
@@ -0,0 +1,280 @@
+From 1bf3e9a04411b483c89d2e2f9096ab66800c3b3f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:12 +0100
+Subject: [PATCH 100/157] [Backport][SME] aarch64: Explicitly record probe
+ registers in frame info
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5ce957484eea15f09503fcffa4dfdfb70ad82f8f
+
+The stack frame is currently divided into three areas:
+
+A: the area above the hard frame pointer
+B: the SVE saves below the hard frame pointer
+C: the outgoing arguments
+
+If the stack frame is allocated in one chunk, the allocation needs a
+probe if the frame size is >= guard_size - 1KiB.  In addition, if the
+function is not a leaf function, it must probe an address no more than
+1KiB above the outgoing SP.  We ensured the second condition by
+
+(1) using single-chunk allocations for non-leaf functions only if
+    the link register save slot is within 512 bytes of the bottom
+    of the frame; and
+
+(2) using the link register save as a probe (meaning, for instance,
+    that it can't be individually shrink wrapped)
+
+If instead the stack is allocated in multiple chunks, then:
+
+* an allocation involving only the outgoing arguments (C above) requires
+  a probe if the allocation size is > 1KiB
+
+* any other allocation requires a probe if the allocation size
+  is >= guard_size - 1KiB
+
+* second and subsequent allocations require the previous allocation
+  to probe at the bottom of the allocated area, regardless of the size
+  of that previous allocation
+
+The final point means that, unlike for single allocations,
+it can be necessary to have both a non-SVE register probe and
+an SVE register probe.  For example:
+
+* allocate A, probe using a non-SVE register save
+* allocate B, probe using an SVE register save
+* allocate C
+
+The non-SVE register used in this case was again the link register.
+It was previously used even if the link register save slot was some
+bytes above the bottom of the non-SVE register saves, but an earlier
+patch avoided that by putting the link register save slot first.
+
+As a belt-and-braces fix, this patch explicitly records which
+probe registers we're using and allows the non-SVE probe to be
+whichever register comes first (as for SVE).
+
+The patch also avoids unnecessary probes in sve/pcs/stack_clash_3.c.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::sve_save_and_probe)
+	(aarch64_frame::hard_fp_save_and_probe): New fields.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Initialize them.
+	Rather than asserting that a leaf function saves LR, instead assert
+	that a leaf function saves something.
+	(aarch64_get_separate_components): Prevent the chosen probe
+	registers from being individually shrink-wrapped.
+	(aarch64_allocate_and_probe_stack_space): Remove workaround for
+	probe registers that aren't at the bottom of the previous allocation.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/pcs/stack_clash_3.c: Avoid redundant probes.
+---
+ gcc/config/aarch64/aarch64.cc                 | 68 +++++++++++++++----
+ gcc/config/aarch64/aarch64.h                  |  8 +++
+ .../aarch64/sve/pcs/stack_clash_3.c           |  6 +-
+ 3 files changed, 64 insertions(+), 18 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 6d835dc8f..dd80ceba8 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8810,15 +8810,11 @@ aarch64_layout_frame (void)
+ 	&& !crtl->abi->clobbers_full_reg_p (regno))
+       frame.reg_offset[regno] = SLOT_REQUIRED;
+ 
+-  /* With stack-clash, LR must be saved in non-leaf functions.  The saving of
+-     LR counts as an implicit probe which allows us to maintain the invariant
+-     described in the comment at expand_prologue.  */
+-  gcc_assert (crtl->is_leaf
+-	      || maybe_ne (frame.reg_offset[R30_REGNUM], SLOT_NOT_REQUIRED));
+ 
+   poly_int64 offset = crtl->outgoing_args_size;
+   gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT));
+   frame.bytes_below_saved_regs = offset;
++  frame.sve_save_and_probe = INVALID_REGNUM;
+ 
+   /* Now assign stack slots for the registers.  Start with the predicate
+      registers, since predicate LDR and STR have a relatively small
+@@ -8826,6 +8822,8 @@ aarch64_layout_frame (void)
+   for (regno = P0_REGNUM; regno <= P15_REGNUM; regno++)
+     if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+       {
++	if (frame.sve_save_and_probe == INVALID_REGNUM)
++	  frame.sve_save_and_probe = regno;
+ 	frame.reg_offset[regno] = offset;
+ 	offset += BYTES_PER_SVE_PRED;
+       }
+@@ -8863,6 +8861,8 @@ aarch64_layout_frame (void)
+     for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
+       if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+ 	{
++	  if (frame.sve_save_and_probe == INVALID_REGNUM)
++	    frame.sve_save_and_probe = regno;
+ 	  frame.reg_offset[regno] = offset;
+ 	  offset += vector_save_size;
+ 	}
+@@ -8872,10 +8872,18 @@ aarch64_layout_frame (void)
+   frame.below_hard_fp_saved_regs_size = offset - frame.bytes_below_saved_regs;
+   bool saves_below_hard_fp_p
+     = maybe_ne (frame.below_hard_fp_saved_regs_size, 0);
++  gcc_assert (!saves_below_hard_fp_p
++	      || (frame.sve_save_and_probe != INVALID_REGNUM
++		  && known_eq (frame.reg_offset[frame.sve_save_and_probe],
++			       frame.bytes_below_saved_regs)));
++
+   frame.bytes_below_hard_fp = offset;
++  frame.hard_fp_save_and_probe = INVALID_REGNUM;
+ 
+   auto allocate_gpr_slot = [&](unsigned int regno)
+     {
++      if (frame.hard_fp_save_and_probe == INVALID_REGNUM)
++	frame.hard_fp_save_and_probe = regno;
+       frame.reg_offset[regno] = offset;
+       if (frame.wb_push_candidate1 == INVALID_REGNUM)
+ 	frame.wb_push_candidate1 = regno;
+@@ -8909,6 +8917,8 @@ aarch64_layout_frame (void)
+   for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
+     if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+       {
++	if (frame.hard_fp_save_and_probe == INVALID_REGNUM)
++	  frame.hard_fp_save_and_probe = regno;
+ 	/* If there is an alignment gap between integer and fp callee-saves,
+ 	   allocate the last fp register to it if possible.  */
+ 	if (regno == last_fp_reg
+@@ -8932,6 +8942,17 @@ aarch64_layout_frame (void)
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+ 
+   frame.saved_regs_size = offset - frame.bytes_below_saved_regs;
++  gcc_assert (known_eq (frame.saved_regs_size,
++			frame.below_hard_fp_saved_regs_size)
++	      || (frame.hard_fp_save_and_probe != INVALID_REGNUM
++		  && known_eq (frame.reg_offset[frame.hard_fp_save_and_probe],
++			       frame.bytes_below_hard_fp)));
++
++  /* With stack-clash, a register must be saved in non-leaf functions.
++     The saving of the bottommost register counts as an implicit probe,
++     which allows us to maintain the invariant described in the comment
++     at expand_prologue.  */
++  gcc_assert (crtl->is_leaf || maybe_ne (frame.saved_regs_size, 0));
+ 
+   offset += get_frame_size ();
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+@@ -9062,6 +9083,25 @@ aarch64_layout_frame (void)
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+ 
++  /* The frame is allocated in pieces, with each non-final piece
++     including a register save at offset 0 that acts as a probe for
++     the following piece.  In addition, the save of the bottommost register
++     acts as a probe for callees and allocas.  Roll back any probes that
++     aren't needed.
++
++     A probe isn't needed if it is associated with the final allocation
++     (including callees and allocas) that happens before the epilogue is
++     executed.  */
++  if (crtl->is_leaf
++      && !cfun->calls_alloca
++      && known_eq (frame.final_adjust, 0))
++    {
++      if (maybe_ne (frame.sve_callee_adjust, 0))
++	frame.sve_save_and_probe = INVALID_REGNUM;
++      else
++	frame.hard_fp_save_and_probe = INVALID_REGNUM;
++    }
++
+   /* Make sure the individual adjustments add up to the full frame size.  */
+   gcc_assert (known_eq (frame.initial_adjust
+ 			+ frame.callee_adjust
+@@ -9639,13 +9679,6 @@ aarch64_get_separate_components (void)
+ 
+ 	poly_int64 offset = frame.reg_offset[regno];
+ 
+-	/* If the register is saved in the first SVE save slot, we use
+-	   it as a stack probe for -fstack-clash-protection.  */
+-	if (flag_stack_clash_protection
+-	    && maybe_ne (frame.below_hard_fp_saved_regs_size, 0)
+-	    && known_eq (offset, frame.bytes_below_saved_regs))
+-	  continue;
+-
+ 	/* Get the offset relative to the register we'll use.  */
+ 	if (frame_pointer_needed)
+ 	  offset -= frame.bytes_below_hard_fp;
+@@ -9680,6 +9713,13 @@ aarch64_get_separate_components (void)
+ 
+   bitmap_clear_bit (components, LR_REGNUM);
+   bitmap_clear_bit (components, SP_REGNUM);
++  if (flag_stack_clash_protection)
++    {
++      if (frame.sve_save_and_probe != INVALID_REGNUM)
++	bitmap_clear_bit (components, frame.sve_save_and_probe);
++      if (frame.hard_fp_save_and_probe != INVALID_REGNUM)
++	bitmap_clear_bit (components, frame.hard_fp_save_and_probe);
++    }
+ 
+   return components;
+ }
+@@ -10226,8 +10266,8 @@ aarch64_epilogue_uses (int regno)
+    When probing is needed, we emit a probe at the start of the prologue
+    and every PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE bytes thereafter.
+ 
+-   We have to track how much space has been allocated and the only stores
+-   to the stack we track as implicit probes are the FP/LR stores.
++   We can also use register saves as probes.  These are stored in
++   sve_save_and_probe and hard_fp_save_and_probe.
+ 
+    For outgoing arguments we probe if the size is larger than 1KB, such that
+    the ABI specified buffer is maintained for the next callee.
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index f340237d0..af480d9e8 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -887,6 +887,14 @@ struct GTY (()) aarch64_frame
+      This is the register they should use.  */
+   unsigned spare_pred_reg;
+ 
++  /* An SVE register that is saved below the hard frame pointer and that acts
++     as a probe for later allocations, or INVALID_REGNUM if none.  */
++  unsigned sve_save_and_probe;
++
++  /* A register that is saved at the hard frame pointer and that acts
++     as a probe for later allocations, or INVALID_REGNUM if none.  */
++  unsigned hard_fp_save_and_probe;
++
+   bool laid_out;
+ 
+   /* True if shadow call stack should be enabled for the current function.  */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_3.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_3.c
+index 3e01ec36c..3530a0d50 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_3.c
+@@ -11,11 +11,10 @@
+ **	mov	x11, sp
+ **	...
+ **	sub	sp, sp, x13
+-**	str	p4, \[sp\]
+ **	cbz	w0, [^\n]*
++**	str	p4, \[sp\]
+ **	...
+ **	ptrue	p0\.b, all
+-**	ldr	p4, \[sp\]
+ **	addvl	sp, sp, #1
+ **	ldr	x24, \[sp\], 32
+ **	ret
+@@ -39,13 +38,12 @@ test_1 (int n)
+ **	mov	x11, sp
+ **	...
+ **	sub	sp, sp, x13
+-**	str	p4, \[sp\]
+ **	cbz	w0, [^\n]*
++**	str	p4, \[sp\]
+ **	str	p5, \[sp, #1, mul vl\]
+ **	str	p6, \[sp, #2, mul vl\]
+ **	...
+ **	ptrue	p0\.b, all
+-**	ldr	p4, \[sp\]
+ **	addvl	sp, sp, #1
+ **	ldr	x24, \[sp\], 32
+ **	ret
+-- 
+2.33.0
+
diff --git a/0200-Backport-SME-aarch64-Remove-below_hard_fp_saved_regs.patch b/0200-Backport-SME-aarch64-Remove-below_hard_fp_saved_regs.patch
new file mode 100644
index 0000000..26cce09
--- /dev/null
+++ b/0200-Backport-SME-aarch64-Remove-below_hard_fp_saved_regs.patch
@@ -0,0 +1,160 @@
+From 5c33afb2173f68a0166bd180977cd1e547df22dc Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:12 +0100
+Subject: [PATCH 101/157] [Backport][SME] aarch64: Remove
+ below_hard_fp_saved_regs_size
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2abfc867d3ba025ac2146bb21b92a93e6325dec1
+
+After previous patches, it's no longer necessary to store
+saved_regs_size and below_hard_fp_saved_regs_size in the frame info.
+All measurements instead use the top or bottom of the frame as
+reference points.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame::saved_regs_size)
+	(aarch64_frame::below_hard_fp_saved_regs_size): Delete.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Update accordingly.
+---
+ gcc/config/aarch64/aarch64.cc | 45 ++++++++++++++++-------------------
+ gcc/config/aarch64/aarch64.h  |  7 ------
+ 2 files changed, 21 insertions(+), 31 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index dd80ceba8..0894ed325 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8869,9 +8869,8 @@ aarch64_layout_frame (void)
+ 
+   /* OFFSET is now the offset of the hard frame pointer from the bottom
+      of the callee save area.  */
+-  frame.below_hard_fp_saved_regs_size = offset - frame.bytes_below_saved_regs;
+-  bool saves_below_hard_fp_p
+-    = maybe_ne (frame.below_hard_fp_saved_regs_size, 0);
++  auto below_hard_fp_saved_regs_size = offset - frame.bytes_below_saved_regs;
++  bool saves_below_hard_fp_p = maybe_ne (below_hard_fp_saved_regs_size, 0);
+   gcc_assert (!saves_below_hard_fp_p
+ 	      || (frame.sve_save_and_probe != INVALID_REGNUM
+ 		  && known_eq (frame.reg_offset[frame.sve_save_and_probe],
+@@ -8941,9 +8940,8 @@ aarch64_layout_frame (void)
+ 
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+ 
+-  frame.saved_regs_size = offset - frame.bytes_below_saved_regs;
+-  gcc_assert (known_eq (frame.saved_regs_size,
+-			frame.below_hard_fp_saved_regs_size)
++  auto saved_regs_size = offset - frame.bytes_below_saved_regs;
++  gcc_assert (known_eq (saved_regs_size, below_hard_fp_saved_regs_size)
+ 	      || (frame.hard_fp_save_and_probe != INVALID_REGNUM
+ 		  && known_eq (frame.reg_offset[frame.hard_fp_save_and_probe],
+ 			       frame.bytes_below_hard_fp)));
+@@ -8952,7 +8950,7 @@ aarch64_layout_frame (void)
+      The saving of the bottommost register counts as an implicit probe,
+      which allows us to maintain the invariant described in the comment
+      at expand_prologue.  */
+-  gcc_assert (crtl->is_leaf || maybe_ne (frame.saved_regs_size, 0));
++  gcc_assert (crtl->is_leaf || maybe_ne (saved_regs_size, 0));
+ 
+   offset += get_frame_size ();
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+@@ -9009,7 +9007,7 @@ aarch64_layout_frame (void)
+ 
+   HOST_WIDE_INT const_size, const_below_saved_regs, const_above_fp;
+   HOST_WIDE_INT const_saved_regs_size;
+-  if (known_eq (frame.saved_regs_size, 0))
++  if (known_eq (saved_regs_size, 0))
+     frame.initial_adjust = frame.frame_size;
+   else if (frame.frame_size.is_constant (&const_size)
+ 	   && const_size < max_push_offset
+@@ -9022,7 +9020,7 @@ aarch64_layout_frame (void)
+       frame.callee_adjust = const_size;
+     }
+   else if (frame.bytes_below_saved_regs.is_constant (&const_below_saved_regs)
+-	   && frame.saved_regs_size.is_constant (&const_saved_regs_size)
++	   && saved_regs_size.is_constant (&const_saved_regs_size)
+ 	   && const_below_saved_regs + const_saved_regs_size < 512
+ 	   /* We could handle this case even with data below the saved
+ 	      registers, provided that that data left us with valid offsets
+@@ -9041,8 +9039,7 @@ aarch64_layout_frame (void)
+       frame.initial_adjust = frame.frame_size;
+     }
+   else if (saves_below_hard_fp_p
+-	   && known_eq (frame.saved_regs_size,
+-			frame.below_hard_fp_saved_regs_size))
++	   && known_eq (saved_regs_size, below_hard_fp_saved_regs_size))
+     {
+       /* Frame in which all saves are SVE saves:
+ 
+@@ -9064,7 +9061,7 @@ aarch64_layout_frame (void)
+ 	 [save SVE registers relative to SP]
+ 	 sub sp, sp, bytes_below_saved_regs  */
+       frame.callee_adjust = const_above_fp;
+-      frame.sve_callee_adjust = frame.below_hard_fp_saved_regs_size;
++      frame.sve_callee_adjust = below_hard_fp_saved_regs_size;
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+   else
+@@ -9079,7 +9076,7 @@ aarch64_layout_frame (void)
+ 	 [save SVE registers relative to SP]
+ 	 sub sp, sp, bytes_below_saved_regs  */
+       frame.initial_adjust = frame.bytes_above_hard_fp;
+-      frame.sve_callee_adjust = frame.below_hard_fp_saved_regs_size;
++      frame.sve_callee_adjust = below_hard_fp_saved_regs_size;
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+ 
+@@ -10231,17 +10228,17 @@ aarch64_epilogue_uses (int regno)
+ 	|  local variables              | <-- frame_pointer_rtx
+ 	|                               |
+ 	+-------------------------------+
+-	|  padding                      | \
+-	+-------------------------------+  |
+-	|  callee-saved registers       |  | frame.saved_regs_size
+-	+-------------------------------+  |
+-	|  LR'                          |  |
+-	+-------------------------------+  |
+-	|  FP'                          |  |
+-	+-------------------------------+  |<- hard_frame_pointer_rtx (aligned)
+-	|  SVE vector registers         |  | \
+-	+-------------------------------+  |  | below_hard_fp_saved_regs_size
+-	|  SVE predicate registers      | /  /
++	|  padding                      |
++	+-------------------------------+
++	|  callee-saved registers       |
++	+-------------------------------+
++	|  LR'                          |
++	+-------------------------------+
++	|  FP'                          |
++	+-------------------------------+ <-- hard_frame_pointer_rtx (aligned)
++	|  SVE vector registers         |
++	+-------------------------------+
++	|  SVE predicate registers      |
+ 	+-------------------------------+
+ 	|  dynamic allocation           |
+ 	+-------------------------------+
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index af480d9e8..292ef2eec 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -801,18 +801,11 @@ struct GTY (()) aarch64_frame
+      STACK_BOUNDARY.  */
+   HOST_WIDE_INT saved_varargs_size;
+ 
+-  /* The size of the callee-save registers with a slot in REG_OFFSET.  */
+-  poly_int64 saved_regs_size;
+-
+   /* The number of bytes between the bottom of the static frame (the bottom
+      of the outgoing arguments) and the bottom of the register save area.
+      This value is always a multiple of STACK_BOUNDARY.  */
+   poly_int64 bytes_below_saved_regs;
+ 
+-  /* The size of the callee-save registers with a slot in REG_OFFSET that
+-     are saved below the hard frame pointer.  */
+-  poly_int64 below_hard_fp_saved_regs_size;
+-
+   /* The number of bytes between the bottom of the static frame (the bottom
+      of the outgoing arguments) and the hard frame pointer.  This value is
+      always a multiple of STACK_BOUNDARY.  */
+-- 
+2.33.0
+
diff --git a/0201-Backport-SME-aarch64-Make-stack-smash-canary-protect.patch b/0201-Backport-SME-aarch64-Make-stack-smash-canary-protect.patch
new file mode 100644
index 0000000..c0d8bf6
--- /dev/null
+++ b/0201-Backport-SME-aarch64-Make-stack-smash-canary-protect.patch
@@ -0,0 +1,301 @@
+From b225443d64481bc225e29bf119d99b719c69cd3c Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Sep 2023 16:05:13 +0100
+Subject: [PATCH 102/157] [Backport][SME] aarch64: Make stack smash canary
+ protect saved registers
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=3e4afea3b192c205c9a9da99f4cac65c68087eaf
+
+AArch64 normally puts the saved registers near the bottom of the frame,
+immediately above any dynamic allocations.  But this means that a
+stack-smash attack on those dynamic allocations could overwrite the
+saved registers without needing to reach as far as the stack smash
+canary.
+
+The same thing could also happen for variable-sized arguments that are
+passed by value, since those are allocated before a call and popped on
+return.
+
+This patch avoids that by putting the locals (and thus the canary) below
+the saved registers when stack smash protection is active.
+
+The patch fixes CVE-2023-4039.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_save_regs_above_locals_p):
+	New function.
+	(aarch64_layout_frame): Use it to decide whether locals should
+	go above or below the saved registers.
+	(aarch64_expand_prologue): Update stack layout comment.
+	Emit a stack tie after the final adjustment.
+
+gcc/testsuite/
+	* gcc.target/aarch64/stack-protector-8.c: New test.
+	* gcc.target/aarch64/stack-protector-9.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                 | 46 +++++++--
+ .../gcc.target/aarch64/stack-protector-8.c    | 95 +++++++++++++++++++
+ .../gcc.target/aarch64/stack-protector-9.c    | 33 +++++++
+ 3 files changed, 168 insertions(+), 6 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-protector-8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-protector-9.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 0894ed325..8d4dd2891 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8733,6 +8733,20 @@ aarch64_needs_frame_chain (void)
+   return aarch64_use_frame_pointer;
+ }
+ 
++/* Return true if the current function should save registers above
++   the locals area, rather than below it.  */
++
++static bool
++aarch64_save_regs_above_locals_p ()
++{
++  /* When using stack smash protection, make sure that the canary slot
++     comes between the locals and the saved registers.  Otherwise,
++     it would be possible for a carefully sized smash attack to change
++     the saved registers (particularly LR and FP) without reaching the
++     canary.  */
++  return crtl->stack_protect_guard;
++}
++
+ /* Mark the registers that need to be saved by the callee and calculate
+    the size of the callee-saved registers area and frame record (both FP
+    and LR may be omitted).  */
+@@ -8744,6 +8758,7 @@ aarch64_layout_frame (void)
+   poly_int64 vector_save_size = GET_MODE_SIZE (vector_save_mode);
+   bool frame_related_fp_reg_p = false;
+   aarch64_frame &frame = cfun->machine->frame;
++  poly_int64 top_of_locals = -1;
+ 
+   frame.emit_frame_chain = aarch64_needs_frame_chain ();
+ 
+@@ -8810,9 +8825,16 @@ aarch64_layout_frame (void)
+ 	&& !crtl->abi->clobbers_full_reg_p (regno))
+       frame.reg_offset[regno] = SLOT_REQUIRED;
+ 
++  bool regs_at_top_p = aarch64_save_regs_above_locals_p ();
+ 
+   poly_int64 offset = crtl->outgoing_args_size;
+   gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT));
++  if (regs_at_top_p)
++    {
++      offset += get_frame_size ();
++      offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
++      top_of_locals = offset;
++    }
+   frame.bytes_below_saved_regs = offset;
+   frame.sve_save_and_probe = INVALID_REGNUM;
+ 
+@@ -8952,15 +8974,18 @@ aarch64_layout_frame (void)
+      at expand_prologue.  */
+   gcc_assert (crtl->is_leaf || maybe_ne (saved_regs_size, 0));
+ 
+-  offset += get_frame_size ();
+-  offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+-  auto top_of_locals = offset;
+-
++  if (!regs_at_top_p)
++    {
++      offset += get_frame_size ();
++      offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
++      top_of_locals = offset;
++    }
+   offset += frame.saved_varargs_size;
+   gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT));
+   frame.frame_size = offset;
+ 
+   frame.bytes_above_hard_fp = frame.frame_size - frame.bytes_below_hard_fp;
++  gcc_assert (known_ge (top_of_locals, 0));
+   frame.bytes_above_locals = frame.frame_size - top_of_locals;
+ 
+   frame.initial_adjust = 0;
+@@ -10225,10 +10250,10 @@ aarch64_epilogue_uses (int regno)
+ 	|  for register varargs         |
+ 	|                               |
+ 	+-------------------------------+
+-	|  local variables              | <-- frame_pointer_rtx
++	|  local variables (1)          | <-- frame_pointer_rtx
+ 	|                               |
+ 	+-------------------------------+
+-	|  padding                      |
++	|  padding (1)                  |
+ 	+-------------------------------+
+ 	|  callee-saved registers       |
+ 	+-------------------------------+
+@@ -10240,6 +10265,10 @@ aarch64_epilogue_uses (int regno)
+ 	+-------------------------------+
+ 	|  SVE predicate registers      |
+ 	+-------------------------------+
++	|  local variables (2)          |
++	+-------------------------------+
++	|  padding (2)                  |
++	+-------------------------------+
+ 	|  dynamic allocation           |
+ 	+-------------------------------+
+ 	|  padding                      |
+@@ -10249,6 +10278,9 @@ aarch64_epilogue_uses (int regno)
+ 	+-------------------------------+
+ 	|                               | <-- stack_pointer_rtx (aligned)
+ 
++   The regions marked (1) and (2) are mutually exclusive.  (2) is used
++   when aarch64_save_regs_above_locals_p is true.
++
+    Dynamic stack allocations via alloca() decrease stack_pointer_rtx
+    but leave frame_pointer_rtx and hard_frame_pointer_rtx
+    unchanged.
+@@ -10444,6 +10476,8 @@ aarch64_expand_prologue (void)
+   gcc_assert (known_eq (bytes_below_sp, final_adjust));
+   aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx, final_adjust,
+ 					  !frame_pointer_needed, true);
++  if (emit_frame_chain && maybe_ne (final_adjust, 0))
++    aarch64_emit_stack_tie (hard_frame_pointer_rtx);
+ }
+ 
+ /* Return TRUE if we can use a simple_return insn.
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c
+new file mode 100644
+index 000000000..e71d820e3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c
+@@ -0,0 +1,95 @@
++/* { dg-options " -O -fstack-protector-strong -mstack-protector-guard=sysreg -mstack-protector-guard-reg=tpidr2_el0 -mstack-protector-guard-offset=16" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void g(void *);
++__SVBool_t *h(void *);
++
++/*
++** test1:
++**	sub	sp, sp, #288
++**	stp	x29, x30, \[sp, #?272\]
++**	add	x29, sp, #?272
++**	mrs	(x[0-9]+), tpidr2_el0
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	str	\2, \[sp, #?264\]
++**	mov	\2, #?0
++**	add	x0, sp, #?8
++**	bl	g
++**	...
++**	mrs	.*
++**	...
++**	bne	.*
++**	...
++**	ldp	x29, x30, \[sp, #?272\]
++**	add	sp, sp, #?288
++**	ret
++**	bl	__stack_chk_fail
++*/
++int test1() {
++  int y[0x40];
++  g(y);
++  return 1;
++}
++
++/*
++** test2:
++**	stp	x29, x30, \[sp, #?-16\]!
++**	mov	x29, sp
++**	sub	sp, sp, #1040
++**	mrs	(x[0-9]+), tpidr2_el0
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	str	\2, \[sp, #?1032\]
++**	mov	\2, #?0
++**	add	x0, sp, #?8
++**	bl	g
++**	...
++**	mrs	.*
++**	...
++**	bne	.*
++**	...
++**	add	sp, sp, #?1040
++**	ldp	x29, x30, \[sp\], #?16
++**	ret
++**	bl	__stack_chk_fail
++*/
++int test2() {
++  int y[0x100];
++  g(y);
++  return 1;
++}
++
++#pragma GCC target "+sve"
++
++/*
++** test3:
++**	stp	x29, x30, \[sp, #?-16\]!
++**	mov	x29, sp
++**	addvl	sp, sp, #-18
++**	...
++**	str	p4, \[sp\]
++**	...
++**	sub	sp, sp, #272
++**	mrs	(x[0-9]+), tpidr2_el0
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	str	\2, \[sp, #?264\]
++**	mov	\2, #?0
++**	add	x0, sp, #?8
++**	bl	h
++**	...
++**	mrs	.*
++**	...
++**	bne	.*
++**	...
++**	add	sp, sp, #?272
++**	...
++**	ldr	p4, \[sp\]
++**	...
++**	addvl	sp, sp, #18
++**	ldp	x29, x30, \[sp\], #?16
++**	ret
++**	bl	__stack_chk_fail
++*/
++__SVBool_t test3() {
++  int y[0x40];
++  return *h(y);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-9.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-9.c
+new file mode 100644
+index 000000000..58f322aa4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-9.c
+@@ -0,0 +1,33 @@
++/* { dg-options "-O2 -mcpu=neoverse-v1 -fstack-protector-all" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++/*
++** main:
++**	...
++**	stp	x29, x30, \[sp, #?-[0-9]+\]!
++**	...
++**	sub	sp, sp, #[0-9]+
++**	...
++**	str	x[0-9]+, \[x29, #?-8\]
++**	...
++*/
++int f(const char *);
++void g(void *);
++int main(int argc, char* argv[])
++{
++  int a;
++  int b;
++  char c[2+f(argv[1])];
++  int d[0x100];
++  char y;
++
++  y=42; a=4; b=10;
++  c[0] = 'h'; c[1] = '\0';
++
++  c[f(argv[2])] = '\0';
++
++  __builtin_printf("%d %d\n%s\n", a, b, c);
++  g(d);
++
++  return 0;
++}
+-- 
+2.33.0
+
diff --git a/0202-Backport-SME-Handle-epilogues-that-contain-jumps.patch b/0202-Backport-SME-Handle-epilogues-that-contain-jumps.patch
new file mode 100644
index 0000000..6348a49
--- /dev/null
+++ b/0202-Backport-SME-Handle-epilogues-that-contain-jumps.patch
@@ -0,0 +1,201 @@
+From 31433584b018cb2dc81e2366351a57bf5e1c4e44 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 17 Oct 2023 23:45:43 +0100
+Subject: [PATCH 103/157] [Backport][SME] Handle epilogues that contain jumps
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=aeb3f0436f8ae84e593eda9641fe4e6fdf0afb3e
+
+The prologue/epilogue pass allows the prologue sequence to contain
+jumps.  The sequence is then partitioned into basic blocks using
+find_many_sub_basic_blocks.
+
+This patch treats epilogues in a similar way.  Since only one block
+might need to be split, the patch (re)introduces a find_sub_basic_blocks
+routine to handle a single block.
+
+The new routine hard-codes the assumption that split_block will chain
+the new block immediately after the original block.  The routine doesn't
+try to replicate the fix for PR81030, since that was specific to
+gimple->rtl expansion.
+
+The patch is needed for follow-on aarch64 patches that add conditional
+code to the epilogue.  The tests are part of those patches.
+
+gcc/
+	* cfgbuild.h (find_sub_basic_blocks): Declare.
+	* cfgbuild.cc (update_profile_for_new_sub_basic_block): New function,
+	split out from...
+	(find_many_sub_basic_blocks): ...here.
+	(find_sub_basic_blocks): New function.
+	* function.cc (thread_prologue_and_epilogue_insns): Handle
+	epilogues that contain jumps.
+---
+ gcc/cfgbuild.cc | 95 +++++++++++++++++++++++++++++++++----------------
+ gcc/cfgbuild.h  |  1 +
+ gcc/function.cc |  4 +++
+ 3 files changed, 70 insertions(+), 30 deletions(-)
+
+diff --git a/gcc/cfgbuild.cc b/gcc/cfgbuild.cc
+index 646a06614..58b865f29 100644
+--- a/gcc/cfgbuild.cc
++++ b/gcc/cfgbuild.cc
+@@ -693,6 +693,43 @@ compute_outgoing_frequencies (basic_block b)
+     }
+ }
+ 
++/* Update the profile information for BB, which was created by splitting
++   an RTL block that had a non-final jump.  */
++
++static void
++update_profile_for_new_sub_basic_block (basic_block bb)
++{
++  edge e;
++  edge_iterator ei;
++
++  bool initialized_src = false, uninitialized_src = false;
++  bb->count = profile_count::zero ();
++  FOR_EACH_EDGE (e, ei, bb->preds)
++    {
++      if (e->count ().initialized_p ())
++	{
++	  bb->count += e->count ();
++	  initialized_src = true;
++	}
++      else
++	uninitialized_src = true;
++    }
++  /* When some edges are missing with read profile, this is
++     most likely because RTL expansion introduced loop.
++     When profile is guessed we may have BB that is reachable
++     from unlikely path as well as from normal path.
++
++     TODO: We should handle loops created during BB expansion
++     correctly here.  For now we assume all those loop to cycle
++     precisely once.  */
++  if (!initialized_src
++      || (uninitialized_src
++	   && profile_status_for_fn (cfun) < PROFILE_GUESSED))
++    bb->count = profile_count::uninitialized ();
++
++  compute_outgoing_frequencies (bb);
++}
++
+ /* Assume that some pass has inserted labels or control flow
+    instructions within a basic block.  Split basic blocks as needed
+    and create edges.  */
+@@ -744,40 +781,15 @@ find_many_sub_basic_blocks (sbitmap blocks)
+   if (profile_status_for_fn (cfun) != PROFILE_ABSENT)
+     FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
+       {
+-	edge e;
+-	edge_iterator ei;
+-
+ 	if (STATE (bb) == BLOCK_ORIGINAL)
+ 	  continue;
+ 	if (STATE (bb) == BLOCK_NEW)
+ 	  {
+-	    bool initialized_src = false, uninitialized_src = false;
+-	    bb->count = profile_count::zero ();
+-	    FOR_EACH_EDGE (e, ei, bb->preds)
+-	      {
+-		if (e->count ().initialized_p ())
+-		  {
+-		    bb->count += e->count ();
+-		    initialized_src = true;
+-		  }
+-		else
+-		  uninitialized_src = true;
+-	      }
+-	    /* When some edges are missing with read profile, this is
+-	       most likely because RTL expansion introduced loop.
+-	       When profile is guessed we may have BB that is reachable
+-	       from unlikely path as well as from normal path.
+-
+-	       TODO: We should handle loops created during BB expansion
+-	       correctly here.  For now we assume all those loop to cycle
+-	       precisely once.  */
+-	    if (!initialized_src
+-		|| (uninitialized_src
+-		     && profile_status_for_fn (cfun) < PROFILE_GUESSED))
+-	      bb->count = profile_count::uninitialized ();
++	    update_profile_for_new_sub_basic_block (bb);
++	    continue;
+ 	  }
+- 	/* If nothing changed, there is no need to create new BBs.  */
+-	else if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
++	/* If nothing changed, there is no need to create new BBs.  */
++	if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+ 	  {
+ 	    /* In rare occassions RTL expansion might have mistakely assigned
+ 	       a probabilities different from what is in CFG.  This happens
+@@ -788,10 +800,33 @@ find_many_sub_basic_blocks (sbitmap blocks)
+ 	      update_br_prob_note (bb);
+ 	    continue;
+ 	  }
+-
+ 	compute_outgoing_frequencies (bb);
+       }
+ 
+   FOR_EACH_BB_FN (bb, cfun)
+     SET_STATE (bb, 0);
+ }
++
++/* Like find_many_sub_basic_blocks, but look only within BB.  */
++
++void
++find_sub_basic_blocks (basic_block bb)
++{
++  basic_block end_bb = bb->next_bb;
++  find_bb_boundaries (bb);
++  if (bb->next_bb == end_bb)
++    return;
++
++  /* Re-scan and wire in all edges.  This expects simple (conditional)
++     jumps at the end of each new basic blocks.  */
++  make_edges (bb, end_bb->prev_bb, 1);
++
++  /* Update branch probabilities.  Expect only (un)conditional jumps
++     to be created with only the forward edges.  */
++  if (profile_status_for_fn (cfun) != PROFILE_ABSENT)
++    {
++      compute_outgoing_frequencies (bb);
++      for (bb = bb->next_bb; bb != end_bb; bb = bb->next_bb)
++	update_profile_for_new_sub_basic_block (bb);
++    }
++}
+diff --git a/gcc/cfgbuild.h b/gcc/cfgbuild.h
+index 85145da7f..53543bb75 100644
+--- a/gcc/cfgbuild.h
++++ b/gcc/cfgbuild.h
+@@ -24,5 +24,6 @@ extern bool inside_basic_block_p (const rtx_insn *);
+ extern bool control_flow_insn_p (const rtx_insn *);
+ extern void rtl_make_eh_edge (sbitmap, basic_block, rtx);
+ extern void find_many_sub_basic_blocks (sbitmap);
++extern void find_sub_basic_blocks (basic_block);
+ 
+ #endif /* GCC_CFGBUILD_H */
+diff --git a/gcc/function.cc b/gcc/function.cc
+index ddab43ca4..f4fc211a0 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -6126,6 +6126,8 @@ thread_prologue_and_epilogue_insns (void)
+ 		  && returnjump_p (BB_END (e->src)))
+ 		e->flags &= ~EDGE_FALLTHRU;
+ 	    }
++
++	  find_sub_basic_blocks (BLOCK_FOR_INSN (epilogue_seq));
+ 	}
+       else if (next_active_insn (BB_END (exit_fallthru_edge->src)))
+ 	{
+@@ -6234,6 +6236,8 @@ thread_prologue_and_epilogue_insns (void)
+ 	  set_insn_locations (seq, epilogue_location);
+ 
+ 	  emit_insn_before (seq, insn);
++
++	  find_sub_basic_blocks (BLOCK_FOR_INSN (insn));
+ 	}
+     }
+ 
+-- 
+2.33.0
+
diff --git a/0203-Backport-SME-aarch64-Use-vecs-to-store-register-save.patch b/0203-Backport-SME-aarch64-Use-vecs-to-store-register-save.patch
new file mode 100644
index 0000000..b9e9c93
--- /dev/null
+++ b/0203-Backport-SME-aarch64-Use-vecs-to-store-register-save.patch
@@ -0,0 +1,709 @@
+From 554c83414c10909c39e0ad30026ffa4821dd9698 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 17 Oct 2023 23:46:33 +0100
+Subject: [PATCH 104/157] [Backport][SME] aarch64: Use vecs to store register
+ save order
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=575858508090b18dcbc176db285c9f55227ca4c0
+
+aarch64_save/restore_callee_saves looped over registers in register
+number order.  This in turn meant that we could only use LDP and STP
+for registers that were consecutive both number-wise and
+offset-wise (after unsaved registers are excluded).
+
+This patch instead builds lists of the registers that we've decided to
+save, in offset order.  We can then form LDP/STP pairs regardless of
+register number order, which in turn means that we can put the LR save
+slot first without losing LDP/STP opportunities.
+
+gcc/
+	* config/aarch64/aarch64.h (aarch64_frame): Add vectors that
+	store the list saved GPRs, FPRs and predicate registers.
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Initialize
+	the lists of saved registers.  Use them to choose push candidates.
+	Invalidate pop candidates if we're not going to do a pop.
+	(aarch64_next_callee_save): Delete.
+	(aarch64_save_callee_saves): Take a list of registers,
+	rather than a range.  Make !skip_wb select only write-back
+	candidates.
+	(aarch64_expand_prologue): Update calls accordingly.
+	(aarch64_restore_callee_saves): Take a list of registers,
+	rather than a range.  Always skip pop candidates.  Also skip
+	LR if shadow call stacks are enabled.
+	(aarch64_expand_epilogue): Update calls accordingly.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/pcs/stack_clash_2.c: Expect restores
+	to happen in offset order.
+	* gcc.target/aarch64/sve/pcs/stack_clash_2_128.c: Likewise.
+	* gcc.target/aarch64/sve/pcs/stack_clash_2_256.c: Likewise.
+	* gcc.target/aarch64/sve/pcs/stack_clash_2_512.c: Likewise.
+	* gcc.target/aarch64/sve/pcs/stack_clash_2_1024.c: Likewise.
+	* gcc.target/aarch64/sve/pcs/stack_clash_2_2048.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                 | 203 +++++++++---------
+ gcc/config/aarch64/aarch64.h                  |   9 +-
+ .../aarch64/sve/pcs/stack_clash_2.c           |   6 +-
+ .../aarch64/sve/pcs/stack_clash_2_1024.c      |   6 +-
+ .../aarch64/sve/pcs/stack_clash_2_128.c       |   6 +-
+ .../aarch64/sve/pcs/stack_clash_2_2048.c      |   6 +-
+ .../aarch64/sve/pcs/stack_clash_2_256.c       |   6 +-
+ .../aarch64/sve/pcs/stack_clash_2_512.c       |   6 +-
+ 8 files changed, 128 insertions(+), 120 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 8d4dd2891..e10c9d763 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8753,13 +8753,17 @@ aarch64_save_regs_above_locals_p ()
+ static void
+ aarch64_layout_frame (void)
+ {
+-  int regno, last_fp_reg = INVALID_REGNUM;
++  unsigned regno, last_fp_reg = INVALID_REGNUM;
+   machine_mode vector_save_mode = aarch64_reg_save_mode (V8_REGNUM);
+   poly_int64 vector_save_size = GET_MODE_SIZE (vector_save_mode);
+   bool frame_related_fp_reg_p = false;
+   aarch64_frame &frame = cfun->machine->frame;
+   poly_int64 top_of_locals = -1;
+ 
++  vec_safe_truncate (frame.saved_gprs, 0);
++  vec_safe_truncate (frame.saved_fprs, 0);
++  vec_safe_truncate (frame.saved_prs, 0);
++
+   frame.emit_frame_chain = aarch64_needs_frame_chain ();
+ 
+   /* Adjust the outgoing arguments size if required.  Keep it in sync with what
+@@ -8844,6 +8848,7 @@ aarch64_layout_frame (void)
+   for (regno = P0_REGNUM; regno <= P15_REGNUM; regno++)
+     if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+       {
++	vec_safe_push (frame.saved_prs, regno);
+ 	if (frame.sve_save_and_probe == INVALID_REGNUM)
+ 	  frame.sve_save_and_probe = regno;
+ 	frame.reg_offset[regno] = offset;
+@@ -8865,7 +8870,7 @@ aarch64_layout_frame (void)
+ 	 If we don't have any vector registers to save, and we know how
+ 	 big the predicate save area is, we can just round it up to the
+ 	 next 16-byte boundary.  */
+-      if (last_fp_reg == (int) INVALID_REGNUM && offset.is_constant ())
++      if (last_fp_reg == INVALID_REGNUM && offset.is_constant ())
+ 	offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+       else
+ 	{
+@@ -8879,10 +8884,11 @@ aarch64_layout_frame (void)
+     }
+ 
+   /* If we need to save any SVE vector registers, add them next.  */
+-  if (last_fp_reg != (int) INVALID_REGNUM && crtl->abi->id () == ARM_PCS_SVE)
++  if (last_fp_reg != INVALID_REGNUM && crtl->abi->id () == ARM_PCS_SVE)
+     for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
+       if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+ 	{
++	  vec_safe_push (frame.saved_fprs, regno);
+ 	  if (frame.sve_save_and_probe == INVALID_REGNUM)
+ 	    frame.sve_save_and_probe = regno;
+ 	  frame.reg_offset[regno] = offset;
+@@ -8903,13 +8909,8 @@ aarch64_layout_frame (void)
+ 
+   auto allocate_gpr_slot = [&](unsigned int regno)
+     {
+-      if (frame.hard_fp_save_and_probe == INVALID_REGNUM)
+-	frame.hard_fp_save_and_probe = regno;
++      vec_safe_push (frame.saved_gprs, regno);
+       frame.reg_offset[regno] = offset;
+-      if (frame.wb_push_candidate1 == INVALID_REGNUM)
+-	frame.wb_push_candidate1 = regno;
+-      else if (frame.wb_push_candidate2 == INVALID_REGNUM)
+-	frame.wb_push_candidate2 = regno;
+       offset += UNITS_PER_WORD;
+     };
+ 
+@@ -8938,8 +8939,7 @@ aarch64_layout_frame (void)
+   for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
+     if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+       {
+-	if (frame.hard_fp_save_and_probe == INVALID_REGNUM)
+-	  frame.hard_fp_save_and_probe = regno;
++	vec_safe_push (frame.saved_fprs, regno);
+ 	/* If there is an alignment gap between integer and fp callee-saves,
+ 	   allocate the last fp register to it if possible.  */
+ 	if (regno == last_fp_reg
+@@ -8952,21 +8952,25 @@ aarch64_layout_frame (void)
+ 	  }
+ 
+ 	frame.reg_offset[regno] = offset;
+-	if (frame.wb_push_candidate1 == INVALID_REGNUM)
+-	  frame.wb_push_candidate1 = regno;
+-	else if (frame.wb_push_candidate2 == INVALID_REGNUM
+-		 && frame.wb_push_candidate1 >= V0_REGNUM)
+-	  frame.wb_push_candidate2 = regno;
+ 	offset += vector_save_size;
+       }
+ 
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+-
+   auto saved_regs_size = offset - frame.bytes_below_saved_regs;
+-  gcc_assert (known_eq (saved_regs_size, below_hard_fp_saved_regs_size)
+-	      || (frame.hard_fp_save_and_probe != INVALID_REGNUM
+-		  && known_eq (frame.reg_offset[frame.hard_fp_save_and_probe],
+-			       frame.bytes_below_hard_fp)));
++
++  array_slice push_regs = (!vec_safe_is_empty (frame.saved_gprs)
++					 ? frame.saved_gprs
++					 : frame.saved_fprs);
++  if (!push_regs.empty ()
++      && known_eq (frame.reg_offset[push_regs[0]], frame.bytes_below_hard_fp))
++    {
++      frame.hard_fp_save_and_probe = push_regs[0];
++      frame.wb_push_candidate1 = push_regs[0];
++      if (push_regs.size () > 1)
++	frame.wb_push_candidate2 = push_regs[1];
++    }
++  else
++    gcc_assert (known_eq (saved_regs_size, below_hard_fp_saved_regs_size));
+ 
+   /* With stack-clash, a register must be saved in non-leaf functions.
+      The saving of the bottommost register counts as an implicit probe,
+@@ -9130,12 +9134,14 @@ aarch64_layout_frame (void)
+ 			+ frame.sve_callee_adjust
+ 			+ frame.final_adjust, frame.frame_size));
+ 
+-  if (!frame.emit_frame_chain && frame.callee_adjust == 0)
++  if (frame.callee_adjust == 0)
+     {
+-      /* We've decided not to associate any register saves with the initial
+-	 stack allocation.  */
+-      frame.wb_pop_candidate1 = frame.wb_push_candidate1 = INVALID_REGNUM;
+-      frame.wb_pop_candidate2 = frame.wb_push_candidate2 = INVALID_REGNUM;
++      /* We've decided not to do a "real" push and pop.  However,
++	 setting up the frame chain is treated as being essentially
++	 a multi-instruction push.  */
++      frame.wb_pop_candidate1 = frame.wb_pop_candidate2 = INVALID_REGNUM;
++      if (!frame.emit_frame_chain)
++	frame.wb_push_candidate1 = frame.wb_push_candidate2 = INVALID_REGNUM;
+     }
+ 
+   frame.laid_out = true;
+@@ -9150,17 +9156,6 @@ aarch64_register_saved_on_entry (int regno)
+   return known_ge (cfun->machine->frame.reg_offset[regno], 0);
+ }
+ 
+-/* Return the next register up from REGNO up to LIMIT for the callee
+-   to save.  */
+-
+-static unsigned
+-aarch64_next_callee_save (unsigned regno, unsigned limit)
+-{
+-  while (regno <= limit && !aarch64_register_saved_on_entry (regno))
+-    regno ++;
+-  return regno;
+-}
+-
+ /* Push the register number REGNO of mode MODE to the stack with write-back
+    adjusting the stack by ADJUSTMENT.  */
+ 
+@@ -9424,41 +9419,46 @@ aarch64_add_cfa_expression (rtx_insn *insn, rtx reg,
+   add_reg_note (insn, REG_CFA_EXPRESSION, gen_rtx_SET (mem, reg));
+ }
+ 
+-/* Emit code to save the callee-saved registers from register number START
+-   to LIMIT to the stack.  The stack pointer is currently BYTES_BELOW_SP
+-   bytes above the bottom of the static frame.  Skip any write-back
+-   candidates if SKIP_WB is true.  HARD_FP_VALID_P is true if the hard
+-   frame pointer has been set up.  */
++/* Emit code to save the callee-saved registers in REGS.  Skip any
++   write-back candidates if SKIP_WB is true, otherwise consider only
++   write-back candidates.
++
++   The stack pointer is currently BYTES_BELOW_SP bytes above the bottom
++   of the static frame.  HARD_FP_VALID_P is true if the hard frame pointer
++   has been set up.  */
+ 
+ static void
+ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+-			   unsigned start, unsigned limit, bool skip_wb,
++			   array_slice regs, bool skip_wb,
+ 			   bool hard_fp_valid_p)
+ {
+   aarch64_frame &frame = cfun->machine->frame;
+   rtx_insn *insn;
+-  unsigned regno;
+-  unsigned regno2;
+   rtx anchor_reg = NULL_RTX, ptrue = NULL_RTX;
+ 
+-  for (regno = aarch64_next_callee_save (start, limit);
+-       regno <= limit;
+-       regno = aarch64_next_callee_save (regno + 1, limit))
++  auto skip_save_p = [&](unsigned int regno)
++    {
++      if (cfun->machine->reg_is_wrapped_separately[regno])
++	return true;
++
++      if (skip_wb == (regno == frame.wb_push_candidate1
++		      || regno == frame.wb_push_candidate2))
++	return true;
++
++      return false;
++    };
++
++  for (unsigned int i = 0; i < regs.size (); ++i)
+     {
+-      rtx reg, mem;
++      unsigned int regno = regs[i];
+       poly_int64 offset;
+       bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno);
+ 
+-      if (skip_wb
+-	  && (regno == frame.wb_push_candidate1
+-	      || regno == frame.wb_push_candidate2))
+-	continue;
+-
+-      if (cfun->machine->reg_is_wrapped_separately[regno])
++      if (skip_save_p (regno))
+ 	continue;
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+-      reg = gen_rtx_REG (mode, regno);
++      rtx reg = gen_rtx_REG (mode, regno);
+       offset = frame.reg_offset[regno] - bytes_below_sp;
+       rtx base_rtx = stack_pointer_rtx;
+       poly_int64 sp_offset = offset;
+@@ -9485,12 +9485,13 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 	    }
+ 	  offset -= fp_offset;
+ 	}
+-      mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset));
++      rtx mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset));
+       bool need_cfa_note_p = (base_rtx != stack_pointer_rtx);
+ 
++      unsigned int regno2;
+       if (!aarch64_sve_mode_p (mode)
+-	  && (regno2 = aarch64_next_callee_save (regno + 1, limit)) <= limit
+-	  && !cfun->machine->reg_is_wrapped_separately[regno2]
++	  && i + 1 < regs.size ()
++	  && (regno2 = regs[i + 1], !skip_save_p (regno2))
+ 	  && known_eq (GET_MODE_SIZE (mode),
+ 		       frame.reg_offset[regno2] - frame.reg_offset[regno]))
+ 	{
+@@ -9516,6 +9517,7 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 	    }
+ 
+ 	  regno = regno2;
++	  ++i;
+ 	}
+       else if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	{
+@@ -9533,49 +9535,57 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+     }
+ }
+ 
+-/* Emit code to restore the callee registers from register number START
+-   up to and including LIMIT.  The stack pointer is currently BYTES_BELOW_SP
+-   bytes above the bottom of the static frame.  Skip any write-back
+-   candidates if SKIP_WB is true.  Write the appropriate REG_CFA_RESTORE
+-   notes into CFI_OPS.  */
++/* Emit code to restore the callee registers in REGS, ignoring pop candidates
++   and any other registers that are handled separately.  Write the appropriate
++   REG_CFA_RESTORE notes into CFI_OPS.
++
++   The stack pointer is currently BYTES_BELOW_SP bytes above the bottom
++   of the static frame.  */
+ 
+ static void
+-aarch64_restore_callee_saves (poly_int64 bytes_below_sp, unsigned start,
+-			      unsigned limit, bool skip_wb, rtx *cfi_ops)
++aarch64_restore_callee_saves (poly_int64 bytes_below_sp,
++			      array_slice regs, rtx *cfi_ops)
+ {
+   aarch64_frame &frame = cfun->machine->frame;
+-  unsigned regno;
+-  unsigned regno2;
+   poly_int64 offset;
+   rtx anchor_reg = NULL_RTX, ptrue = NULL_RTX;
+ 
+-  for (regno = aarch64_next_callee_save (start, limit);
+-       regno <= limit;
+-       regno = aarch64_next_callee_save (regno + 1, limit))
++  auto skip_restore_p = [&](unsigned int regno)
+     {
+-      bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno);
+       if (cfun->machine->reg_is_wrapped_separately[regno])
+-	continue;
++	return true;
++
++      if (regno == frame.wb_pop_candidate1
++	  || regno == frame.wb_pop_candidate2)
++	return true;
+ 
+-      rtx reg, mem;
++      /* The shadow call stack code restores LR separately.  */
++      if (frame.is_scs_enabled && regno == LR_REGNUM)
++	return true;
+ 
+-      if (skip_wb
+-	  && (regno == frame.wb_pop_candidate1
+-	      || regno == frame.wb_pop_candidate2))
++      return false;
++    };
++
++  for (unsigned int i = 0; i < regs.size (); ++i)
++    {
++      unsigned int regno = regs[i];
++      bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno);
++      if (skip_restore_p (regno))
+ 	continue;
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+-      reg = gen_rtx_REG (mode, regno);
++      rtx reg = gen_rtx_REG (mode, regno);
+       offset = frame.reg_offset[regno] - bytes_below_sp;
+       rtx base_rtx = stack_pointer_rtx;
+       if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg,
+ 					     offset, ptrue);
+-      mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset));
++      rtx mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset));
+ 
++      unsigned int regno2;
+       if (!aarch64_sve_mode_p (mode)
+-	  && (regno2 = aarch64_next_callee_save (regno + 1, limit)) <= limit
+-	  && !cfun->machine->reg_is_wrapped_separately[regno2]
++	  && i + 1 < regs.size ()
++	  && (regno2 = regs[i + 1], !skip_restore_p (regno2))
+ 	  && known_eq (GET_MODE_SIZE (mode),
+ 		       frame.reg_offset[regno2] - frame.reg_offset[regno]))
+ 	{
+@@ -9588,6 +9598,7 @@ aarch64_restore_callee_saves (poly_int64 bytes_below_sp, unsigned start,
+ 
+ 	  *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg2, *cfi_ops);
+ 	  regno = regno2;
++	  ++i;
+ 	}
+       else if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	emit_insn (gen_aarch64_pred_mov (mode, reg, ptrue, mem));
+@@ -10409,13 +10420,10 @@ aarch64_expand_prologue (void)
+ 				 - frame.bytes_above_hard_fp);
+       gcc_assert (known_ge (chain_offset, 0));
+ 
++      gcc_assert (reg1 == R29_REGNUM && reg2 == R30_REGNUM);
+       if (callee_adjust == 0)
+-	{
+-	  reg1 = R29_REGNUM;
+-	  reg2 = R30_REGNUM;
+-	  aarch64_save_callee_saves (bytes_below_sp, reg1, reg2,
+-				     false, false);
+-	}
++	aarch64_save_callee_saves (bytes_below_sp, frame.saved_gprs,
++				   false, false);
+       else
+ 	gcc_assert (known_eq (chain_offset, 0));
+       aarch64_add_offset (Pmode, hard_frame_pointer_rtx,
+@@ -10453,8 +10461,7 @@ aarch64_expand_prologue (void)
+       aarch64_emit_stack_tie (hard_frame_pointer_rtx);
+     }
+ 
+-  aarch64_save_callee_saves (bytes_below_sp, R0_REGNUM, R30_REGNUM,
+-			     callee_adjust != 0 || emit_frame_chain,
++  aarch64_save_callee_saves (bytes_below_sp, frame.saved_gprs, true,
+ 			     emit_frame_chain);
+   if (maybe_ne (sve_callee_adjust, 0))
+     {
+@@ -10465,10 +10472,9 @@ aarch64_expand_prologue (void)
+ 					      !frame_pointer_needed, false);
+       bytes_below_sp -= sve_callee_adjust;
+     }
+-  aarch64_save_callee_saves (bytes_below_sp, P0_REGNUM, P15_REGNUM,
+-			     false, emit_frame_chain);
+-  aarch64_save_callee_saves (bytes_below_sp, V0_REGNUM, V31_REGNUM,
+-			     callee_adjust != 0 || emit_frame_chain,
++  aarch64_save_callee_saves (bytes_below_sp, frame.saved_prs, true,
++			     emit_frame_chain);
++  aarch64_save_callee_saves (bytes_below_sp, frame.saved_fprs, true,
+ 			     emit_frame_chain);
+ 
+   /* We may need to probe the final adjustment if it is larger than the guard
+@@ -10514,8 +10520,6 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+   poly_int64 bytes_below_hard_fp = frame.bytes_below_hard_fp;
+   unsigned reg1 = frame.wb_pop_candidate1;
+   unsigned reg2 = frame.wb_pop_candidate2;
+-  unsigned int last_gpr = (frame.is_scs_enabled
+-			   ? R29_REGNUM : R30_REGNUM);
+   rtx cfi_ops = NULL;
+   rtx_insn *insn;
+   /* A stack clash protection prologue may not have left EP0_REGNUM or
+@@ -10579,10 +10583,8 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ 
+   /* Restore the vector registers before the predicate registers,
+      so that we can use P4 as a temporary for big-endian SVE frames.  */
+-  aarch64_restore_callee_saves (final_adjust, V0_REGNUM, V31_REGNUM,
+-				callee_adjust != 0, &cfi_ops);
+-  aarch64_restore_callee_saves (final_adjust, P0_REGNUM, P15_REGNUM,
+-				false, &cfi_ops);
++  aarch64_restore_callee_saves (final_adjust, frame.saved_fprs, &cfi_ops);
++  aarch64_restore_callee_saves (final_adjust, frame.saved_prs, &cfi_ops);
+   if (maybe_ne (sve_callee_adjust, 0))
+     aarch64_add_sp (NULL_RTX, NULL_RTX, sve_callee_adjust, true);
+ 
+@@ -10590,8 +10592,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+      restore x30, we don't need to restore x30 again in the traditional
+      way.  */
+   aarch64_restore_callee_saves (final_adjust + sve_callee_adjust,
+-				R0_REGNUM, last_gpr,
+-				callee_adjust != 0, &cfi_ops);
++				frame.saved_gprs, &cfi_ops);
+ 
+   if (need_barrier_p)
+     aarch64_emit_stack_tie (stack_pointer_rtx);
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 292ef2eec..1591cde8b 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -787,7 +787,7 @@ extern enum aarch64_processor aarch64_tune;
+ 
+ #define DEFAULT_PCC_STRUCT_RETURN 0
+ 
+-#ifdef HAVE_POLY_INT_H
++#if defined(HAVE_POLY_INT_H) && defined(GCC_VEC_H)
+ struct GTY (()) aarch64_frame
+ {
+   /* The offset from the bottom of the static frame (the bottom of the
+@@ -795,6 +795,13 @@ struct GTY (()) aarch64_frame
+      needed.  */
+   poly_int64 reg_offset[LAST_SAVED_REGNUM + 1];
+ 
++  /* The list of GPRs, FPRs and predicate registers that have nonnegative
++     entries in reg_offset.  The registers are listed in order of
++     increasing offset (rather than increasing register number).  */
++  vec *saved_gprs;
++  vec *saved_fprs;
++  vec *saved_prs;
++
+   /* The number of extra stack bytes taken up by register varargs.
+      This area is allocated by the callee at the very top of the
+      frame.  This value is rounded up to a multiple of
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2.c
+index 4622a1eed..bbb45d266 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2.c
+@@ -215,9 +215,9 @@ test_7 (void)
+ **	add	sp, sp, #?16
+ **	ldr	p4, \[sp\]
+ **	addvl	sp, sp, #1
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -283,9 +283,9 @@ test_9 (int n)
+ **	addvl	sp, x29, #-1
+ **	ldr	p4, \[sp\]
+ **	addvl	sp, sp, #1
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -319,9 +319,9 @@ test_10 (int n)
+ **	addvl	sp, x29, #-1
+ **	ldr	p4, \[sp\]
+ **	addvl	sp, sp, #1
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	add	sp, sp, #?3008
+ **	add	sp, sp, #?126976
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_1024.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_1024.c
+index e31200fc2..9437c7a85 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_1024.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_1024.c
+@@ -176,9 +176,9 @@ test_7 (void)
+ **	add	sp, sp, #?16
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?128
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -234,9 +234,9 @@ test_9 (int n)
+ **	sub	sp, x29, #128
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?128
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -268,9 +268,9 @@ test_10 (int n)
+ **	sub	sp, x29, #128
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?128
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	add	sp, sp, #?3008
+ **	add	sp, sp, #?126976
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c
+index 41193b411..b4e1627fa 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_128.c
+@@ -176,9 +176,9 @@ test_7 (void)
+ **	add	sp, sp, #?16
+ **	ldr	p4, \[sp\]
+ **	add	sp, sp, #?16
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -234,9 +234,9 @@ test_9 (int n)
+ **	sub	sp, x29, #16
+ **	ldr	p4, \[sp\]
+ **	add	sp, sp, #?16
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -267,9 +267,9 @@ test_10 (int n)
+ **	sub	sp, x29, #16
+ **	ldr	p4, \[sp\]
+ **	add	sp, sp, #?16
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	add	sp, sp, #?3008
+ **	add	sp, sp, #?126976
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_2048.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_2048.c
+index f63751678..921209379 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_2048.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_2048.c
+@@ -176,9 +176,9 @@ test_7 (void)
+ **	add	sp, sp, #?16
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?256
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -234,9 +234,9 @@ test_9 (int n)
+ **	sub	sp, x29, #256
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?256
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -268,9 +268,9 @@ test_10 (int n)
+ **	sub	sp, x29, #256
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?256
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	add	sp, sp, #?3008
+ **	add	sp, sp, #?126976
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_256.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_256.c
+index 6bcbb5772..bd8bef0f0 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_256.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_256.c
+@@ -176,9 +176,9 @@ test_7 (void)
+ **	add	sp, sp, #?16
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?32
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -234,9 +234,9 @@ test_9 (int n)
+ **	sub	sp, x29, #32
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?32
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -267,9 +267,9 @@ test_10 (int n)
+ **	sub	sp, x29, #32
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?32
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	add	sp, sp, #?3008
+ **	add	sp, sp, #?126976
+ **	ret
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_512.c b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_512.c
+index dc7df8e6b..2c76ccecd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_512.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/stack_clash_2_512.c
+@@ -176,9 +176,9 @@ test_7 (void)
+ **	add	sp, sp, #?16
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?64
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -234,9 +234,9 @@ test_9 (int n)
+ **	sub	sp, x29, #64
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?64
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	mov	x12, #?4144
+ **	add	sp, sp, x12
+ **	ret
+@@ -268,9 +268,9 @@ test_10 (int n)
+ **	sub	sp, x29, #64
+ **	ldr	z16, \[sp\]
+ **	add	sp, sp, #?64
++**	ldp	x29, x30, \[sp\]
+ **	ldp	x24, x25, \[sp, 16\]
+ **	ldr	x26, \[sp, 32\]
+-**	ldp	x29, x30, \[sp\]
+ **	add	sp, sp, #?3008
+ **	add	sp, sp, #?126976
+ **	ret
+-- 
+2.33.0
+
diff --git a/0204-Backport-SME-aarch64-Put-LR-save-slot-first-in-more-.patch b/0204-Backport-SME-aarch64-Put-LR-save-slot-first-in-more-.patch
new file mode 100644
index 0000000..25a3b36
--- /dev/null
+++ b/0204-Backport-SME-aarch64-Put-LR-save-slot-first-in-more-.patch
@@ -0,0 +1,107 @@
+From ccc3ca614bbaa242fe25ec82b903dfcac03fe2de Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 17 Oct 2023 23:46:33 +0100
+Subject: [PATCH 105/157] [Backport][SME] aarch64: Put LR save slot first in
+ more cases
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=773306e9ef4ea1407f89686eb513a50602493666
+
+Now that the prologue and epilogue code iterates over saved
+registers in offset order, we can put the LR save slot first
+without compromising LDP/STP formation.
+
+This isn't worthwhile when shadow call stacks are enabled, since the
+first two registers are also push/pop candidates, and LR cannot be
+popped when shadow call stacks are enabled.  (LR is instead loaded
+first and compared against the shadow stack's value.)
+
+But otherwise, it seems better to put the LR save slot first,
+to reduce unnecessary variation with the layout for stack clash
+protection.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_layout_frame): Don't make
+	the position of the LR save slot dependent on stack clash
+	protection unless shadow call stacks are enabled.
+
+gcc/testsuite/
+	* gcc.target/aarch64/test_frame_2.c: Expect x30 to come before x19.
+	* gcc.target/aarch64/test_frame_4.c: Likewise.
+	* gcc.target/aarch64/test_frame_7.c: Likewise.
+	* gcc.target/aarch64/test_frame_10.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                    | 2 +-
+ gcc/testsuite/gcc.target/aarch64/test_frame_10.c | 4 ++--
+ gcc/testsuite/gcc.target/aarch64/test_frame_2.c  | 4 ++--
+ gcc/testsuite/gcc.target/aarch64/test_frame_4.c  | 4 ++--
+ gcc/testsuite/gcc.target/aarch64/test_frame_7.c  | 4 ++--
+ 5 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index e10c9d763..1c127192d 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8920,7 +8920,7 @@ aarch64_layout_frame (void)
+       allocate_gpr_slot (R29_REGNUM);
+       allocate_gpr_slot (R30_REGNUM);
+     }
+-  else if (flag_stack_clash_protection
++  else if ((flag_stack_clash_protection || !frame.is_scs_enabled)
+ 	   && known_eq (frame.reg_offset[R30_REGNUM], SLOT_REQUIRED))
+     /* Put the LR save slot first, since it makes a good choice of probe
+        for stack clash purposes.  The idea is that the link register usually
+diff --git a/gcc/testsuite/gcc.target/aarch64/test_frame_10.c b/gcc/testsuite/gcc.target/aarch64/test_frame_10.c
+index c19505082..c54ab2d0c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/test_frame_10.c
++++ b/gcc/testsuite/gcc.target/aarch64/test_frame_10.c
+@@ -14,6 +14,6 @@
+ t_frame_pattern_outgoing (test10, 480, "x19", 24, a[8], a[9], a[10])
+ t_frame_run (test10)
+ 
+-/* { dg-final { scan-assembler-times "stp\tx19, x30, \\\[sp, \[0-9\]+\\\]" 1 } } */
+-/* { dg-final { scan-assembler "ldp\tx19, x30, \\\[sp, \[0-9\]+\\\]" } } */
++/* { dg-final { scan-assembler-times "stp\tx30, x19, \\\[sp, \[0-9\]+\\\]" 1 } } */
++/* { dg-final { scan-assembler "ldp\tx30, x19, \\\[sp, \[0-9\]+\\\]" } } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/test_frame_2.c b/gcc/testsuite/gcc.target/aarch64/test_frame_2.c
+index 7e5df84cf..0d715314c 100644
+--- a/gcc/testsuite/gcc.target/aarch64/test_frame_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/test_frame_2.c
+@@ -14,6 +14,6 @@ t_frame_pattern (test2, 200, "x19")
+ t_frame_run (test2)
+ 
+ 
+-/* { dg-final { scan-assembler-times "stp\tx19, x30, \\\[sp, -\[0-9\]+\\\]!" 1 } } */
+-/* { dg-final { scan-assembler "ldp\tx19, x30, \\\[sp\\\], \[0-9\]+" } } */
++/* { dg-final { scan-assembler-times "stp\tx30, x19, \\\[sp, -\[0-9\]+\\\]!" 1 } } */
++/* { dg-final { scan-assembler "ldp\tx30, x19, \\\[sp\\\], \[0-9\]+" } } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/test_frame_4.c b/gcc/testsuite/gcc.target/aarch64/test_frame_4.c
+index ed13487a0..b41229c42 100644
+--- a/gcc/testsuite/gcc.target/aarch64/test_frame_4.c
++++ b/gcc/testsuite/gcc.target/aarch64/test_frame_4.c
+@@ -13,6 +13,6 @@
+ t_frame_pattern (test4, 400, "x19")
+ t_frame_run (test4)
+ 
+-/* { dg-final { scan-assembler-times "stp\tx19, x30, \\\[sp, -\[0-9\]+\\\]!" 1 } } */
+-/* { dg-final { scan-assembler "ldp\tx19, x30, \\\[sp\\\], \[0-9\]+" } } */
++/* { dg-final { scan-assembler-times "stp\tx30, x19, \\\[sp, -\[0-9\]+\\\]!" 1 } } */
++/* { dg-final { scan-assembler "ldp\tx30, x19, \\\[sp\\\], \[0-9\]+" } } */
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/test_frame_7.c b/gcc/testsuite/gcc.target/aarch64/test_frame_7.c
+index 964527949..5702656a5 100644
+--- a/gcc/testsuite/gcc.target/aarch64/test_frame_7.c
++++ b/gcc/testsuite/gcc.target/aarch64/test_frame_7.c
+@@ -13,6 +13,6 @@
+ t_frame_pattern (test7, 700, "x19")
+ t_frame_run (test7)
+ 
+-/* { dg-final { scan-assembler-times "stp\tx19, x30, \\\[sp]" 1 } } */
+-/* { dg-final { scan-assembler "ldp\tx19, x30, \\\[sp\\\]" } } */
++/* { dg-final { scan-assembler-times "stp\tx30, x19, \\\[sp]" 1 } } */
++/* { dg-final { scan-assembler "ldp\tx30, x19, \\\[sp\\\]" } } */
+ 
+-- 
+2.33.0
+
diff --git a/0205-Backport-SME-aarch64-Switch-PSTATE.SM-around-calls.patch b/0205-Backport-SME-aarch64-Switch-PSTATE.SM-around-calls.patch
new file mode 100644
index 0000000..d0a23d2
--- /dev/null
+++ b/0205-Backport-SME-aarch64-Switch-PSTATE.SM-around-calls.patch
@@ -0,0 +1,3270 @@
+From 88a41bc24eb793eee27aa9f4ef6b763b3c3e76e6 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:25 +0000
+Subject: [PATCH 106/157] [Backport][SME] aarch64: Switch PSTATE.SM around
+ calls
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=dd8090f40079fa41ee58d9f76b2e50ed4f95c6bf
+
+This patch adds support for switching to the appropriate SME mode
+for each call.  Switching to streaming mode requires an SMSTART SM
+instruction and switching to non-streaming mode requires an SMSTOP SM
+instruction.  If the call is being made from streaming-compatible code,
+these switches are conditional on the current mode being the opposite
+of the one that the call needs.
+
+Since changing PSTATE.SM changes the vector length and effectively
+changes the ISA, the code to do the switching has to be emitted late.
+The patch does this using a new pass that runs next to late prologue/
+epilogue insertion.  (It doesn't use md_reorg because later additions
+need the CFG.)
+
+If a streaming-compatible function needs to switch mode for a call,
+it must restore the original mode afterwards.  The old mode must
+therefore be available immediately after the call.  The easiest
+way of ensuring this is to force the use of a hard frame pointer
+and ensure that the old state is saved at an in-range offset
+from there.
+
+Changing modes clobbers the Z and P registers, so we need to
+save and restore live Z and P state around each mode switch.
+However, mode switches are not expected to be performance
+critical, so it seemed better to err on the side of being
+correct rather than trying to optimise the save and restore
+with surrounding code.
+
+gcc/
+	* config/aarch64/aarch64-passes.def
+	(pass_late_thread_prologue_and_epilogue): New pass.
+	* config/aarch64/aarch64-sme.md: New file.
+	* config/aarch64/aarch64.md: Include it.
+	(*tb1): Rename to...
+	(@aarch64_tb): ...this.
+	(call, call_value, sibcall, sibcall_value): Don't require operand 2
+	to be a CONST_INT.
+	* config/aarch64/aarch64-protos.h (aarch64_emit_call_insn): Return
+	the insn.
+	(make_pass_switch_sm_state): Declare.
+	* config/aarch64/aarch64.h (TARGET_STREAMING_COMPATIBLE): New macro.
+	(CALL_USED_REGISTER): Mark VG as call-preserved.
+	(aarch64_frame::old_svcr_offset): New member variable.
+	(machine_function::call_switches_sm_state): Likewise.
+	(CUMULATIVE_ARGS::num_sme_mode_switch_args): Likewise.
+	(CUMULATIVE_ARGS::sme_mode_switch_args): Likewise.
+	* config/aarch64/aarch64.cc: Include tree-pass.h and cfgbuild.h.
+	(aarch64_cfun_incoming_pstate_sm): New function.
+	(aarch64_call_switches_pstate_sm): Likewise.
+	(aarch64_reg_save_mode): Return DImode for VG_REGNUM.
+	(aarch64_callee_isa_mode): New function.
+	(aarch64_insn_callee_isa_mode): Likewise.
+	(aarch64_guard_switch_pstate_sm): Likewise.
+	(aarch64_switch_pstate_sm): Likewise.
+	(aarch64_sme_mode_switch_regs): New class.
+	(aarch64_record_sme_mode_switch_args): New function.
+	(aarch64_finish_sme_mode_switch_args): Likewise.
+	(aarch64_function_arg): Handle the end marker by returning a
+	PARALLEL that contains the ABI cookie that we used previously
+	alongside the result of aarch64_finish_sme_mode_switch_args.
+	(aarch64_init_cumulative_args): Initialize num_sme_mode_switch_args.
+	(aarch64_function_arg_advance): If a call would switch SM state,
+	record all argument registers that would need to be saved around
+	the mode switch.
+	(aarch64_need_old_pstate_sm): New function.
+	(aarch64_layout_frame): Decide whether the frame needs to store the
+	incoming value of PSTATE.SM and allocate a save slot for it if so.
+	If a function switches SME state, arrange to save the old value
+	of the DWARF VG register.  Handle the case where this is the only
+	register save slot above the FP.
+	(aarch64_save_callee_saves): Handles saves of the DWARF VG register.
+	(aarch64_get_separate_components): Prevent such saves from being
+	shrink-wrapped.
+	(aarch64_old_svcr_mem): New function.
+	(aarch64_read_old_svcr): Likewise.
+	(aarch64_guard_switch_pstate_sm): Likewise.
+	(aarch64_expand_prologue): Handle saves of the DWARF VG register.
+	Initialize any SVCR save slot.
+	(aarch64_expand_call): Allow the cookie to be PARALLEL that contains
+	both the UNSPEC_CALLEE_ABI value and a list of registers that need
+	to be preserved across a change to PSTATE.SM.  If the call does
+	involve such a change to PSTATE.SM, record the registers that
+	would be clobbered by this process.  Also emit an instruction
+	to mark the temporary change in VG.  Update call_switches_pstate_sm.
+	(aarch64_emit_call_insn): Return the emitted instruction.
+	(aarch64_frame_pointer_required): New function.
+	(aarch64_conditional_register_usage): Prevent VG_REGNUM from being
+	treated as a register operand.
+	(aarch64_switch_pstate_sm_for_call): New function.
+	(pass_data_switch_pstate_sm): New pass variable.
+	(pass_switch_pstate_sm): New pass class.
+	(make_pass_switch_pstate_sm): New function.
+	(TARGET_FRAME_POINTER_REQUIRED): Define.
+	* config/aarch64/t-aarch64 (s-check-sve-md): Add aarch64-sme.md.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/call_sm_switch_1.c: New test.
+	* gcc.target/aarch64/sme/call_sm_switch_2.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_3.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_4.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_5.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_6.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_7.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_8.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_9.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_10.c: Likewise.
+---
+ gcc/config/aarch64/aarch64-passes.def         |   1 +
+ gcc/config/aarch64/aarch64-protos.h           |   3 +-
+ gcc/config/aarch64/aarch64-sme.md             | 171 ++++
+ gcc/config/aarch64/aarch64.cc                 | 883 +++++++++++++++++-
+ gcc/config/aarch64/aarch64.h                  |  25 +-
+ gcc/config/aarch64/aarch64.md                 |  13 +-
+ gcc/config/aarch64/t-aarch64                  |   5 +-
+ .../gcc.target/aarch64/sme/call_sm_switch_1.c | 233 +++++
+ .../aarch64/sme/call_sm_switch_10.c           |  37 +
+ .../gcc.target/aarch64/sme/call_sm_switch_2.c |  43 +
+ .../gcc.target/aarch64/sme/call_sm_switch_3.c | 166 ++++
+ .../gcc.target/aarch64/sme/call_sm_switch_4.c |  43 +
+ .../gcc.target/aarch64/sme/call_sm_switch_5.c | 318 +++++++
+ .../gcc.target/aarch64/sme/call_sm_switch_6.c |  45 +
+ .../gcc.target/aarch64/sme/call_sm_switch_7.c | 516 ++++++++++
+ .../gcc.target/aarch64/sme/call_sm_switch_8.c |  87 ++
+ .../gcc.target/aarch64/sme/call_sm_switch_9.c | 103 ++
+ 17 files changed, 2668 insertions(+), 24 deletions(-)
+ create mode 100644 gcc/config/aarch64/aarch64-sme.md
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_10.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_6.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_7.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_9.c
+
+diff --git a/gcc/config/aarch64/aarch64-passes.def b/gcc/config/aarch64/aarch64-passes.def
+index a2babc112..c6cbbf2ef 100644
+--- a/gcc/config/aarch64/aarch64-passes.def
++++ b/gcc/config/aarch64/aarch64-passes.def
+@@ -20,6 +20,7 @@
+ 
+ INSERT_PASS_AFTER (pass_regrename, 1, pass_fma_steering);
+ INSERT_PASS_BEFORE (pass_reorder_blocks, 1, pass_track_speculation);
++INSERT_PASS_BEFORE (pass_late_thread_prologue_and_epilogue, 1, pass_switch_pstate_sm);
+ INSERT_PASS_AFTER (pass_machine_reorg, 1, pass_tag_collision_avoidance);
+ INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_bti);
+ INSERT_PASS_AFTER (pass_if_after_combine, 1, pass_cc_fusion);
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 9b03410dc..737f47026 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -913,7 +913,7 @@ void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
+ 				   const_tree, unsigned, bool = false);
+ void aarch64_init_expanders (void);
+ void aarch64_init_simd_builtins (void);
+-void aarch64_emit_call_insn (rtx);
++rtx_call_insn *aarch64_emit_call_insn (rtx);
+ void aarch64_register_pragmas (void);
+ void aarch64_relayout_simd_types (void);
+ void aarch64_reset_previous_fndecl (void);
+@@ -1055,6 +1055,7 @@ rtl_opt_pass *make_pass_track_speculation (gcc::context *);
+ rtl_opt_pass *make_pass_tag_collision_avoidance (gcc::context *);
+ rtl_opt_pass *make_pass_insert_bti (gcc::context *ctxt);
+ rtl_opt_pass *make_pass_cc_fusion (gcc::context *ctxt);
++rtl_opt_pass *make_pass_switch_pstate_sm (gcc::context *ctxt);
+ 
+ poly_uint64 aarch64_regmode_natural_size (machine_mode);
+ 
+diff --git a/gcc/config/aarch64/aarch64-sme.md b/gcc/config/aarch64/aarch64-sme.md
+new file mode 100644
+index 000000000..52427b4f1
+--- /dev/null
++++ b/gcc/config/aarch64/aarch64-sme.md
+@@ -0,0 +1,171 @@
++;; Machine description for AArch64 SME.
++;; Copyright (C) 2023 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
++;; .
++
++;; The file is organised into the following sections (search for the full
++;; line):
++;;
++;; == State management
++;; ---- Test current state
++;; ---- PSTATE.SM management
++
++;; =========================================================================
++;; == State management
++;; =========================================================================
++;;
++;; Many of the instructions in this section are only valid when SME is
++;; present.  However, they don't have a TARGET_SME condition since
++;; (a) they are only emitted under direct control of aarch64 code and
++;; (b) they are sometimes used conditionally, particularly in streaming-
++;; compatible code.
++;;
++;; =========================================================================
++
++;; -------------------------------------------------------------------------
++;; ---- Test current state
++;; -------------------------------------------------------------------------
++
++(define_c_enum "unspec" [
++  UNSPEC_OLD_VG_SAVED
++  UNSPEC_UPDATE_VG
++  UNSPEC_GET_SME_STATE
++  UNSPEC_READ_SVCR
++])
++
++;; A marker instruction to say that the old value of the DWARF VG register
++;; has been saved to the stack, for CFI purposes.  Operand 0 is the old
++;; value of the register and operand 1 is the save slot.
++(define_insn "aarch64_old_vg_saved"
++  [(set (reg:DI VG_REGNUM)
++	(unspec:DI [(match_operand 0)
++		    (match_operand 1)] UNSPEC_OLD_VG_SAVED))]
++  ""
++  ""
++  [(set_attr "type" "no_insn")]
++)
++
++;; A marker to indicate places where a call temporarily changes VG.
++(define_insn "aarch64_update_vg"
++  [(set (reg:DI VG_REGNUM)
++	(unspec:DI [(reg:DI VG_REGNUM)] UNSPEC_UPDATE_VG))]
++  ""
++  ""
++  [(set_attr "type" "no_insn")]
++)
++
++(define_insn "aarch64_get_sme_state"
++  [(set (reg:TI R0_REGNUM)
++	(unspec_volatile:TI [(const_int 0)] UNSPEC_GET_SME_STATE))
++   (clobber (reg:DI R16_REGNUM))
++   (clobber (reg:DI R17_REGNUM))
++   (clobber (reg:DI R18_REGNUM))
++   (clobber (reg:DI R30_REGNUM))
++   (clobber (reg:CC CC_REGNUM))]
++  ""
++  "bl\t__arm_sme_state"
++)
++
++(define_insn "aarch64_read_svcr"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(unspec_volatile:DI [(const_int 0)] UNSPEC_READ_SVCR))]
++  ""
++  "mrs\t%0, svcr"
++)
++
++;; -------------------------------------------------------------------------
++;; ---- PSTATE.SM management
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - SMSTART SM
++;; - SMSTOP SM
++;; -------------------------------------------------------------------------
++
++(define_c_enum "unspec" [
++  UNSPEC_SMSTART_SM
++  UNSPEC_SMSTOP_SM
++])
++
++;; Turn on streaming mode.  This clobbers all SVE state.
++;;
++;; Depend on VG_REGNUM to ensure that the VG save slot has already been
++;; initialized.
++(define_insn "aarch64_smstart_sm"
++  [(unspec_volatile [(const_int 0)] UNSPEC_SMSTART_SM)
++   (use (reg:DI VG_REGNUM))
++   (clobber (reg:V4x16QI V0_REGNUM))
++   (clobber (reg:V4x16QI V4_REGNUM))
++   (clobber (reg:V4x16QI V8_REGNUM))
++   (clobber (reg:V4x16QI V12_REGNUM))
++   (clobber (reg:V4x16QI V16_REGNUM))
++   (clobber (reg:V4x16QI V20_REGNUM))
++   (clobber (reg:V4x16QI V24_REGNUM))
++   (clobber (reg:V4x16QI V28_REGNUM))
++   (clobber (reg:VNx16BI P0_REGNUM))
++   (clobber (reg:VNx16BI P1_REGNUM))
++   (clobber (reg:VNx16BI P2_REGNUM))
++   (clobber (reg:VNx16BI P3_REGNUM))
++   (clobber (reg:VNx16BI P4_REGNUM))
++   (clobber (reg:VNx16BI P5_REGNUM))
++   (clobber (reg:VNx16BI P6_REGNUM))
++   (clobber (reg:VNx16BI P7_REGNUM))
++   (clobber (reg:VNx16BI P8_REGNUM))
++   (clobber (reg:VNx16BI P9_REGNUM))
++   (clobber (reg:VNx16BI P10_REGNUM))
++   (clobber (reg:VNx16BI P11_REGNUM))
++   (clobber (reg:VNx16BI P12_REGNUM))
++   (clobber (reg:VNx16BI P13_REGNUM))
++   (clobber (reg:VNx16BI P14_REGNUM))
++   (clobber (reg:VNx16BI P15_REGNUM))]
++  ""
++  "smstart\tsm"
++)
++
++;; Turn off streaming mode.  This clobbers all SVE state.
++;;
++;; Depend on VG_REGNUM to ensure that the VG save slot has already been
++;; initialized.
++(define_insn "aarch64_smstop_sm"
++  [(unspec_volatile [(const_int 0)] UNSPEC_SMSTOP_SM)
++   (use (reg:DI VG_REGNUM))
++   (clobber (reg:V4x16QI V0_REGNUM))
++   (clobber (reg:V4x16QI V4_REGNUM))
++   (clobber (reg:V4x16QI V8_REGNUM))
++   (clobber (reg:V4x16QI V12_REGNUM))
++   (clobber (reg:V4x16QI V16_REGNUM))
++   (clobber (reg:V4x16QI V20_REGNUM))
++   (clobber (reg:V4x16QI V24_REGNUM))
++   (clobber (reg:V4x16QI V28_REGNUM))
++   (clobber (reg:VNx16BI P0_REGNUM))
++   (clobber (reg:VNx16BI P1_REGNUM))
++   (clobber (reg:VNx16BI P2_REGNUM))
++   (clobber (reg:VNx16BI P3_REGNUM))
++   (clobber (reg:VNx16BI P4_REGNUM))
++   (clobber (reg:VNx16BI P5_REGNUM))
++   (clobber (reg:VNx16BI P6_REGNUM))
++   (clobber (reg:VNx16BI P7_REGNUM))
++   (clobber (reg:VNx16BI P8_REGNUM))
++   (clobber (reg:VNx16BI P9_REGNUM))
++   (clobber (reg:VNx16BI P10_REGNUM))
++   (clobber (reg:VNx16BI P11_REGNUM))
++   (clobber (reg:VNx16BI P12_REGNUM))
++   (clobber (reg:VNx16BI P13_REGNUM))
++   (clobber (reg:VNx16BI P14_REGNUM))
++   (clobber (reg:VNx16BI P15_REGNUM))]
++  ""
++  "smstop\tsm"
++)
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 1c127192d..82f8e574e 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -82,6 +82,8 @@
+ #include "tree-dfa.h"
+ #include "asan.h"
+ #include "aarch64-feature-deps.h"
++#include "tree-pass.h"
++#include "cfgbuild.h"
+ 
+ /* This file should be included last.  */
+ #include "target-def.h"
+@@ -4377,6 +4379,26 @@ aarch64_fndecl_isa_mode (const_tree fndecl)
+   return aarch64_fndecl_pstate_sm (fndecl);
+ }
+ 
++/* Return the state of PSTATE.SM on entry to the current function.
++   This might be different from the state of PSTATE.SM in the function
++   body.  */
++
++static aarch64_feature_flags
++aarch64_cfun_incoming_pstate_sm ()
++{
++  return aarch64_fntype_pstate_sm (TREE_TYPE (cfun->decl));
++}
++
++/* Return true if a call from the current function to a function with
++   ISA mode CALLEE_MODE would involve a change to PSTATE.SM around
++   the BL instruction.  */
++
++static bool
++aarch64_call_switches_pstate_sm (aarch64_feature_flags callee_mode)
++{
++  return (callee_mode & ~AARCH64_ISA_MODE & AARCH64_FL_SM_STATE) != 0;
++}
++
+ /* Implement TARGET_COMPATIBLE_VECTOR_TYPES_P.  */
+ 
+ static bool
+@@ -4400,7 +4422,7 @@ aarch64_emit_cfi_for_reg_p (unsigned int regno)
+ static machine_mode
+ aarch64_reg_save_mode (unsigned int regno)
+ {
+-  if (GP_REGNUM_P (regno))
++  if (GP_REGNUM_P (regno) || regno == VG_REGNUM)
+     return DImode;
+ 
+   if (FP_REGNUM_P (regno))
+@@ -4459,6 +4481,16 @@ aarch64_callee_abi (rtx cookie)
+   return function_abis[UINTVAL (cookie) >> AARCH64_NUM_ISA_MODES];
+ }
+ 
++/* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx.  Return the
++   required ISA mode on entry to the callee, which is also the ISA
++   mode on return from the callee.  */
++
++static aarch64_feature_flags
++aarch64_callee_isa_mode (rtx cookie)
++{
++  return UINTVAL (cookie) & AARCH64_FL_ISA_MODES;
++}
++
+ /* INSN is a call instruction.  Return the CONST_INT stored in its
+    UNSPEC_CALLEE_ABI rtx.  */
+ 
+@@ -4481,6 +4513,15 @@ aarch64_insn_callee_abi (const rtx_insn *insn)
+   return aarch64_callee_abi (aarch64_insn_callee_cookie (insn));
+ }
+ 
++/* INSN is a call instruction.  Return the required ISA mode on entry to
++   the callee, which is also the ISA mode on return from the callee.  */
++
++static aarch64_feature_flags
++aarch64_insn_callee_isa_mode (const rtx_insn *insn)
++{
++  return aarch64_callee_isa_mode (aarch64_insn_callee_cookie (insn));
++}
++
+ /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The callee only saves
+    the lower 64 bits of a 128-bit register.  Tell the compiler the callee
+    clobbers the top 64 bits when restoring the bottom 64 bits.  */
+@@ -6645,6 +6686,437 @@ aarch64_sub_sp (rtx temp1, rtx temp2, poly_int64 delta, bool frame_related_p,
+ 		      temp1, temp2, frame_related_p, emit_move_imm);
+ }
+ 
++/* A streaming-compatible function needs to switch temporarily to the known
++   PSTATE.SM mode described by LOCAL_MODE.  The low bit of OLD_SVCR contains
++   the runtime state of PSTATE.SM in the streaming-compatible code, before
++   the start of the switch to LOCAL_MODE.
++
++   Emit instructions to branch around the mode switch if PSTATE.SM already
++   matches LOCAL_MODE.  Return the label that the branch jumps to.  */
++
++static rtx_insn *
++aarch64_guard_switch_pstate_sm (rtx old_svcr, aarch64_feature_flags local_mode)
++{
++  local_mode &= AARCH64_FL_SM_STATE;
++  gcc_assert (local_mode != 0);
++  auto already_ok_cond = (local_mode & AARCH64_FL_SM_ON ? NE : EQ);
++  auto *label = gen_label_rtx ();
++  auto *jump = emit_jump_insn (gen_aarch64_tb (already_ok_cond, DImode, DImode,
++					       old_svcr, const0_rtx, label));
++  JUMP_LABEL (jump) = label;
++  return label;
++}
++
++/* Emit code to switch from the PSTATE.SM state in OLD_MODE to the PSTATE.SM
++   state in NEW_MODE.  This is known to involve either an SMSTART SM or
++   an SMSTOP SM.  */
++
++static void
++aarch64_switch_pstate_sm (aarch64_feature_flags old_mode,
++			  aarch64_feature_flags new_mode)
++{
++  old_mode &= AARCH64_FL_SM_STATE;
++  new_mode &= AARCH64_FL_SM_STATE;
++  gcc_assert (old_mode != new_mode);
++
++  if ((new_mode & AARCH64_FL_SM_ON)
++      || (new_mode == 0 && (old_mode & AARCH64_FL_SM_OFF)))
++    emit_insn (gen_aarch64_smstart_sm ());
++  else
++    emit_insn (gen_aarch64_smstop_sm ());
++}
++
++/* As a side-effect, SMSTART SM and SMSTOP SM clobber the contents of all
++   FP and predicate registers.  This class emits code to preserve any
++   necessary registers around the mode switch.
++
++   The class uses four approaches to saving and restoring contents, enumerated
++   by group_type:
++
++   - GPR: save and restore the contents of FP registers using GPRs.
++     This is used if the FP register contains no more than 64 significant
++     bits.  The registers used are FIRST_GPR onwards.
++
++   - MEM_128: save and restore 128-bit SIMD registers using memory.
++
++   - MEM_SVE_PRED: save and restore full SVE predicate registers using memory.
++
++   - MEM_SVE_DATA: save and restore full SVE vector registers using memory.
++
++   The save slots within each memory group are consecutive, with the
++   MEM_SVE_PRED slots occupying a region below the MEM_SVE_DATA slots.
++
++   There will only be two mode switches for each use of SME, so they should
++   not be particularly performance-sensitive.  It's also rare for SIMD, SVE
++   or predicate registers to be live across mode switches.  We therefore
++   don't preallocate the save slots but instead allocate them locally on
++   demand.  This makes the code emitted by the class self-contained.  */
++
++class aarch64_sme_mode_switch_regs
++{
++public:
++  static const unsigned int FIRST_GPR = R10_REGNUM;
++
++  void add_reg (machine_mode, unsigned int);
++  void add_call_args (rtx_call_insn *);
++  void add_call_result (rtx_call_insn *);
++
++  void emit_prologue ();
++  void emit_epilogue ();
++
++  /* The number of GPRs needed to save FP registers, starting from
++     FIRST_GPR.  */
++  unsigned int num_gprs () { return m_group_count[GPR]; }
++
++private:
++  enum sequence { PROLOGUE, EPILOGUE };
++  enum group_type { GPR, MEM_128, MEM_SVE_PRED, MEM_SVE_DATA, NUM_GROUPS };
++
++  /* Information about the save location for one FP, SIMD, SVE data, or
++     SVE predicate register.  */
++  struct save_location {
++    /* The register to be saved.  */
++    rtx reg;
++
++    /* Which group the save location belongs to.  */
++    group_type group;
++
++    /* A zero-based index of the register within the group.  */
++    unsigned int index;
++  };
++
++  unsigned int sve_data_headroom ();
++  rtx get_slot_mem (machine_mode, poly_int64);
++  void emit_stack_adjust (sequence, poly_int64);
++  void emit_mem_move (sequence, const save_location &, poly_int64);
++
++  void emit_gpr_moves (sequence);
++  void emit_mem_128_moves (sequence);
++  void emit_sve_sp_adjust (sequence);
++  void emit_sve_pred_moves (sequence);
++  void emit_sve_data_moves (sequence);
++
++  /* All save locations, in no particular order.  */
++  auto_vec m_save_locations;
++
++  /* The number of registers in each group.  */
++  unsigned int m_group_count[NUM_GROUPS] = {};
++};
++
++/* Record that (reg:MODE REGNO) needs to be preserved around the mode
++   switch.  */
++
++void
++aarch64_sme_mode_switch_regs::add_reg (machine_mode mode, unsigned int regno)
++{
++  if (!FP_REGNUM_P (regno) && !PR_REGNUM_P (regno))
++    return;
++
++  unsigned int end_regno = end_hard_regno (mode, regno);
++  unsigned int vec_flags = aarch64_classify_vector_mode (mode);
++  gcc_assert ((vec_flags & VEC_STRUCT) || end_regno == regno + 1);
++  for (; regno < end_regno; regno++)
++    {
++      machine_mode submode = mode;
++      if (vec_flags & VEC_STRUCT)
++	{
++	  if (vec_flags & VEC_SVE_DATA)
++	    submode = SVE_BYTE_MODE;
++	  else if (vec_flags & VEC_PARTIAL)
++	    submode = V8QImode;
++	  else
++	    submode = V16QImode;
++	}
++      save_location loc;
++      loc.reg = gen_rtx_REG (submode, regno);
++      if (vec_flags == VEC_SVE_PRED)
++	{
++	  gcc_assert (PR_REGNUM_P (regno));
++	  loc.group = MEM_SVE_PRED;
++	}
++      else
++	{
++	  gcc_assert (FP_REGNUM_P (regno));
++	  if (known_le (GET_MODE_SIZE (submode), 8))
++	    loc.group = GPR;
++	  else if (known_eq (GET_MODE_SIZE (submode), 16))
++	    loc.group = MEM_128;
++	  else
++	    loc.group = MEM_SVE_DATA;
++	}
++      loc.index = m_group_count[loc.group]++;
++      m_save_locations.quick_push (loc);
++    }
++}
++
++/* Record that the arguments to CALL_INSN need to be preserved around
++   the mode switch.  */
++
++void
++aarch64_sme_mode_switch_regs::add_call_args (rtx_call_insn *call_insn)
++{
++  for (rtx node = CALL_INSN_FUNCTION_USAGE (call_insn);
++       node; node = XEXP (node, 1))
++    {
++      rtx item = XEXP (node, 0);
++      if (GET_CODE (item) != USE)
++	continue;
++      item = XEXP (item, 0);
++      if (!REG_P (item))
++	continue;
++      add_reg (GET_MODE (item), REGNO (item));
++    }
++}
++
++/* Record that the return value from CALL_INSN (if any) needs to be
++   preserved around the mode switch.  */
++
++void
++aarch64_sme_mode_switch_regs::add_call_result (rtx_call_insn *call_insn)
++{
++  rtx pat = PATTERN (call_insn);
++  gcc_assert (GET_CODE (pat) == PARALLEL);
++  pat = XVECEXP (pat, 0, 0);
++  if (GET_CODE (pat) == CALL)
++    return;
++  rtx dest = SET_DEST (pat);
++  if (GET_CODE (dest) == PARALLEL)
++    for (int i = 0; i < XVECLEN (dest, 0); ++i)
++      {
++	rtx x = XVECEXP (dest, 0, i);
++	gcc_assert (GET_CODE (x) == EXPR_LIST);
++	rtx reg = XEXP (x, 0);
++	add_reg (GET_MODE (reg), REGNO (reg));
++      }
++  else
++    add_reg (GET_MODE (dest), REGNO (dest));
++}
++
++/* Emit code to save registers before the mode switch.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_prologue ()
++{
++  emit_sve_sp_adjust (PROLOGUE);
++  emit_sve_pred_moves (PROLOGUE);
++  emit_sve_data_moves (PROLOGUE);
++  emit_mem_128_moves (PROLOGUE);
++  emit_gpr_moves (PROLOGUE);
++}
++
++/* Emit code to restore registers after the mode switch.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_epilogue ()
++{
++  emit_gpr_moves (EPILOGUE);
++  emit_mem_128_moves (EPILOGUE);
++  emit_sve_pred_moves (EPILOGUE);
++  emit_sve_data_moves (EPILOGUE);
++  emit_sve_sp_adjust (EPILOGUE);
++}
++
++/* The SVE predicate registers are stored below the SVE data registers,
++   with the predicate save area being padded to a data-register-sized
++   boundary.  Return the size of this padded area as a whole number
++   of data register slots.  */
++
++unsigned int
++aarch64_sme_mode_switch_regs::sve_data_headroom ()
++{
++  return CEIL (m_group_count[MEM_SVE_PRED], 8);
++}
++
++/* Return a memory reference of mode MODE to OFFSET bytes from the
++   stack pointer.  */
++
++rtx
++aarch64_sme_mode_switch_regs::get_slot_mem (machine_mode mode,
++					    poly_int64 offset)
++{
++  rtx addr = plus_constant (Pmode, stack_pointer_rtx, offset);
++  return gen_rtx_MEM (mode, addr);
++}
++
++/* Allocate or deallocate SIZE bytes of stack space: SEQ decides which.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_stack_adjust (sequence seq,
++						 poly_int64 size)
++{
++  if (seq == PROLOGUE)
++    size = -size;
++  emit_insn (gen_rtx_SET (stack_pointer_rtx,
++			  plus_constant (Pmode, stack_pointer_rtx, size)));
++}
++
++/* Save or restore the register in LOC, whose slot is OFFSET bytes from
++   the stack pointer.  SEQ chooses between saving and restoring.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_mem_move (sequence seq,
++					     const save_location &loc,
++					     poly_int64 offset)
++{
++  rtx mem = get_slot_mem (GET_MODE (loc.reg), offset);
++  if (seq == PROLOGUE)
++    emit_move_insn (mem, loc.reg);
++  else
++    emit_move_insn (loc.reg, mem);
++}
++
++/* Emit instructions to save or restore the GPR group.  SEQ chooses between
++   saving and restoring.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_gpr_moves (sequence seq)
++{
++  for (auto &loc : m_save_locations)
++    if (loc.group == GPR)
++      {
++	gcc_assert (loc.index < 8);
++	rtx gpr = gen_rtx_REG (GET_MODE (loc.reg), FIRST_GPR + loc.index);
++	if (seq == PROLOGUE)
++	  emit_move_insn (gpr, loc.reg);
++	else
++	  emit_move_insn (loc.reg, gpr);
++      }
++}
++
++/* Emit instructions to save or restore the MEM_128 group.  SEQ chooses
++   between saving and restoring.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_mem_128_moves (sequence seq)
++{
++  HOST_WIDE_INT count = m_group_count[MEM_128];
++  if (count == 0)
++    return;
++
++  auto sp = stack_pointer_rtx;
++  auto sp_adjust = (seq == PROLOGUE ? -count : count) * 16;
++
++  /* Pick a common mode that supports LDR & STR with pre/post-modification
++     and LDP & STP with pre/post-modification.  */
++  auto mode = TFmode;
++
++  /* An instruction pattern that should be emitted at the end.  */
++  rtx last_pat = NULL_RTX;
++
++  /* A previous MEM_128 location that hasn't been handled yet.  */
++  save_location *prev_loc = nullptr;
++
++  /* Look for LDP/STPs and record any leftover LDR/STR in PREV_LOC.  */
++  for (auto &loc : m_save_locations)
++    if (loc.group == MEM_128)
++      {
++	if (!prev_loc)
++	  {
++	    prev_loc = &loc;
++	    continue;
++	  }
++	gcc_assert (loc.index == prev_loc->index + 1);
++
++	/* The offset of the base of the save area from the current
++	   stack pointer.  */
++	HOST_WIDE_INT bias = 0;
++	if (prev_loc->index == 0 && seq == PROLOGUE)
++	  bias = sp_adjust;
++
++	/* Get the two sets in the LDP/STP.  */
++	rtx ops[] = {
++	  gen_rtx_REG (mode, REGNO (prev_loc->reg)),
++	  get_slot_mem (mode, prev_loc->index * 16 + bias),
++	  gen_rtx_REG (mode, REGNO (loc.reg)),
++	  get_slot_mem (mode, loc.index * 16 + bias)
++	};
++	unsigned int lhs = (seq == PROLOGUE);
++	rtx set1 = gen_rtx_SET (ops[lhs], ops[1 - lhs]);
++	rtx set2 = gen_rtx_SET (ops[lhs + 2], ops[3 - lhs]);
++
++	/* Combine the sets with any stack allocation/deallocation.  */
++	rtvec vec;
++	if (prev_loc->index == 0)
++	  {
++	    rtx plus_sp = plus_constant (Pmode, sp, sp_adjust);
++	    vec = gen_rtvec (3, gen_rtx_SET (sp, plus_sp), set1, set2);
++	  }
++	else
++	  vec = gen_rtvec (2, set1, set2);
++	rtx pat = gen_rtx_PARALLEL (VOIDmode, vec);
++
++	/* Queue a deallocation to the end, otherwise emit the
++	   instruction now.  */
++	if (seq == EPILOGUE && prev_loc->index == 0)
++	  last_pat = pat;
++	else
++	  emit_insn (pat);
++	prev_loc = nullptr;
++      }
++
++  /* Handle any leftover LDR/STR.  */
++  if (prev_loc)
++    {
++      rtx reg = gen_rtx_REG (mode, REGNO (prev_loc->reg));
++      rtx addr;
++      if (prev_loc->index != 0)
++	addr = plus_constant (Pmode, sp, prev_loc->index * 16);
++      else if (seq == PROLOGUE)
++	{
++	  rtx allocate = plus_constant (Pmode, sp, -count * 16);
++	  addr = gen_rtx_PRE_MODIFY (Pmode, sp, allocate);
++	}
++      else
++	{
++	  rtx deallocate = plus_constant (Pmode, sp, count * 16);
++	  addr = gen_rtx_POST_MODIFY (Pmode, sp, deallocate);
++	}
++      rtx mem = gen_rtx_MEM (mode, addr);
++      if (seq == PROLOGUE)
++	emit_move_insn (mem, reg);
++      else
++	emit_move_insn (reg, mem);
++    }
++
++  if (last_pat)
++    emit_insn (last_pat);
++}
++
++/* Allocate or deallocate the stack space needed by the SVE groups.
++   SEQ chooses between allocating and deallocating.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_sve_sp_adjust (sequence seq)
++{
++  if (unsigned int count = m_group_count[MEM_SVE_DATA] + sve_data_headroom ())
++    emit_stack_adjust (seq, count * BYTES_PER_SVE_VECTOR);
++}
++
++/* Save or restore the MEM_SVE_DATA group.  SEQ chooses between saving
++   and restoring.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_sve_data_moves (sequence seq)
++{
++  for (auto &loc : m_save_locations)
++    if (loc.group == MEM_SVE_DATA)
++      {
++	auto index = loc.index + sve_data_headroom ();
++	emit_mem_move (seq, loc, index * BYTES_PER_SVE_VECTOR);
++      }
++}
++
++/* Save or restore the MEM_SVE_PRED group.  SEQ chooses between saving
++   and restoring.  */
++
++void
++aarch64_sme_mode_switch_regs::emit_sve_pred_moves (sequence seq)
++{
++  for (auto &loc : m_save_locations)
++    if (loc.group == MEM_SVE_PRED)
++      emit_mem_move (seq, loc, loc.index * BYTES_PER_SVE_PRED);
++}
++
+ /* Set DEST to (vec_series BASE STEP).  */
+ 
+ static void
+@@ -8211,6 +8683,40 @@ on_stack:
+   return;
+ }
+ 
++/* Add the current argument register to the set of those that need
++   to be saved and restored around a change to PSTATE.SM.  */
++
++static void
++aarch64_record_sme_mode_switch_args (CUMULATIVE_ARGS *pcum)
++{
++  subrtx_var_iterator::array_type array;
++  FOR_EACH_SUBRTX_VAR (iter, array, pcum->aapcs_reg, NONCONST)
++    {
++      rtx x = *iter;
++      if (REG_P (x) && (FP_REGNUM_P (REGNO (x)) || PR_REGNUM_P (REGNO (x))))
++	{
++	  unsigned int i = pcum->num_sme_mode_switch_args++;
++	  gcc_assert (i < ARRAY_SIZE (pcum->sme_mode_switch_args));
++	  pcum->sme_mode_switch_args[i] = x;
++	}
++    }
++}
++
++/* Return a parallel that contains all the registers that need to be
++   saved around a change to PSTATE.SM.  Return const0_rtx if there is
++   no such mode switch, or if no registers need to be saved.  */
++
++static rtx
++aarch64_finish_sme_mode_switch_args (CUMULATIVE_ARGS *pcum)
++{
++  if (!pcum->num_sme_mode_switch_args)
++    return const0_rtx;
++
++  auto argvec = gen_rtvec_v (pcum->num_sme_mode_switch_args,
++			     pcum->sme_mode_switch_args);
++  return gen_rtx_PARALLEL (VOIDmode, argvec);
++}
++
+ /* Implement TARGET_FUNCTION_ARG.  */
+ 
+ static rtx
+@@ -8222,7 +8728,13 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
+ 	      || pcum->pcs_variant == ARM_PCS_SVE);
+ 
+   if (arg.end_marker_p ())
+-    return aarch64_gen_callee_cookie (pcum->isa_mode, pcum->pcs_variant);
++    {
++      rtx abi_cookie = aarch64_gen_callee_cookie (pcum->isa_mode,
++						  pcum->pcs_variant);
++      rtx sme_mode_switch_args = aarch64_finish_sme_mode_switch_args (pcum);
++      return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, abi_cookie,
++						    sme_mode_switch_args));
++    }
+ 
+   aarch64_layout_arg (pcum_v, arg);
+   return pcum->aapcs_reg;
+@@ -8257,6 +8769,7 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum,
+   pcum->aapcs_stack_words = 0;
+   pcum->aapcs_stack_size = 0;
+   pcum->silent_p = silent_p;
++  pcum->num_sme_mode_switch_args = 0;
+ 
+   if (!silent_p
+       && !TARGET_FLOAT
+@@ -8297,6 +8810,10 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v,
+       aarch64_layout_arg (pcum_v, arg);
+       gcc_assert ((pcum->aapcs_reg != NULL_RTX)
+ 		  != (pcum->aapcs_stack_words != 0));
++      if (pcum->aapcs_reg
++	  && aarch64_call_switches_pstate_sm (pcum->isa_mode))
++	aarch64_record_sme_mode_switch_args (pcum);
++
+       pcum->aapcs_arg_processed = false;
+       pcum->aapcs_ncrn = pcum->aapcs_nextncrn;
+       pcum->aapcs_nvrn = pcum->aapcs_nextnvrn;
+@@ -8747,6 +9264,30 @@ aarch64_save_regs_above_locals_p ()
+   return crtl->stack_protect_guard;
+ }
+ 
++/* Return true if the current function needs to record the incoming
++   value of PSTATE.SM.  */
++static bool
++aarch64_need_old_pstate_sm ()
++{
++  /* Exit early if the incoming value of PSTATE.SM is known at
++     compile time.  */
++  if (aarch64_cfun_incoming_pstate_sm () != 0)
++    return false;
++
++  if (cfun->machine->call_switches_pstate_sm)
++    for (auto insn = get_insns (); insn; insn = NEXT_INSN (insn))
++      if (auto *call = dyn_cast (insn))
++	if (!SIBLING_CALL_P (call))
++	  {
++	    /* Return true if there is a call to a non-streaming-compatible
++	       function.  */
++	    auto callee_isa_mode = aarch64_insn_callee_isa_mode (call);
++	    if (aarch64_call_switches_pstate_sm (callee_isa_mode))
++	      return true;
++	  }
++  return false;
++}
++
+ /* Mark the registers that need to be saved by the callee and calculate
+    the size of the callee-saved registers area and frame record (both FP
+    and LR may be omitted).  */
+@@ -8780,6 +9321,7 @@ aarch64_layout_frame (void)
+   /* First mark all the registers that really need to be saved...  */
+   for (regno = 0; regno <= LAST_SAVED_REGNUM; regno++)
+     frame.reg_offset[regno] = SLOT_NOT_REQUIRED;
++  frame.old_svcr_offset = SLOT_NOT_REQUIRED;
+ 
+   /* ... that includes the eh data registers (if needed)...  */
+   if (crtl->calls_eh_return)
+@@ -8932,6 +9474,21 @@ aarch64_layout_frame (void)
+     if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED))
+       allocate_gpr_slot (regno);
+ 
++  if (aarch64_need_old_pstate_sm ())
++    {
++      frame.old_svcr_offset = offset;
++      offset += UNITS_PER_WORD;
++    }
++
++  /* If the current function changes the SVE vector length, ensure that the
++     old value of the DWARF VG register is saved and available in the CFI,
++     so that outer frames with VL-sized offsets can be processed correctly.  */
++  if (cfun->machine->call_switches_pstate_sm)
++    {
++      frame.reg_offset[VG_REGNUM] = offset;
++      offset += UNITS_PER_WORD;
++    }
++
+   poly_int64 max_int_offset = offset;
+   offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT);
+   bool has_align_gap = maybe_ne (offset, max_int_offset);
+@@ -8969,8 +9526,6 @@ aarch64_layout_frame (void)
+       if (push_regs.size () > 1)
+ 	frame.wb_push_candidate2 = push_regs[1];
+     }
+-  else
+-    gcc_assert (known_eq (saved_regs_size, below_hard_fp_saved_regs_size));
+ 
+   /* With stack-clash, a register must be saved in non-leaf functions.
+      The saving of the bottommost register counts as an implicit probe,
+@@ -9078,7 +9633,8 @@ aarch64_layout_frame (void)
+       frame.initial_adjust = frame.frame_size - frame.bytes_below_saved_regs;
+       frame.final_adjust = frame.bytes_below_saved_regs;
+     }
+-  else if (frame.bytes_above_hard_fp.is_constant (&const_above_fp)
++  else if (frame.wb_push_candidate1 != INVALID_REGNUM
++	   && frame.bytes_above_hard_fp.is_constant (&const_above_fp)
+ 	   && const_above_fp < max_push_offset)
+     {
+       /* Frame with large area below the saved registers, or with SVE saves,
+@@ -9459,7 +10015,13 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 
+       machine_mode mode = aarch64_reg_save_mode (regno);
+       rtx reg = gen_rtx_REG (mode, regno);
++      rtx move_src = reg;
+       offset = frame.reg_offset[regno] - bytes_below_sp;
++      if (regno == VG_REGNUM)
++	{
++	  move_src = gen_rtx_REG (DImode, IP0_REGNUM);
++	  emit_move_insn (move_src, gen_int_mode (aarch64_sve_vg, DImode));
++	}
+       rtx base_rtx = stack_pointer_rtx;
+       poly_int64 sp_offset = offset;
+ 
+@@ -9467,7 +10029,7 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+       if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg,
+ 					     offset, ptrue);
+-      else if (GP_REGNUM_P (regno)
++      else if (GP_REGNUM_P (REGNO (reg))
+ 	       && (!offset.is_constant (&const_offset) || const_offset >= 512))
+ 	{
+ 	  poly_int64 fp_offset = frame.bytes_below_hard_fp - bytes_below_sp;
+@@ -9490,6 +10052,7 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 
+       unsigned int regno2;
+       if (!aarch64_sve_mode_p (mode)
++	  && reg == move_src
+ 	  && i + 1 < regs.size ()
+ 	  && (regno2 = regs[i + 1], !skip_save_p (regno2))
+ 	  && known_eq (GET_MODE_SIZE (mode),
+@@ -9521,17 +10084,24 @@ aarch64_save_callee_saves (poly_int64 bytes_below_sp,
+ 	}
+       else if (mode == VNx2DImode && BYTES_BIG_ENDIAN)
+ 	{
+-	  insn = emit_insn (gen_aarch64_pred_mov (mode, mem, ptrue, reg));
++	  insn = emit_insn (gen_aarch64_pred_mov (mode, mem, ptrue, move_src));
+ 	  need_cfa_note_p = true;
+ 	}
+       else if (aarch64_sve_mode_p (mode))
+-	insn = emit_insn (gen_rtx_SET (mem, reg));
++	insn = emit_insn (gen_rtx_SET (mem, move_src));
+       else
+-	insn = emit_move_insn (mem, reg);
++	insn = emit_move_insn (mem, move_src);
+ 
+       RTX_FRAME_RELATED_P (insn) = frame_related_p;
+       if (frame_related_p && need_cfa_note_p)
+ 	aarch64_add_cfa_expression (insn, reg, stack_pointer_rtx, sp_offset);
++      else if (frame_related_p && move_src != reg)
++	add_reg_note (insn, REG_FRAME_RELATED_EXPR, gen_rtx_SET (mem, reg));
++
++      /* Emit a fake instruction to indicate that the VG save slot has
++	 been initialized.  */
++      if (regno == VG_REGNUM)
++	emit_insn (gen_aarch64_old_vg_saved (move_src, mem));
+     }
+ }
+ 
+@@ -9754,6 +10324,10 @@ aarch64_get_separate_components (void)
+ 	bitmap_clear_bit (components, frame.hard_fp_save_and_probe);
+     }
+ 
++  /* The VG save sequence needs a temporary GPR.  Punt for now on trying
++     to find one.  */
++  bitmap_clear_bit (components, VG_REGNUM);
++
+   return components;
+ }
+ 
+@@ -10249,6 +10823,47 @@ aarch64_epilogue_uses (int regno)
+   return 0;
+ }
+ 
++/* The current function's frame has a save slot for the incoming state
++   of SVCR.  Return a legitimate memory for the slot, based on the hard
++   frame pointer.  */
++
++static rtx
++aarch64_old_svcr_mem ()
++{
++  gcc_assert (frame_pointer_needed
++	      && known_ge (cfun->machine->frame.old_svcr_offset, 0));
++  rtx base = hard_frame_pointer_rtx;
++  poly_int64 offset = (0
++		       /* hard fp -> bottom of frame.  */
++		       - cfun->machine->frame.bytes_below_hard_fp
++		       /* bottom of frame -> save slot.  */
++		       + cfun->machine->frame.old_svcr_offset);
++  return gen_frame_mem (DImode, plus_constant (Pmode, base, offset));
++}
++
++/* The current function's frame has a save slot for the incoming state
++   of SVCR.  Load the slot into register REGNO and return the register.  */
++
++static rtx
++aarch64_read_old_svcr (unsigned int regno)
++{
++  rtx svcr = gen_rtx_REG (DImode, regno);
++  emit_move_insn (svcr, aarch64_old_svcr_mem ());
++  return svcr;
++}
++
++/* Like the rtx version of aarch64_guard_switch_pstate_sm, but first
++   load the incoming value of SVCR from its save slot into temporary
++   register REGNO.  */
++
++static rtx_insn *
++aarch64_guard_switch_pstate_sm (unsigned int regno,
++				aarch64_feature_flags local_mode)
++{
++  rtx old_svcr = aarch64_read_old_svcr (regno);
++  return aarch64_guard_switch_pstate_sm (old_svcr, local_mode);
++}
++
+ /* AArch64 stack frames generated by this compiler look like:
+ 
+ 	+-------------------------------+
+@@ -10463,6 +11078,12 @@ aarch64_expand_prologue (void)
+ 
+   aarch64_save_callee_saves (bytes_below_sp, frame.saved_gprs, true,
+ 			     emit_frame_chain);
++  if (maybe_ge (frame.reg_offset[VG_REGNUM], 0))
++    {
++      unsigned int saved_regs[] = { VG_REGNUM };
++      aarch64_save_callee_saves (bytes_below_sp, saved_regs, true,
++				 emit_frame_chain);
++    }
+   if (maybe_ne (sve_callee_adjust, 0))
+     {
+       gcc_assert (!flag_stack_clash_protection
+@@ -10484,6 +11105,40 @@ aarch64_expand_prologue (void)
+ 					  !frame_pointer_needed, true);
+   if (emit_frame_chain && maybe_ne (final_adjust, 0))
+     aarch64_emit_stack_tie (hard_frame_pointer_rtx);
++
++  /* Save the incoming value of PSTATE.SM, if required.  */
++  if (known_ge (frame.old_svcr_offset, 0))
++    {
++      rtx mem = aarch64_old_svcr_mem ();
++      MEM_VOLATILE_P (mem) = 1;
++      if (TARGET_SME)
++	{
++	  rtx reg = gen_rtx_REG (DImode, IP0_REGNUM);
++	  emit_insn (gen_aarch64_read_svcr (reg));
++	  emit_move_insn (mem, reg);
++	}
++      else
++	{
++	  rtx old_r0 = NULL_RTX, old_r1 = NULL_RTX;
++	  auto &args = crtl->args.info;
++	  if (args.aapcs_ncrn > 0)
++	    {
++	      old_r0 = gen_rtx_REG (DImode, PROBE_STACK_FIRST_REGNUM);
++	      emit_move_insn (old_r0, gen_rtx_REG (DImode, R0_REGNUM));
++	    }
++	  if (args.aapcs_ncrn > 1)
++	    {
++	      old_r1 = gen_rtx_REG (DImode, PROBE_STACK_SECOND_REGNUM);
++	      emit_move_insn (old_r1, gen_rtx_REG (DImode, R1_REGNUM));
++	    }
++	  emit_insn (gen_aarch64_get_sme_state ());
++	  emit_move_insn (mem, gen_rtx_REG (DImode, R0_REGNUM));
++	  if (old_r0)
++	    emit_move_insn (gen_rtx_REG (DImode, R0_REGNUM), old_r0);
++	  if (old_r1)
++	    emit_move_insn (gen_rtx_REG (DImode, R1_REGNUM), old_r1);
++	}
++    }
+ }
+ 
+ /* Return TRUE if we can use a simple_return insn.
+@@ -11730,17 +12385,33 @@ aarch64_start_call_args (cumulative_args_t ca_v)
+    RESULT is the register in which the result is returned.  It's NULL for
+    "call" and "sibcall".
+    MEM is the location of the function call.
+-   CALLEE_ABI is a const_int that gives the arm_pcs of the callee.
++   COOKIE is either:
++     - a const_int that gives the argument to the call's UNSPEC_CALLEE_ABI.
++     - a PARALLEL that contains such a const_int as its first element.
++       The second element is a PARALLEL that lists all the argument
++       registers that need to be saved and restored around a change
++       in PSTATE.SM, or const0_rtx if no such switch is needed.
+    SIBCALL indicates whether this function call is normal call or sibling call.
+    It will generate different pattern accordingly.  */
+ 
+ void
+-aarch64_expand_call (rtx result, rtx mem, rtx callee_abi, bool sibcall)
++aarch64_expand_call (rtx result, rtx mem, rtx cookie, bool sibcall)
+ {
+   rtx call, callee, tmp;
+   rtvec vec;
+   machine_mode mode;
+ 
++  rtx callee_abi = cookie;
++  rtx sme_mode_switch_args = const0_rtx;
++  if (GET_CODE (cookie) == PARALLEL)
++    {
++      callee_abi = XVECEXP (cookie, 0, 0);
++      sme_mode_switch_args = XVECEXP (cookie, 0, 1);
++    }
++
++  gcc_assert (CONST_INT_P (callee_abi));
++  auto callee_isa_mode = aarch64_callee_isa_mode (callee_abi);
++
+   gcc_assert (MEM_P (mem));
+   callee = XEXP (mem, 0);
+   mode = GET_MODE (callee);
+@@ -11765,26 +12436,75 @@ aarch64_expand_call (rtx result, rtx mem, rtx callee_abi, bool sibcall)
+   else
+     tmp = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM));
+ 
+-  gcc_assert (CONST_INT_P (callee_abi));
+   callee_abi = gen_rtx_UNSPEC (DImode, gen_rtvec (1, callee_abi),
+ 			       UNSPEC_CALLEE_ABI);
+ 
+   vec = gen_rtvec (3, call, callee_abi, tmp);
+   call = gen_rtx_PARALLEL (VOIDmode, vec);
+ 
+-  aarch64_emit_call_insn (call);
++  auto call_insn = aarch64_emit_call_insn (call);
++
++  /* Check whether the call requires a change to PSTATE.SM.  We can't
++     emit the instructions to change PSTATE.SM yet, since they involve
++     a change in vector length and a change in instruction set, which
++     cannot be represented in RTL.
++
++     For now, just record which registers will be clobbered and used
++     by the changes to PSTATE.SM.  */
++  if (!sibcall && aarch64_call_switches_pstate_sm (callee_isa_mode))
++    {
++      aarch64_sme_mode_switch_regs args_switch;
++      if (sme_mode_switch_args != const0_rtx)
++	{
++	  unsigned int num_args = XVECLEN (sme_mode_switch_args, 0);
++	  for (unsigned int i = 0; i < num_args; ++i)
++	    {
++	      rtx x = XVECEXP (sme_mode_switch_args, 0, i);
++	      args_switch.add_reg (GET_MODE (x), REGNO (x));
++	    }
++	}
++
++      aarch64_sme_mode_switch_regs result_switch;
++      if (result)
++	result_switch.add_call_result (call_insn);
++
++      unsigned int num_gprs = MAX (args_switch.num_gprs (),
++				   result_switch.num_gprs ());
++      for (unsigned int i = 0; i < num_gprs; ++i)
++	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++		     gen_rtx_REG (DImode, args_switch.FIRST_GPR + i));
++
++      for (int regno = V0_REGNUM; regno < V0_REGNUM + 32; regno += 4)
++	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++		     gen_rtx_REG (V4x16QImode, regno));
++
++      for (int regno = P0_REGNUM; regno < P0_REGNUM + 16; regno += 1)
++	clobber_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++		     gen_rtx_REG (VNx16BImode, regno));
++
++      /* Ensure that the VG save slot has been initialized.  Also emit
++	 an instruction to model the effect of the temporary clobber
++	 of VG, so that the prologue/epilogue pass sees the need to
++	 save the old value.  */
++      use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++	       gen_rtx_REG (DImode, VG_REGNUM));
++      emit_insn_before (gen_aarch64_update_vg (), call_insn);
++
++      cfun->machine->call_switches_pstate_sm = true;
++    }
+ }
+ 
+ /* Emit call insn with PAT and do aarch64-specific handling.  */
+ 
+-void
++rtx_call_insn *
+ aarch64_emit_call_insn (rtx pat)
+ {
+-  rtx insn = emit_call_insn (pat);
++  auto insn = emit_call_insn (pat);
+ 
+   rtx *fusage = &CALL_INSN_FUNCTION_USAGE (insn);
+   clobber_reg (fusage, gen_rtx_REG (word_mode, IP0_REGNUM));
+   clobber_reg (fusage, gen_rtx_REG (word_mode, IP1_REGNUM));
++  return as_a (insn);
+ }
+ 
+ machine_mode
+@@ -13069,6 +13789,16 @@ aarch64_secondary_memory_needed (machine_mode mode, reg_class_t class1,
+   return false;
+ }
+ 
++/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
++
++static bool
++aarch64_frame_pointer_required ()
++{
++  /* If the function needs to record the incoming value of PSTATE.SM,
++     make sure that the slot is accessible from the frame pointer.  */
++  return aarch64_need_old_pstate_sm ();
++}
++
+ static bool
+ aarch64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+ {
+@@ -20607,7 +21337,8 @@ aarch64_conditional_register_usage (void)
+ 	call_used_regs[i] = 1;
+       }
+ 
+-  /* Only allow the FFR and FFRT to be accessed via special patterns.  */
++  /* Only allow these registers to be accessed via special patterns.  */
++  CLEAR_HARD_REG_BIT (operand_reg_set, VG_REGNUM);
+   CLEAR_HARD_REG_BIT (operand_reg_set, FFR_REGNUM);
+   CLEAR_HARD_REG_BIT (operand_reg_set, FFRT_REGNUM);
+ 
+@@ -27903,6 +28634,123 @@ aarch64_indirect_call_asm (rtx addr)
+   return "";
+ }
+ 
++/* If CALL involves a change in PSTATE.SM, emit the instructions needed
++   to switch to the new mode and the instructions needed to restore the
++   original mode.  Return true if something changed.  */
++static bool
++aarch64_switch_pstate_sm_for_call (rtx_call_insn *call)
++{
++  /* Mode switches for sibling calls are handled via the epilogue.  */
++  if (SIBLING_CALL_P (call))
++    return false;
++
++  auto callee_isa_mode = aarch64_insn_callee_isa_mode (call);
++  if (!aarch64_call_switches_pstate_sm (callee_isa_mode))
++    return false;
++
++  /* Switch mode before the call, preserving any argument registers
++     across the switch.  */
++  start_sequence ();
++  rtx_insn *args_guard_label = nullptr;
++  if (TARGET_STREAMING_COMPATIBLE)
++    args_guard_label = aarch64_guard_switch_pstate_sm (IP0_REGNUM,
++						       callee_isa_mode);
++  aarch64_sme_mode_switch_regs args_switch;
++  args_switch.add_call_args (call);
++  args_switch.emit_prologue ();
++  aarch64_switch_pstate_sm (AARCH64_ISA_MODE, callee_isa_mode);
++  args_switch.emit_epilogue ();
++  if (args_guard_label)
++    emit_label (args_guard_label);
++  auto args_seq = get_insns ();
++  end_sequence ();
++  emit_insn_before (args_seq, call);
++
++  if (find_reg_note (call, REG_NORETURN, NULL_RTX))
++    return true;
++
++  /* Switch mode after the call, preserving any return registers across
++     the switch.  */
++  start_sequence ();
++  rtx_insn *return_guard_label = nullptr;
++  if (TARGET_STREAMING_COMPATIBLE)
++    return_guard_label = aarch64_guard_switch_pstate_sm (IP0_REGNUM,
++							 callee_isa_mode);
++  aarch64_sme_mode_switch_regs return_switch;
++  return_switch.add_call_result (call);
++  return_switch.emit_prologue ();
++  aarch64_switch_pstate_sm (callee_isa_mode, AARCH64_ISA_MODE);
++  return_switch.emit_epilogue ();
++  if (return_guard_label)
++    emit_label (return_guard_label);
++  auto result_seq = get_insns ();
++  end_sequence ();
++  emit_insn_after (result_seq, call);
++  return true;
++}
++
++namespace {
++
++const pass_data pass_data_switch_pstate_sm =
++{
++  RTL_PASS, // type
++  "smstarts", // name
++  OPTGROUP_NONE, // optinfo_flags
++  TV_NONE, // tv_id
++  0, // properties_required
++  0, // properties_provided
++  0, // properties_destroyed
++  0, // todo_flags_start
++  TODO_df_finish, // todo_flags_finish
++};
++
++class pass_switch_pstate_sm : public rtl_opt_pass
++{
++public:
++  pass_switch_pstate_sm (gcc::context *ctxt)
++    : rtl_opt_pass (pass_data_switch_pstate_sm, ctxt)
++  {}
++
++  // opt_pass methods:
++  bool gate (function *) override final;
++  unsigned int execute (function *) override final;
++};
++
++bool
++pass_switch_pstate_sm::gate (function *)
++{
++  return cfun->machine->call_switches_pstate_sm;
++}
++
++/* Emit any instructions needed to switch PSTATE.SM.  */
++unsigned int
++pass_switch_pstate_sm::execute (function *fn)
++{
++  basic_block bb;
++
++  auto_sbitmap blocks (last_basic_block_for_fn (cfun));
++  bitmap_clear (blocks);
++  FOR_EACH_BB_FN (bb, fn)
++    {
++      rtx_insn *insn;
++      FOR_BB_INSNS (bb, insn)
++	if (auto *call = dyn_cast (insn))
++	  if (aarch64_switch_pstate_sm_for_call (call))
++	    bitmap_set_bit (blocks, bb->index);
++    }
++  find_many_sub_basic_blocks (blocks);
++  clear_aux_for_blocks ();
++  return 0;
++}
++
++}
++
++rtl_opt_pass *
++make_pass_switch_pstate_sm (gcc::context *ctxt)
++{
++  return new pass_switch_pstate_sm (ctxt);
++}
++
+ /* Target-specific selftests.  */
+ 
+ #if CHECKING_P
+@@ -28176,6 +29024,9 @@ aarch64_get_v16qi_mode ()
+ #undef TARGET_CALLEE_COPIES
+ #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_false
+ 
++#undef TARGET_FRAME_POINTER_REQUIRED
++#define TARGET_FRAME_POINTER_REQUIRED aarch64_frame_pointer_required
++
+ #undef TARGET_CAN_ELIMINATE
+ #define TARGET_CAN_ELIMINATE aarch64_can_eliminate
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 1591cde8b..6bfe55968 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -255,6 +255,10 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ /* The current function is a normal non-streaming function.  */
+ #define TARGET_NON_STREAMING (AARCH64_ISA_SM_OFF)
+ 
++/* The current function has a streaming-compatible body.  */
++#define TARGET_STREAMING_COMPATIBLE \
++  ((aarch64_isa_flags & AARCH64_FL_SM_STATE) == 0)
++
+ /* Crypto is an optional extension to AdvSIMD.  */
+ #define TARGET_CRYPTO (AARCH64_ISA_CRYPTO)
+ 
+@@ -461,7 +465,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+     0, 0, 0, 0,   0, 0, 0, 0,	/* V8 - V15 */		\
+     1, 1, 1, 1,   1, 1, 1, 1,   /* V16 - V23 */         \
+     1, 1, 1, 1,   1, 1, 1, 1,   /* V24 - V31 */         \
+-    1, 1, 1, 1,			/* SFP, AP, CC, VG */	\
++    1, 1, 1, 0,			/* SFP, AP, CC, VG */	\
+     1, 1, 1, 1,   1, 1, 1, 1,	/* P0 - P7 */		\
+     1, 1, 1, 1,   1, 1, 1, 1,	/* P8 - P15 */		\
+     1, 1			/* FFR and FFRT */	\
+@@ -802,6 +806,13 @@ struct GTY (()) aarch64_frame
+   vec *saved_fprs;
+   vec *saved_prs;
+ 
++  /* The offset from the base of the frame of a 64-bit slot whose low
++     bit contains the incoming value of PSTATE.SM.  This slot must be
++     within reach of the hard frame pointer.
++
++     The offset is -1 if such a slot isn't needed.  */
++  poly_int64 old_svcr_offset;
++
+   /* The number of extra stack bytes taken up by register varargs.
+      This area is allocated by the callee at the very top of the
+      frame.  This value is rounded up to a multiple of
+@@ -910,6 +921,12 @@ typedef struct GTY (()) machine_function
+   /* One entry for each general purpose register.  */
+   rtx call_via[SP_REGNUM];
+   bool label_is_assembled;
++
++  /* True if we've expanded at least one call to a function that changes
++     PSTATE.SM.  This should only be used for saving compile time: false
++     guarantees that no such mode switch exists.  */
++  bool call_switches_pstate_sm;
++
+   /* A set of all decls that have been passed to a vld1 intrinsic in the
+      current function.  This is used to help guide the vector cost model.  */
+   hash_set *vector_load_decls;
+@@ -978,6 +995,12 @@ typedef struct
+ 				   stack arg area so far.  */
+   bool silent_p;		/* True if we should act silently, rather than
+ 				   raise an error for invalid calls.  */
++
++  /* A list of registers that need to be saved and restored around a
++     change to PSTATE.SM.  An auto_vec would be more convenient, but those
++     can't be copied.  */
++  unsigned int num_sme_mode_switch_args;
++  rtx sme_mode_switch_args[12];
+ } CUMULATIVE_ARGS;
+ #endif
+ 
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 2ce123255..bb867de74 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -970,7 +970,7 @@
+ 					 operands[1]);
+ })
+ 
+-(define_insn "*tb1"
++(define_insn "@aarch64_tb"
+   [(set (pc) (if_then_else
+ 	      (EQL (zero_extract:GPI (match_operand:ALLI 0 "register_operand" "r")
+ 				     (const_int 1)
+@@ -1057,7 +1057,7 @@
+   [(parallel
+      [(call (match_operand 0 "memory_operand")
+ 	    (match_operand 1 "general_operand"))
+-      (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
++      (unspec:DI [(match_operand 2)] UNSPEC_CALLEE_ABI)
+       (clobber (reg:DI LR_REGNUM))])]
+   ""
+   "
+@@ -1083,7 +1083,7 @@
+      [(set (match_operand 0 "")
+ 	   (call (match_operand 1 "memory_operand")
+ 		 (match_operand 2 "general_operand")))
+-     (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
++     (unspec:DI [(match_operand 3)] UNSPEC_CALLEE_ABI)
+      (clobber (reg:DI LR_REGNUM))])]
+   ""
+   "
+@@ -1110,7 +1110,7 @@
+   [(parallel
+      [(call (match_operand 0 "memory_operand")
+ 	    (match_operand 1 "general_operand"))
+-      (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
++      (unspec:DI [(match_operand 2)] UNSPEC_CALLEE_ABI)
+       (return)])]
+   ""
+   {
+@@ -1124,7 +1124,7 @@
+      [(set (match_operand 0 "")
+ 	   (call (match_operand 1 "memory_operand")
+ 		 (match_operand 2 "general_operand")))
+-      (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
++      (unspec:DI [(match_operand 3)] UNSPEC_CALLEE_ABI)
+       (return)])]
+   ""
+   {
+@@ -7747,3 +7747,6 @@
+ 
+ ;; SVE2.
+ (include "aarch64-sve2.md")
++
++;; SME and extensions
++(include "aarch64-sme.md")
+diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
+index 10cd8f093..49731ba92 100644
+--- a/gcc/config/aarch64/t-aarch64
++++ b/gcc/config/aarch64/t-aarch64
+@@ -186,9 +186,12 @@ MULTILIB_DIRNAMES   = $(subst $(comma), ,$(TM_MULTILIB_CONFIG))
+ insn-conditions.md: s-check-sve-md
+ s-check-sve-md: $(srcdir)/config/aarch64/check-sve-md.awk \
+ 		$(srcdir)/config/aarch64/aarch64-sve.md \
+-		$(srcdir)/config/aarch64/aarch64-sve2.md
++		$(srcdir)/config/aarch64/aarch64-sve2.md \
++		$(srcdir)/config/aarch64/aarch64-sme.md
+ 	$(AWK) -f $(srcdir)/config/aarch64/check-sve-md.awk \
+ 	  $(srcdir)/config/aarch64/aarch64-sve.md
+ 	$(AWK) -f $(srcdir)/config/aarch64/check-sve-md.awk \
+ 	  $(srcdir)/config/aarch64/aarch64-sve2.md
++	$(AWK) -f $(srcdir)/config/aarch64/check-sve-md.awk \
++	  $(srcdir)/config/aarch64/aarch64-sme.md
+ 	$(STAMP) s-check-sve-md
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c
+new file mode 100644
+index 000000000..a2de55773
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c
+@@ -0,0 +1,233 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++void ns_callee ();
++ void s_callee () [[arm::streaming]];
++ void sc_callee () [[arm::streaming_compatible]];
++
++void ns_callee_stack (int, int, int, int, int, int, int, int, int);
++
++struct callbacks {
++  void (*ns_ptr) ();
++   void (*s_ptr) () [[arm::streaming]];
++   void (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++/*
++** n_caller:	{ target lp64 }
++**	stp	x30, (x19|x2[0-8]), \[sp, #?-96\]!
++**	cntd	x16
++**	str	x16, \[sp, #?16\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	mov	\1, x0
++**	bl	ns_callee
++**	smstart	sm
++**	bl	s_callee
++**	smstop	sm
++**	bl	sc_callee
++**	ldr	(x[0-9]+), \[\1\]
++**	blr	\2
++**	ldr	(x[0-9]+), \[\1, #?8\]
++**	smstart	sm
++**	blr	\3
++**	smstop	sm
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	blr	\4
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x30, \1, \[sp\], #?96
++**	ret
++*/
++void
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr ();
++  c->sc_ptr ();
++}
++
++/*
++** s_caller:	{ target lp64 }
++**	stp	x30, (x19|x2[0-8]), \[sp, #?-96\]!
++**	cntd	x16
++**	str	x16, \[sp, #?16\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	mov	\1, x0
++**	smstop	sm
++**	bl	ns_callee
++**	smstart	sm
++**	bl	s_callee
++**	bl	sc_callee
++**	ldr	(x[0-9]+), \[\1\]
++**	smstop	sm
++**	blr	\2
++**	smstart	sm
++**	ldr	(x[0-9]+), \[\1, #?8\]
++**	blr	\3
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	blr	\4
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x30, \1, \[sp\], #?96
++**	ret
++*/
++void
++s_caller (struct callbacks *c) [[arm::streaming]]
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr ();
++  c->sc_ptr ();
++}
++
++/*
++** sc_caller_sme:
++**	stp	x29, x30, \[sp, #?-96\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	mrs	x16, svcr
++**	str	x16, \[x29, #?16\]
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	smstop	sm
++**	bl	ns_callee
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	smstart	sm
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, .*
++**	smstart	sm
++**	bl	s_callee
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, .*
++**	smstop	sm
++**	bl	sc_callee
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x29, x30, \[sp\], #?96
++**	ret
++*/
++void
++sc_caller_sme () [[arm::streaming_compatible]]
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++}
++
++#pragma GCC target "+nosme"
++
++/*
++** sc_caller:
++**	stp	x29, x30, \[sp, #?-96\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	bl	__arm_sme_state
++**	str	x0, \[x29, #?16\]
++**	...
++**	bl	sc_callee
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x29, x30, \[sp\], #?96
++**	ret
++*/
++void
++sc_caller () [[arm::streaming_compatible]]
++{
++  ns_callee ();
++  sc_callee ();
++}
++
++/*
++** sc_caller_x0:
++**	...
++**	mov	x10, x0
++**	bl	__arm_sme_state
++**	...
++**	str	wzr, \[x10\]
++**	...
++*/
++void
++sc_caller_x0 (int *ptr) [[arm::streaming_compatible]]
++{
++  *ptr = 0;
++  ns_callee ();
++  sc_callee ();
++}
++
++/*
++** sc_caller_x1:
++**	...
++**	mov	x10, x0
++**	mov	x11, x1
++**	bl	__arm_sme_state
++**	...
++**	str	w11, \[x10\]
++**	...
++*/
++void
++sc_caller_x1 (int *ptr, int a) [[arm::streaming_compatible]]
++{
++  *ptr = a;
++  ns_callee ();
++  sc_callee ();
++}
++
++/*
++** sc_caller_stack:
++**	sub	sp, sp, #112
++**	stp	x29, x30, \[sp, #?16\]
++**	add	x29, sp, #?16
++**	...
++**	stp	d8, d9, \[sp, #?48\]
++**	...
++**	bl	__arm_sme_state
++**	str	x0, \[x29, #?16\]
++**	...
++**	bl	ns_callee_stack
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	smstart	sm
++**	...
++*/
++void
++sc_caller_stack () [[arm::streaming_compatible]]
++{
++  ns_callee_stack (0, 0, 0, 0, 0, 0, 0, 0, 0);
++}
++
++/* { dg-final { scan-assembler {n_caller:(?:(?!ret).)*\.cfi_offset 46, -80\n} } } */
++/* { dg-final { scan-assembler {s_caller:(?:(?!ret).)*\.cfi_offset 46, -80\n} } } */
++/* { dg-final { scan-assembler {sc_caller_sme:(?:(?!ret).)*\.cfi_offset 46, -72\n} } } */
++/* { dg-final { scan-assembler {sc_caller:(?:(?!ret).)*\.cfi_offset 46, -72\n} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_10.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_10.c
+new file mode 100644
+index 000000000..49c5e4a6a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_10.c
+@@ -0,0 +1,37 @@
++// { dg-options "" }
++
++#pragma GCC target "+nosme"
++
++void ns_callee ();
++ void s_callee () [[arm::streaming]];
++ void sc_callee () [[arm::streaming_compatible]];
++
++struct callbacks {
++  void (*ns_ptr) ();
++   void (*s_ptr) () [[arm::streaming]];
++   void (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++void
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  s_callee (); // { dg-error "calling a streaming function requires the ISA extension 'sme'" }
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr (); // { dg-error "calling a streaming function requires the ISA extension 'sme'" }
++  c->sc_ptr ();
++}
++
++void
++sc_caller_sme (struct callbacks *c) [[arm::streaming_compatible]]
++{
++  ns_callee ();
++  s_callee (); // { dg-error "calling a streaming function requires the ISA extension 'sme'" }
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr (); // { dg-error "calling a streaming function requires the ISA extension 'sme'" }
++  c->sc_ptr ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_2.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_2.c
+new file mode 100644
+index 000000000..890fcbc5b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_2.c
+@@ -0,0 +1,43 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++
++void ns_callee ();
++ void s_callee () [[arm::streaming]];
++ void sc_callee () [[arm::streaming_compatible]];
++
++struct callbacks {
++  void (*ns_ptr) ();
++   void (*s_ptr) () [[arm::streaming]];
++   void (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++void
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->sc_ptr ();
++}
++
++void
++s_caller (struct callbacks *c) [[arm::streaming]]
++{
++  s_callee ();
++  sc_callee ();
++
++  c->s_ptr ();
++  c->sc_ptr ();
++}
++
++void
++sc_caller (struct callbacks *c) [[arm::streaming_compatible]]
++{
++  sc_callee ();
++
++  c->sc_ptr ();
++}
++
++// { dg-final { scan-assembler-not {[dpqz][0-9]+,} } }
++// { dg-final { scan-assembler-not {smstart\tsm} } }
++// { dg-final { scan-assembler-not {smstop\tsm} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c
+new file mode 100644
+index 000000000..ed999d085
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c
+@@ -0,0 +1,166 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++__attribute__((aarch64_vector_pcs)) void ns_callee ();
++__attribute__((aarch64_vector_pcs)) void s_callee () [[arm::streaming]];
++__attribute__((aarch64_vector_pcs)) void sc_callee () [[arm::streaming_compatible]];
++
++struct callbacks {
++  __attribute__((aarch64_vector_pcs)) void (*ns_ptr) ();
++  __attribute__((aarch64_vector_pcs)) void (*s_ptr) () [[arm::streaming]];
++  __attribute__((aarch64_vector_pcs)) void (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++/*
++** n_caller:	{ target lp64 }
++**	stp	x30, (x19|x2[0-8]), \[sp, #?-288\]!
++**	cntd	x16
++**	str	x16, \[sp, #?16\]
++**	stp	q8, q9, \[sp, #?32\]
++**	stp	q10, q11, \[sp, #?64\]
++**	stp	q12, q13, \[sp, #?96\]
++**	stp	q14, q15, \[sp, #?128\]
++**	stp	q16, q17, \[sp, #?160\]
++**	stp	q18, q19, \[sp, #?192\]
++**	stp	q20, q21, \[sp, #?224\]
++**	stp	q22, q23, \[sp, #?256\]
++**	mov	\1, x0
++**	bl	ns_callee
++**	smstart	sm
++**	bl	s_callee
++**	smstop	sm
++**	bl	sc_callee
++**	ldr	(x[0-9]+), \[\1\]
++**	blr	\2
++**	ldr	(x[0-9]+), \[\1, #?8\]
++**	smstart	sm
++**	blr	\3
++**	smstop	sm
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	blr	\4
++**	ldp	q8, q9, \[sp, #?32\]
++**	ldp	q10, q11, \[sp, #?64\]
++**	ldp	q12, q13, \[sp, #?96\]
++**	ldp	q14, q15, \[sp, #?128\]
++**	ldp	q16, q17, \[sp, #?160\]
++**	ldp	q18, q19, \[sp, #?192\]
++**	ldp	q20, q21, \[sp, #?224\]
++**	ldp	q22, q23, \[sp, #?256\]
++**	ldp	x30, \1, \[sp\], #?288
++**	ret
++*/
++void __attribute__((aarch64_vector_pcs))
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr ();
++  c->sc_ptr ();
++}
++
++/*
++** s_caller:	{ target lp64 }
++**	stp	x30, (x19|x2[0-8]), \[sp, #?-288\]!
++**	cntd	x16
++**	str	x16, \[sp, #?16\]
++**	stp	q8, q9, \[sp, #?32\]
++**	stp	q10, q11, \[sp, #?64\]
++**	stp	q12, q13, \[sp, #?96\]
++**	stp	q14, q15, \[sp, #?128\]
++**	stp	q16, q17, \[sp, #?160\]
++**	stp	q18, q19, \[sp, #?192\]
++**	stp	q20, q21, \[sp, #?224\]
++**	stp	q22, q23, \[sp, #?256\]
++**	mov	\1, x0
++**	smstop	sm
++**	bl	ns_callee
++**	smstart	sm
++**	bl	s_callee
++**	bl	sc_callee
++**	ldr	(x[0-9]+), \[\1\]
++**	smstop	sm
++**	blr	\2
++**	smstart	sm
++**	ldr	(x[0-9]+), \[\1, #?8\]
++**	blr	\3
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	blr	\4
++**	ldp	q8, q9, \[sp, #?32\]
++**	ldp	q10, q11, \[sp, #?64\]
++**	ldp	q12, q13, \[sp, #?96\]
++**	ldp	q14, q15, \[sp, #?128\]
++**	ldp	q16, q17, \[sp, #?160\]
++**	ldp	q18, q19, \[sp, #?192\]
++**	ldp	q20, q21, \[sp, #?224\]
++**	ldp	q22, q23, \[sp, #?256\]
++**	ldp	x30, \1, \[sp\], #?288
++**	ret
++*/
++void __attribute__((aarch64_vector_pcs))
++s_caller (struct callbacks *c) [[arm::streaming]]
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr ();
++  c->sc_ptr ();
++}
++
++/*
++** sc_caller:
++**	stp	x29, x30, \[sp, #?-288\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	stp	q8, q9, \[sp, #?32\]
++**	stp	q10, q11, \[sp, #?64\]
++**	stp	q12, q13, \[sp, #?96\]
++**	stp	q14, q15, \[sp, #?128\]
++**	stp	q16, q17, \[sp, #?160\]
++**	stp	q18, q19, \[sp, #?192\]
++**	stp	q20, q21, \[sp, #?224\]
++**	stp	q22, q23, \[sp, #?256\]
++**	mrs	x16, svcr
++**	str	x16, \[x29, #?16\]
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	smstop	sm
++**	bl	ns_callee
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	smstart	sm
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, .*
++**	smstart	sm
++**	bl	s_callee
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, .*
++**	smstop	sm
++**	bl	sc_callee
++**	ldp	q8, q9, \[sp, #?32\]
++**	ldp	q10, q11, \[sp, #?64\]
++**	ldp	q12, q13, \[sp, #?96\]
++**	ldp	q14, q15, \[sp, #?128\]
++**	ldp	q16, q17, \[sp, #?160\]
++**	ldp	q18, q19, \[sp, #?192\]
++**	ldp	q20, q21, \[sp, #?224\]
++**	ldp	q22, q23, \[sp, #?256\]
++**	ldp	x29, x30, \[sp\], #?288
++**	ret
++*/
++void __attribute__((aarch64_vector_pcs))
++sc_caller () [[arm::streaming_compatible]]
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++}
++
++/* { dg-final { scan-assembler {n_caller:(?:(?!ret).)*\.cfi_offset 46, -272\n} } } */
++/* { dg-final { scan-assembler {s_caller:(?:(?!ret).)*\.cfi_offset 46, -272\n} } } */
++/* { dg-final { scan-assembler {sc_caller:(?:(?!ret).)*\.cfi_offset 46, -264\n} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_4.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_4.c
+new file mode 100644
+index 000000000..f93a67f97
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_4.c
+@@ -0,0 +1,43 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++
++__attribute__((aarch64_vector_pcs)) void ns_callee ();
++__attribute__((aarch64_vector_pcs)) void s_callee () [[arm::streaming]];
++__attribute__((aarch64_vector_pcs)) void sc_callee () [[arm::streaming_compatible]];
++
++struct callbacks {
++  __attribute__((aarch64_vector_pcs)) void (*ns_ptr) ();
++  __attribute__((aarch64_vector_pcs)) void (*s_ptr) () [[arm::streaming]];
++  __attribute__((aarch64_vector_pcs)) void (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++void __attribute__((aarch64_vector_pcs))
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->sc_ptr ();
++}
++
++void __attribute__((aarch64_vector_pcs))
++s_caller (struct callbacks *c) [[arm::streaming]]
++{
++  s_callee ();
++  sc_callee ();
++
++  c->s_ptr ();
++  c->sc_ptr ();
++}
++
++void __attribute__((aarch64_vector_pcs))
++sc_caller (struct callbacks *c) [[arm::streaming_compatible]]
++{
++  sc_callee ();
++
++  c->sc_ptr ();
++}
++
++// { dg-final { scan-assembler-not {[dpqz][0-9]+,} } }
++// { dg-final { scan-assembler-not {smstart\tsm} } }
++// { dg-final { scan-assembler-not {smstop\tsm} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+new file mode 100644
+index 000000000..be9b5cc04
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+@@ -0,0 +1,318 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++#include 
++
++svbool_t ns_callee ();
++ svbool_t s_callee () [[arm::streaming]];
++ svbool_t sc_callee () [[arm::streaming_compatible]];
++
++struct callbacks {
++  svbool_t (*ns_ptr) ();
++   svbool_t (*s_ptr) () [[arm::streaming]];
++   svbool_t (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++/*
++** n_caller:	{ target lp64 }
++**	stp	x30, (x19|x2[0-8]), \[sp, #?-32\]!
++**	cntd	x16
++**	str	x16, \[sp, #?16\]
++**	addvl	sp, sp, #-18
++**	str	p4, \[sp\]
++**	str	p5, \[sp, #1, mul vl\]
++**	str	p6, \[sp, #2, mul vl\]
++**	str	p7, \[sp, #3, mul vl\]
++**	str	p8, \[sp, #4, mul vl\]
++**	str	p9, \[sp, #5, mul vl\]
++**	str	p10, \[sp, #6, mul vl\]
++**	str	p11, \[sp, #7, mul vl\]
++**	str	p12, \[sp, #8, mul vl\]
++**	str	p13, \[sp, #9, mul vl\]
++**	str	p14, \[sp, #10, mul vl\]
++**	str	p15, \[sp, #11, mul vl\]
++**	str	z8, \[sp, #2, mul vl\]
++**	str	z9, \[sp, #3, mul vl\]
++**	str	z10, \[sp, #4, mul vl\]
++**	str	z11, \[sp, #5, mul vl\]
++**	str	z12, \[sp, #6, mul vl\]
++**	str	z13, \[sp, #7, mul vl\]
++**	str	z14, \[sp, #8, mul vl\]
++**	str	z15, \[sp, #9, mul vl\]
++**	str	z16, \[sp, #10, mul vl\]
++**	str	z17, \[sp, #11, mul vl\]
++**	str	z18, \[sp, #12, mul vl\]
++**	str	z19, \[sp, #13, mul vl\]
++**	str	z20, \[sp, #14, mul vl\]
++**	str	z21, \[sp, #15, mul vl\]
++**	str	z22, \[sp, #16, mul vl\]
++**	str	z23, \[sp, #17, mul vl\]
++**	mov	\1, x0
++**	bl	ns_callee
++**	smstart	sm
++**	bl	s_callee
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	bl	sc_callee
++**	ldr	(x[0-9]+), \[\1\]
++**	blr	\2
++**	ldr	(x[0-9]+), \[\1, #?8\]
++**	smstart	sm
++**	blr	\3
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	blr	\4
++**	ldr	z8, \[sp, #2, mul vl\]
++**	ldr	z9, \[sp, #3, mul vl\]
++**	ldr	z10, \[sp, #4, mul vl\]
++**	ldr	z11, \[sp, #5, mul vl\]
++**	ldr	z12, \[sp, #6, mul vl\]
++**	ldr	z13, \[sp, #7, mul vl\]
++**	ldr	z14, \[sp, #8, mul vl\]
++**	ldr	z15, \[sp, #9, mul vl\]
++**	ldr	z16, \[sp, #10, mul vl\]
++**	ldr	z17, \[sp, #11, mul vl\]
++**	ldr	z18, \[sp, #12, mul vl\]
++**	ldr	z19, \[sp, #13, mul vl\]
++**	ldr	z20, \[sp, #14, mul vl\]
++**	ldr	z21, \[sp, #15, mul vl\]
++**	ldr	z22, \[sp, #16, mul vl\]
++**	ldr	z23, \[sp, #17, mul vl\]
++**	ldr	p4, \[sp\]
++**	ldr	p5, \[sp, #1, mul vl\]
++**	ldr	p6, \[sp, #2, mul vl\]
++**	ldr	p7, \[sp, #3, mul vl\]
++**	ldr	p8, \[sp, #4, mul vl\]
++**	ldr	p9, \[sp, #5, mul vl\]
++**	ldr	p10, \[sp, #6, mul vl\]
++**	ldr	p11, \[sp, #7, mul vl\]
++**	ldr	p12, \[sp, #8, mul vl\]
++**	ldr	p13, \[sp, #9, mul vl\]
++**	ldr	p14, \[sp, #10, mul vl\]
++**	ldr	p15, \[sp, #11, mul vl\]
++**	addvl	sp, sp, #18
++**	ldp	x30, \1, \[sp\], #?32
++**	ret
++*/
++svbool_t
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr ();
++  return c->sc_ptr ();
++}
++
++/*
++** s_caller:	{ target lp64 }
++**	stp	x30, (x19|x2[0-8]), \[sp, #?-32\]!
++**	cntd	x16
++**	str	x16, \[sp, #?16\]
++**	addvl	sp, sp, #-18
++**	str	p4, \[sp\]
++**	str	p5, \[sp, #1, mul vl\]
++**	str	p6, \[sp, #2, mul vl\]
++**	str	p7, \[sp, #3, mul vl\]
++**	str	p8, \[sp, #4, mul vl\]
++**	str	p9, \[sp, #5, mul vl\]
++**	str	p10, \[sp, #6, mul vl\]
++**	str	p11, \[sp, #7, mul vl\]
++**	str	p12, \[sp, #8, mul vl\]
++**	str	p13, \[sp, #9, mul vl\]
++**	str	p14, \[sp, #10, mul vl\]
++**	str	p15, \[sp, #11, mul vl\]
++**	str	z8, \[sp, #2, mul vl\]
++**	str	z9, \[sp, #3, mul vl\]
++**	str	z10, \[sp, #4, mul vl\]
++**	str	z11, \[sp, #5, mul vl\]
++**	str	z12, \[sp, #6, mul vl\]
++**	str	z13, \[sp, #7, mul vl\]
++**	str	z14, \[sp, #8, mul vl\]
++**	str	z15, \[sp, #9, mul vl\]
++**	str	z16, \[sp, #10, mul vl\]
++**	str	z17, \[sp, #11, mul vl\]
++**	str	z18, \[sp, #12, mul vl\]
++**	str	z19, \[sp, #13, mul vl\]
++**	str	z20, \[sp, #14, mul vl\]
++**	str	z21, \[sp, #15, mul vl\]
++**	str	z22, \[sp, #16, mul vl\]
++**	str	z23, \[sp, #17, mul vl\]
++**	mov	\1, x0
++**	smstop	sm
++**	bl	ns_callee
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	bl	s_callee
++**	bl	sc_callee
++**	ldr	(x[0-9]+), \[\1\]
++**	smstop	sm
++**	blr	\2
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	ldr	(x[0-9]+), \[\1, #?8\]
++**	blr	\3
++**	ldr	(x[0-9]+), \[\1, #?16\]
++**	blr	\4
++**	ldr	z8, \[sp, #2, mul vl\]
++**	ldr	z9, \[sp, #3, mul vl\]
++**	ldr	z10, \[sp, #4, mul vl\]
++**	ldr	z11, \[sp, #5, mul vl\]
++**	ldr	z12, \[sp, #6, mul vl\]
++**	ldr	z13, \[sp, #7, mul vl\]
++**	ldr	z14, \[sp, #8, mul vl\]
++**	ldr	z15, \[sp, #9, mul vl\]
++**	ldr	z16, \[sp, #10, mul vl\]
++**	ldr	z17, \[sp, #11, mul vl\]
++**	ldr	z18, \[sp, #12, mul vl\]
++**	ldr	z19, \[sp, #13, mul vl\]
++**	ldr	z20, \[sp, #14, mul vl\]
++**	ldr	z21, \[sp, #15, mul vl\]
++**	ldr	z22, \[sp, #16, mul vl\]
++**	ldr	z23, \[sp, #17, mul vl\]
++**	ldr	p4, \[sp\]
++**	ldr	p5, \[sp, #1, mul vl\]
++**	ldr	p6, \[sp, #2, mul vl\]
++**	ldr	p7, \[sp, #3, mul vl\]
++**	ldr	p8, \[sp, #4, mul vl\]
++**	ldr	p9, \[sp, #5, mul vl\]
++**	ldr	p10, \[sp, #6, mul vl\]
++**	ldr	p11, \[sp, #7, mul vl\]
++**	ldr	p12, \[sp, #8, mul vl\]
++**	ldr	p13, \[sp, #9, mul vl\]
++**	ldr	p14, \[sp, #10, mul vl\]
++**	ldr	p15, \[sp, #11, mul vl\]
++**	addvl	sp, sp, #18
++**	ldp	x30, \1, \[sp\], #?32
++**	ret
++*/
++svbool_t
++s_caller (struct callbacks *c) [[arm::streaming]]
++{
++  ns_callee ();
++  s_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  c->s_ptr ();
++  return c->sc_ptr ();
++}
++
++/*
++** sc_caller:
++**	stp	x29, x30, \[sp, #?-32\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	addvl	sp, sp, #-18
++**	str	p4, \[sp\]
++**	str	p5, \[sp, #1, mul vl\]
++**	str	p6, \[sp, #2, mul vl\]
++**	str	p7, \[sp, #3, mul vl\]
++**	str	p8, \[sp, #4, mul vl\]
++**	str	p9, \[sp, #5, mul vl\]
++**	str	p10, \[sp, #6, mul vl\]
++**	str	p11, \[sp, #7, mul vl\]
++**	str	p12, \[sp, #8, mul vl\]
++**	str	p13, \[sp, #9, mul vl\]
++**	str	p14, \[sp, #10, mul vl\]
++**	str	p15, \[sp, #11, mul vl\]
++**	str	z8, \[sp, #2, mul vl\]
++**	str	z9, \[sp, #3, mul vl\]
++**	str	z10, \[sp, #4, mul vl\]
++**	str	z11, \[sp, #5, mul vl\]
++**	str	z12, \[sp, #6, mul vl\]
++**	str	z13, \[sp, #7, mul vl\]
++**	str	z14, \[sp, #8, mul vl\]
++**	str	z15, \[sp, #9, mul vl\]
++**	str	z16, \[sp, #10, mul vl\]
++**	str	z17, \[sp, #11, mul vl\]
++**	str	z18, \[sp, #12, mul vl\]
++**	str	z19, \[sp, #13, mul vl\]
++**	str	z20, \[sp, #14, mul vl\]
++**	str	z21, \[sp, #15, mul vl\]
++**	str	z22, \[sp, #16, mul vl\]
++**	str	z23, \[sp, #17, mul vl\]
++**	mrs	x16, svcr
++**	str	x16, \[x29, #?16\]
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	smstop	sm
++**	bl	ns_callee
++**	ldr	x16, \[x29, #?16\]
++**	tbz	x16, 0, .*
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, .*
++**	smstart	sm
++**	bl	s_callee
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, .*
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	bl	sc_callee
++**	ldr	z8, \[sp, #2, mul vl\]
++**	ldr	z9, \[sp, #3, mul vl\]
++**	ldr	z10, \[sp, #4, mul vl\]
++**	ldr	z11, \[sp, #5, mul vl\]
++**	ldr	z12, \[sp, #6, mul vl\]
++**	ldr	z13, \[sp, #7, mul vl\]
++**	ldr	z14, \[sp, #8, mul vl\]
++**	ldr	z15, \[sp, #9, mul vl\]
++**	ldr	z16, \[sp, #10, mul vl\]
++**	ldr	z17, \[sp, #11, mul vl\]
++**	ldr	z18, \[sp, #12, mul vl\]
++**	ldr	z19, \[sp, #13, mul vl\]
++**	ldr	z20, \[sp, #14, mul vl\]
++**	ldr	z21, \[sp, #15, mul vl\]
++**	ldr	z22, \[sp, #16, mul vl\]
++**	ldr	z23, \[sp, #17, mul vl\]
++**	ldr	p4, \[sp\]
++**	ldr	p5, \[sp, #1, mul vl\]
++**	ldr	p6, \[sp, #2, mul vl\]
++**	ldr	p7, \[sp, #3, mul vl\]
++**	ldr	p8, \[sp, #4, mul vl\]
++**	ldr	p9, \[sp, #5, mul vl\]
++**	ldr	p10, \[sp, #6, mul vl\]
++**	ldr	p11, \[sp, #7, mul vl\]
++**	ldr	p12, \[sp, #8, mul vl\]
++**	ldr	p13, \[sp, #9, mul vl\]
++**	ldr	p14, \[sp, #10, mul vl\]
++**	ldr	p15, \[sp, #11, mul vl\]
++**	addvl	sp, sp, #18
++**	ldp	x29, x30, \[sp\], #?32
++**	ret
++*/
++svbool_t
++sc_caller () [[arm::streaming_compatible]]
++{
++  ns_callee ();
++  s_callee ();
++  return sc_callee ();
++}
++
++/* { dg-final { scan-assembler {n_caller:(?:(?!ret).)*\.cfi_offset 46, -16\n} } } */
++/* { dg-final { scan-assembler {s_caller:(?:(?!ret).)*\.cfi_offset 46, -16\n} } } */
++/* { dg-final { scan-assembler {sc_caller:(?:(?!ret).)*\.cfi_offset 46, -8\n} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_6.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_6.c
+new file mode 100644
+index 000000000..0f6bc4f6c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_6.c
+@@ -0,0 +1,45 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++
++#include 
++
++svbool_t ns_callee ();
++ svbool_t s_callee () [[arm::streaming]];
++ svbool_t sc_callee () [[arm::streaming_compatible]];
++
++struct callbacks {
++  svbool_t (*ns_ptr) ();
++   svbool_t (*s_ptr) () [[arm::streaming]];
++   svbool_t (*sc_ptr) () [[arm::streaming_compatible]];
++};
++
++svbool_t
++n_caller (struct callbacks *c)
++{
++  ns_callee ();
++  sc_callee ();
++
++  c->ns_ptr ();
++  return c->sc_ptr ();
++}
++
++svbool_t
++s_caller (struct callbacks *c) [[arm::streaming]]
++{
++  s_callee ();
++  sc_callee ();
++
++  c->s_ptr ();
++  return c->sc_ptr ();
++}
++
++svbool_t
++sc_caller (struct callbacks *c) [[arm::streaming_compatible]]
++{
++  sc_callee ();
++
++  return c->sc_ptr ();
++}
++
++// { dg-final { scan-assembler-not {[dpqz][0-9]+,} } }
++// { dg-final { scan-assembler-not {smstart\tsm} } }
++// { dg-final { scan-assembler-not {smstop\tsm} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_7.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_7.c
+new file mode 100644
+index 000000000..6482a489f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_7.c
+@@ -0,0 +1,516 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++#include 
++#include 
++
++double produce_d0 ();
++void consume_d0 (double);
++
++/*
++** test_d0:
++**	...
++**	smstop	sm
++**	bl	produce_d0
++**	fmov	x10, d0
++**	smstart	sm
++**	fmov	d0, x10
++**	fmov	x10, d0
++**	smstop	sm
++**	fmov	d0, x10
++**	bl	consume_d0
++**	...
++*/
++void
++test_d0 () [[arm::streaming]]
++{
++  double res = produce_d0 ();
++  asm volatile ("");
++  consume_d0 (res);
++}
++
++int8x8_t produce_d0_vec ();
++void consume_d0_vec (int8x8_t);
++
++/*
++** test_d0_vec:
++**	...
++**	smstop	sm
++**	bl	produce_d0_vec
++** (
++**	fmov	x10, d0
++** |
++**	umov	x10, v0.d\[0\]
++** )
++**	smstart	sm
++**	fmov	d0, x10
++** (
++**	fmov	x10, d0
++** |
++**	umov	x10, v0.d\[0\]
++** )
++**	smstop	sm
++**	fmov	d0, x10
++**	bl	consume_d0_vec
++**	...
++*/
++void
++test_d0_vec () [[arm::streaming]]
++{
++  int8x8_t res = produce_d0_vec ();
++  asm volatile ("");
++  consume_d0_vec (res);
++}
++
++int8x16_t produce_q0 ();
++void consume_q0 (int8x16_t);
++
++/*
++** test_q0:
++**	...
++**	smstop	sm
++**	bl	produce_q0
++**	str	q0, \[sp, #?-16\]!
++**	smstart	sm
++**	ldr	q0, \[sp\], #?16
++**	str	q0, \[sp, #?-16\]!
++**	smstop	sm
++**	ldr	q0, \[sp\], #?16
++**	bl	consume_q0
++**	...
++*/
++void
++test_q0 () [[arm::streaming]]
++{
++  int8x16_t res = produce_q0 ();
++  asm volatile ("");
++  consume_q0 (res);
++}
++
++int8x16x2_t produce_q1 ();
++void consume_q1 (int8x16x2_t);
++
++/*
++** test_q1:
++**	...
++**	smstop	sm
++**	bl	produce_q1
++**	stp	q0, q1, \[sp, #?-32\]!
++**	smstart	sm
++**	ldp	q0, q1, \[sp\], #?32
++**	stp	q0, q1, \[sp, #?-32\]!
++**	smstop	sm
++**	ldp	q0, q1, \[sp\], #?32
++**	bl	consume_q1
++**	...
++*/
++void
++test_q1 () [[arm::streaming]]
++{
++  int8x16x2_t res = produce_q1 ();
++  asm volatile ("");
++  consume_q1 (res);
++}
++
++int8x16x3_t produce_q2 ();
++void consume_q2 (int8x16x3_t);
++
++/*
++** test_q2:
++**	...
++**	smstop	sm
++**	bl	produce_q2
++**	stp	q0, q1, \[sp, #?-48\]!
++**	str	q2, \[sp, #?32\]
++**	smstart	sm
++**	ldr	q2, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?48
++**	stp	q0, q1, \[sp, #?-48\]!
++**	str	q2, \[sp, #?32\]
++**	smstop	sm
++**	ldr	q2, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?48
++**	bl	consume_q2
++**	...
++*/
++void
++test_q2 () [[arm::streaming]]
++{
++  int8x16x3_t res = produce_q2 ();
++  asm volatile ("");
++  consume_q2 (res);
++}
++
++int8x16x4_t produce_q3 ();
++void consume_q3 (int8x16x4_t);
++
++/*
++** test_q3:
++**	...
++**	smstop	sm
++**	bl	produce_q3
++**	stp	q0, q1, \[sp, #?-64\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	smstart	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?64
++**	stp	q0, q1, \[sp, #?-64\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	smstop	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?64
++**	bl	consume_q3
++**	...
++*/
++void
++test_q3 () [[arm::streaming]]
++{
++  int8x16x4_t res = produce_q3 ();
++  asm volatile ("");
++  consume_q3 (res);
++}
++
++svint8_t produce_z0 ();
++void consume_z0 (svint8_t);
++
++/*
++** test_z0:
++**	...
++**	smstop	sm
++**	bl	produce_z0
++**	addvl	sp, sp, #-1
++**	str	z0, \[sp\]
++**	smstart	sm
++**	ldr	z0, \[sp\]
++**	addvl	sp, sp, #1
++**	addvl	sp, sp, #-1
++**	str	z0, \[sp\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	addvl	sp, sp, #1
++**	bl	consume_z0
++**	...
++*/
++void
++test_z0 () [[arm::streaming]]
++{
++  svint8_t res = produce_z0 ();
++  asm volatile ("");
++  consume_z0 (res);
++}
++
++svint8x4_t produce_z3 ();
++void consume_z3 (svint8x4_t);
++
++/*
++** test_z3:
++**	...
++**	smstop	sm
++**	bl	produce_z3
++**	addvl	sp, sp, #-4
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	smstart	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	addvl	sp, sp, #4
++**	addvl	sp, sp, #-4
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	addvl	sp, sp, #4
++**	bl	consume_z3
++**	...
++*/
++void
++test_z3 () [[arm::streaming]]
++{
++  svint8x4_t res = produce_z3 ();
++  asm volatile ("");
++  consume_z3 (res);
++}
++
++svbool_t produce_p0 ();
++void consume_p0 (svbool_t);
++
++/*
++** test_p0:
++**	...
++**	smstop	sm
++**	bl	produce_p0
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	bl	consume_p0
++**	...
++*/
++void
++test_p0 () [[arm::streaming]]
++{
++  svbool_t res = produce_p0 ();
++  asm volatile ("");
++  consume_p0 (res);
++}
++
++void consume_d7 (double, double, double, double, double, double, double,
++		 double);
++
++/*
++** test_d7:
++**	...
++**	fmov	x10, d0
++**	fmov	x11, d1
++**	fmov	x12, d2
++**	fmov	x13, d3
++**	fmov	x14, d4
++**	fmov	x15, d5
++**	fmov	x16, d6
++**	fmov	x17, d7
++**	smstop	sm
++**	fmov	d0, x10
++**	fmov	d1, x11
++**	fmov	d2, x12
++**	fmov	d3, x13
++**	fmov	d4, x14
++**	fmov	d5, x15
++**	fmov	d6, x16
++**	fmov	d7, x17
++**	bl	consume_d7
++**	...
++*/
++void
++test_d7 () [[arm::streaming]]
++{
++  consume_d7 (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
++}
++
++void consume_d7_vec (int8x8_t, int8x8_t, int8x8_t, int8x8_t, int8x8_t,
++		     int8x8_t, int8x8_t, int8x8_t);
++
++/*
++** test_d7_vec:
++**	...
++** (
++**	fmov	x10, d0
++**	fmov	x11, d1
++**	fmov	x12, d2
++**	fmov	x13, d3
++**	fmov	x14, d4
++**	fmov	x15, d5
++**	fmov	x16, d6
++**	fmov	x17, d7
++** |
++**	umov	x10, v0.d\[0\]
++**	umov	x11, v1.d\[0\]
++**	umov	x12, v2.d\[0\]
++**	umov	x13, v3.d\[0\]
++**	umov	x14, v4.d\[0\]
++**	umov	x15, v5.d\[0\]
++**	umov	x16, v6.d\[0\]
++**	umov	x17, v7.d\[0\]
++** )
++**	smstop	sm
++**	fmov	d0, x10
++**	fmov	d1, x11
++**	fmov	d2, x12
++**	fmov	d3, x13
++**	fmov	d4, x14
++**	fmov	d5, x15
++**	fmov	d6, x16
++**	fmov	d7, x17
++**	bl	consume_d7_vec
++**	...
++*/
++void
++test_d7_vec (int8x8_t *ptr) [[arm::streaming]]
++{
++  consume_d7_vec (*ptr, *ptr, *ptr, *ptr, *ptr, *ptr, *ptr, *ptr);
++}
++
++void consume_q7 (int8x16_t, int8x16_t, int8x16_t, int8x16_t, int8x16_t,
++		 int8x16_t, int8x16_t, int8x16_t);
++
++/*
++** test_q7:
++**	...
++**	stp	q0, q1, \[sp, #?-128\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	stp	q4, q5, \[sp, #?64\]
++**	stp	q6, q7, \[sp, #?96\]
++**	smstop	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q4, q5, \[sp, #?64\]
++**	ldp	q6, q7, \[sp, #?96\]
++**	ldp	q0, q1, \[sp\], #?128
++**	bl	consume_q7
++**	...
++*/
++void
++test_q7 (int8x16_t *ptr) [[arm::streaming]]
++{
++  consume_q7 (*ptr, *ptr, *ptr, *ptr, *ptr, *ptr, *ptr, *ptr);
++}
++
++void consume_z7 (svint8_t, svint8_t, svint8_t, svint8_t, svint8_t,
++		 svint8_t, svint8_t, svint8_t);
++
++/*
++** test_z7:
++**	...
++**	addvl	sp, sp, #-8
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	str	z4, \[sp, #4, mul vl\]
++**	str	z5, \[sp, #5, mul vl\]
++**	str	z6, \[sp, #6, mul vl\]
++**	str	z7, \[sp, #7, mul vl\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	ldr	z4, \[sp, #4, mul vl\]
++**	ldr	z5, \[sp, #5, mul vl\]
++**	ldr	z6, \[sp, #6, mul vl\]
++**	ldr	z7, \[sp, #7, mul vl\]
++**	addvl	sp, sp, #8
++**	bl	consume_z7
++**	...
++*/
++void
++test_z7 (svint8_t *ptr) [[arm::streaming]]
++{
++  consume_z7 (*ptr, *ptr, *ptr, *ptr, *ptr, *ptr, *ptr, *ptr);
++}
++
++void consume_p3 (svbool_t, svbool_t, svbool_t, svbool_t);
++
++/*
++** test_p3:
++**	...
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	str	p1, \[sp, #1, mul vl\]
++**	str	p2, \[sp, #2, mul vl\]
++**	str	p3, \[sp, #3, mul vl\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	ldr	p1, \[sp, #1, mul vl\]
++**	ldr	p2, \[sp, #2, mul vl\]
++**	ldr	p3, \[sp, #3, mul vl\]
++**	addvl	sp, sp, #1
++**	bl	consume_p3
++**	...
++*/
++void
++test_p3 (svbool_t *ptr) [[arm::streaming]]
++{
++  consume_p3 (*ptr, *ptr, *ptr, *ptr);
++}
++
++void consume_mixed (float, double, float32x4_t, svfloat32_t,
++		    float, double, float64x2_t, svfloat64_t,
++		    svbool_t, svbool_t, svbool_t, svbool_t);
++
++/*
++** test_mixed:
++**	...
++**	addvl	sp, sp, #-3
++**	str	p0, \[sp\]
++**	str	p1, \[sp, #1, mul vl\]
++**	str	p2, \[sp, #2, mul vl\]
++**	str	p3, \[sp, #3, mul vl\]
++**	str	z3, \[sp, #1, mul vl\]
++**	str	z7, \[sp, #2, mul vl\]
++**	stp	q2, q6, \[sp, #?-32\]!
++**	fmov	w10, s0
++**	fmov	x11, d1
++**	fmov	w12, s4
++**	fmov	x13, d5
++**	smstop	sm
++**	fmov	s0, w10
++**	fmov	d1, x11
++**	fmov	s4, w12
++**	fmov	d5, x13
++**	ldp	q2, q6, \[sp\], #?32
++**	ldr	p0, \[sp\]
++**	ldr	p1, \[sp, #1, mul vl\]
++**	ldr	p2, \[sp, #2, mul vl\]
++**	ldr	p3, \[sp, #3, mul vl\]
++**	ldr	z3, \[sp, #1, mul vl\]
++**	ldr	z7, \[sp, #2, mul vl\]
++**	addvl	sp, sp, #3
++**	bl	consume_mixed
++**	...
++*/
++void
++test_mixed (float32x4_t *float32x4_ptr,
++	    svfloat32_t *svfloat32_ptr,
++	    float64x2_t *float64x2_ptr,
++	    svfloat64_t *svfloat64_ptr,
++	    svbool_t *svbool_ptr) [[arm::streaming]]
++{
++  consume_mixed (1.0f, 2.0, *float32x4_ptr, *svfloat32_ptr,
++		 3.0f, 4.0, *float64x2_ptr, *svfloat64_ptr,
++		 *svbool_ptr, *svbool_ptr, *svbool_ptr, *svbool_ptr);
++}
++
++void consume_varargs (float, ...);
++
++/*
++** test_varargs:
++**	...
++**	stp	q3, q7, \[sp, #?-32\]!
++**	fmov	w10, s0
++**	fmov	x11, d1
++** (
++**	fmov	x12, d2
++** |
++**	umov	x12, v2.d\[0\]
++** )
++**	fmov	x13, d4
++**	fmov	x14, d5
++** (
++**	fmov	x15, d6
++** |
++**	umov	x15, v6.d\[0\]
++** )
++**	smstop	sm
++**	fmov	s0, w10
++**	fmov	d1, x11
++**	fmov	d2, x12
++**	fmov	d4, x13
++**	fmov	d5, x14
++**	fmov	d6, x15
++**	ldp	q3, q7, \[sp\], #?32
++**	bl	consume_varargs
++**	...
++*/
++void
++test_varargs (float32x2_t *float32x2_ptr,
++	      float32x4_t *float32x4_ptr,
++	      float64x1_t *float64x1_ptr,
++	      float64x2_t *float64x2_ptr) [[arm::streaming]]
++{
++  consume_varargs (1.0f, 2.0, *float32x2_ptr, *float32x4_ptr,
++		   3.0f, 4.0, *float64x1_ptr, *float64x2_ptr);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c
+new file mode 100644
+index 000000000..f44724df3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c
+@@ -0,0 +1,87 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls -msve-vector-bits=128" }
++// { dg-final { check-function-bodies "**" "" } }
++
++#include 
++
++svint8_t produce_z0 ();
++void consume_z0 (svint8_t);
++
++/*
++** test_z0:
++**	...
++**	smstop	sm
++**	bl	produce_z0
++**	str	q0, \[sp, #?-16\]!
++**	smstart	sm
++**	ldr	q0, \[sp\], #?16
++**	str	q0, \[sp, #?-16\]!
++**	smstop	sm
++**	ldr	q0, \[sp\], #?16
++**	bl	consume_z0
++**	...
++*/
++void
++test_z0 () [[arm::streaming]]
++{
++  svint8_t res = produce_z0 ();
++  asm volatile ("");
++  consume_z0 (res);
++}
++
++svint8x4_t produce_z3 ();
++void consume_z3 (svint8x4_t);
++
++/*
++** test_z3:
++**	...
++**	smstop	sm
++**	bl	produce_z3
++**	stp	q0, q1, \[sp, #?-64\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	smstart	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?64
++**	stp	q0, q1, \[sp, #?-64\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	smstop	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?64
++**	bl	consume_z3
++**	...
++*/
++void
++test_z3 () [[arm::streaming]]
++{
++  svint8x4_t res = produce_z3 ();
++  asm volatile ("");
++  consume_z3 (res);
++}
++
++svbool_t produce_p0 ();
++void consume_p0 (svbool_t);
++
++/*
++** test_p0:
++**	...
++**	smstop	sm
++**	bl	produce_p0
++**	sub	sp, sp, #?16
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	add	sp, sp, #?16
++**	sub	sp, sp, #?16
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	add	sp, sp, #?16
++**	bl	consume_p0
++**	...
++*/
++void
++test_p0 () [[arm::streaming]]
++{
++  svbool_t res = produce_p0 ();
++  asm volatile ("");
++  consume_p0 (res);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_9.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_9.c
+new file mode 100644
+index 000000000..83b4073ee
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_9.c
+@@ -0,0 +1,103 @@
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls -msve-vector-bits=256" }
++// { dg-final { check-function-bodies "**" "" } }
++
++#include 
++
++svint8_t produce_z0 ();
++void consume_z0 (svint8_t);
++
++/*
++** test_z0:
++**	...
++**	smstop	sm
++**	bl	produce_z0
++**	sub	sp, sp, #?32
++**	str	z0, \[sp\]
++**	smstart	sm
++**	ldr	z0, \[sp\]
++**	add	sp, sp, #?32
++**	sub	sp, sp, #?32
++**	str	z0, \[sp\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	add	sp, sp, #?32
++**	bl	consume_z0
++**	...
++*/
++void
++test_z0 () [[arm::streaming]]
++{
++  svint8_t res = produce_z0 ();
++  asm volatile ("");
++  consume_z0 (res);
++}
++
++svint8x4_t produce_z3 ();
++void consume_z3 (svint8x4_t);
++
++/*
++** test_z3:
++**	...
++**	smstop	sm
++**	bl	produce_z3
++**	sub	sp, sp, #?128
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	smstart	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	add	sp, sp, #?128
++**	sub	sp, sp, #?128
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	add	sp, sp, #?128
++**	bl	consume_z3
++**	...
++*/
++void
++test_z3 () [[arm::streaming]]
++{
++  svint8x4_t res = produce_z3 ();
++  asm volatile ("");
++  consume_z3 (res);
++}
++
++svbool_t produce_p0 ();
++void consume_p0 (svbool_t);
++
++/*
++** test_p0:
++**	...
++**	smstop	sm
++**	bl	produce_p0
++**	sub	sp, sp, #?32
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	add	sp, sp, #?32
++**	sub	sp, sp, #?32
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	add	sp, sp, #?32
++**	bl	consume_p0
++**	...
++*/
++void
++test_p0 () [[arm::streaming]]
++{
++  svbool_t res = produce_p0 ();
++  asm volatile ("");
++  consume_p0 (res);
++}
+-- 
+2.33.0
+
diff --git a/0206-Backport-SME-aarch64-Add-support-for-SME-ZA-attribut.patch b/0206-Backport-SME-aarch64-Add-support-for-SME-ZA-attribut.patch
new file mode 100644
index 0000000..f15e7f6
--- /dev/null
+++ b/0206-Backport-SME-aarch64-Add-support-for-SME-ZA-attribut.patch
@@ -0,0 +1,4324 @@
+From 1efd433c779f66440facc8ba5cd23bdbdd6672ba Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:26 +0000
+Subject: [PATCH 107/157] [Backport][SME] aarch64: Add support for SME ZA
+ attributes
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=3af9ceb631b741095d8eabd055ff7c23d4a69e6f
+
+SME has an array called ZA that can be enabled and disabled separately
+from streaming mode.  A status bit called PSTATE.ZA indicates whether
+ZA is currently enabled or not.
+
+In C and C++, the state of PSTATE.ZA is controlled using function
+attributes.  There are four attributes that can be attached to
+function types to indicate that the function shares ZA with its
+caller.  These are:
+
+- arm::in("za")
+- arm::out("za")
+- arm::inout("za")
+- arm::preserves("za")
+
+If a function's type has one of these shared-ZA attributes,
+PSTATE.ZA is specified to be 1 on entry to the function and on return
+from the function.  Otherwise, the caller and callee have separate
+ZA contexts; they do not use ZA to share data.
+
+Although normal non-shared-ZA functions have a separate ZA context
+from their callers, nested uses of ZA are expected to be rare.
+The ABI therefore defines a cooperative lazy saving scheme that
+allows saves and restore of ZA to be kept to a minimum.
+(Callers still have the option of doing a full save and restore
+if they prefer.)
+
+Functions that want to use ZA internally have an arm::new("za")
+attribute, which tells the compiler to enable PSTATE.ZA for
+the duration of the function body.  It also tells the compiler
+to commit any lazy save initiated by a caller.
+
+The patch uses various abstract hard registers to track dataflow
+relating to ZA.  See the comments in the patch for details.
+
+The lazy save scheme is intended to be transparent to most normal
+functions, so that they don't need to be recompiled for SME.
+This is reflected in the way that most normal functions ignore
+the new hard registers added in the patch.
+
+As with arm::streaming and arm::streaming_compatible, the attributes are
+also available as __arm_.  This has two advantages: it triggers an
+error on compilers that don't understand the attributes, and it eases
+use on C, where [[...]] attributes were only added in C23.
+
+gcc/
+	* config/aarch64/aarch64-isa-modes.def (ZA_ON): New ISA mode.
+	* config/aarch64/aarch64-protos.h (aarch64_rdsvl_immediate_p)
+	(aarch64_output_rdsvl, aarch64_optimize_mode_switching)
+	(aarch64_restore_za): Declare.
+	* config/aarch64/constraints.md (UsR): New constraint.
+	* config/aarch64/aarch64.md (LOWERING_REGNUM, TPIDR_BLOCK_REGNUM)
+	(SME_STATE_REGNUM, TPIDR2_SETUP_REGNUM, ZA_FREE_REGNUM)
+	(ZA_SAVED_REGNUM, ZA_REGNUM, FIRST_FAKE_REGNUM): New constants.
+	(LAST_FAKE_REGNUM): Likewise.
+	(UNSPEC_SAVE_NZCV, UNSPEC_RESTORE_NZCV, UNSPEC_SME_VQ): New unspecs.
+	(arches): Add sme.
+	(arch_enabled): Handle it.
+	(*cb1): Rename to...
+	(aarch64_cb1): ...this.
+	(*movsi_aarch64): Add an alternative for RDSVL.
+	(*movdi_aarch64): Likewise.
+	(aarch64_save_nzcv, aarch64_restore_nzcv): New insns.
+	* config/aarch64/aarch64-sme.md (UNSPEC_SMSTOP_ZA)
+	(UNSPEC_INITIAL_ZERO_ZA, UNSPEC_TPIDR2_SAVE, UNSPEC_TPIDR2_RESTORE)
+	(UNSPEC_READ_TPIDR2, UNSPEC_WRITE_TPIDR2, UNSPEC_SETUP_LOCAL_TPIDR2)
+	(UNSPEC_RESTORE_ZA, UNSPEC_START_PRIVATE_ZA_CALL): New unspecs.
+	(UNSPEC_END_PRIVATE_ZA_CALL, UNSPEC_COMMIT_LAZY_SAVE): Likewise.
+	(UNSPECV_ASM_UPDATE_ZA): New unspecv.
+	(aarch64_tpidr2_save, aarch64_smstart_za, aarch64_smstop_za)
+	(aarch64_initial_zero_za, aarch64_setup_local_tpidr2)
+	(aarch64_clear_tpidr2, aarch64_write_tpidr2, aarch64_read_tpidr2)
+	(aarch64_tpidr2_restore, aarch64_restore_za, aarch64_asm_update_za)
+	(aarch64_start_private_za_call, aarch64_end_private_za_call)
+	(aarch64_commit_lazy_save): New patterns.
+	* config/aarch64/aarch64.h (AARCH64_ISA_ZA_ON, TARGET_ZA): New macros.
+	(FIXED_REGISTERS, REGISTER_NAMES): Add the new fake ZA registers.
+	(CALL_USED_REGISTERS): Replace with...
+	(CALL_REALLY_USED_REGISTERS): ...this and add the fake ZA registers.
+	(FIRST_PSEUDO_REGISTER): Bump to include the fake ZA registers.
+	(FAKE_REGS): New register class.
+	(REG_CLASS_NAMES): Update accordingly.
+	(REG_CLASS_CONTENTS): Likewise.
+	(machine_function::tpidr2_block): New member variable.
+	(machine_function::tpidr2_block_ptr): Likewise.
+	(machine_function::za_save_buffer): Likewise.
+	(machine_function::next_asm_update_za_id): Likewise.
+	(CUMULATIVE_ARGS::shared_za_flags): Likewise.
+	(aarch64_mode_entity, aarch64_local_sme_state): New enums.
+	(aarch64_tristate_mode): Likewise.
+	(OPTIMIZE_MODE_SWITCHING, NUM_MODES_FOR_MODE_SWITCHING): Define.
+	* config/aarch64/aarch64.cc (AARCH64_STATE_SHARED, AARCH64_STATE_IN)
+	(AARCH64_STATE_OUT): New constants.
+	(aarch64_attribute_shared_state_flags): New function.
+	(aarch64_lookup_shared_state_flags, aarch64_fndecl_has_new_state)
+	(aarch64_check_state_string, cmp_string_csts): Likewise.
+	(aarch64_merge_string_arguments, aarch64_check_arm_new_against_type)
+	(handle_arm_new, handle_arm_shared): Likewise.
+	(handle_arm_new_za_attribute): New
+	(aarch64_arm_attribute_table): Add new, preserves, in, out, and inout.
+	(aarch64_hard_regno_nregs): Handle FAKE_REGS.
+	(aarch64_hard_regno_mode_ok): Likewise.
+	(aarch64_fntype_shared_flags, aarch64_fntype_pstate_za): New functions.
+	(aarch64_fntype_isa_mode): Include aarch64_fntype_pstate_za.
+	(aarch64_fndecl_has_state, aarch64_fndecl_pstate_za): New functions.
+	(aarch64_fndecl_isa_mode): Include aarch64_fndecl_pstate_za.
+	(aarch64_cfun_incoming_pstate_za, aarch64_cfun_shared_flags)
+	(aarch64_cfun_has_new_state, aarch64_cfun_has_state): New functions.
+	(aarch64_sme_vq_immediate, aarch64_sme_vq_unspec_p): Likewise.
+	(aarch64_rdsvl_immediate_p, aarch64_output_rdsvl): Likewise.
+	(aarch64_expand_mov_immediate): Handle RDSVL immediates.
+	(aarch64_function_arg): Add the ZA sharing flags as a third limb
+	of the PARALLEL.
+	(aarch64_init_cumulative_args): Record the ZA sharing flags.
+	(aarch64_extra_live_on_entry): New function.  Handle the new
+	ZA-related fake registers.
+	(aarch64_epilogue_uses): Handle the new ZA-related fake registers.
+	(aarch64_cannot_force_const_mem): Handle UNSPEC_SME_VQ constants.
+	(aarch64_get_tpidr2_block, aarch64_get_tpidr2_ptr): New functions.
+	(aarch64_init_tpidr2_block, aarch64_restore_za): Likewise.
+	(aarch64_layout_frame): Check whether the current function creates
+	new ZA state.  Record that it clobbers LR if so.
+	(aarch64_expand_prologue): Handle functions that create new ZA state.
+	(aarch64_expand_epilogue): Likewise.
+	(aarch64_create_tpidr2_block): New function.
+	(aarch64_restore_za): Likewise.
+	(aarch64_start_call_args): Disallow calls to shared-ZA functions
+	from functions that have no ZA state.  Emit a marker instruction
+	before calls to private-ZA functions from functions that have
+	SME state.
+	(aarch64_expand_call): Add return registers for state that is
+	managed via attributes.  Record the use and clobber information
+	for the ZA registers.
+	(aarch64_end_call_args): New function.
+	(aarch64_regno_regclass): Handle FAKE_REGS.
+	(aarch64_class_max_nregs): Likewise.
+	(aarch64_override_options_internal): Require TARGET_SME for
+	functions that have ZA state.
+	(aarch64_conditional_register_usage): Handle FAKE_REGS.
+	(aarch64_mov_operand_p): Handle RDSVL immediates.
+	(aarch64_comp_type_attributes): Check that the ZA sharing flags
+	are equal.
+	(aarch64_merge_decl_attributes): New function.
+	(aarch64_optimize_mode_switching, aarch64_mode_emit_za_save_buffer)
+	(aarch64_mode_emit_local_sme_state, aarch64_mode_emit):  Likewise.
+	(aarch64_insn_references_sme_state_p): Likewise.
+	(aarch64_mode_needed_local_sme_state): Likewise.
+	(aarch64_mode_needed_za_save_buffer, aarch64_mode_needed): Likewise.
+	(aarch64_mode_after_local_sme_state, aarch64_mode_after): Likewise.
+	(aarch64_local_sme_confluence, aarch64_mode_confluence): Likewise.
+	(aarch64_one_shot_backprop, aarch64_local_sme_backprop): Likewise.
+	(aarch64_mode_backprop, aarch64_mode_entry): Likewise.
+	(aarch64_mode_exit, aarch64_mode_eh_handler): Likewise.
+	(aarch64_mode_priority, aarch64_md_asm_adjust): Likewise.
+	(TARGET_END_CALL_ARGS, TARGET_MERGE_DECL_ATTRIBUTES): Define.
+	(TARGET_MODE_EMIT, TARGET_MODE_NEEDED, TARGET_MODE_AFTER): Likewise.
+	(TARGET_MODE_CONFLUENCE, TARGET_MODE_BACKPROP): Likewise.
+	(TARGET_MODE_ENTRY, TARGET_MODE_EXIT): Likewise.
+	(TARGET_MODE_EH_HANDLER, TARGET_MODE_PRIORITY): Likewise.
+	(TARGET_EXTRA_LIVE_ON_ENTRY): Likewise.
+	(TARGET_MD_ASM_ADJUST): Use aarch64_md_asm_adjust.
+	* config/aarch64/aarch64-c.cc (aarch64_define_unconditional_macros):
+	Define __arm_new, __arm_preserves,__arm_in, __arm_out, and __arm_inout.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/za_state_1.c: New test.
+	* gcc.target/aarch64/sme/za_state_2.c: Likewise.
+	* gcc.target/aarch64/sme/za_state_3.c: Likewise.
+	* gcc.target/aarch64/sme/za_state_4.c: Likewise.
+	* gcc.target/aarch64/sme/za_state_5.c: Likewise.
+	* gcc.target/aarch64/sme/za_state_6.c: Likewise.
+	* g++.target/aarch64/sme/exceptions_1.C: Likewise.
+	* gcc.target/aarch64/sme/keyword_macros_1.c: Add ZA macros.
+	* g++.target/aarch64/sme/keyword_macros_1.C: Likewise.
+---
+ gcc/config/aarch64/aarch64-c.cc               |   32 +
+ gcc/config/aarch64/aarch64-isa-modes.def      |    5 +
+ gcc/config/aarch64/aarch64-protos.h           |    5 +
+ gcc/config/aarch64/aarch64-sme.md             |  287 ++++
+ gcc/config/aarch64/aarch64.cc                 | 1371 ++++++++++++++++-
+ gcc/config/aarch64/aarch64.h                  |   98 +-
+ gcc/config/aarch64/aarch64.md                 |   81 +-
+ gcc/config/aarch64/constraints.md             |    6 +
+ .../g++.target/aarch64/sme/exceptions_1.C     |  189 +++
+ .../g++.target/aarch64/sme/keyword_macros_1.C |    5 +
+ .../gcc.target/aarch64/sme/keyword_macros_1.c |    5 +
+ .../gcc.target/aarch64/sme/za_state_1.c       |  154 ++
+ .../gcc.target/aarch64/sme/za_state_2.c       |   73 +
+ .../gcc.target/aarch64/sme/za_state_3.c       |   31 +
+ .../gcc.target/aarch64/sme/za_state_4.c       |  585 +++++++
+ .../gcc.target/aarch64/sme/za_state_5.c       |  595 +++++++
+ .../gcc.target/aarch64/sme/za_state_6.c       |   23 +
+ 17 files changed, 3523 insertions(+), 22 deletions(-)
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/za_state_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/za_state_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/za_state_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/za_state_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/za_state_6.c
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 397745fbd..76c20848f 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -73,6 +73,8 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
+ 
+   builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
+ 
++  builtin_define ("__ARM_STATE_ZA");
++
+   /* Define keyword attributes like __arm_streaming as macros that expand
+      to the associated [[...]] attribute.  Use __extension__ in the attribute
+      for C, since the [[...]] syntax was only added in C23.  */
+@@ -86,6 +88,36 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
+   DEFINE_ARM_KEYWORD_MACRO ("streaming_compatible");
+ 
+ #undef DEFINE_ARM_KEYWORD_MACRO
++
++  /* Same for the keyword attributes that take arguments.  The snag here
++     is that some old modes warn about or reject variadic arguments.  */
++  auto *cpp_opts = cpp_get_options (parse_in);
++  if (!cpp_opts->traditional)
++    {
++      auto old_warn_variadic_macros = cpp_opts->warn_variadic_macros;
++      auto old_cpp_warn_c90_c99_compat = cpp_opts->cpp_warn_c90_c99_compat;
++
++      cpp_opts->warn_variadic_macros = false;
++      cpp_opts->cpp_warn_c90_c99_compat = 0;
++
++#define DEFINE_ARM_KEYWORD_MACRO_ARGS(NAME) \
++  builtin_define_with_value ("__arm_" NAME "(...)", \
++			     lang_GNU_CXX () \
++			     ? "[[arm::" NAME "(__VA_ARGS__)]]" \
++			     : "[[__extension__ arm::" NAME \
++			       "(__VA_ARGS__)]]", 0);
++
++      DEFINE_ARM_KEYWORD_MACRO_ARGS ("new");
++      DEFINE_ARM_KEYWORD_MACRO_ARGS ("preserves");
++      DEFINE_ARM_KEYWORD_MACRO_ARGS ("in");
++      DEFINE_ARM_KEYWORD_MACRO_ARGS ("out");
++      DEFINE_ARM_KEYWORD_MACRO_ARGS ("inout");
++
++#undef DEFINE_ARM_KEYWORD_MACRO_ARGS
++
++      cpp_opts->warn_variadic_macros = old_warn_variadic_macros;
++      cpp_opts->cpp_warn_c90_c99_compat = old_cpp_warn_c90_c99_compat;
++    }
+ }
+ 
+ /* Undefine/redefine macros that depend on the current backend state and may
+diff --git a/gcc/config/aarch64/aarch64-isa-modes.def b/gcc/config/aarch64/aarch64-isa-modes.def
+index 5915c98a8..c0ada35bd 100644
+--- a/gcc/config/aarch64/aarch64-isa-modes.def
++++ b/gcc/config/aarch64/aarch64-isa-modes.def
+@@ -32,4 +32,9 @@
+ DEF_AARCH64_ISA_MODE(SM_ON)
+ DEF_AARCH64_ISA_MODE(SM_OFF)
+ 
++/* Indicates that PSTATE.ZA is known to be 1.  The converse is that
++   PSTATE.ZA might be 0 or 1, depending on whether there is an uncommitted
++   lazy save.  */
++DEF_AARCH64_ISA_MODE(ZA_ON)
++
+ #undef DEF_AARCH64_ISA_MODE
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 737f47026..0883ddd1a 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -808,6 +808,8 @@ bool aarch64_sve_addvl_addpl_immediate_p (rtx);
+ bool aarch64_sve_vector_inc_dec_immediate_p (rtx);
+ int aarch64_add_offset_temporaries (rtx);
+ void aarch64_split_add_offset (scalar_int_mode, rtx, rtx, rtx, rtx, rtx);
++bool aarch64_rdsvl_immediate_p (const_rtx);
++char *aarch64_output_rdsvl (const_rtx);
+ bool aarch64_mov_operand_p (rtx, machine_mode);
+ rtx aarch64_reverse_mask (machine_mode, unsigned int);
+ bool aarch64_offset_7bit_signed_scaled_p (machine_mode, poly_int64);
+@@ -1083,4 +1085,7 @@ extern bool aarch64_harden_sls_blr_p (void);
+ 
+ extern void aarch64_output_patchable_area (unsigned int, bool);
+ 
++bool aarch64_optimize_mode_switching (aarch64_mode_entity);
++void aarch64_restore_za (rtx);
++
+ #endif /* GCC_AARCH64_PROTOS_H */
+diff --git a/gcc/config/aarch64/aarch64-sme.md b/gcc/config/aarch64/aarch64-sme.md
+index 52427b4f1..d4973098e 100644
+--- a/gcc/config/aarch64/aarch64-sme.md
++++ b/gcc/config/aarch64/aarch64-sme.md
+@@ -23,6 +23,7 @@
+ ;; == State management
+ ;; ---- Test current state
+ ;; ---- PSTATE.SM management
++;; ---- PSTATE.ZA management
+ 
+ ;; =========================================================================
+ ;; == State management
+@@ -169,3 +170,289 @@
+   ""
+   "smstop\tsm"
+ )
++
++;; -------------------------------------------------------------------------
++;; ---- PSTATE.ZA management
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - SMSTART ZA
++;; - SMSTOP ZA
++;; plus calls to support routines.
++;; -------------------------------------------------------------------------
++
++(define_c_enum "unspec" [
++  UNSPEC_SMSTOP_ZA
++  UNSPEC_INITIAL_ZERO_ZA
++  UNSPEC_TPIDR2_SAVE
++  UNSPEC_TPIDR2_RESTORE
++  UNSPEC_READ_TPIDR2
++  UNSPEC_WRITE_TPIDR2
++  UNSPEC_SETUP_LOCAL_TPIDR2
++  UNSPEC_RESTORE_ZA
++  UNSPEC_START_PRIVATE_ZA_CALL
++  UNSPEC_END_PRIVATE_ZA_CALL
++  UNSPEC_COMMIT_LAZY_SAVE
++])
++
++(define_c_enum "unspecv" [
++  UNSPECV_ASM_UPDATE_ZA
++])
++
++;; Use the ABI-defined routine to commit an uncommitted lazy save.
++;; This relies on the current PSTATE.ZA, so depends on SME_STATE_REGNUM.
++;; The fake TPIDR2_SETUP_REGNUM register initially holds the incoming
++;; value of the architected TPIDR2_EL0.
++(define_insn "aarch64_tpidr2_save"
++  [(set (reg:DI ZA_FREE_REGNUM)
++	(unspec:DI [(reg:DI SME_STATE_REGNUM)
++		    (reg:DI TPIDR2_SETUP_REGNUM)] UNSPEC_TPIDR2_SAVE))
++   (clobber (reg:DI R14_REGNUM))
++   (clobber (reg:DI R15_REGNUM))
++   (clobber (reg:DI R16_REGNUM))
++   (clobber (reg:DI R17_REGNUM))
++   (clobber (reg:DI R18_REGNUM))
++   (clobber (reg:DI R30_REGNUM))
++   (clobber (reg:CC CC_REGNUM))]
++  ""
++  "bl\t__arm_tpidr2_save"
++)
++
++;; Set PSTATE.ZA to 1.  If ZA was previously dormant or active,
++;; it remains in the same state afterwards, with the same contents.
++;; Otherwise, it goes from off to on with zeroed contents.
++;;
++;; Later writes of TPIDR2_EL0 to a nonzero value must not be moved
++;; up past this instruction, since that could create an invalid
++;; combination of having an active lazy save while ZA is off.
++;; Create an anti-dependence by reading the current contents
++;; of TPIDR2_SETUP_REGNUM.
++;;
++;; Making this depend on ZA_FREE_REGNUM ensures that contents belonging
++;; to the caller have already been saved.  That isn't necessary for this
++;; instruction itself, since PSTATE.ZA is already 1 if it contains data.
++;; But doing this here means that other uses of ZA can just depend on
++;; SME_STATE_REGNUM, rather than both SME_STATE_REGNUM and ZA_FREE_REGNUM.
++(define_insn "aarch64_smstart_za"
++  [(set (reg:DI SME_STATE_REGNUM)
++	(const_int 1))
++   (use (reg:DI TPIDR2_SETUP_REGNUM))
++   (use (reg:DI ZA_FREE_REGNUM))]
++  ""
++  "smstart\tza"
++)
++
++;; Disable ZA and discard its current contents.
++;;
++;; The ABI says that the ZA save buffer must be null whenever PSTATE.ZA
++;; is zero, so earlier writes to TPIDR2_EL0 must not be moved down past
++;; this instruction.  Depend on TPIDR2_SETUP_REGNUM to ensure this.
++;;
++;; We can only turn ZA off once we know that it is free (i.e. doesn't
++;; contain data belonging to the caller).  Depend on ZA_FREE_REGNUM
++;; to ensure this.
++;;
++;; We only turn ZA off when the current function's ZA state is dead,
++;; or perhaps if we're sure that the contents are saved.  Either way,
++;; we know whether ZA is saved or not.
++(define_insn "aarch64_smstop_za"
++  [(set (reg:DI SME_STATE_REGNUM)
++	(const_int 0))
++   (set (reg:DI ZA_SAVED_REGNUM)
++	(unspec:DI [(reg:DI TPIDR2_SETUP_REGNUM)
++		    (reg:DI ZA_FREE_REGNUM)] UNSPEC_SMSTOP_ZA))]
++  ""
++  "smstop\tza"
++)
++
++;; Zero ZA after committing a lazy save.  The sequencing is enforced
++;; by reading ZA_FREE_REGNUM.
++(define_insn "aarch64_initial_zero_za"
++  [(set (reg:DI ZA_REGNUM)
++	(unspec:DI [(reg:DI SME_STATE_REGNUM)
++		    (reg:DI ZA_FREE_REGNUM)] UNSPEC_INITIAL_ZERO_ZA))]
++  ""
++  "zero\t{ za }"
++)
++
++;; Initialize the abstract TPIDR2_BLOCK_REGNUM from the contents of
++;; the current function's TPIDR2 block.  Other instructions can then
++;; depend on TPIDR2_BLOCK_REGNUM rather than on the memory block.
++(define_insn "aarch64_setup_local_tpidr2"
++  [(set (reg:DI TPIDR2_BLOCK_REGNUM)
++	(unspec:DI [(match_operand:V16QI 0 "memory_operand" "m")]
++		   UNSPEC_SETUP_LOCAL_TPIDR2))]
++  ""
++  ""
++  [(set_attr "type" "no_insn")]
++)
++
++;; Clear TPIDR2_EL0, cancelling any uncommitted lazy save.
++(define_insn "aarch64_clear_tpidr2"
++  [(set (reg:DI TPIDR2_SETUP_REGNUM)
++	(const_int 0))]
++  ""
++  "msr\ttpidr2_el0, xzr"
++)
++
++;; Point TPIDR2_EL0 to the current function's TPIDR2 block, whose address
++;; is given by operand 0.  TPIDR2_BLOCK_REGNUM represents the contents of the
++;; pointed-to block.
++(define_insn "aarch64_write_tpidr2"
++  [(set (reg:DI TPIDR2_SETUP_REGNUM)
++	(unspec:DI [(match_operand 0 "pmode_register_operand" "r")
++		    (reg:DI TPIDR2_BLOCK_REGNUM)] UNSPEC_WRITE_TPIDR2))]
++  ""
++  "msr\ttpidr2_el0, %0"
++)
++
++;; Check whether ZA has been saved.  The system depends on the value that
++;; we wrote to TPIDR2_EL0 previously, so it depends on TPDIR2_SETUP_REGNUM.
++(define_insn "aarch64_read_tpidr2"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(unspec:DI [(reg:DI TPIDR2_SETUP_REGNUM)
++		    (reg:DI ZA_SAVED_REGNUM)] UNSPEC_READ_TPIDR2))]
++  ""
++  "mrs\t%0, tpidr2_el0"
++)
++
++;; Use the ABI-defined routine to restore lazy-saved ZA contents
++;; from the TPIDR2 block pointed to by X0.  ZA must already be active.
++(define_insn "aarch64_tpidr2_restore"
++  [(set (reg:DI ZA_SAVED_REGNUM)
++	(unspec:DI [(reg:DI R0_REGNUM)] UNSPEC_TPIDR2_RESTORE))
++   (set (reg:DI SME_STATE_REGNUM)
++	(unspec:DI [(reg:DI SME_STATE_REGNUM)] UNSPEC_TPIDR2_RESTORE))
++   (clobber (reg:DI R14_REGNUM))
++   (clobber (reg:DI R15_REGNUM))
++   (clobber (reg:DI R16_REGNUM))
++   (clobber (reg:DI R17_REGNUM))
++   (clobber (reg:DI R18_REGNUM))
++   (clobber (reg:DI R30_REGNUM))
++   (clobber (reg:CC CC_REGNUM))]
++  ""
++  "bl\t__arm_tpidr2_restore"
++)
++
++;; Check whether a lazy save set up by aarch64_save_za was committed
++;; and restore the saved contents if so.
++;;
++;; Operand 0 is the address of the current function's TPIDR2 block.
++(define_insn_and_split "aarch64_restore_za"
++  [(set (reg:DI ZA_SAVED_REGNUM)
++	(unspec:DI [(match_operand 0 "pmode_register_operand" "r")
++		    (reg:DI SME_STATE_REGNUM)
++		    (reg:DI TPIDR2_SETUP_REGNUM)
++		    (reg:DI ZA_SAVED_REGNUM)] UNSPEC_RESTORE_ZA))
++   (clobber (reg:DI R0_REGNUM))
++   (clobber (reg:DI R14_REGNUM))
++   (clobber (reg:DI R15_REGNUM))
++   (clobber (reg:DI R16_REGNUM))
++   (clobber (reg:DI R17_REGNUM))
++   (clobber (reg:DI R18_REGNUM))
++   (clobber (reg:DI R30_REGNUM))
++   (clobber (reg:CC CC_REGNUM))]
++  ""
++  "#"
++  "&& epilogue_completed"
++  [(const_int 0)]
++  {
++    auto label = gen_label_rtx ();
++    auto tpidr2 = gen_rtx_REG (DImode, R16_REGNUM);
++    emit_insn (gen_aarch64_read_tpidr2 (tpidr2));
++    auto jump = emit_likely_jump_insn (gen_aarch64_cbnedi1 (tpidr2, label));
++    JUMP_LABEL (jump) = label;
++
++    aarch64_restore_za (operands[0]);
++    emit_label (label);
++    DONE;
++  }
++)
++
++;; This instruction is emitted after asms that alter ZA, in order to model
++;; the effect on dataflow.  The asm itself can't have ZA as an input or
++;; an output, since there is no associated data type.  Instead it retains
++;; the original "za" clobber, which on its own would indicate that ZA
++;; is dead.
++;;
++;; The operand is a unique identifier.
++(define_insn "aarch64_asm_update_za"
++  [(set (reg:VNx16QI ZA_REGNUM)
++	(unspec_volatile:VNx16QI
++	  [(reg:VNx16QI ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand 0 "const_int_operand")]
++	  UNSPECV_ASM_UPDATE_ZA))]
++  ""
++  ""
++  [(set_attr "type" "no_insn")]
++)
++
++;; This pseudo-instruction is emitted as part of a call to a private-ZA
++;; function from a function with ZA state.  It marks a natural place to set
++;; up a lazy save, if that turns out to be necessary.  The save itself
++;; is managed by the mode-switching pass.
++(define_insn "aarch64_start_private_za_call"
++  [(set (reg:DI LOWERING_REGNUM)
++	(unspec:DI [(reg:DI LOWERING_REGNUM)] UNSPEC_START_PRIVATE_ZA_CALL))]
++  ""
++  ""
++  [(set_attr "type" "no_insn")]
++)
++
++;; This pseudo-instruction is emitted as part of a call to a private-ZA
++;; function from a function with ZA state.  It marks a natural place to restore
++;; the current function's ZA contents from the lazy save buffer, if that
++;; turns out to be necessary.  The save itself is managed by the
++;; mode-switching pass.
++(define_insn "aarch64_end_private_za_call"
++  [(set (reg:DI LOWERING_REGNUM)
++	(unspec:DI [(reg:DI LOWERING_REGNUM)] UNSPEC_END_PRIVATE_ZA_CALL))]
++  ""
++  ""
++  [(set_attr "type" "no_insn")]
++)
++
++;; This pseudo-instruction is emitted before a private-ZA function uses
++;; PSTATE.ZA state for the first time.  The instruction checks whether
++;; ZA currently contains data belonging to a caller and commits the
++;; lazy save if so.
++;;
++;; Operand 0 is the incoming value of TPIDR2_EL0.  Operand 1 is nonzero
++;; if ZA is live, and should therefore be zeroed after committing a save.
++;;
++;; The instruction is generated by the mode-switching pass.  It is a
++;; define_insn_and_split rather than a define_expand because of the
++;; internal control flow.
++(define_insn_and_split "aarch64_commit_lazy_save"
++  [(set (reg:DI ZA_FREE_REGNUM)
++	(unspec:DI [(match_operand 0 "pmode_register_operand" "r")
++		    (match_operand 1 "const_int_operand")
++		    (reg:DI SME_STATE_REGNUM)
++		    (reg:DI TPIDR2_SETUP_REGNUM)
++		    (reg:VNx16QI ZA_REGNUM)] UNSPEC_COMMIT_LAZY_SAVE))
++   (set (reg:DI ZA_REGNUM)
++	(unspec:DI [(reg:DI SME_STATE_REGNUM)
++		    (reg:DI ZA_FREE_REGNUM)] UNSPEC_INITIAL_ZERO_ZA))
++   (clobber (reg:DI R14_REGNUM))
++   (clobber (reg:DI R15_REGNUM))
++   (clobber (reg:DI R16_REGNUM))
++   (clobber (reg:DI R17_REGNUM))
++   (clobber (reg:DI R18_REGNUM))
++   (clobber (reg:DI R30_REGNUM))
++   (clobber (reg:CC CC_REGNUM))]
++  ""
++  "#"
++  "true"
++  [(const_int 0)]
++  {
++    auto label = gen_label_rtx ();
++    auto jump = emit_jump_insn (gen_aarch64_cbeqdi1 (operands[0], label));
++    JUMP_LABEL (jump) = label;
++    emit_insn (gen_aarch64_tpidr2_save ());
++    emit_insn (gen_aarch64_clear_tpidr2 ());
++    if (INTVAL (operands[1]) != 0)
++      emit_insn (gen_aarch64_initial_zero_za ());
++    emit_label (label);
++    DONE;
++  }
++)
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 82f8e574e..a6e996c5b 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -91,6 +91,26 @@
+ /* Defined for convenience.  */
+ #define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
+ 
++/* Flags that describe how a function shares certain architectural state
++   with its callers.
++
++   - AARCH64_STATE_SHARED indicates that the function does share the state
++     with callers.
++
++   - AARCH64_STATE_IN indicates that the function reads (or might read) the
++     incoming state.  The converse is that the function ignores the incoming
++     state.
++
++   - AARCH64_STATE_OUT indicates that the function returns new state.
++     The converse is that the state on return is the same as it was on entry.
++
++   A function that partially modifies the state treats it as both IN
++   and OUT (because the value on return depends to some extent on the
++   value on input).  */
++constexpr auto AARCH64_STATE_SHARED = 1U << 0;
++constexpr auto AARCH64_STATE_IN = 1U << 1;
++constexpr auto AARCH64_STATE_OUT = 1U << 2;
++
+ /* Information about a legitimate vector immediate operand.  */
+ struct simd_immediate_info
+ {
+@@ -2959,6 +2979,151 @@ static const struct processor all_cores[] =
+ /* The current tuning set.  */
+ struct tune_params aarch64_tune_params = generic_tunings;
+ 
++/* If NAME is the name of an arm:: attribute that describes shared state,
++   return its associated AARCH64_STATE_* flags, otherwise return 0.  */
++static unsigned int
++aarch64_attribute_shared_state_flags (const char *name)
++{
++  if (strcmp (name, "in") == 0)
++    return AARCH64_STATE_SHARED | AARCH64_STATE_IN;
++  if (strcmp (name, "inout") == 0)
++    return AARCH64_STATE_SHARED | AARCH64_STATE_IN | AARCH64_STATE_OUT;
++  if (strcmp (name, "out") == 0)
++    return AARCH64_STATE_SHARED | AARCH64_STATE_OUT;
++  if (strcmp (name, "preserves") == 0)
++    return AARCH64_STATE_SHARED;
++  return 0;
++}
++
++/* See whether attribute list ATTRS has any sharing information
++   for state STATE_NAME.  Return the associated state flags if so,
++   otherwise return 0.  */
++static unsigned int
++aarch64_lookup_shared_state_flags (tree attrs, const char *state_name)
++{
++  for (tree attr = attrs; attr; attr = TREE_CHAIN (attr))
++    {
++      if (!cxx11_attribute_p (attr))
++	continue;
++
++      auto ns = IDENTIFIER_POINTER (TREE_PURPOSE (TREE_PURPOSE (attr)));
++      if (strcmp (ns, "arm") != 0)
++	continue;
++
++      auto attr_name = IDENTIFIER_POINTER (TREE_VALUE (TREE_PURPOSE (attr)));
++      auto flags = aarch64_attribute_shared_state_flags (attr_name);
++      if (!flags)
++	continue;
++
++      for (tree arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
++	{
++	  tree value = TREE_VALUE (arg);
++	  if (TREE_CODE (value) == STRING_CST
++	      && strcmp (TREE_STRING_POINTER (value), state_name) == 0)
++	    return flags;
++	}
++    }
++  return 0;
++}
++
++/* Return true if DECL creates a new scope for state STATE_STRING.  */
++static bool
++aarch64_fndecl_has_new_state (const_tree decl, const char *state_name)
++{
++  if (tree attr = lookup_attribute ("arm", "new", DECL_ATTRIBUTES (decl)))
++    for (tree arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
++      {
++	tree value = TREE_VALUE (arg);
++	if (TREE_CODE (value) == STRING_CST
++	    && strcmp (TREE_STRING_POINTER (value), state_name) == 0)
++	  return true;
++      }
++  return false;
++}
++
++/* Return true if attribute argument VALUE is a recognized state string,
++   otherwise report an error.  NAME is the name of the attribute to which
++   VALUE is being passed.  */
++static bool
++aarch64_check_state_string (tree name, tree value)
++{
++  if (TREE_CODE (value) != STRING_CST)
++    {
++      error ("the arguments to %qE must be constant strings", name);
++      return false;
++    }
++
++  const char *state_name = TREE_STRING_POINTER (value);
++  if (strcmp (state_name, "za") != 0)
++    {
++      error ("unrecognized state string %qs", state_name);
++      return false;
++    }
++
++  return true;
++}
++
++/* qsort callback to compare two STRING_CSTs.  */
++static int
++cmp_string_csts (const void *a, const void *b)
++{
++  return strcmp (TREE_STRING_POINTER (*(const_tree const *) a),
++		 TREE_STRING_POINTER (*(const_tree const *) b));
++}
++
++/* Canonicalize a list of state strings.  ARGS contains the arguments to
++   a new attribute while OLD_ATTR, if nonnull, contains a previous attribute
++   of the same type.  If CAN_MERGE_IN_PLACE, it is safe to adjust OLD_ATTR's
++   arguments and drop the new attribute.  Otherwise, the new attribute must
++   be kept and ARGS must include the information in OLD_ATTR.
++
++   In both cases, the new arguments must be a sorted list of state strings
++   with duplicates removed.
++
++   Return true if new attribute should be kept, false if it should be
++   dropped.  */
++static bool
++aarch64_merge_string_arguments (tree args, tree old_attr,
++				bool can_merge_in_place)
++{
++  /* Get a sorted list of all state strings (including duplicates).  */
++  auto add_args = [](vec &strings, const_tree args)
++    {
++      for (const_tree arg = args; arg; arg = TREE_CHAIN (arg))
++	if (TREE_CODE (TREE_VALUE (arg)) == STRING_CST)
++	  strings.safe_push (TREE_VALUE (arg));
++    };
++  auto_vec strings;
++  add_args (strings, args);
++  if (old_attr)
++    add_args (strings, TREE_VALUE (old_attr));
++  strings.qsort (cmp_string_csts);
++
++  /* The list can be empty if there was no previous attribute and if all
++     the new arguments are erroneous.  Drop the attribute in that case.  */
++  if (strings.is_empty ())
++    return false;
++
++  /* Destructively modify one of the argument lists, removing duplicates
++     on the fly.  */
++  bool use_old_attr = old_attr && can_merge_in_place;
++  tree *end = use_old_attr ? &TREE_VALUE (old_attr) : &args;
++  tree prev = NULL_TREE;
++  for (tree arg : strings)
++    {
++      if (prev && simple_cst_equal (arg, prev))
++	continue;
++      prev = arg;
++      if (!*end)
++	*end = tree_cons (NULL_TREE, arg, NULL_TREE);
++      else
++	TREE_VALUE (*end) = arg;
++      end = &TREE_CHAIN (*end);
++    }
++  *end = NULL_TREE;
++  return !use_old_attr;
++}
++
+ /* Check whether an 'aarch64_vector_pcs' attribute is valid.  */
+ 
+ static tree
+@@ -2987,6 +3152,101 @@ handle_aarch64_vector_pcs_attribute (tree *node, tree name, tree,
+   gcc_unreachable ();
+ }
+ 
++/* Return true if arm::new(ARGS) is compatible with the type of decl DECL,
++   otherwise report an error.  */
++static bool
++aarch64_check_arm_new_against_type (tree args, tree decl)
++{
++  tree type_attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
++  for (tree arg = args; arg; arg = TREE_CHAIN (arg))
++    {
++      tree value = TREE_VALUE (arg);
++      if (TREE_CODE (value) == STRING_CST)
++	{
++	  const char *state_name = TREE_STRING_POINTER (value);
++	  if (aarch64_lookup_shared_state_flags (type_attrs, state_name))
++	    {
++	      error_at (DECL_SOURCE_LOCATION (decl),
++			"cannot create a new %qs scope since %qs is shared"
++			" with callers", state_name, state_name);
++	      return false;
++	    }
++	}
++    }
++  return true;
++}
++
++/* Callback for arm::new attributes.  */
++static tree
++handle_arm_new (tree *node, tree name, tree args, int, bool *no_add_attrs)
++{
++  tree decl = *node;
++  if (TREE_CODE (decl) != FUNCTION_DECL)
++    {
++      error ("%qE attribute applies only to function definitions", name);
++      *no_add_attrs = true;
++      return NULL_TREE;
++    }
++  if (TREE_TYPE (decl) == error_mark_node)
++    {
++      *no_add_attrs = true;
++      return NULL_TREE;
++    }
++
++  for (tree arg = args; arg; arg = TREE_CHAIN (arg))
++    aarch64_check_state_string (name, TREE_VALUE (arg));
++
++  if (!aarch64_check_arm_new_against_type (args, decl))
++    {
++      *no_add_attrs = true;
++      return NULL_TREE;
++    }
++
++  /* If there is an old attribute, we should try to update it in-place,
++     so that there is only one (definitive) arm::new attribute on the decl.  */
++  tree old_attr = lookup_attribute ("arm", "new", DECL_ATTRIBUTES (decl));
++  if (!aarch64_merge_string_arguments (args, old_attr, true))
++    *no_add_attrs = true;
++
++  return NULL_TREE;
++}
++
++/* Callback for arm::{in,out,inout,preserves} attributes.  */
++static tree
++handle_arm_shared (tree *node, tree name, tree args,
++		   int, bool *no_add_attrs)
++{
++  tree type = *node;
++  tree old_attrs = TYPE_ATTRIBUTES (type);
++  auto flags = aarch64_attribute_shared_state_flags (IDENTIFIER_POINTER (name));
++  for (tree arg = args; arg; arg = TREE_CHAIN (arg))
++    {
++      tree value = TREE_VALUE (arg);
++      if (aarch64_check_state_string (name, value))
++	{
++	  const char *state_name = TREE_STRING_POINTER (value);
++	  auto old_flags = aarch64_lookup_shared_state_flags (old_attrs,
++							      state_name);
++	  if (old_flags && old_flags != flags)
++	    {
++	      error ("inconsistent attributes for state %qs", state_name);
++	      *no_add_attrs = true;
++	      return NULL_TREE;
++	    }
++	}
++    }
++
++  /* We can't update an old attribute in-place, since types are shared.
++     Instead make sure that this new attribute contains all the
++     information, so that the old attribute becomes redundant.  */
++  tree old_attr = lookup_attribute ("arm", IDENTIFIER_POINTER (name),
++				    old_attrs);
++  if (!aarch64_merge_string_arguments (args, old_attr, false))
++    *no_add_attrs = true;
++
++  return NULL_TREE;
++}
++
+ /* Mutually-exclusive function type attributes for controlling PSTATE.SM.  */
+ static const struct attribute_spec::exclusions attr_streaming_exclusions[] =
+ {
+@@ -3023,6 +3283,16 @@ static const attribute_spec aarch64_arm_attributes[] =
+ 			  NULL, attr_streaming_exclusions },
+   { "streaming_compatible", 0, 0, false, true,  true,  true,
+ 			  NULL, attr_streaming_exclusions },
++  { "new",		  1, -1, true, false, false, false,
++			  handle_arm_new, NULL },
++  { "preserves",	  1, -1, false, true,  true,  true,
++			  handle_arm_shared, NULL },
++  { "in",		  1, -1, false, true,  true,  true,
++			  handle_arm_shared, NULL },
++  { "out",		  1, -1, false, true,  true,  true,
++			  handle_arm_shared, NULL },
++  { "inout",		  1, -1, false, true,  true,  true,
++			  handle_arm_shared, NULL }
+ };
+ 
+ static const scoped_attribute_specs aarch64_arm_attribute_table =
+@@ -4202,6 +4472,7 @@ aarch64_hard_regno_nregs (unsigned regno, machine_mode mode)
+     case PR_HI_REGS:
+     case FFR_REGS:
+     case PR_AND_FFR_REGS:
++    case FAKE_REGS:
+       return 1;
+     default:
+       return CEIL (lowest_size, UNITS_PER_WORD);
+@@ -4232,6 +4503,10 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode)
+   if (pr_or_ffr_regnum_p (regno))
+     return false;
+ 
++  /* These registers are abstract; their modes don't matter.  */
++  if (FAKE_REGNUM_P (regno))
++    return true;
++
+   if (regno == SP_REGNUM)
+     /* The purpose of comparing with ptr_mode is to support the
+        global register variable associated with the stack pointer
+@@ -4352,12 +4627,34 @@ aarch64_fntype_pstate_sm (const_tree fntype)
+   return AARCH64_FL_SM_OFF;
+ }
+ 
++/* Return state flags that describe whether and how functions of type
++   FNTYPE share state STATE_NAME with their callers.  */
++
++static unsigned int
++aarch64_fntype_shared_flags (const_tree fntype, const char *state_name)
++{
++  return aarch64_lookup_shared_state_flags (TYPE_ATTRIBUTES (fntype),
++					    state_name);
++}
++
++/* Return the state of PSTATE.ZA on entry to functions of type FNTYPE.  */
++
++static aarch64_feature_flags
++aarch64_fntype_pstate_za (const_tree fntype)
++{
++  if (aarch64_fntype_shared_flags (fntype, "za"))
++    return AARCH64_FL_ZA_ON;
++
++  return 0;
++}
++
+ /* Return the ISA mode on entry to functions of type FNTYPE.  */
+ 
+ static aarch64_feature_flags
+ aarch64_fntype_isa_mode (const_tree fntype)
+ {
+-  return aarch64_fntype_pstate_sm (fntype);
++  return (aarch64_fntype_pstate_sm (fntype)
++	  | aarch64_fntype_pstate_za (fntype));
+ }
+ 
+ /* Return the state of PSTATE.SM when compiling the body of
+@@ -4370,13 +4667,37 @@ aarch64_fndecl_pstate_sm (const_tree fndecl)
+   return aarch64_fntype_pstate_sm (TREE_TYPE (fndecl));
+ }
+ 
++/* Return true if function FNDECL has state STATE_NAME, either by creating
++   new state itself or by sharing state with callers.  */
++
++static bool
++aarch64_fndecl_has_state (tree fndecl, const char *state_name)
++{
++  return (aarch64_fndecl_has_new_state (fndecl, state_name)
++	  || aarch64_fntype_shared_flags (TREE_TYPE (fndecl),
++					  state_name) != 0);
++}
++
++/* Return the state of PSTATE.ZA when compiling the body of function FNDECL.
++   This might be different from the state of PSTATE.ZA on entry.  */
++
++static aarch64_feature_flags
++aarch64_fndecl_pstate_za (const_tree fndecl)
++{
++  if (aarch64_fndecl_has_new_state (fndecl, "za"))
++    return AARCH64_FL_ZA_ON;
++
++  return aarch64_fntype_pstate_za (TREE_TYPE (fndecl));
++}
++
+ /* Return the ISA mode that should be used to compile the body of
+    function FNDECL.  */
+ 
+ static aarch64_feature_flags
+ aarch64_fndecl_isa_mode (const_tree fndecl)
+ {
+-  return aarch64_fndecl_pstate_sm (fndecl);
++  return (aarch64_fndecl_pstate_sm (fndecl)
++	  | aarch64_fndecl_pstate_za (fndecl));
+ }
+ 
+ /* Return the state of PSTATE.SM on entry to the current function.
+@@ -4389,6 +4710,44 @@ aarch64_cfun_incoming_pstate_sm ()
+   return aarch64_fntype_pstate_sm (TREE_TYPE (cfun->decl));
+ }
+ 
++/* Return the state of PSTATE.ZA on entry to the current function.
++   This might be different from the state of PSTATE.ZA in the function
++   body.  */
++
++static aarch64_feature_flags
++aarch64_cfun_incoming_pstate_za ()
++{
++  return aarch64_fntype_pstate_za (TREE_TYPE (cfun->decl));
++}
++
++/* Return state flags that describe whether and how the current function shares
++   state STATE_NAME with callers.  */
++
++static unsigned int
++aarch64_cfun_shared_flags (const char *state_name)
++{
++  return aarch64_fntype_shared_flags (TREE_TYPE (cfun->decl), state_name);
++}
++
++/* Return true if the current function creates new state of type STATE_NAME
++   (as opposed to sharing the state with its callers or ignoring the state
++   altogether).  */
++
++static bool
++aarch64_cfun_has_new_state (const char *state_name)
++{
++  return aarch64_fndecl_has_new_state (cfun->decl, state_name);
++}
++
++/* Return true if the current function has state STATE_NAME, either by
++   creating new state itself or by sharing state with callers.  */
++
++static bool
++aarch64_cfun_has_state (const char *state_name)
++{
++  return aarch64_fndecl_has_state (cfun->decl, state_name);
++}
++
+ /* Return true if a call from the current function to a function with
+    ISA mode CALLEE_MODE would involve a change to PSTATE.SM around
+    the BL instruction.  */
+@@ -5952,6 +6311,74 @@ aarch64_output_sve_vector_inc_dec (const char *operands, rtx x)
+ 					     factor, nelts_per_vq);
+ }
+ 
++/* Return a constant that represents FACTOR multiplied by the
++   number of 128-bit quadwords in an SME vector.  ISA_MODE is the
++   ISA mode in which the calculation is being performed.  */
++
++static rtx
++aarch64_sme_vq_immediate (machine_mode mode, HOST_WIDE_INT factor,
++			  aarch64_feature_flags isa_mode)
++{
++  gcc_assert (aarch64_sve_rdvl_factor_p (factor));
++  if (isa_mode & AARCH64_FL_SM_ON)
++    /* We're in streaming mode, so we can use normal poly-int values.  */
++    return gen_int_mode ({ factor, factor }, mode);
++
++  rtvec vec = gen_rtvec (1, gen_int_mode (factor, SImode));
++  rtx unspec = gen_rtx_UNSPEC (mode, vec, UNSPEC_SME_VQ);
++  return gen_rtx_CONST (mode, unspec);
++}
++
++/* Return true if X is a constant that represents some number X
++   multiplied by the number of quadwords in an SME vector.  Store this X
++   in *FACTOR if so.  */
++
++static bool
++aarch64_sme_vq_unspec_p (const_rtx x, HOST_WIDE_INT *factor)
++{
++  if (!TARGET_SME || GET_CODE (x) != CONST)
++    return false;
++
++  x = XEXP (x, 0);
++  if (GET_CODE (x) != UNSPEC
++      || XINT (x, 1) != UNSPEC_SME_VQ
++      || XVECLEN (x, 0) != 1)
++    return false;
++
++  x = XVECEXP (x, 0, 0);
++  if (!CONST_INT_P (x))
++    return false;
++
++  *factor = INTVAL (x);
++  return true;
++}
++
++/* Return true if X is a constant that represents some number Y
++   multiplied by the number of quadwords in an SME vector, and if
++   that Y is in the range of RDSVL.  */
++
++bool
++aarch64_rdsvl_immediate_p (const_rtx x)
++{
++  HOST_WIDE_INT factor;
++  return (aarch64_sme_vq_unspec_p (x, &factor)
++	  && aarch64_sve_rdvl_factor_p (factor));
++}
++
++/* Return the asm string for an RDSVL instruction that calculates X,
++   which is a constant that satisfies aarch64_rdsvl_immediate_p.  */
++
++char *
++aarch64_output_rdsvl (const_rtx x)
++{
++  gcc_assert (aarch64_rdsvl_immediate_p (x));
++  static char buffer[sizeof ("rdsvl\t%x0, #-") + 3 * sizeof (int)];
++  x = XVECEXP (XEXP (x, 0), 0, 0);
++  snprintf (buffer, sizeof (buffer), "rdsvl\t%%x0, #%d",
++	    (int) INTVAL (x) / 16);
++  return buffer;
++}
++
+ /* Multipliers for repeating bitmasks of width 32, 16, 8, 4, and 2.  */
+ 
+ static const unsigned HOST_WIDE_INT bitmask_imm_mul[] =
+@@ -7717,6 +8144,15 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 	  return;
+ 	}
+ 
++      if (aarch64_rdsvl_immediate_p (base))
++	{
++	  /* We could handle non-constant offsets if they are ever
++	     generated.  */
++	  gcc_assert (const_offset == 0);
++	  emit_insn (gen_rtx_SET (dest, imm));
++	  return;
++	}
++
+       sty = aarch64_classify_symbol (base, const_offset);
+       switch (sty)
+ 	{
+@@ -8732,8 +9168,10 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
+       rtx abi_cookie = aarch64_gen_callee_cookie (pcum->isa_mode,
+ 						  pcum->pcs_variant);
+       rtx sme_mode_switch_args = aarch64_finish_sme_mode_switch_args (pcum);
+-      return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, abi_cookie,
+-						    sme_mode_switch_args));
++      rtx shared_za_flags = gen_int_mode (pcum->shared_za_flags, SImode);
++      return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (3, abi_cookie,
++						    sme_mode_switch_args,
++						    shared_za_flags));
+     }
+ 
+   aarch64_layout_arg (pcum_v, arg);
+@@ -8744,7 +9182,7 @@ void
+ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum,
+ 			      const_tree fntype,
+ 			      rtx libname ATTRIBUTE_UNUSED,
+-			      const_tree fndecl ATTRIBUTE_UNUSED,
++			      const_tree fndecl,
+ 			      unsigned n_named ATTRIBUTE_UNUSED,
+ 			      bool silent_p)
+ {
+@@ -8769,6 +9207,8 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum,
+   pcum->aapcs_stack_words = 0;
+   pcum->aapcs_stack_size = 0;
+   pcum->silent_p = silent_p;
++  pcum->shared_za_flags
++    = (fntype ? aarch64_fntype_shared_flags (fntype, "za") : 0U);
+   pcum->num_sme_mode_switch_args = 0;
+ 
+   if (!silent_p
+@@ -10803,14 +11243,31 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+     }
+ }
+ 
++/* Implement TARGET_EXTRA_LIVE_ON_ENTRY.  */
++
++void
++aarch64_extra_live_on_entry (bitmap regs)
++{
++  if (TARGET_ZA)
++    {
++      bitmap_set_bit (regs, LOWERING_REGNUM);
++      bitmap_set_bit (regs, SME_STATE_REGNUM);
++      bitmap_set_bit (regs, TPIDR2_SETUP_REGNUM);
++      bitmap_set_bit (regs, ZA_FREE_REGNUM);
++      bitmap_set_bit (regs, ZA_SAVED_REGNUM);
++
++      /* The only time ZA can't have live contents on entry is when
++	 the function explicitly treats it as a pure output.  */
++      auto za_flags = aarch64_cfun_shared_flags ("za");
++      if (za_flags != (AARCH64_STATE_SHARED | AARCH64_STATE_OUT))
++	bitmap_set_bit (regs, ZA_REGNUM);
++    }
++}
++
+ /* Return 1 if the register is used by the epilogue.  We need to say the
+    return register is used, but only after epilogue generation is complete.
+    Note that in the case of sibcalls, the values "used by the epilogue" are
+-   considered live at the start of the called function.
+-
+-   For SIMD functions we need to return 1 for FP registers that are saved and
+-   restored by a function but are not zero in call_used_regs.  If we do not do 
+-   this optimizations may remove the restore of the register.  */
++   considered live at the start of the called function.  */
+ 
+ int
+ aarch64_epilogue_uses (int regno)
+@@ -10820,6 +11277,18 @@ aarch64_epilogue_uses (int regno)
+       if (regno == LR_REGNUM)
+ 	return 1;
+     }
++  if (regno == LOWERING_REGNUM && TARGET_ZA)
++    return 1;
++  if (regno == SME_STATE_REGNUM && TARGET_ZA)
++    return 1;
++  if (regno == TPIDR2_SETUP_REGNUM && TARGET_ZA)
++    return 1;
++  /* If the function shares SME state with its caller, ensure that that
++     data is not in the lazy save buffer on exit.  */
++  if (regno == ZA_SAVED_REGNUM && aarch64_cfun_incoming_pstate_za () != 0)
++    return 1;
++  if (regno == ZA_REGNUM && aarch64_cfun_shared_flags ("za") != 0)
++    return 1;
+   return 0;
+ }
+ 
+@@ -11501,8 +11970,10 @@ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+ 
+   /* There's no way to calculate VL-based values using relocations.  */
+   subrtx_iterator::array_type array;
++  HOST_WIDE_INT factor;
+   FOR_EACH_SUBRTX (iter, array, x, ALL)
+-    if (GET_CODE (*iter) == CONST_POLY_INT)
++    if (GET_CODE (*iter) == CONST_POLY_INT
++	|| aarch64_sme_vq_unspec_p (x, &factor))
+       return true;
+ 
+   poly_int64 offset;
+@@ -12364,6 +12835,72 @@ aarch64_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+   return true;
+ }
+ 
++/* Return a fresh memory reference to the current function's TPIDR2 block,
++   creating a block if necessary.  */
++
++static rtx
++aarch64_get_tpidr2_block ()
++{
++  if (!cfun->machine->tpidr2_block)
++    /* The TPIDR2 block is 16 bytes in size and must be aligned to a 128-bit
++       boundary.  */
++    cfun->machine->tpidr2_block = assign_stack_local (V16QImode, 16, 128);
++  return copy_rtx (cfun->machine->tpidr2_block);
++}
++
++/* Return a fresh register that points to the current function's
++   TPIDR2 block, creating a block if necessary.  */
++
++static rtx
++aarch64_get_tpidr2_ptr ()
++{
++  rtx block = aarch64_get_tpidr2_block ();
++  return force_reg (Pmode, XEXP (block, 0));
++}
++
++/* Emit instructions to allocate a ZA lazy save buffer and initialize the
++   current function's TPIDR2 block.  */
++
++static void
++aarch64_init_tpidr2_block ()
++{
++  rtx block = aarch64_get_tpidr2_block ();
++
++  /* The ZA save buffer is SVL.B*SVL.B bytes in size.  */
++  rtx svl_bytes = aarch64_sme_vq_immediate (Pmode, 16, AARCH64_ISA_MODE);
++  rtx svl_bytes_reg = force_reg (DImode, svl_bytes);
++  rtx za_size = expand_simple_binop (Pmode, MULT, svl_bytes_reg,
++				     svl_bytes_reg, NULL, 0, OPTAB_LIB_WIDEN);
++  rtx za_save_buffer = allocate_dynamic_stack_space (za_size, 128,
++						     BITS_PER_UNIT, -1, true);
++  za_save_buffer = force_reg (Pmode, za_save_buffer);
++  cfun->machine->za_save_buffer = za_save_buffer;
++
++  /* The first word of the block points to the save buffer and the second
++     word is the number of ZA slices to save.  */
++  rtx block_0 = adjust_address (block, DImode, 0);
++  rtx block_8 = adjust_address (block, DImode, 8);
++  emit_insn (gen_store_pair_dw_didi (block_0, za_save_buffer,
++				     block_8, svl_bytes_reg));
++
++  if (!memory_operand (block, V16QImode))
++    block = replace_equiv_address (block, force_reg (Pmode, XEXP (block, 0)));
++  emit_insn (gen_aarch64_setup_local_tpidr2 (block));
++}
++
++/* Restore the contents of ZA from the lazy save buffer, given that
++   register TPIDR2_BLOCK points to the current function's TPIDR2 block.
++   PSTATE.ZA is known to be 0 and TPIDR2_EL0 is known to be null.  */
++
++void
++aarch64_restore_za (rtx tpidr2_block)
++{
++  emit_insn (gen_aarch64_smstart_za ());
++  if (REGNO (tpidr2_block) != R0_REGNUM)
++    emit_move_insn (gen_rtx_REG (Pmode, R0_REGNUM), tpidr2_block);
++  emit_insn (gen_aarch64_tpidr2_restore ());
++}
++
+ /* Implement TARGET_START_CALL_ARGS.  */
+ 
+ static void
+@@ -12379,6 +12916,20 @@ aarch64_start_call_args (cumulative_args_t ca_v)
+ 	      " option %<-march%>, or by using the %"
+ 	      " attribute or pragma", "sme");
+     }
++
++  if ((ca->shared_za_flags & (AARCH64_STATE_IN | AARCH64_STATE_OUT))
++      && !aarch64_cfun_has_state ("za"))
++    error ("call to a function that shares %qs state from a function"
++	   " that has no %qs state", "za", "za");
++  else if (!TARGET_ZA && (ca->isa_mode & AARCH64_FL_ZA_ON))
++    error ("call to a function that shares SME state from a function"
++	   " that has no SME state");
++
++  /* If this is a call to a private ZA function, emit a marker to
++     indicate where any necessary set-up code could be inserted.
++     The code itself is inserted by the mode-switching pass.  */
++  if (TARGET_ZA && !(ca->isa_mode & AARCH64_FL_ZA_ON))
++    emit_insn (gen_aarch64_start_private_za_call ());
+ }
+ 
+ /* This function is used by the call expanders of the machine description.
+@@ -12391,6 +12942,8 @@ aarch64_start_call_args (cumulative_args_t ca_v)
+        The second element is a PARALLEL that lists all the argument
+        registers that need to be saved and restored around a change
+        in PSTATE.SM, or const0_rtx if no such switch is needed.
++       The third element is a const_int that contains the sharing flags
++       for ZA.
+    SIBCALL indicates whether this function call is normal call or sibling call.
+    It will generate different pattern accordingly.  */
+ 
+@@ -12403,10 +12956,12 @@ aarch64_expand_call (rtx result, rtx mem, rtx cookie, bool sibcall)
+ 
+   rtx callee_abi = cookie;
+   rtx sme_mode_switch_args = const0_rtx;
++  unsigned int shared_za_flags = 0;
+   if (GET_CODE (cookie) == PARALLEL)
+     {
+       callee_abi = XVECEXP (cookie, 0, 0);
+       sme_mode_switch_args = XVECEXP (cookie, 0, 1);
++      shared_za_flags = INTVAL (XVECEXP (cookie, 0, 2));
+     }
+ 
+   gcc_assert (CONST_INT_P (callee_abi));
+@@ -12426,6 +12981,41 @@ aarch64_expand_call (rtx result, rtx mem, rtx cookie, bool sibcall)
+       : !REG_P (callee))
+     XEXP (mem, 0) = force_reg (mode, callee);
+ 
++  /* Accumulate the return values, including state that is shared via
++     attributes.  */
++  auto_vec return_values;
++  if (result)
++    {
++      if (GET_CODE (result) == PARALLEL)
++	for (int i = 0; i < XVECLEN (result, 0); ++i)
++	  return_values.safe_push (XVECEXP (result, 0, i));
++      else
++	return_values.safe_push (result);
++    }
++  unsigned int orig_num_return_values = return_values.length ();
++  if (shared_za_flags & AARCH64_STATE_OUT)
++    return_values.safe_push (gen_rtx_REG (VNx16BImode, ZA_REGNUM));
++  /* When calling private-ZA functions from functions with ZA state,
++     we want to know whether the call committed a lazy save.  */
++  if (TARGET_ZA && !shared_za_flags)
++    return_values.safe_push (gen_rtx_REG (VNx16BImode, ZA_SAVED_REGNUM));
++
++  /* Create the new return value, if necessary.  */
++  if (orig_num_return_values != return_values.length ())
++    {
++      if (return_values.length () == 1)
++	result = return_values[0];
++      else
++	{
++	  for (rtx &x : return_values)
++	    if (GET_CODE (x) != EXPR_LIST)
++	      x = gen_rtx_EXPR_LIST (VOIDmode, x, const0_rtx);
++	  rtvec v = gen_rtvec_v (return_values.length (),
++				 return_values.address ());
++	  result = gen_rtx_PARALLEL (VOIDmode, v);
++	}
++    }
++
+   call = gen_rtx_CALL (VOIDmode, mem, const0_rtx);
+ 
+   if (result != NULL_RTX)
+@@ -12492,6 +13082,50 @@ aarch64_expand_call (rtx result, rtx mem, rtx cookie, bool sibcall)
+ 
+       cfun->machine->call_switches_pstate_sm = true;
+     }
++
++  /* Add any ZA-related information.
++     ZA_REGNUM represents the current function's ZA state, rather than
++     the contents of the ZA register itself.  We ensure that the function's
++     ZA state is preserved by private-ZA call sequences, so the call itself
++     does not use or clobber ZA_REGNUM.  */
++  if (TARGET_ZA)
++    {
++      /* The callee requires ZA to be active if the callee is shared-ZA,
++	 otherwise it requires ZA to be dormant or off.  The state of ZA is
++	 captured by a combination of SME_STATE_REGNUM, TPIDR2_SETUP_REGNUM,
++	 and ZA_SAVED_REGNUM.  */
++      use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++	       gen_rtx_REG (DImode, SME_STATE_REGNUM));
++      use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++	       gen_rtx_REG (DImode, TPIDR2_SETUP_REGNUM));
++      use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++	       gen_rtx_REG (VNx16BImode, ZA_SAVED_REGNUM));
++
++      /* Keep the aarch64_start/end_private_za_call markers live.  */
++      if (!(callee_isa_mode & AARCH64_FL_ZA_ON))
++	use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++		 gen_rtx_REG (VNx16BImode, LOWERING_REGNUM));
++
++      /* If the callee is a shared-ZA function, record whether it uses the
++	 current value of ZA.  */
++      if (shared_za_flags & AARCH64_STATE_IN)
++	use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
++		 gen_rtx_REG (VNx16BImode, ZA_REGNUM));
++    }
++}
++
++/* Implement TARGET_END_CALL_ARGS.  */
++
++static void
++aarch64_end_call_args (cumulative_args_t ca_v)
++{
++  CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
++
++  /* If this is a call to a private ZA function, emit a marker to
++     indicate where any necessary restoration code could be inserted.
++     The code itself is inserted by the mode-switching pass.  */
++  if (TARGET_ZA && !(ca->isa_mode & AARCH64_FL_ZA_ON))
++    emit_insn (gen_aarch64_end_private_za_call ());
+ }
+ 
+ /* Emit call insn with PAT and do aarch64-specific handling.  */
+@@ -13602,6 +14236,9 @@ aarch64_regno_regclass (unsigned regno)
+   if (regno == FFR_REGNUM || regno == FFRT_REGNUM)
+     return FFR_REGS;
+ 
++  if (FAKE_REGNUM_P (regno))
++    return FAKE_REGS;
++
+   return NO_REGS;
+ }
+ 
+@@ -13957,12 +14594,14 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode)
+       return (vec_flags & VEC_ADVSIMD
+ 	      ? CEIL (lowest_size, UNITS_PER_VREG)
+ 	      : CEIL (lowest_size, UNITS_PER_WORD));
++
+     case STACK_REG:
+     case PR_REGS:
+     case PR_LO_REGS:
+     case PR_HI_REGS:
+     case FFR_REGS:
+     case PR_AND_FFR_REGS:
++    case FAKE_REGS:
+       return 1;
+ 
+     case NO_REGS:
+@@ -19002,10 +19641,14 @@ aarch64_override_options_internal (struct gcc_options *opts)
+       && !fixed_regs[R18_REGNUM])
+     error ("%<-fsanitize=shadow-call-stack%> requires %<-ffixed-x18%>");
+ 
+-  if ((opts->x_aarch64_isa_flags & AARCH64_FL_SM_ON)
++  if ((opts->x_aarch64_isa_flags & (AARCH64_FL_SM_ON | AARCH64_FL_ZA_ON))
+       && !(opts->x_aarch64_isa_flags & AARCH64_FL_SME))
+     {
+-      error ("streaming functions require the ISA extension %qs", "sme");
++      if (opts->x_aarch64_isa_flags & AARCH64_FL_SM_ON)
++	error ("streaming functions require the ISA extension %qs", "sme");
++      else
++	error ("functions with SME state require the ISA extension %qs",
++	       "sme");
+       inform (input_location, "you can enable %qs using the command-line"
+ 	      " option %<-march%>, or by using the %"
+ 	      " attribute or pragma", "sme");
+@@ -21341,6 +21984,8 @@ aarch64_conditional_register_usage (void)
+   CLEAR_HARD_REG_BIT (operand_reg_set, VG_REGNUM);
+   CLEAR_HARD_REG_BIT (operand_reg_set, FFR_REGNUM);
+   CLEAR_HARD_REG_BIT (operand_reg_set, FFRT_REGNUM);
++  for (int i = FIRST_FAKE_REGNUM; i <= LAST_FAKE_REGNUM; ++i)
++    CLEAR_HARD_REG_BIT (operand_reg_set, i);
+ 
+   /* When tracking speculation, we need a couple of call-clobbered registers
+      to track the speculation state.  It would be nice to just use
+@@ -22795,6 +23440,9 @@ aarch64_mov_operand_p (rtx x, machine_mode mode)
+ 	  || aarch64_sve_rdvl_immediate_p (x)))
+     return true;
+ 
++  if (aarch64_rdsvl_immediate_p (x))
++    return true;
++
+   return aarch64_classify_symbolic_expression (x)
+     == SYMBOL_TINY_ABSOLUTE;
+ }
+@@ -28266,9 +28914,45 @@ aarch64_comp_type_attributes (const_tree type1, const_tree type2)
+     return 0;
+   if (!check_attr ("arm", "streaming_compatible"))
+     return 0;
++  if (aarch64_lookup_shared_state_flags (TYPE_ATTRIBUTES (type1), "za")
++      != aarch64_lookup_shared_state_flags (TYPE_ATTRIBUTES (type2), "za"))
++    return 0;
+   return 1;
+ }
+ 
++/* Implement TARGET_MERGE_DECL_ATTRIBUTES.  */
++
++static tree
++aarch64_merge_decl_attributes (tree olddecl, tree newdecl)
++{
++  tree old_attrs = DECL_ATTRIBUTES (olddecl);
++  tree old_new = lookup_attribute ("arm", "new", old_attrs);
++
++  tree new_attrs = DECL_ATTRIBUTES (newdecl);
++  tree new_new = lookup_attribute ("arm", "new", new_attrs);
++
++  if (DECL_INITIAL (olddecl) && new_new)
++    {
++      error ("cannot apply attribute %qs to %q+D after the function"
++	     " has been defined", "new", newdecl);
++      inform (DECL_SOURCE_LOCATION (olddecl), "%q+D defined here",
++	      newdecl);
++    }
++  else
++    {
++      if (old_new && new_new)
++	{
++	  old_attrs = remove_attribute ("arm", "new", old_attrs);
++	  TREE_VALUE (new_new) = chainon (TREE_VALUE (new_new),
++					  TREE_VALUE (old_new));
++	}
++      if (new_new)
++	aarch64_check_arm_new_against_type (TREE_VALUE (new_new), newdecl);
++    }
++
++  return merge_attributes (old_attrs, new_attrs);
++}
++
+ /* Implement TARGET_GET_MULTILIB_ABI_NAME */
+ 
+ static const char *
+@@ -28634,6 +29318,629 @@ aarch64_indirect_call_asm (rtx addr)
+   return "";
+ }
+ 
++/* Implement OPTIMIZE_MODE_SWITCHING.  */
++
++bool
++aarch64_optimize_mode_switching (aarch64_mode_entity entity)
++{
++  bool have_sme_state = (aarch64_cfun_incoming_pstate_za () != 0
++			 || (aarch64_cfun_has_new_state ("za")
++			     && df_regs_ever_live_p (ZA_REGNUM)));
++
++  if (have_sme_state && nonlocal_goto_handler_labels)
++    {
++      static bool reported;
++      if (!reported)
++	{
++	  sorry ("non-local gotos in functions with SME state");
++	  reported = true;
++	}
++    }
++
++  switch (entity)
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return have_sme_state && !nonlocal_goto_handler_labels;
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_EMIT for ZA_SAVE_BUFFER.  */
++
++static void
++aarch64_mode_emit_za_save_buffer (aarch64_tristate_mode mode,
++				  aarch64_tristate_mode prev_mode)
++{
++  if (mode == aarch64_tristate_mode::YES)
++    {
++      gcc_assert (prev_mode == aarch64_tristate_mode::NO);
++      aarch64_init_tpidr2_block ();
++    }
++  else
++    gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_EMIT for LOCAL_SME_STATE.  */
++
++static void
++aarch64_mode_emit_local_sme_state (aarch64_local_sme_state mode,
++				   aarch64_local_sme_state prev_mode)
++{
++  /* Back-propagation should ensure that we're always starting from
++     a known mode.  */
++  gcc_assert (prev_mode != aarch64_local_sme_state::ANY);
++
++  if (prev_mode == aarch64_local_sme_state::INACTIVE_CALLER)
++    {
++      /* Commit any uncommitted lazy save.  This leaves ZA either active
++	 and zero (lazy save case) or off (normal case).
++
++	 The sequence is:
++
++	     mrs , tpidr2_el0
++	     cbz , no_save
++	     bl __arm_tpidr2_save
++	     msr tpidr2_el0, xzr
++	     zero { za }       // Only if ZA is live
++	 no_save:  */
++      bool is_active = (mode == aarch64_local_sme_state::ACTIVE_LIVE
++			|| mode == aarch64_local_sme_state::ACTIVE_DEAD);
++      auto tmp_reg = gen_reg_rtx (DImode);
++      auto active_flag = gen_int_mode (is_active, DImode);
++      emit_insn (gen_aarch64_read_tpidr2 (tmp_reg));
++      emit_insn (gen_aarch64_commit_lazy_save (tmp_reg, active_flag));
++    }
++
++  if (mode == aarch64_local_sme_state::ACTIVE_LIVE
++      || mode == aarch64_local_sme_state::ACTIVE_DEAD)
++    {
++      if (prev_mode == aarch64_local_sme_state::INACTIVE_LOCAL)
++	{
++	  /* Make ZA active after being inactive.
++
++	     First handle the case in which the lazy save we set up was
++	     committed by a callee.  If the function's source-level ZA state
++	     is live then we must conditionally restore it from the lazy
++	     save buffer.  Otherwise we can just force PSTATE.ZA to 1.  */
++	  if (mode == aarch64_local_sme_state::ACTIVE_LIVE)
++	    emit_insn (gen_aarch64_restore_za (aarch64_get_tpidr2_ptr ()));
++	  else
++	    emit_insn (gen_aarch64_smstart_za ());
++
++	  /* Now handle the case in which the lazy save was not committed.
++	     In that case, ZA still contains the current function's ZA state,
++	     and we just need to cancel the lazy save.  */
++	  emit_insn (gen_aarch64_clear_tpidr2 ());
++	  return;
++	}
++
++      if (prev_mode == aarch64_local_sme_state::SAVED_LOCAL)
++	{
++	  /* Retrieve the current function's ZA state from the lazy save
++	     buffer.  */
++	  aarch64_restore_za (aarch64_get_tpidr2_ptr ());
++	  return;
++	}
++
++      if (prev_mode == aarch64_local_sme_state::INACTIVE_CALLER
++	  || prev_mode == aarch64_local_sme_state::OFF)
++	{
++	  /* INACTIVE_CALLER means that we are enabling ZA for the first
++	     time in this function.  The code above means that ZA is either
++	     active and zero (if we committed a lazy save) or off.  Handle
++	     the latter case by forcing ZA on.
++
++	     OFF means that PSTATE.ZA is guaranteed to be 0.  We just need
++	     to force it to 1.
++
++	     Both cases leave ZA zeroed.  */
++	  emit_insn (gen_aarch64_smstart_za ());
++	  return;
++	}
++
++      if (prev_mode == aarch64_local_sme_state::ACTIVE_DEAD
++	  || prev_mode == aarch64_local_sme_state::ACTIVE_LIVE)
++	/* A simple change in liveness, such as in a CFG structure where
++	   ZA is only conditionally defined.  No code is needed.  */
++	return;
++
++      gcc_unreachable ();
++    }
++
++  if (mode == aarch64_local_sme_state::INACTIVE_LOCAL)
++    {
++      if (prev_mode == aarch64_local_sme_state::ACTIVE_LIVE
++	  || prev_mode == aarch64_local_sme_state::ACTIVE_DEAD
++	  || prev_mode == aarch64_local_sme_state::INACTIVE_CALLER)
++	{
++	  /* A transition from ACTIVE_LIVE to INACTIVE_LOCAL is the usual
++	     case of setting up a lazy save buffer before a call.
++	     A transition from INACTIVE_CALLER is similar, except that
++	     the contents of ZA are known to be zero.
++
++	     A transition from ACTIVE_DEAD means that ZA is live at the
++	     point of the transition, but is dead on at least one incoming
++	     edge.  (That is, ZA is only conditionally initialized.)
++	     For efficiency, we want to set up a lazy save even for
++	     dead contents, since forcing ZA off would make later code
++	     restore ZA from the lazy save buffer.  */
++	  emit_insn (gen_aarch64_write_tpidr2 (aarch64_get_tpidr2_ptr ()));
++	  return;
++	}
++
++      if (prev_mode == aarch64_local_sme_state::SAVED_LOCAL
++	  || prev_mode == aarch64_local_sme_state::OFF)
++	/* We're simply discarding the information about which inactive
++	   state applies.  */
++	return;
++
++      gcc_unreachable ();
++    }
++
++  if (mode == aarch64_local_sme_state::INACTIVE_CALLER
++      || mode == aarch64_local_sme_state::OFF)
++    {
++      /* The transition to INACTIVE_CALLER is used before returning from
++	 new("za") functions.  Any state in ZA belongs to the current
++	 function rather than a caller, but that state is no longer
++	 needed.  Clear any pending lazy save and turn ZA off.
++
++	 The transition to OFF is used before calling a private-ZA function.
++	 We committed any incoming lazy save above, so at this point any
++	 contents in ZA belong to the current function.  */
++      if (prev_mode == aarch64_local_sme_state::INACTIVE_LOCAL)
++	emit_insn (gen_aarch64_clear_tpidr2 ());
++
++      if (prev_mode != aarch64_local_sme_state::OFF
++	  && prev_mode != aarch64_local_sme_state::SAVED_LOCAL)
++	emit_insn (gen_aarch64_smstop_za ());
++
++      return;
++    }
++
++  if (mode == aarch64_local_sme_state::SAVED_LOCAL)
++    {
++      /* This is a transition to an exception handler.  */
++      gcc_assert (prev_mode == aarch64_local_sme_state::OFF
++		  || prev_mode == aarch64_local_sme_state::INACTIVE_LOCAL);
++      return;
++    }
++
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_EMIT.  */
++
++static void
++aarch64_mode_emit (int entity, int mode, int prev_mode, HARD_REG_SET live)
++{
++  if (mode == prev_mode)
++    return;
++
++  start_sequence ();
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      aarch64_mode_emit_za_save_buffer (aarch64_tristate_mode (mode),
++					aarch64_tristate_mode (prev_mode));
++      break;
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      aarch64_mode_emit_local_sme_state (aarch64_local_sme_state (mode),
++					 aarch64_local_sme_state (prev_mode));
++      break;
++    }
++  rtx_insn *seq = get_insns ();
++  end_sequence ();
++
++  /* Get the set of clobbered registers that are currently live.  */
++  HARD_REG_SET clobbers = {};
++  for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
++    {
++      vec_rtx_properties properties;
++      properties.add_insn (insn, false);
++      for (rtx_obj_reference ref : properties.refs ())
++	if (ref.is_write () && HARD_REGISTER_NUM_P (ref.regno))
++	  SET_HARD_REG_BIT (clobbers, ref.regno);
++    }
++  clobbers &= live;
++
++  /* Emit instructions to save clobbered registers to pseudos.  Queue
++     instructions to restore the registers afterwards.
++
++     This should only needed in rare situations.  */
++  auto_vec after;
++  for (unsigned int regno = R0_REGNUM; regno < R30_REGNUM; ++regno)
++    if (TEST_HARD_REG_BIT (clobbers, regno))
++      {
++	rtx hard_reg = gen_rtx_REG (DImode, regno);
++	rtx pseudo_reg = gen_reg_rtx (DImode);
++	emit_move_insn (pseudo_reg, hard_reg);
++	after.quick_push (gen_move_insn (hard_reg, pseudo_reg));
++      }
++  if (TEST_HARD_REG_BIT (clobbers, CC_REGNUM))
++    {
++      rtx pseudo_reg = gen_reg_rtx (DImode);
++      emit_insn (gen_aarch64_save_nzcv (pseudo_reg));
++      after.quick_push (gen_aarch64_restore_nzcv (pseudo_reg));
++    }
++
++  /* Emit the transition instructions themselves.  */
++  emit_insn (seq);
++
++  /* Restore the clobbered registers.  */
++  for (auto *insn : after)
++    emit_insn (insn);
++}
++
++/* Return true if INSN references the SME state represented by hard register
++   REGNO.  */
++
++static bool
++aarch64_insn_references_sme_state_p (rtx_insn *insn, unsigned int regno)
++{
++  df_ref ref;
++  FOR_EACH_INSN_DEF (ref, insn)
++    if (!DF_REF_FLAGS_IS_SET (ref, DF_REF_MUST_CLOBBER)
++	&& DF_REF_REGNO (ref) == regno)
++      return true;
++  FOR_EACH_INSN_USE (ref, insn)
++    if (DF_REF_REGNO (ref) == regno)
++      return true;
++  return false;
++}
++
++/* Implement TARGET_MODE_NEEDED for LOCAL_SME_STATE.  */
++
++static aarch64_local_sme_state
++aarch64_mode_needed_local_sme_state (rtx_insn *insn, HARD_REG_SET live)
++{
++  if (!CALL_P (insn)
++      && find_reg_note (insn, REG_EH_REGION, NULL_RTX))
++    {
++      static bool reported;
++      if (!reported)
++	{
++	  sorry ("catching non-call exceptions in functions with SME state");
++	  reported = true;
++	}
++      /* Aim for graceful error recovery by picking the value that is
++	 least likely to generate an ICE.  */
++      return aarch64_local_sme_state::INACTIVE_LOCAL;
++    }
++
++  /* A non-local goto is equivalent to a return.  We disallow non-local
++     receivers in functions with SME state, so we know that the target
++     expects ZA to be dormant or off.  */
++  if (JUMP_P (insn)
++      && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
++    return aarch64_local_sme_state::INACTIVE_CALLER;
++
++  /* start_private_za_call and end_private_za_call bracket a sequence
++     that calls a private-ZA function.  Force ZA to be turned off if the
++     function doesn't have any live ZA state, otherwise require ZA to be
++     inactive.  */
++  auto icode = recog_memoized (insn);
++  if (icode == CODE_FOR_aarch64_start_private_za_call
++      || icode == CODE_FOR_aarch64_end_private_za_call)
++    return (TEST_HARD_REG_BIT (live, ZA_REGNUM)
++	    ? aarch64_local_sme_state::INACTIVE_LOCAL
++	    : aarch64_local_sme_state::OFF);
++
++  /* Force ZA to contain the current function's ZA state if INSN wants
++     to access it.  */
++  if (aarch64_insn_references_sme_state_p (insn, ZA_REGNUM))
++    return (TEST_HARD_REG_BIT (live, ZA_REGNUM)
++	    ? aarch64_local_sme_state::ACTIVE_LIVE
++	    : aarch64_local_sme_state::ACTIVE_DEAD);
++
++  return aarch64_local_sme_state::ANY;
++}
++
++/* Implement TARGET_MODE_NEEDED for ZA_SAVE_BUFFER.  */
++
++static aarch64_tristate_mode
++aarch64_mode_needed_za_save_buffer (rtx_insn *insn, HARD_REG_SET live)
++{
++  /* We need to set up a lazy save buffer no later than the first
++     transition to INACTIVE_LOCAL (which involves setting up a lazy save).  */
++  if (aarch64_mode_needed_local_sme_state (insn, live)
++      == aarch64_local_sme_state::INACTIVE_LOCAL)
++    return aarch64_tristate_mode::YES;
++
++  /* Also make sure that the lazy save buffer is set up before the first
++     insn that throws internally.  The exception handler will sometimes
++     load from it.  */
++  if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
++    return aarch64_tristate_mode::YES;
++
++  return aarch64_tristate_mode::MAYBE;
++}
++
++/* Implement TARGET_MODE_NEEDED.  */
++
++static int
++aarch64_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET live)
++{
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      return int (aarch64_mode_needed_za_save_buffer (insn, live));
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_mode_needed_local_sme_state (insn, live));
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_AFTER for LOCAL_SME_STATE.  */
++
++static aarch64_local_sme_state
++aarch64_mode_after_local_sme_state (aarch64_local_sme_state mode,
++				    HARD_REG_SET live)
++{
++  /* Note places where ZA dies, so that we can try to avoid saving and
++     restoring state that isn't needed.  */
++  if (mode == aarch64_local_sme_state::ACTIVE_LIVE
++      && !TEST_HARD_REG_BIT (live, ZA_REGNUM))
++    return aarch64_local_sme_state::ACTIVE_DEAD;
++
++  /* Note where ZA is born, e.g. when moving past an __arm_out("za")
++     function.  */
++  if (mode == aarch64_local_sme_state::ACTIVE_DEAD
++      && TEST_HARD_REG_BIT (live, ZA_REGNUM))
++    return aarch64_local_sme_state::ACTIVE_LIVE;
++
++  return mode;
++}
++
++/* Implement TARGET_MODE_AFTER.  */
++
++static int
++aarch64_mode_after (int entity, int mode, rtx_insn *, HARD_REG_SET live)
++{
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      return mode;
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_mode_after_local_sme_state
++		  (aarch64_local_sme_state (mode), live));
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_CONFLUENCE for LOCAL_SME_STATE.  */
++
++static aarch64_local_sme_state
++aarch64_local_sme_confluence (aarch64_local_sme_state mode1,
++			      aarch64_local_sme_state mode2)
++{
++  /* Perform a symmetrical check for two values.  */
++  auto is_pair = [&](aarch64_local_sme_state val1,
++		     aarch64_local_sme_state val2)
++    {
++      return ((mode1 == val1 && mode2 == val2)
++	      || (mode1 == val2 && mode2 == val1));
++    };
++
++  /* INACTIVE_CALLER means ZA is off or it has dormant contents belonging
++     to a caller.  OFF is one of the options.  */
++  if (is_pair (aarch64_local_sme_state::INACTIVE_CALLER,
++	       aarch64_local_sme_state::OFF))
++    return aarch64_local_sme_state::INACTIVE_CALLER;
++
++  /* Similarly for dormant contents belonging to the current function.  */
++  if (is_pair (aarch64_local_sme_state::INACTIVE_LOCAL,
++	       aarch64_local_sme_state::OFF))
++    return aarch64_local_sme_state::INACTIVE_LOCAL;
++
++  /* Treat a conditionally-initialized value as a fully-initialized value.  */
++  if (is_pair (aarch64_local_sme_state::ACTIVE_LIVE,
++	       aarch64_local_sme_state::ACTIVE_DEAD))
++    return aarch64_local_sme_state::ACTIVE_LIVE;
++
++  return aarch64_local_sme_state::ANY;
++}
++
++/* Implement TARGET_MODE_CONFLUENCE.  */
++
++static int
++aarch64_mode_confluence (int entity, int mode1, int mode2)
++{
++  gcc_assert (mode1 != mode2);
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      return int (aarch64_tristate_mode::MAYBE);
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_local_sme_confluence
++		  (aarch64_local_sme_state (mode1),
++		   aarch64_local_sme_state (mode2)));
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_BACKPROP for an entity that either stays
++   NO throughput, or makes one transition from NO to YES.  */
++
++static aarch64_tristate_mode
++aarch64_one_shot_backprop (aarch64_tristate_mode mode1,
++			   aarch64_tristate_mode mode2)
++{
++  /* Keep bringing the transition forward until it starts from NO.  */
++  if (mode1 == aarch64_tristate_mode::MAYBE
++      && mode2 == aarch64_tristate_mode::YES)
++    return mode2;
++
++  return aarch64_tristate_mode::MAYBE;
++}
++
++/* Implement TARGET_MODE_BACKPROP for LOCAL_SME_STATE.  */
++
++static aarch64_local_sme_state
++aarch64_local_sme_backprop (aarch64_local_sme_state mode1,
++			    aarch64_local_sme_state mode2)
++{
++  /* We always need to know what the current state is when transitioning
++     to a new state.  Force any location with indeterminate starting state
++     to be active.  */
++  if (mode1 == aarch64_local_sme_state::ANY)
++    switch (mode2)
++      {
++      case aarch64_local_sme_state::INACTIVE_CALLER:
++      case aarch64_local_sme_state::OFF:
++      case aarch64_local_sme_state::ACTIVE_DEAD:
++	/* The current function's ZA state is not live.  */
++	return aarch64_local_sme_state::ACTIVE_DEAD;
++
++      case aarch64_local_sme_state::INACTIVE_LOCAL:
++      case aarch64_local_sme_state::ACTIVE_LIVE:
++	/* The current function's ZA state is live.  */
++	return aarch64_local_sme_state::ACTIVE_LIVE;
++
++      case aarch64_local_sme_state::SAVED_LOCAL:
++	/* This is a transition to an exception handler.  Since we don't
++	   support non-call exceptions for SME functions, the source of
++	   the transition must be known.  We'll assert later if that's
++	   not the case.  */
++	return aarch64_local_sme_state::ANY;
++
++      case aarch64_local_sme_state::ANY:
++	return aarch64_local_sme_state::ANY;
++      }
++
++  return aarch64_local_sme_state::ANY;
++}
++
++/* Implement TARGET_MODE_BACKPROP.  */
++
++static int
++aarch64_mode_backprop (int entity, int mode1, int mode2)
++{
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      return int (aarch64_one_shot_backprop (aarch64_tristate_mode (mode1),
++					     aarch64_tristate_mode (mode2)));
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_local_sme_backprop
++		  (aarch64_local_sme_state (mode1),
++		   aarch64_local_sme_state (mode2)));
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_ENTRY.  */
++
++static int
++aarch64_mode_entry (int entity)
++{
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      return int (aarch64_tristate_mode::NO);
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_cfun_shared_flags ("za") != 0
++		  ? aarch64_local_sme_state::ACTIVE_LIVE
++		  : aarch64_local_sme_state::INACTIVE_CALLER);
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_EXIT.  */
++
++static int
++aarch64_mode_exit (int entity)
++{
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      return int (aarch64_tristate_mode::MAYBE);
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_cfun_shared_flags ("za") != 0
++		  ? aarch64_local_sme_state::ACTIVE_LIVE
++		  : aarch64_local_sme_state::INACTIVE_CALLER);
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_EH_HANDLER.  */
++
++static int
++aarch64_mode_eh_handler (int entity)
++{
++  switch (aarch64_mode_entity (entity))
++    {
++    case aarch64_mode_entity::HAVE_ZA_SAVE_BUFFER:
++      /* Require a lazy save buffer to be allocated before the first
++	 insn that can throw.  */
++      return int (aarch64_tristate_mode::YES);
++
++    case aarch64_mode_entity::LOCAL_SME_STATE:
++      return int (aarch64_local_sme_state::SAVED_LOCAL);
++    }
++  gcc_unreachable ();
++}
++
++/* Implement TARGET_MODE_PRIORITY.  */
++
++static int
++aarch64_mode_priority (int, int n)
++{
++  return n;
++}
++
++/* Implement TARGET_MD_ASM_ADJUST.  */
++
++static rtx_insn *
++aarch64_md_asm_adjust (vec &outputs, vec &inputs,
++		       vec &input_modes,
++		       vec &constraints,
++		       vec &uses, vec &clobbers,
++		       HARD_REG_SET &clobbered_regs, location_t loc)
++{
++  rtx_insn *seq = arm_md_asm_adjust (outputs, inputs, input_modes, constraints,
++				     uses, clobbers, clobbered_regs, loc);
++
++  /* "za" in the clobber list of a function with ZA state is defined to
++     mean that the asm can read from and write to ZA.  We can model the
++     read using a USE, but unfortunately, it's not possible to model the
++     write directly.   Use a separate insn to model the effect.
++
++     We must ensure that ZA is active on entry, which is enforced by using
++     SME_STATE_REGNUM.  The asm must ensure that ZA is active on return.  */
++  if (TARGET_ZA)
++    for (unsigned int i = clobbers.length (); i-- > 0; )
++      {
++	rtx x = clobbers[i];
++	if (REG_P (x) && REGNO (x) == ZA_REGNUM)
++	  {
++	    auto id = cfun->machine->next_asm_update_za_id++;
++
++	    start_sequence ();
++	    if (seq)
++	      emit_insn (seq);
++	    emit_insn (gen_aarch64_asm_update_za (gen_int_mode (id, SImode)));
++	    seq = get_insns ();
++	    end_sequence ();
++
++	    uses.safe_push (gen_rtx_REG (VNx16QImode, ZA_REGNUM));
++	    uses.safe_push (gen_rtx_REG (DImode, SME_STATE_REGNUM));
++
++	    clobbers.ordered_remove (i);
++	    CLEAR_HARD_REG_BIT (clobbered_regs, ZA_REGNUM);
++	  }
++      }
++  return seq;
++}
++
+ /* If CALL involves a change in PSTATE.SM, emit the instructions needed
+    to switch to the new mode and the instructions needed to restore the
+    original mode.  Return true if something changed.  */
+@@ -29108,6 +30415,9 @@ aarch64_get_v16qi_mode ()
+ #undef TARGET_START_CALL_ARGS
+ #define TARGET_START_CALL_ARGS aarch64_start_call_args
+ 
++#undef TARGET_END_CALL_ARGS
++#define TARGET_END_CALL_ARGS aarch64_end_call_args
++
+ #undef TARGET_GIMPLE_FOLD_BUILTIN
+ #define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin
+ 
+@@ -29473,6 +30783,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_COMP_TYPE_ATTRIBUTES
+ #define TARGET_COMP_TYPE_ATTRIBUTES aarch64_comp_type_attributes
+ 
++#undef TARGET_MERGE_DECL_ATTRIBUTES
++#define TARGET_MERGE_DECL_ATTRIBUTES aarch64_merge_decl_attributes
++
+ #undef TARGET_GET_MULTILIB_ABI_NAME
+ #define TARGET_GET_MULTILIB_ABI_NAME aarch64_get_multilib_abi_name
+ 
+@@ -29493,8 +30806,35 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_STRICT_ARGUMENT_NAMING
+ #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+ 
++#undef TARGET_MODE_EMIT
++#define TARGET_MODE_EMIT aarch64_mode_emit
++
++#undef TARGET_MODE_NEEDED
++#define TARGET_MODE_NEEDED aarch64_mode_needed
++
++#undef TARGET_MODE_AFTER
++#define TARGET_MODE_AFTER aarch64_mode_after
++
++#undef TARGET_MODE_CONFLUENCE
++#define TARGET_MODE_CONFLUENCE aarch64_mode_confluence
++
++#undef TARGET_MODE_BACKPROP
++#define TARGET_MODE_BACKPROP aarch64_mode_backprop
++
++#undef TARGET_MODE_ENTRY
++#define TARGET_MODE_ENTRY aarch64_mode_entry
++
++#undef TARGET_MODE_EXIT
++#define TARGET_MODE_EXIT aarch64_mode_exit
++
++#undef TARGET_MODE_EH_HANDLER
++#define TARGET_MODE_EH_HANDLER aarch64_mode_eh_handler
++
++#undef TARGET_MODE_PRIORITY
++#define TARGET_MODE_PRIORITY aarch64_mode_priority
++
+ #undef TARGET_MD_ASM_ADJUST
+-#define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
++#define TARGET_MD_ASM_ADJUST aarch64_md_asm_adjust
+ 
+ #undef TARGET_ASM_FILE_END
+ #define TARGET_ASM_FILE_END aarch64_asm_file_end
+@@ -29505,6 +30845,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_HAVE_SHADOW_CALL_STACK
+ #define TARGET_HAVE_SHADOW_CALL_STACK true
+ 
++#undef TARGET_EXTRA_LIVE_ON_ENTRY
++#define TARGET_EXTRA_LIVE_ON_ENTRY aarch64_extra_live_on_entry
++
+ #undef TARGET_EMIT_EPILOGUE_FOR_SIBCALL
+ #define TARGET_EMIT_EPILOGUE_FOR_SIBCALL aarch64_expand_epilogue
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 6bfe55968..89d30b9bf 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -207,6 +207,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ /* Macros to test ISA flags.  */
+ 
+ #define AARCH64_ISA_SM_OFF         (aarch64_isa_flags & AARCH64_FL_SM_OFF)
++#define AARCH64_ISA_ZA_ON          (aarch64_isa_flags & AARCH64_FL_ZA_ON)
+ #define AARCH64_ISA_MODE           (aarch64_isa_flags & AARCH64_FL_ISA_MODES)
+ #define AARCH64_ISA_CRC            (aarch64_isa_flags & AARCH64_FL_CRC)
+ #define AARCH64_ISA_CRYPTO         (aarch64_isa_flags & AARCH64_FL_CRYPTO)
+@@ -259,6 +260,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ #define TARGET_STREAMING_COMPATIBLE \
+   ((aarch64_isa_flags & AARCH64_FL_SM_STATE) == 0)
+ 
++/* PSTATE.ZA is enabled in the current function body.  */
++#define TARGET_ZA (AARCH64_ISA_ZA_ON)
++
+ /* Crypto is an optional extension to AdvSIMD.  */
+ #define TARGET_CRYPTO (AARCH64_ISA_CRYPTO)
+ 
+@@ -445,7 +449,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+     1, 1, 1, 1,			/* SFP, AP, CC, VG */	\
+     0, 0, 0, 0,   0, 0, 0, 0,   /* P0 - P7 */           \
+     0, 0, 0, 0,   0, 0, 0, 0,   /* P8 - P15 */          \
+-    1, 1			/* FFR and FFRT */	\
++    1, 1,			/* FFR and FFRT */	\
++    1, 1, 1, 1, 1, 1, 1		/* Fake registers */	\
+   }
+ 
+ /* X30 is marked as caller-saved which is in line with regular function call
+@@ -455,7 +460,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+    true but not until function epilogues have been generated.  This ensures
+    that X30 is available for use in leaf functions if needed.  */
+ 
+-#define CALL_USED_REGISTERS				\
++#define CALL_REALLY_USED_REGISTERS			\
+   {							\
+     1, 1, 1, 1,   1, 1, 1, 1,	/* R0 - R7 */		\
+     1, 1, 1, 1,   1, 1, 1, 1,	/* R8 - R15 */		\
+@@ -468,7 +473,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+     1, 1, 1, 0,			/* SFP, AP, CC, VG */	\
+     1, 1, 1, 1,   1, 1, 1, 1,	/* P0 - P7 */		\
+     1, 1, 1, 1,   1, 1, 1, 1,	/* P8 - P15 */		\
+-    1, 1			/* FFR and FFRT */	\
++    1, 1,			/* FFR and FFRT */	\
++    0, 0, 0, 0, 0, 0, 0		/* Fake registers */	\
+   }
+ 
+ #define REGISTER_NAMES						\
+@@ -484,7 +490,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+     "sfp", "ap",  "cc",  "vg",					\
+     "p0",  "p1",  "p2",  "p3",  "p4",  "p5",  "p6",  "p7",	\
+     "p8",  "p9",  "p10", "p11", "p12", "p13", "p14", "p15",	\
+-    "ffr", "ffrt"						\
++    "ffr", "ffrt",						\
++    "lowering", "tpidr2_block", "sme_state", "tpidr2_setup",	\
++    "za_free", "za_saved", "za"					\
+   }
+ 
+ /* Generate the register aliases for core register N */
+@@ -533,7 +541,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ #define FRAME_POINTER_REGNUM		SFP_REGNUM
+ #define STACK_POINTER_REGNUM		SP_REGNUM
+ #define ARG_POINTER_REGNUM		AP_REGNUM
+-#define FIRST_PSEUDO_REGISTER		(FFRT_REGNUM + 1)
++#define FIRST_PSEUDO_REGISTER		(LAST_FAKE_REGNUM + 1)
+ 
+ /* The number of argument registers available for each class.  */
+ #define NUM_ARG_REGS			8
+@@ -657,6 +665,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ 
+ #define FP_SIMD_SAVED_REGNUM_P(REGNO)			\
+   (((unsigned) (REGNO - V8_REGNUM)) <= (V23_REGNUM - V8_REGNUM))
++
++#define FAKE_REGNUM_P(REGNO) \
++  IN_RANGE (REGNO, FIRST_FAKE_REGNUM, LAST_FAKE_REGNUM)
+ 
+ /* Register and constant classes.  */
+ 
+@@ -677,6 +688,7 @@ enum reg_class
+   PR_REGS,
+   FFR_REGS,
+   PR_AND_FFR_REGS,
++  FAKE_REGS,
+   ALL_REGS,
+   LIM_REG_CLASSES		/* Last */
+ };
+@@ -700,6 +712,7 @@ enum reg_class
+   "PR_REGS",					\
+   "FFR_REGS",					\
+   "PR_AND_FFR_REGS",				\
++  "FAKE_REGS",					\
+   "ALL_REGS"					\
+ }
+ 
+@@ -720,6 +733,7 @@ enum reg_class
+   { 0x00000000, 0x00000000, 0x000ffff0 },	/* PR_REGS */		\
+   { 0x00000000, 0x00000000, 0x00300000 },	/* FFR_REGS */		\
+   { 0x00000000, 0x00000000, 0x003ffff0 },	/* PR_AND_FFR_REGS */	\
++  { 0x00000000, 0x00000000, 0x1fc00000 },	/* FAKE_REGS */		\
+   { 0xffffffff, 0xffffffff, 0x000fffff }	/* ALL_REGS */		\
+ }
+ 
+@@ -920,6 +934,15 @@ typedef struct GTY (()) machine_function
+   bool reg_is_wrapped_separately[LAST_SAVED_REGNUM];
+   /* One entry for each general purpose register.  */
+   rtx call_via[SP_REGNUM];
++
++  /* A pseudo register that points to the function's TPIDR2 block, or null
++     if the function doesn't have a TPIDR2 block.  */
++  rtx tpidr2_block;
++
++  /* A pseudo register that points to the function's ZA save buffer,
++     or null if none.  */
++  rtx za_save_buffer;
++
+   bool label_is_assembled;
+ 
+   /* True if we've expanded at least one call to a function that changes
+@@ -927,6 +950,10 @@ typedef struct GTY (()) machine_function
+      guarantees that no such mode switch exists.  */
+   bool call_switches_pstate_sm;
+ 
++  /* Used to generated unique identifiers for each update to ZA by an
++     asm statement.  */
++  unsigned int next_asm_update_za_id;
++
+   /* A set of all decls that have been passed to a vld1 intrinsic in the
+      current function.  This is used to help guide the vector cost model.  */
+   hash_set *vector_load_decls;
+@@ -996,6 +1023,10 @@ typedef struct
+   bool silent_p;		/* True if we should act silently, rather than
+ 				   raise an error for invalid calls.  */
+ 
++  /* AARCH64_STATE_* flags that describe whether the function shares ZA
++     with its callers.  */
++  unsigned int shared_za_flags;
++
+   /* A list of registers that need to be saved and restored around a
+      change to PSTATE.SM.  An auto_vec would be more convenient, but those
+      can't be copied.  */
+@@ -1344,4 +1375,61 @@ extern poly_uint16 aarch64_sve_vg;
+ 		STACK_BOUNDARY / BITS_PER_UNIT)		   \
+     : (crtl->outgoing_args_size + STACK_POINTER_OFFSET))
+ 
++#ifndef USED_FOR_TARGET
++
++/* Enumerates the mode-switching "entities" for AArch64.  */
++enum class aarch64_mode_entity : int
++{
++  /* An aarch64_tristate_mode that says whether we have created a local
++     save buffer for the current function's ZA state.  The only transition
++     is from NO to YES.  */
++  HAVE_ZA_SAVE_BUFFER,
++
++  /* An aarch64_local_sme_state that reflects the state of all data
++     controlled by PSTATE.ZA.  */
++  LOCAL_SME_STATE
++};
++
++/* Describes the state of all data controlled by PSTATE.ZA  */
++enum class aarch64_local_sme_state : int
++{
++  /* ZA is in the off or dormant state.  If it is dormant, the contents
++     of ZA belong to a caller.  */
++  INACTIVE_CALLER,
++
++  /* ZA is in the off state: PSTATE.ZA is 0 and TPIDR2_EL0 is null.  */
++  OFF,
++
++  /* ZA is in the off or dormant state.  If it is dormant, the contents
++     of ZA belong to the current function.  */
++  INACTIVE_LOCAL,
++
++  /* ZA is in the off state and the current function's ZA contents are
++     stored in the lazy save buffer.  This is the state on entry to
++     exception handlers.  */
++  SAVED_LOCAL,
++
++  /* ZA is in the active state: PSTATE.ZA is 1 and TPIDR2_EL0 is null.
++     The contents of ZA are live.  */
++  ACTIVE_LIVE,
++
++  /* ZA is in the active state: PSTATE.ZA is 1 and TPIDR2_EL0 is null.
++     The contents of ZA are dead.  */
++  ACTIVE_DEAD,
++
++  /* ZA could be in multiple states.  */
++  ANY
++};
++
++enum class aarch64_tristate_mode : int { NO, YES, MAYBE };
++
++#define OPTIMIZE_MODE_SWITCHING(ENTITY) \
++  aarch64_optimize_mode_switching (aarch64_mode_entity (ENTITY))
++
++#define NUM_MODES_FOR_MODE_SWITCHING \
++  { int (aarch64_tristate_mode::MAYBE), \
++    int (aarch64_local_sme_state::ANY) }
++
++#endif
++
+ #endif /* GCC_AARCH64_H */
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index bb867de74..05a7c6675 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -111,6 +111,56 @@
+     ;; "FFR token": a fake register used for representing the scheduling
+     ;; restrictions on FFR-related operations.
+     (FFRT_REGNUM	85)
++
++    ;; ----------------------------------------------------------------
++    ;; Fake registers
++    ;; ----------------------------------------------------------------
++    ;; These registers represent abstract things, rather than real
++    ;; architected registers.
++
++    ;; Sometimes we use placeholder instructions to mark where later
++    ;; ABI-related lowering is needed.  These placeholders read and
++    ;; write this register.  Instructions that depend on the lowering
++    ;; read the register.
++    (LOWERING_REGNUM 86)
++
++    ;; Represents the contents of the current function's TPIDR2 block,
++    ;; in abstract form.
++    (TPIDR2_BLOCK_REGNUM 87)
++
++    ;; Holds the value that the current function wants PSTATE.ZA to be.
++    ;; The actual value can sometimes vary, because it does not track
++    ;; changes to PSTATE.ZA that happen during a lazy save and restore.
++    ;; Those effects are instead tracked by ZA_SAVED_REGNUM.
++    (SME_STATE_REGNUM 88)
++
++    ;; Instructions write to this register if they set TPIDR2_EL0 to a
++    ;; well-defined value.  Instructions read from the register if they
++    ;; depend on the result of such writes.
++    ;;
++    ;; The register does not model the architected TPIDR2_ELO, just the
++    ;; current function's management of it.
++    (TPIDR2_SETUP_REGNUM 89)
++
++    ;; Represents the property "has an incoming lazy save been committed?".
++    (ZA_FREE_REGNUM 90)
++
++    ;; Represents the property "are the current function's ZA contents
++    ;; stored in the lazy save buffer, rather than in ZA itself?".
++    (ZA_SAVED_REGNUM 91)
++
++    ;; Represents the contents of the current function's ZA state in
++    ;; abstract form.  At various times in the function, these contents
++    ;; might be stored in ZA itself, or in the function's lazy save buffer.
++    ;;
++    ;; The contents persist even when the architected ZA is off.  Private-ZA
++    ;; functions have no effect on its contents.
++    (ZA_REGNUM 92)
++    ;; ----------------------------------------------------------------
++    (FIRST_FAKE_REGNUM	LOWERING_REGNUM)
++    (LAST_FAKE_REGNUM	ZA_REGNUM)
++    ;; ----------------------------------------------------------------
++
+     ;; The pair of scratch registers used for stack probing with -fstack-check.
+     ;; Leave R9 alone as a possible choice for the static chain.
+     ;; Note that the use of these registers is mutually exclusive with the use
+@@ -303,7 +353,12 @@
+     UNSPEC_TAG_SPACE		; Translate address to MTE tag address space.
+     UNSPEC_LD1RO
+     UNSPEC_SALT_ADDR
++    UNSPEC_SAVE_NZCV
++    UNSPEC_RESTORE_NZCV
+     UNSPECV_PATCHABLE_AREA
++    ;; Wraps a constant integer that should be multiplied by the number
++    ;; of quadwords in an SME vector.
++    UNSPEC_SME_VQ
+ ])
+ 
+ (define_c_enum "unspecv" [
+@@ -379,7 +434,7 @@
+ ;; Q registers and is equivalent to "simd".
+ 
+ (define_enum "arches" [any rcpc8_4 fp fp_q base_simd nobase_simd
+-		       simd nosimd sve fp16])
++		       simd nosimd sve fp16 sme])
+ 
+ (define_enum_attr "arch" "arches" (const_string "any"))
+ 
+@@ -423,7 +478,10 @@
+ 	     (match_test "TARGET_FP_F16INST"))
+ 
+ 	(and (eq_attr "arch" "sve")
+-	     (match_test "TARGET_SVE")))
++	     (match_test "TARGET_SVE"))
++
++	(and (eq_attr "arch" "sme")
++	     (match_test "TARGET_SME")))
+     (const_string "yes")
+     (const_string "no")))
+ 
+@@ -928,7 +986,7 @@
+    (set_attr "sls_length" "retbr")]
+ )
+ 
+-(define_insn "*cb1"
++(define_insn "aarch64_cb1"
+   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
+ 				(const_int 0))
+ 			   (label_ref (match_operand 1 "" ""))
+@@ -1291,6 +1349,7 @@
+      /* The "mov_imm" type for CNT is just a placeholder.  */
+      [r  , Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
+      [r  , Usr; mov_imm  , sve,  4] << aarch64_output_sve_rdvl (operands[1]);
++     [r  , UsR; mov_imm  , sme,  4] << aarch64_output_rdsvl (operands[1]);
+      [r  , m  ; load_4   , *   , 4] ldr\t%w0, %1
+      [w  , m  ; load_4   , fp  , 4] ldr\t%s0, %1
+      [m  , r Z; store_4  , *   , 4] str\t%w1, %0
+@@ -1326,6 +1385,7 @@
+      /* The "mov_imm" type for CNT is just a placeholder.  */
+      [r, Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
+      [r, Usr; mov_imm  , sve,  4] << aarch64_output_sve_rdvl (operands[1]);
++     [r, UsR; mov_imm  , sme,  4] << aarch64_output_rdsvl (operands[1]);
+      [r, m  ; load_8   , *   , 4] ldr\t%x0, %1
+      [w, m  ; load_8   , fp  , 4] ldr\t%d0, %1
+      [m, r Z; store_8  , *   , 4] str\t%x1, %0
+@@ -7733,6 +7793,21 @@
+   [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))]
+ )
+ 
++(define_insn "aarch64_save_nzcv"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(unspec:DI [(reg:CC CC_REGNUM)] UNSPEC_SAVE_NZCV))]
++  ""
++  "mrs\t%0, nzcv"
++)
++
++(define_insn "aarch64_restore_nzcv"
++  [(set (reg:CC CC_REGNUM)
++	(unspec:CC [(match_operand:DI 0 "register_operand" "r")]
++		   UNSPEC_RESTORE_NZCV))]
++  ""
++  "msr\tnzcv, %0"
++)
++
+ ;; AdvSIMD Stuff
+ (include "aarch64-simd.md")
+ 
+diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
+index 212a73416..88fb9a07c 100644
+--- a/gcc/config/aarch64/constraints.md
++++ b/gcc/config/aarch64/constraints.md
+@@ -220,6 +220,12 @@
+  (and (match_code "const_poly_int")
+       (match_test "aarch64_sve_rdvl_immediate_p (op)")))
+ 
++(define_constraint "UsR"
++  "@internal
++   A constraint that matches a value produced by RDSVL."
++ (and (match_code "const")
++      (match_test "aarch64_rdsvl_immediate_p (op)")))
++
+ (define_constraint "Usv"
+   "@internal
+    A constraint that matches a VG-based constant that can be loaded by
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C b/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C
+new file mode 100644
+index 000000000..a245546d8
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C
+@@ -0,0 +1,189 @@
++// { dg-options "-O -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++void callee_inout() __arm_inout("za");
++void callee_in() noexcept __arm_in("za");
++void callee_out() noexcept __arm_out("za");
++void callee_normal();
++
++/*
++** _Z5test1v:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	bl	__cxa_begin_catch
++**	bl	__cxa_end_catch
++**	mov	w0, #?2
++**	...
++*/
++__arm_new("za") int
++test1 ()
++{
++  try
++    {
++      callee_inout();
++      return 1;
++    }
++  catch (...)
++    {
++      return 2;
++    }
++}
++
++/*
++** _Z5test2v:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	bl	__cxa_begin_catch
++**	smstart	za
++**	bl	_Z10callee_outv
++**	bl	_Z9callee_inv
++**	smstop	za
++**	bl	__cxa_end_catch
++**	mov	w0, #?2
++**	...
++*/
++__arm_new("za") int
++test2 ()
++{
++  try
++    {
++      callee_inout();
++      return 1;
++    }
++  catch (...)
++    {
++      callee_out();
++      callee_in();
++      return 2;
++    }
++}
++
++/*
++** _Z5test3v:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	smstop	za
++**	...
++**	bl	_Z13callee_normalv
++**	...
++**	bl	__cxa_begin_catch
++**	smstart	za
++**	bl	_Z10callee_outv
++**	bl	_Z9callee_inv
++**	smstop	za
++**	bl	__cxa_end_catch
++**	mov	w0, #?2
++**	...
++*/
++__arm_new("za") int
++test3 ()
++{
++  try
++    {
++      callee_normal();
++      return 1;
++    }
++  catch (...)
++    {
++      callee_out();
++      callee_in();
++      return 2;
++    }
++}
++
++__arm_new("za") int
++test4 ()
++{
++  try
++    {
++      // No lazy save set up because this is a shared-ZA function.
++      callee_inout();
++      return 1;
++    }
++  catch (...)
++    {
++      callee_inout();
++      return 2;
++    }
++}
++// { dg-final { scan-assembler {_Z5test4v:(?:(?!msr\ttpidr2_el0, x[0-9]+).)*\tret} } }
++
++/*
++** _Z5test5v:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	smstart	za
++**	...
++**	bl	_Z12callee_inoutv
++**	add	(x[0-9]+), [^\n]+
++**	msr	tpidr2_el0, \1
++**	bl	_Z13callee_normalv
++**	msr	tpidr2_el0, xzr
++**	smstop	za
++**	...
++**	bl	__cxa_begin_catch
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	msr	tpidr2_el0, xzr
++**	bl	_Z12callee_inoutv
++**	smstop	za
++**	bl	__cxa_end_catch
++**	mov	w0, #?2
++**	...
++*/
++__arm_new("za") int
++test5 ()
++{
++  try
++    {
++      callee_inout();
++      callee_normal();
++      return 1;
++    }
++  catch (...)
++    {
++      callee_inout();
++      return 2;
++    }
++}
++
++/*
++** _Z5test6v:
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	bl	_Z13callee_normalv
++**	msr	tpidr2_el0, xzr
++**	...
++**	bl	__cxa_begin_catch
++**	bl	__cxa_end_catch
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++int
++test6 () __arm_inout("za")
++{
++  try
++    {
++      callee_normal();
++      callee_out();
++      return 1;
++    }
++  catch (...)
++    {
++      return 2;
++    }
++}
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+index 032485adf..8b0755014 100644
+--- a/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
++++ b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+@@ -2,3 +2,8 @@
+ 
+ void f1 () __arm_streaming;
+ void f2 () __arm_streaming_compatible;
++void f3 () __arm_in("za");
++void f4 () __arm_out("za");
++void f5 () __arm_inout("za");
++void f6 () __arm_preserves("za");
++__arm_new("za") void f7 () {}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+index 8f1b83676..fcabe3edc 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+@@ -2,3 +2,8 @@
+ 
+ void f1 () __arm_streaming;
+ void f2 () __arm_streaming_compatible;
++void f3 () __arm_in("za");
++void f4 () __arm_out("za");
++void f5 () __arm_inout("za");
++void f6 () __arm_preserves("za");
++__arm_new("za") void f7 () {}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_1.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_1.c
+new file mode 100644
+index 000000000..856880e21
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_1.c
+@@ -0,0 +1,154 @@
++// { dg-options "" }
++
++void shared_a () [[arm::inout("za")]];
++void shared_a (); // { dg-error "conflicting types" }
++
++void shared_b ();
++void shared_b () [[arm::inout("za")]]; // { dg-error "conflicting types" }
++
++void shared_c () [[arm::inout("za")]];
++void shared_c () {} // Inherits attribute from declaration (confusingly).
++
++void shared_d ();
++void shared_d () [[arm::inout("za")]] {} // { dg-error "conflicting types" }
++
++void shared_e () [[arm::inout("za")]] {}
++void shared_e (); // { dg-error "conflicting types" }
++
++void shared_f () {}
++void shared_f () [[arm::inout("za")]]; // { dg-error "conflicting types" }
++
++extern void (*shared_g) ();
++extern void (*shared_g) () [[arm::inout("za")]]; // { dg-error "conflicting types" }
++
++extern void (*shared_h) () [[arm::inout("za")]];
++extern void (*shared_h) (); // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++void preserved_a () [[arm::preserves("za")]];
++void preserved_a (); // { dg-error "conflicting types" }
++
++void preserved_b ();
++void preserved_b () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++void preserved_c () [[arm::preserves("za")]];
++void preserved_c () {} // Inherits attribute from declaration (confusingly).
++
++void preserved_d ();
++void preserved_d () [[arm::preserves("za")]] {} // { dg-error "conflicting types" }
++
++void preserved_e () [[arm::preserves("za")]] {}
++void preserved_e (); // { dg-error "conflicting types" }
++
++void preserved_f () {}
++void preserved_f () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++extern void (*preserved_g) ();
++extern void (*preserved_g) () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++extern void (*preserved_h) () [[arm::preserves("za")]];
++extern void (*preserved_h) (); // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++void replicated_1 () [[arm::in("za", "za"), arm::in("za")]];
++void replicated_2 () [[arm::out("za", "za"), arm::out("za")]];
++void replicated_3 () [[arm::inout("za", "za"), arm::inout("za")]];
++void replicated_4 () [[arm::preserves("za", "za"), arm::preserves("za")]];
++
++//----------------------------------------------------------------------------
++
++void invalid_1 () [[arm::in]]; // { dg-error "wrong number of arguments" }
++void invalid_2 () [[arm::in()]]; // { dg-error "parentheses must be omitted" }
++  // { dg-error "wrong number of arguments" "" { target *-*-* } .-1 }
++void invalid_3 () [[arm::in("")]]; // { dg-error "unrecognized state string ''" }
++void invalid_4 () [[arm::in("foo")]]; // { dg-error "unrecognized state string 'foo'" }
++void invalid_5 () [[arm::in(42)]]; // { dg-error "the arguments to 'in' must be constant strings" }
++void invalid_6 () [[arm::in(*(int *)0 ? "za" : "za")]]; // { dg-error "the arguments to 'in' must be constant strings" }
++
++//----------------------------------------------------------------------------
++
++void mixed_a () [[arm::preserves("za")]];
++void mixed_a () [[arm::inout("za")]]; // { dg-error "conflicting types" }
++
++void mixed_b () [[arm::inout("za")]];
++void mixed_b () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++void mixed_c () [[arm::preserves("za")]];
++void mixed_c () [[arm::in("za")]] {} // { dg-error "conflicting types" }
++
++void mixed_d () [[arm::inout("za")]];
++void mixed_d () [[arm::in("za")]] {} // { dg-error "conflicting types" }
++
++void mixed_e () [[arm::out("za")]] {}
++void mixed_e () [[arm::in("za")]]; // { dg-error "conflicting types" }
++
++void mixed_f () [[arm::inout("za")]] {}
++void mixed_f () [[arm::out("za")]]; // { dg-error "conflicting types" }
++
++extern void (*mixed_g) () [[arm::in("za")]];
++extern void (*mixed_g) () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++extern void (*mixed_h) () [[arm::preserves("za")]];
++extern void (*mixed_h) () [[arm::out("za")]]; // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++void contradiction_1 () [[arm::preserves("za"), arm::inout("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++void contradiction_2 () [[arm::inout("za"), arm::preserves("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++
++int [[arm::inout("za")]] int_attr; // { dg-warning "only applies to function types" }
++void *[[arm::preserves("za")]] ptr_attr; // { dg-warning "only applies to function types" }
++
++typedef void preserved_callback () [[arm::preserves("za")]];
++typedef void shared_callback () [[arm::inout("za")]];
++
++void (*preserved_callback_ptr) () [[arm::preserves("za")]];
++void (*shared_callback_ptr) () [[arm::inout("za")]];
++
++typedef void contradiction_callback_1 () [[arm::preserves("za"), arm::inout("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++typedef void contradiction_callback_2 () [[arm::inout("za"), arm::preserves("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++
++void (*contradiction_callback_ptr_1) () [[arm::preserves("za"), arm::inout("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++void (*contradiction_callback_ptr_2) () [[arm::inout("za"), arm::preserves("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++
++struct s {
++  void (*contradiction_callback_ptr_1) () [[arm::preserves("za"), arm::inout("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++  void (*contradiction_callback_ptr_2) () [[arm::inout("za"), arm::preserves("za")]]; // { dg-error "inconsistent attributes for state 'za'" }
++};
++
++//----------------------------------------------------------------------------
++
++void keyword_ok_1 () __arm_inout("za");
++void keyword_ok_1 () __arm_inout("za");
++
++void keyword_ok_2 () __arm_in("za");
++void keyword_ok_2 () [[arm::in("za")]];
++
++void keyword_ok_3 () [[arm::out("za")]];
++void keyword_ok_3 () __arm_out("za");
++
++void keyword_ok_4 () __arm_inout("za") [[arm::inout("za")]];
++
++void keyword_ok_5 () __arm_preserves("za");
++void keyword_ok_5 () [[arm::preserves("za")]];
++
++__arm_new("za") void keyword_ok_6 () {}
++
++//----------------------------------------------------------------------------
++
++void keyword_conflict_1 () __arm_inout("za");
++void keyword_conflict_1 (); // { dg-error "conflicting types" }
++
++void keyword_conflict_2 ();
++void keyword_conflict_2 () __arm_inout("za"); // { dg-error "conflicting types" }
++
++void keyword_conflict_3 () __arm_inout("za");
++void keyword_conflict_3 () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++void keyword_conflict_4 () [[arm::preserves("za")]];
++void keyword_conflict_4 () __arm_inout("za"); // { dg-error "conflicting types" }
++
++__arm_new("za") void keyword_conflict_5 () __arm_inout("za") {} // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
++__arm_new("za") void keyword_conflict_6 () __arm_preserves("za") {} // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_2.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_2.c
+new file mode 100644
+index 000000000..572ff309f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_2.c
+@@ -0,0 +1,73 @@
++// { dg-options "" }
++
++[[arm::new("za")]] void new_za_a ();
++void new_za_a ();
++
++void new_za_b ();
++[[arm::new("za")]] void new_za_b ();
++
++[[arm::new("za")]] void new_za_c ();
++void new_za_c () {}
++
++void new_za_d ();
++[[arm::new("za")]] void new_za_d () {}
++
++[[arm::new("za")]] void new_za_e () {}
++void new_za_e ();
++
++void new_za_f () {}
++[[arm::new("za")]] void new_za_f (); // { dg-error "cannot apply attribute 'new' to 'new_za_f' after the function has been defined" }
++
++//----------------------------------------------------------------------------
++
++[[arm::new("za")]] void shared_a ();
++void shared_a () [[arm::inout("za")]]; // { dg-error "conflicting types" }
++
++void shared_b () [[arm::inout("za")]];
++[[arm::new("za")]] void shared_b (); // { dg-error "conflicting types" }
++
++[[arm::new("za")]] void shared_c ();
++void shared_c () [[arm::in("za")]] {} // { dg-error "conflicting types" }
++
++void shared_d () [[arm::in("za")]];
++[[arm::new("za")]] void shared_d () {} // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
++
++[[arm::new("za")]] void shared_e () {}
++void shared_e () [[arm::out("za")]]; // { dg-error "conflicting types" }
++
++void shared_f () [[arm::out("za")]] {}
++[[arm::new("za")]] void shared_f (); // { dg-error "conflicting types" }
++
++[[arm::new("za")]] void shared_g () {}
++void shared_g () [[arm::preserves("za")]]; // { dg-error "conflicting types" }
++
++void shared_h () [[arm::preserves("za")]] {}
++[[arm::new("za")]] void shared_h (); // { dg-error "conflicting types" }
++
++//----------------------------------------------------------------------------
++
++[[arm::new("za")]] void contradiction_1 () [[arm::inout("za")]]; // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
++void contradiction_2 [[arm::new("za")]] () [[arm::inout("za")]]; // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
++[[arm::new("za")]] void contradiction_3 () [[arm::preserves("za")]]; // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
++void contradiction_4 [[arm::new("za")]] () [[arm::preserves("za")]]; // { dg-error "cannot create a new 'za' scope since 'za' is shared with callers" }
++
++int [[arm::new("za")]] int_attr; // { dg-warning "does not apply to types" }
++[[arm::new("za")]] int int_var_attr; // { dg-error "applies only to function definitions" }
++typedef void new_za_callback () [[arm::new("za")]]; // { dg-warning "does not apply to types" }
++[[arm::new("za")]] void (*new_za_var_callback) (); // { dg-error "applies only to function definitions" }
++
++//----------------------------------------------------------------------------
++
++[[arm::new("za")]] void complementary_1 () [[arm::streaming]] {}
++void complementary_2 [[arm::new("za")]] () [[arm::streaming]] {}
++[[arm::new("za")]] void complementary_3 () [[arm::streaming_compatible]] {}
++void complementary_4 [[arm::new("za")]] () [[arm::streaming_compatible]] {}
++
++//----------------------------------------------------------------------------
++
++#pragma GCC target "+nosme"
++
++[[arm::new("za")]] void bereft_1 ();
++[[arm::new("za")]] void bereft_2 () {} // { dg-error "functions with SME state require the ISA extension 'sme'" }
++void bereft_3 () [[arm::inout("za")]];
++void bereft_4 () [[arm::inout("za")]] {} // { dg-error "functions with SME state require the ISA extension 'sme'" }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_3.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_3.c
+new file mode 100644
+index 000000000..203f6ae8a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_3.c
+@@ -0,0 +1,31 @@
++// { dg-options "" }
++
++void normal_callee ();
++void in_callee () [[arm::in("za")]];
++void out_callee () [[arm::out("za")]];
++void inout_callee () [[arm::inout("za")]];
++void preserves_callee () [[arm::preserves("za")]];
++
++struct callbacks {
++  void (*normal_ptr) ();
++  void (*in_ptr) () [[arm::in("za")]];
++  void (*out_ptr) () [[arm::out("za")]];
++  void (*inout_ptr) () [[arm::inout("za")]];
++  void (*preserves_ptr) () [[arm::preserves("za")]];
++};
++
++void
++normal_caller (struct callbacks *c)
++{
++  normal_callee ();
++  in_callee (); // { dg-error {call to a function that shares 'za' state from a function that has no 'za' state} }
++  out_callee (); // { dg-error {call to a function that shares 'za' state from a function that has no 'za' state} }
++  inout_callee (); // { dg-error {call to a function that shares 'za' state from a function that has no 'za' state} }
++  preserves_callee (); // { dg-error {call to a function that shares SME state from a function that has no SME state} }
++
++  c->normal_ptr ();
++  c->in_ptr (); // { dg-error {call to a function that shares 'za' state from a function that has no 'za' state} }
++  c->out_ptr (); // { dg-error {call to a function that shares 'za' state from a function that has no 'za' state} }
++  c->inout_ptr (); // { dg-error {call to a function that shares 'za' state from a function that has no 'za' state} }
++  c->preserves_ptr (); // { dg-error {call to a function that shares SME state from a function that has no SME state} }
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c
+new file mode 100644
+index 000000000..cec0abf0e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c
+@@ -0,0 +1,585 @@
++// { dg-options "-O -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++void private_za();
++void out_za() __arm_out("za");
++void in_za() __arm_in("za");
++void inout_za() __arm_inout("za");
++void preserves_za() __arm_preserves("za");
++
++/*
++** test1:
++**	ret
++*/
++__arm_new("za") void test1()
++{
++}
++
++/*
++** test2:
++**	ldr	w0, \[x0\]
++**	ret
++*/
++__arm_new("za") int test2(int *ptr)
++{
++  return *ptr;
++}
++
++/*
++** test3:
++**	stp	[^\n]+
++**	mov	x29, sp
++**	bl	private_za
++** (
++**	mov	w0, 0
++**	ldp	[^\n]+
++** |
++**	ldp	[^\n]+
++**	mov	w0, 0
++** )
++**	ret
++*/
++__arm_new("za") int test3()
++{
++  private_za();
++  return 0;
++}
++
++/*
++** test4:
++**	...
++**	mrs	x0, tpidr2_el0
++**	cbz	x0, [^\n]+
++**	bl	__arm_tpidr2_save
++**	msr	tpidr2_el0, xzr
++**	zero	{ za }
++**	smstart	za
++**	bl	in_za
++**	smstop	za
++**	ldp	[^\n]+
++**	ret
++*/
++__arm_new("za") void test4()
++{
++  in_za(); // Uses zeroed contents.
++}
++
++/*
++** test5:
++**	...
++**	mrs	x0, tpidr2_el0
++**	cbz	x0, [^\n]+
++**	bl	__arm_tpidr2_save
++**	msr	tpidr2_el0, xzr
++**	smstop	za
++**	bl	private_za
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	bl	private_za
++**	ldp	[^\n]+
++**	ret
++*/
++__arm_new("za") void test5()
++{
++  private_za();
++  out_za();
++  in_za();
++  private_za();
++}
++
++// Despite the long test, there shouldn't be too much scope for variation
++// here.  The point is both to test correctness and code quality.
++/*
++** test6:
++**	stp	[^\n]+
++**	mov	x29, sp
++**	mrs	x0, tpidr2_el0
++**	cbz	x0, [^\n]+
++**	bl	__arm_tpidr2_save
++**	msr	tpidr2_el0, xzr
++**	smstart	za
++**	bl	out_za
++**	rdsvl	(x[0-9]+), #1
++**	mul	(x[0-9]+), \1, \1
++**	sub	sp, sp, \2
++**	mov	(x[0-9]+), sp
++**	stp	\3, \1, \[x29, #?16\]
++**	add	(x[0-9]+), x29, #?16
++**	msr	tpidr2_el0, \4
++**	bl	private_za
++** (
++**	add	(x[0-9]+), x29, #?16
++**	mrs	(x[0-9]+), tpidr2_el0
++**	cbnz	\6, [^\n]+
++**	smstart	za
++**	mov	x0, \5
++** |
++**	add	x0, x29, #?16
++**	mrs	(x[0-9]+), tpidr2_el0
++**	cbnz	\6, [^\n]+
++**	smstart	za
++** )
++**	bl	__arm_tpidr2_restore
++**	msr	tpidr2_el0, xzr
++**	bl	in_za
++**	smstop	za
++**	mov	sp, x29
++**	ldp	[^\n]+
++**	ret
++*/
++__arm_new("za") void test6()
++{
++  out_za();
++  private_za();
++  in_za();
++}
++
++// Rely on previous tests for the part leading up to the smstart.
++/*
++** test7:
++**	...
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	bl	private_za
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	ldp	[^\n]+
++**	ret
++*/
++__arm_new("za") void test7()
++{
++  out_za();
++  in_za();
++  private_za();
++  out_za();
++  in_za();
++}
++
++/*
++** test8:
++**	...
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	bl	private_za
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	bl	private_za
++**	ldp	[^\n]+
++**	ret
++*/
++__arm_new("za") void test8()
++{
++  out_za();
++  in_za();
++  private_za();
++  out_za();
++  in_za();
++  private_za();
++}
++
++/*
++** test9:
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	bl	private_za
++**	bl	private_za
++**	bl	private_za
++**	bl	private_za
++**	add	x[0-9]+, x29, #?16
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++*/
++__arm_new("za") void test9()
++{
++  out_za();
++  private_za();
++  private_za();
++  private_za();
++  private_za();
++  in_za();
++}
++
++/*
++** test10:
++**	ldr	(w[0-9]+), \[x0\]
++**	cbz	\1, [^\n]+
++**	ldr	[^\n]+
++**	add	[^\n]+
++**	str	[^\n]+
++**	ret
++**	...
++*/
++__arm_new("za") void test10(volatile int *ptr)
++{
++  if (__builtin_expect (*ptr != 0, 1))
++    *ptr = *ptr + 1;
++  else
++    inout_za();
++}
++
++/*
++** test11:
++**	...
++**	ldr	w[0-9]+, [^\n]+
++**	add	(w[0-9]+), [^\n]+
++**	str	\1, [^\n]+
++**	...
++**	ret
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	bl	inout_za
++**	ldr	(w[0-9]+), [^\n]+
++**	cbnz	\2, [^\n]+
++**	smstop	za
++**	...
++*/
++__arm_new("za") void test11(volatile int *ptr)
++{
++  if (__builtin_expect (*ptr == 0, 0))
++    do
++      inout_za();
++    while (*ptr);
++  else
++    *ptr += 1;
++}
++
++__arm_new("za") void test12(volatile int *ptr)
++{
++  do
++    {
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++  out_za();
++  in_za();
++}
++
++/*
++** test13:
++**	stp	[^\n]+
++**	...
++**	stp	[^\n]+
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	cbnz	[^\n]+
++**	smstart	za
++**	msr	tpidr2_el0, xzr
++**	bl	out_za
++**	bl	in_za
++**	...
++**	smstop	za
++**	...
++*/
++__arm_new("za") void test13(volatile int *ptr)
++{
++  do
++    {
++      private_za();
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++  out_za();
++  in_za();
++}
++
++/*
++** test14:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	smstart	za
++**	bl	inout_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	...
++*/
++__arm_new("za") void test14(volatile int *ptr)
++{
++  do
++    inout_za();
++  while (*ptr);
++  out_za();
++  in_za();
++}
++
++/*
++** test15:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	smstop	za
++**	bl	private_za
++**	ldr	[^\n]+
++**	ldp	[^\n]+
++**	ret
++*/
++__arm_new("za") void test15(volatile int *ptr)
++{
++  do
++    {
++      out_za();
++      in_za();
++    }
++  while (*ptr);
++  private_za();
++}
++
++/*
++** test16:
++**	...
++**	bl	__arm_tpidr2_save
++**	...
++**	smstart	za
++**	b	[^\n]+
++-- loop:
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	msr	tpidr2_el0, xzr
++-- loop_entry:
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	bl	private_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	msr	tpidr2_el0, xzr
++**	smstop	za
++**	bl	private_za
++**	...
++*/
++__arm_new("za") void test16(volatile int *ptr)
++{
++  do
++    {
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++  private_za();
++}
++
++/*
++** test17:
++**	...
++**	bl	private_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++**	smstop	za
++**	...
++*/
++__arm_new("za") void test17(volatile int *ptr)
++{
++  do
++    {
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++}
++
++/*
++** test18:
++**	ldr	w[0-9]+, [^\n]+
++**	cbnz	w[0-9]+, [^\n]+
++**	ret
++**	...
++**	smstop	za
++**	bl	private_za
++**	...
++*/
++__arm_new("za") void test18(volatile int *ptr)
++{
++  if (__builtin_expect (*ptr, 0))
++    {
++      out_za();
++      in_za();
++      private_za();
++    }
++}
++
++/*
++** test19:
++**	...
++**	ldr	w[0-9]+, [^\n]+
++**	cbz	w[0-9]+, [^\n]+
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstop	za
++**	bl	private_za
++**	...
++*/
++__arm_new("za") void test19(volatile int *ptr)
++{
++  if (__builtin_expect (*ptr != 0, 1))
++    private_za();
++  else
++    do
++      {
++	inout_za();
++	private_za();
++      }
++    while (*ptr);
++}
++
++/*
++** test20:
++**	...
++**	bl	a20
++**	(?:(?!x0).)*
++**	bl	b20
++**	...
++**	mov	([wx][0-9]+), [wx]0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	mov	[wx]0, \1
++**	...
++**	bl	c20
++**	...
++*/
++__arm_new("za") void test20()
++{
++  extern int a20() __arm_inout("za");
++  extern int b20(int);
++  extern void c20(int) __arm_inout("za");
++  c20(b20(a20()));
++}
++
++/*
++** test21:
++**	...
++**	bl	a21
++**	(?:(?!x0).)*
++**	bl	b21
++**	...
++**	mov	(x[0-9]+), x0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	mov	x0, \1
++**	...
++**	bl	c21
++**	...
++*/
++__arm_new("za") void test21()
++{
++  extern __UINT64_TYPE__ a21() __arm_inout("za");
++  extern __UINT64_TYPE__ b21(__UINT64_TYPE__);
++  extern void c21(__UINT64_TYPE__) __arm_inout("za");
++  c21(b21(a21()));
++}
++
++/*
++** test22:
++**	(?:(?!rdsvl).)*
++**	rdsvl	x[0-9]+, #1
++**	(?:(?!rdsvl).)*
++*/
++__arm_new("za") void test22(volatile int *ptr)
++{
++  inout_za();
++  if (*ptr)
++    *ptr += 1;
++  else
++    private_za();
++  private_za();
++  in_za();
++}
++
++/*
++** test23:
++**	(?:(?!__arm_tpidr2_save).)*
++**	bl	__arm_tpidr2_save
++**	(?:(?!__arm_tpidr2_save).)*
++*/
++__arm_new("za") void test23(volatile int *ptr)
++{
++  if (*ptr)
++    *ptr += 1;
++  else
++    inout_za();
++  inout_za();
++}
++
++/*
++** test24:
++**	...
++**	bl	in_za
++**	...
++**	incb	x1
++**	...
++**	bl	out_za
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	incb	x1
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	incb	x1
++**	...
++**	smstop	za
++**	...
++**	bl	private_za
++**	...
++**	ret
++*/
++__arm_new("za") void test24()
++{
++  in_za();
++  asm ("incb\tx1" ::: "x1", "za");
++  out_za();
++  inout_za();
++  private_za();
++  asm ("incb\tx1" ::: "x1", "za");
++  private_za();
++  asm ("incb\tx1" ::: "x1", "za");
++  in_za();
++  private_za();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_5.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_5.c
+new file mode 100644
+index 000000000..d54840d3d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_5.c
+@@ -0,0 +1,595 @@
++// { dg-options "-O2 -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++void private_za();
++void out_za() __arm_out("za");
++void in_za() __arm_in("za");
++void inout_za() __arm_inout("za");
++void preserves_za() __arm_preserves("za");
++
++/*
++** test1:
++**	ret
++*/
++void test1() __arm_inout("za")
++{
++}
++
++/*
++** test2:
++**	ldr	w0, \[x0\]
++**	ret
++*/
++int test2(int *ptr) __arm_inout("za")
++{
++  return *ptr;
++}
++
++/*
++** test3:
++**	...
++**	sub	sp, sp, x[0-9]+
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++int test3() __arm_inout("za")
++{
++  private_za();
++  return 0;
++}
++
++/*
++** test4:
++**	stp	[^\n]+
++**	[^\n]+
++**	bl	in_za
++**	ldp	[^\n]+
++**	ret
++*/
++void test4() __arm_inout("za")
++{
++  in_za();
++}
++
++/*
++** test5:
++**	...
++**	smstop	za
++**	...
++**	bl	private_za
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	...
++**	sub	sp, sp, x[0-9]+
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++void test5() __arm_inout("za")
++{
++  private_za();
++  out_za();
++  in_za();
++  private_za();
++}
++
++/*
++** test6:
++**	...
++**	bl	out_za
++**	...
++**	sub	sp, sp, x[0-9]+
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++**	bl	in_za
++**	...
++*/
++void test6() __arm_inout("za")
++{
++  out_za();
++  private_za();
++  in_za();
++}
++
++/*
++** test7:
++**	stp	[^\n]+
++**	[^\n]+
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	bl	private_za
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	ldp	[^\n]+
++**	ret
++*/
++void test7() __arm_inout("za")
++{
++  out_za();
++  in_za();
++  private_za();
++  out_za();
++  in_za();
++}
++
++/*
++** test8:
++**	stp	[^\n]+
++**	[^\n]+
++**	bl	out_za
++**	bl	in_za
++**	smstop	za
++**	bl	private_za
++**	smstart	za
++**	bl	out_za
++**	bl	in_za
++**	...
++**	sub	sp, sp, x[0-9]+
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++**	ret
++*/
++void test8() __arm_inout("za")
++{
++  out_za();
++  in_za();
++  private_za();
++  out_za();
++  in_za();
++  private_za();
++}
++
++/*
++** test9:
++**	stp	[^\n]+
++**	[^\n]+
++**	bl	out_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	bl	private_za
++**	bl	private_za
++**	bl	private_za
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++void test9() __arm_inout("za")
++{
++  out_za();
++  private_za();
++  private_za();
++  private_za();
++  private_za();
++  in_za();
++}
++
++/*
++** test10:
++**	ldr	(w[0-9]+), \[x0\]
++**	cbz	\1, [^\n]+
++**	ldr	[^\n]+
++**	add	[^\n]+
++**	str	[^\n]+
++**	ret
++**	...
++*/
++void test10(volatile int *ptr) __arm_inout("za")
++{
++  if (__builtin_expect (*ptr != 0, 1))
++    *ptr = *ptr + 1;
++  else
++    inout_za();
++}
++
++/*
++** test11:
++**	(?!.*(\t__arm|\tza|tpidr2_el0)).*
++*/
++void test11(volatile int *ptr) __arm_inout("za")
++{
++  if (__builtin_expect (*ptr == 0, 0))
++    do
++      inout_za();
++    while (*ptr);
++  else
++    *ptr += 1;
++}
++
++void test12(volatile int *ptr) __arm_inout("za")
++{
++  do
++    {
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++  out_za();
++  in_za();
++}
++
++/*
++** test13:
++**	stp	[^\n]+
++**	...
++**	stp	[^\n]+
++**	...
++-- loop:
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	smstart	za
++**	msr	tpidr2_el0, xzr
++**	bl	out_za
++**	bl	in_za
++**	[^\n]+
++**	[^\n]+
++**	ldp	[^\n]+
++**	ret
++*/
++void test13(volatile int *ptr) __arm_inout("za")
++{
++  do
++    {
++      private_za();
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++  out_za();
++  in_za();
++}
++
++/*
++** test14:
++**	...
++**	bl	inout_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	bl	out_za
++**	bl	in_za
++**	...
++*/
++void test14(volatile int *ptr) __arm_inout("za")
++{
++  do
++    inout_za();
++  while (*ptr);
++  out_za();
++  in_za();
++}
++
++/*
++** test15:
++**	...
++**	bl	out_za
++**	bl	in_za
++**	ldr	[^\n]+
++**	cbnz	[^\n]+
++**	...
++**	stp	[^\n]+
++**	...
++**	msr	tpidr2_el0, [^\n]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++void test15(volatile int *ptr) __arm_inout("za")
++{
++  do
++    {
++      out_za();
++      in_za();
++    }
++  while (*ptr);
++  private_za();
++}
++
++/*
++** test16:
++**	stp	[^\n]+
++**	...
++**	stp	[^\n]+
++**	...
++**	b	[^\n]+
++-- loop:
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	msr	tpidr2_el0, xzr
++-- loop_entry:
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++void test16(volatile int *ptr) __arm_inout("za")
++{
++  do
++    {
++      inout_za();
++      private_za();
++    }
++  while (*ptr);
++  private_za();
++}
++
++/*
++** test17:
++**	...
++-- loop:
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	smstart	za
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++**	cbnz	[^\n]+
++**	[^\n]+
++**	[^\n]+
++**	ldp	[^\n]+
++**	ret
++*/
++void test17(volatile int *ptr) __arm_inout("za")
++{
++  do
++    {
++      inout_za();
++      private_za();
++      while (*ptr)
++	ptr += 1;
++    }
++  while (*ptr);
++}
++
++/*
++** test18:
++**	ldr	w[0-9]+, [^\n]+
++**	cbnz	w[0-9]+, [^\n]+
++**	ret
++**	...
++**	bl	out_za
++**	bl	in_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	msr	tpidr2_el0, xzr
++**	...
++*/
++void test18(volatile int *ptr) __arm_inout("za")
++{
++  if (__builtin_expect (*ptr, 0))
++    {
++      out_za();
++      in_za();
++      private_za();
++    }
++}
++
++void test19(volatile int *ptr) __arm_inout("za")
++{
++  if (__builtin_expect (*ptr != 0, 1))
++    private_za();
++  else
++    do
++      {
++	inout_za();
++	private_za();
++      }
++    while (*ptr);
++}
++
++/*
++** test20:
++**	...
++**	bl	a20
++**	(?:(?!x0).)*
++**	bl	b20
++**	...
++**	mov	([wx][0-9]+), [wx]0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	mov	[wx]0, \1
++**	...
++**	bl	c20
++**	...
++*/
++void test20() __arm_inout("za")
++{
++  extern int a20() __arm_inout("za");
++  extern int b20(int);
++  extern void c20(int) __arm_inout("za");
++  c20(b20(a20()));
++}
++
++/*
++** test21:
++**	...
++**	bl	a21
++**	(?:(?!x0).)*
++**	bl	b21
++**	...
++**	mov	(x[0-9]+), x0
++**	...
++**	bl	__arm_tpidr2_restore
++**	...
++**	mov	x0, \1
++**	...
++**	bl	c21
++**	...
++*/
++void test21() __arm_inout("za")
++{
++  extern __UINT64_TYPE__ a21() __arm_inout("za");
++  extern __UINT64_TYPE__ b21(__UINT64_TYPE__);
++  extern void c21(__UINT64_TYPE__) __arm_inout("za");
++  c21(b21(a21()));
++}
++
++/*
++** test22:
++**	(?:(?!rdsvl).)*
++**	rdsvl	x[0-9]+, #1
++**	(?:(?!rdsvl).)*
++*/
++void test22(volatile int *ptr) __arm_inout("za")
++{
++  inout_za();
++  if (*ptr)
++    *ptr += 1;
++  else
++    private_za();
++  private_za();
++  in_za();
++}
++
++void test23(volatile int *ptr) __arm_inout("za")
++{
++  if (*ptr)
++    *ptr += 1;
++  else
++    inout_za();
++  inout_za();
++}
++
++/*
++** test24:
++**	...
++**	bl	in_za
++**	...
++**	incb	x1
++**	...
++**	bl	out_za
++**	bl	inout_za
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	incb	x1
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	incb	x1
++**	...
++**	msr	tpidr2_el0, x[0-9]+
++**	...
++**	bl	private_za
++**	...
++**	mrs	x[0-9]+, tpidr2_el0
++**	...
++**	ret
++*/
++void test24() __arm_inout("za")
++{
++  in_za();
++  asm ("incb\tx1" ::: "x1", "za");
++  out_za();
++  inout_za();
++  private_za();
++  asm ("incb\tx1" ::: "x1", "za");
++  private_za();
++  asm ("incb\tx1" ::: "x1", "za");
++  in_za();
++  private_za();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_6.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_6.c
+new file mode 100644
+index 000000000..d5b226ae1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_6.c
+@@ -0,0 +1,23 @@
++// { dg-options "-O -fno-optimize-sibling-calls -fomit-frame-pointer" }
++
++void private_za();
++void out_za() __arm_out("za");
++void in_za() __arm_in("za");
++
++__arm_new("za") void test20(volatile int *ptr)
++{
++  if (*ptr)
++    out_za();
++  else
++    *ptr += 1;
++  *ptr += 1;
++  if (*ptr)
++    in_za();
++  else
++    *ptr += 1;
++}
++
++// { dg-final { scan-assembler {\tbl\t__arm_tpidr2_save\n} } }
++// { dg-final { scan-assembler {\tsmstart\tza\n} } }
++// { dg-final { scan-assembler {\tsmstop\tza\n} } }
++// { dg-final { scan-assembler-not {\tsub\tsp, sp, x[0-9]+\n} } }
+-- 
+2.33.0
+
diff --git a/0207-Backport-SME-aarch64-Add-a-register-class-for-w12-w1.patch b/0207-Backport-SME-aarch64-Add-a-register-class-for-w12-w1.patch
new file mode 100644
index 0000000..3d69ca5
--- /dev/null
+++ b/0207-Backport-SME-aarch64-Add-a-register-class-for-w12-w1.patch
@@ -0,0 +1,103 @@
+From 9866b4c1d85d88fd9e25ff3ac5224b69d4e0f0b2 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:26 +0000
+Subject: [PATCH 108/157] [Backport][SME] aarch64: Add a register class for
+ w12-w15
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=084122adb5792a9c8e7f7876e2c1d59ba80c228b
+
+Some SME instructions use w12-w15 to index ZA.  This patch
+adds a register class for that range.
+
+gcc/
+	* config/aarch64/aarch64.h (W12_W15_REGNUM_P): New macro.
+	(W12_W15_REGS): New register class.
+	(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add entries for it.
+	* config/aarch64/aarch64.cc (aarch64_regno_regclass)
+	(aarch64_class_max_nregs, aarch64_register_move_cost): Handle
+	W12_W15_REGS.
+---
+ gcc/config/aarch64/aarch64.cc | 12 +++++++-----
+ gcc/config/aarch64/aarch64.h  |  6 ++++++
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index a6e996c5b..112dfeabb 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -14213,6 +14213,9 @@ aarch64_label_mentioned_p (rtx x)
+ enum reg_class
+ aarch64_regno_regclass (unsigned regno)
+ {
++  if (W12_W15_REGNUM_P (regno))
++    return W12_W15_REGS;
++
+   if (STUB_REGNUM_P (regno))
+     return STUB_REGS;
+ 
+@@ -14577,6 +14580,7 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode)
+   unsigned int nregs, vec_flags;
+   switch (regclass)
+     {
++    case W12_W15_REGS:
+     case STUB_REGS:
+     case TAILCALL_ADDR_REGS:
+     case POINTER_REGS:
+@@ -16926,13 +16930,11 @@ aarch64_register_move_cost (machine_mode mode,
+   const struct cpu_regmove_cost *regmove_cost
+     = aarch64_tune_params.regmove_cost;
+ 
+-  /* Caller save and pointer regs are equivalent to GENERAL_REGS.  */
+-  if (to == TAILCALL_ADDR_REGS || to == POINTER_REGS
+-      || to == STUB_REGS)
++  /* Trest any subset of POINTER_REGS as though it were GENERAL_REGS.  */
++  if (reg_class_subset_p (to, POINTER_REGS))
+     to = GENERAL_REGS;
+ 
+-  if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS
+-      || from == STUB_REGS)
++  if (reg_class_subset_p (from, POINTER_REGS))
+     from = GENERAL_REGS;
+ 
+   /* Make RDFFR very expensive.  In particular, if we know that the FFR
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 89d30b9bf..8b21faf34 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -648,6 +648,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+    && (REGNO) != R17_REGNUM \
+    && (REGNO) != R30_REGNUM) \
+ 
++#define W12_W15_REGNUM_P(REGNO) \
++  IN_RANGE (REGNO, R12_REGNUM, R15_REGNUM)
++
+ #define FP_REGNUM_P(REGNO)			\
+   (((unsigned) (REGNO - V0_REGNUM)) <= (V31_REGNUM - V0_REGNUM))
+ 
+@@ -674,6 +677,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ enum reg_class
+ {
+   NO_REGS,
++  W12_W15_REGS,
+   TAILCALL_ADDR_REGS,
+   STUB_REGS,
+   GENERAL_REGS,
+@@ -698,6 +702,7 @@ enum reg_class
+ #define REG_CLASS_NAMES				\
+ {						\
+   "NO_REGS",					\
++  "W12_W15_REGS",				\
+   "TAILCALL_ADDR_REGS",				\
+   "STUB_REGS",					\
+   "GENERAL_REGS",				\
+@@ -719,6 +724,7 @@ enum reg_class
+ #define REG_CLASS_CONTENTS						\
+ {									\
+   { 0x00000000, 0x00000000, 0x00000000 },	/* NO_REGS */		\
++  { 0x0000f000, 0x00000000, 0x00000000 },	/* W12_W15_REGS */	\
+   { 0x00030000, 0x00000000, 0x00000000 },	/* TAILCALL_ADDR_REGS */\
+   { 0x3ffcffff, 0x00000000, 0x00000000 },	/* STUB_REGS */		\
+   { 0x7fffffff, 0x00000000, 0x00000003 },	/* GENERAL_REGS */	\
+-- 
+2.33.0
+
diff --git a/0208-Backport-SME-aarch64-Add-a-VNx1TI-mode.patch b/0208-Backport-SME-aarch64-Add-a-VNx1TI-mode.patch
new file mode 100644
index 0000000..eefe7d8
--- /dev/null
+++ b/0208-Backport-SME-aarch64-Add-a-VNx1TI-mode.patch
@@ -0,0 +1,72 @@
+From 8310c0df319a86bc2f63b8d3198dd1c394827bac Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:27 +0000
+Subject: [PATCH 109/157] [Backport][SME] aarch64: Add a VNx1TI mode
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=80fc055cf00fee4b1f9f19f77c8880b12226e086
+
+Although TI isn't really a native SVE element mode, it's convenient
+for SME if we define VNx1TI anyway, so that it can be used to
+distinguish .Q ZA operations from others.  It's purely an RTL
+convenience and isn't (yet) a valid storage mode.
+
+gcc/
+	* config/aarch64/aarch64-modes.def: Add VNx1TI.
+---
+ gcc/config/aarch64/aarch64-modes.def | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def
+index 8f399225a..8fa66fdb3 100644
+--- a/gcc/config/aarch64/aarch64-modes.def
++++ b/gcc/config/aarch64/aarch64-modes.def
+@@ -146,7 +146,7 @@ ADV_SIMD_Q_REG_STRUCT_MODES (4, V4x16, V4x8, V4x4, V4x2)
+    for 8-bit, 16-bit, 32-bit and 64-bit elements respectively.  It isn't
+    strictly necessary to set the alignment here, since the default would
+    be clamped to BIGGEST_ALIGNMENT anyhow, but it seems clearer.  */
+-#define SVE_MODES(NVECS, VB, VH, VS, VD) \
++#define SVE_MODES(NVECS, VB, VH, VS, VD, VT) \
+   VECTOR_MODES_WITH_PREFIX (VNx, INT, 16 * NVECS, NVECS == 1 ? 1 : 4); \
+   VECTOR_MODES_WITH_PREFIX (VNx, FLOAT, 16 * NVECS, NVECS == 1 ? 1 : 4); \
+   \
+@@ -154,6 +154,7 @@ ADV_SIMD_Q_REG_STRUCT_MODES (4, V4x16, V4x8, V4x4, V4x2)
+   ADJUST_NUNITS (VH##HI, aarch64_sve_vg * NVECS * 4); \
+   ADJUST_NUNITS (VS##SI, aarch64_sve_vg * NVECS * 2); \
+   ADJUST_NUNITS (VD##DI, aarch64_sve_vg * NVECS); \
++  ADJUST_NUNITS (VT##TI, exact_div (aarch64_sve_vg * NVECS, 2)); \
+   ADJUST_NUNITS (VH##BF, aarch64_sve_vg * NVECS * 4); \
+   ADJUST_NUNITS (VH##HF, aarch64_sve_vg * NVECS * 4); \
+   ADJUST_NUNITS (VS##SF, aarch64_sve_vg * NVECS * 2); \
+@@ -163,17 +164,23 @@ ADV_SIMD_Q_REG_STRUCT_MODES (4, V4x16, V4x8, V4x4, V4x2)
+   ADJUST_ALIGNMENT (VH##HI, 16); \
+   ADJUST_ALIGNMENT (VS##SI, 16); \
+   ADJUST_ALIGNMENT (VD##DI, 16); \
++  ADJUST_ALIGNMENT (VT##TI, 16); \
+   ADJUST_ALIGNMENT (VH##BF, 16); \
+   ADJUST_ALIGNMENT (VH##HF, 16); \
+   ADJUST_ALIGNMENT (VS##SF, 16); \
+   ADJUST_ALIGNMENT (VD##DF, 16);
+ 
+-/* Give SVE vectors the names normally used for 256-bit vectors.
+-   The actual number depends on command-line flags.  */
+-SVE_MODES (1, VNx16, VNx8, VNx4, VNx2)
+-SVE_MODES (2, VNx32, VNx16, VNx8, VNx4)
+-SVE_MODES (3, VNx48, VNx24, VNx12, VNx6)
+-SVE_MODES (4, VNx64, VNx32, VNx16, VNx8)
++/* Give SVE vectors names of the form VNxX, where X describes what is
++   stored in each 128-bit unit.  The actual size of the mode depends
++   on command-line flags.
++
++   VNx1TI isn't really a native SVE mode, but it can be useful in some
++   limited situations.  */
++VECTOR_MODE_WITH_PREFIX (VNx, INT, TI, 1, 1);
++SVE_MODES (1, VNx16, VNx8, VNx4, VNx2, VNx1)
++SVE_MODES (2, VNx32, VNx16, VNx8, VNx4, VNx2)
++SVE_MODES (3, VNx48, VNx24, VNx12, VNx6, VNx3)
++SVE_MODES (4, VNx64, VNx32, VNx16, VNx8, VNx4)
+ 
+ /* Partial SVE vectors:
+ 
+-- 
+2.33.0
+
diff --git a/0209-Backport-SME-aarch64-Generalise-unspec_based_functio.patch b/0209-Backport-SME-aarch64-Generalise-unspec_based_functio.patch
new file mode 100644
index 0000000..1c2ac4e
--- /dev/null
+++ b/0209-Backport-SME-aarch64-Generalise-unspec_based_functio.patch
@@ -0,0 +1,118 @@
+From e3c0d3d98ab1f60900533f3f75c598f899f37c9f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:27 +0000
+Subject: [PATCH 110/157] [Backport][SME] aarch64: Generalise
+ unspec_based_function_base
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1ec23d5a29bc5d89cef60e2aba2fe4095ee12a8f
+
+Until now, SVE intrinsics that map directly to unspecs
+have always used type suffix 0 to distinguish between signed
+integers, unsigned integers, and floating-point values.
+SME adds functions that need to use type suffix 1 instead.
+This patch generalises the classes accordingly.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins-functions.h
+	(unspec_based_function_base): Allow type suffix 1 to determine
+	the mode of the operation.
+	(unspec_based_function): Update accordingly.
+	(unspec_based_fused_function): Likewise.
+	(unspec_based_fused_lane_function): Likewise.
+---
+ .../aarch64/aarch64-sve-builtins-functions.h  | 29 ++++++++++++-------
+ 1 file changed, 18 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+index 94a6d1207..f5fa4030c 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+@@ -250,18 +250,21 @@ class unspec_based_function_base : public function_base
+ public:
+   CONSTEXPR unspec_based_function_base (int unspec_for_sint,
+ 					int unspec_for_uint,
+-					int unspec_for_fp)
++					int unspec_for_fp,
++					unsigned int suffix_index = 0)
+     : m_unspec_for_sint (unspec_for_sint),
+       m_unspec_for_uint (unspec_for_uint),
+-      m_unspec_for_fp (unspec_for_fp)
++      m_unspec_for_fp (unspec_for_fp),
++      m_suffix_index (suffix_index)
+   {}
+ 
+   /* Return the unspec code to use for INSTANCE, based on type suffix 0.  */
+   int
+   unspec_for (const function_instance &instance) const
+   {
+-    return (!instance.type_suffix (0).integer_p ? m_unspec_for_fp
+-	    : instance.type_suffix (0).unsigned_p ? m_unspec_for_uint
++    auto &suffix = instance.type_suffix (m_suffix_index);
++    return (!suffix.integer_p ? m_unspec_for_fp
++	    : suffix.unsigned_p ? m_unspec_for_uint
+ 	    : m_unspec_for_sint);
+   }
+ 
+@@ -270,6 +273,9 @@ public:
+   int m_unspec_for_sint;
+   int m_unspec_for_uint;
+   int m_unspec_for_fp;
++
++  /* Which type suffix is used to choose between the unspecs.  */
++  unsigned int m_suffix_index;
+ };
+ 
+ /* A function_base for functions that have an associated unspec code.
+@@ -336,7 +342,8 @@ public:
+   rtx
+   expand (function_expander &e) const OVERRIDE
+   {
+-    return e.use_exact_insn (CODE (unspec_for (e), e.vector_mode (0)));
++    return e.use_exact_insn (CODE (unspec_for (e),
++				   e.vector_mode (m_suffix_index)));
+   }
+ };
+ 
+@@ -395,16 +402,16 @@ public:
+   {
+     int unspec = unspec_for (e);
+     insn_code icode;
+-    if (e.type_suffix (0).float_p)
++    if (e.type_suffix (m_suffix_index).float_p)
+       {
+ 	/* Put the operands in the normal (fma ...) order, with the accumulator
+ 	   last.  This fits naturally since that's also the unprinted operand
+ 	   in the asm output.  */
+ 	e.rotate_inputs_left (0, e.pred != PRED_none ? 4 : 3);
+-	icode = code_for_aarch64_sve (unspec, e.vector_mode (0));
++	icode = code_for_aarch64_sve (unspec, e.vector_mode (m_suffix_index));
+       }
+     else
+-      icode = INT_CODE (unspec, e.vector_mode (0));
++      icode = INT_CODE (unspec, e.vector_mode (m_suffix_index));
+     return e.use_exact_insn (icode);
+   }
+ };
+@@ -430,16 +437,16 @@ public:
+   {
+     int unspec = unspec_for (e);
+     insn_code icode;
+-    if (e.type_suffix (0).float_p)
++    if (e.type_suffix (m_suffix_index).float_p)
+       {
+ 	/* Put the operands in the normal (fma ...) order, with the accumulator
+ 	   last.  This fits naturally since that's also the unprinted operand
+ 	   in the asm output.  */
+ 	e.rotate_inputs_left (0, e.pred != PRED_none ? 5 : 4);
+-	icode = code_for_aarch64_lane (unspec, e.vector_mode (0));
++	icode = code_for_aarch64_lane (unspec, e.vector_mode (m_suffix_index));
+       }
+     else
+-      icode = INT_CODE (unspec, e.vector_mode (0));
++      icode = INT_CODE (unspec, e.vector_mode (m_suffix_index));
+     return e.use_exact_insn (icode);
+   }
+ };
+-- 
+2.33.0
+
diff --git a/0210-Backport-SME-aarch64-Generalise-_m-rules-for-SVE-int.patch b/0210-Backport-SME-aarch64-Generalise-_m-rules-for-SVE-int.patch
new file mode 100644
index 0000000..75de62e
--- /dev/null
+++ b/0210-Backport-SME-aarch64-Generalise-_m-rules-for-SVE-int.patch
@@ -0,0 +1,117 @@
+From 3d721b42c97baba562b77988cec0fec229217519 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:28 +0000
+Subject: [PATCH 111/157] [Backport][SME] aarch64: Generalise _m rules for SVE
+ intrinsics
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=8de9304d94d4ec42863a25c1cb1a1ba9a1e3e0fe
+
+In SVE there was a simple rule that unary merging (_m) intrinsics
+had a separate initial argument to specify the values of inactive
+lanes, whereas other merging functions took inactive lanes from
+the first operand to the operation.
+
+That rule began to break down in SVE2, and it continues to do
+so in SME.  This patch therefore adds a virtual function to
+specify whether the separate initial argument is present or not.
+The old rule is still the default.
+
+gcc/
+	* config/aarch64/aarch64-sve-builtins.h
+	(function_shape::has_merge_argument_p): New member function.
+	* config/aarch64/aarch64-sve-builtins.cc:
+	(function_resolver::check_gp_argument): Use it.
+	(function_expander::get_fallback_value): Likewise.
+	* config/aarch64/aarch64-sve-builtins-shapes.cc
+	(apply_predication): Likewise.
+	(unary_convert_narrowt_def::has_merge_argument_p): New function.
+---
+ gcc/config/aarch64/aarch64-sve-builtins-shapes.cc | 10 ++++++++--
+ gcc/config/aarch64/aarch64-sve-builtins.cc        |  4 ++--
+ gcc/config/aarch64/aarch64-sve-builtins.h         | 13 +++++++++++++
+ 3 files changed, 23 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index 95e40d8f3..c536949ba 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -66,8 +66,8 @@ apply_predication (const function_instance &instance, tree return_type,
+ 	 the same type as the result.  For unary_convert_narrowt it also
+ 	 provides the "bottom" half of active elements, and is present
+ 	 for all types of predication.  */
+-      if ((argument_types.length () == 2 && instance.pred == PRED_m)
+-	  || instance.shape == shapes::unary_convert_narrowt)
++      auto nargs = argument_types.length () - 1;
++      if (instance.shape->has_merge_argument_p (instance, nargs))
+ 	argument_types.quick_insert (0, return_type);
+     }
+ }
+@@ -3271,6 +3271,12 @@ SHAPE (unary_convert)
+    predicate.  */
+ struct unary_convert_narrowt_def : public overloaded_base<1>
+ {
++  bool
++  has_merge_argument_p (const function_instance &, unsigned int) const override
++  {
++    return true;
++  }
++
+   void
+   build (function_builder &b, const function_group_info &group) const OVERRIDE
+   {
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 5f3a2baea..3441b4294 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -2287,7 +2287,7 @@ function_resolver::check_gp_argument (unsigned int nops,
+   if (pred != PRED_none)
+     {
+       /* Unary merge operations should use resolve_unary instead.  */
+-      gcc_assert (nops != 1 || pred != PRED_m);
++      gcc_assert (!shape->has_merge_argument_p (*this, nops));
+       nargs = nops + 1;
+       if (!check_num_arguments (nargs)
+ 	  || !require_vector_type (i, VECTOR_TYPE_svbool_t))
+@@ -2931,7 +2931,7 @@ function_expander::get_fallback_value (machine_mode mode, unsigned int nops,
+ 
+   gcc_assert (pred == PRED_m || pred == PRED_x);
+   if (merge_argno == DEFAULT_MERGE_ARGNO)
+-    merge_argno = nops == 1 && pred == PRED_m ? 0 : 1;
++    merge_argno = shape->has_merge_argument_p (*this, nops) ? 0 : 1;
+ 
+   if (merge_argno == 0)
+     return args[argno++];
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 7132b6e77..f16ac3947 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -710,6 +710,9 @@ public:
+ class function_shape
+ {
+ public:
++  virtual bool has_merge_argument_p (const function_instance &,
++				     unsigned int) const;
++
+   virtual bool explicit_type_suffix_p (unsigned int) const = 0;
+ 
+   /* True if the group suffix is present in overloaded names.
+@@ -982,6 +985,16 @@ function_base::vectors_per_tuple (const function_instance &instance) const
+   return instance.group_suffix ().vectors_per_tuple;
+ }
+ 
++/* Return true if INSTANCE (which has NARGS arguments) has an initial
++   vector argument whose only purpose is to specify the values of
++   inactive lanes.  */
++inline bool
++function_shape::has_merge_argument_p (const function_instance &instance,
++				      unsigned int nargs) const
++{
++  return nargs == 1 && instance.pred == PRED_m;
++}
++
+ /* Return the mode of the result of a call.  */
+ inline machine_mode
+ function_expander::result_mode () const
+-- 
+2.33.0
+
diff --git a/0211-Backport-SME-aarch64-Add-support-for-arm_sme.h.patch b/0211-Backport-SME-aarch64-Add-support-for-arm_sme.h.patch
new file mode 100644
index 0000000..b83e594
--- /dev/null
+++ b/0211-Backport-SME-aarch64-Add-support-for-arm_sme.h.patch
@@ -0,0 +1,15955 @@
+From 6c651a11f8e68244c4c53ad7b29983f54a3bc737 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:28 +0000
+Subject: [PATCH 112/157] [Backport][SME] aarch64: Add support for 
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=4f6ab9537051e156d52bd8e9df40107ba6685895
+
+This adds support for the SME parts of arm_sme.h.
+
+gcc/
+	* doc/invoke.texi: Document +sme-i16i64 and +sme-f64f64.
+	* config.gcc (aarch64*-*-*): Add arm_sme.h to the list of headers
+	to install and aarch64-sve-builtins-sme.o to the list of objects
+	to build.
+	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Define
+	or undefine TARGET_SME, TARGET_SME_I16I64 and TARGET_SME_F64F64.
+	(aarch64_pragma_aarch64): Handle arm_sme.h.
+	* config/aarch64/aarch64-option-extensions.def (sme-i16i64)
+	(sme-f64f64): New extensions.
+	* config/aarch64/aarch64-protos.h (aarch64_sme_vq_immediate)
+	(aarch64_addsvl_addspl_immediate_p, aarch64_output_addsvl_addspl)
+	(aarch64_output_sme_zero_za): Declare.
+	(aarch64_output_move_struct): Delete.
+	(aarch64_sme_ldr_vnum_offset): Declare.
+	(aarch64_sve::handle_arm_sme_h): Likewise.
+	* config/aarch64/aarch64.h (AARCH64_ISA_SM_ON): New macro.
+	(AARCH64_ISA_SME_I16I64, AARCH64_ISA_SME_F64F64): Likewise.
+	(TARGET_STREAMING, TARGET_STREAMING_SME): Likewise.
+	(TARGET_SME_I16I64, TARGET_SME_F64F64): Likewise.
+	* config/aarch64/aarch64.cc (aarch64_sve_rdvl_factor_p): Rename to...
+	(aarch64_sve_rdvl_addvl_factor_p): ...this.
+	(aarch64_sve_rdvl_immediate_p): Update accordingly.
+	(aarch64_rdsvl_immediate_p, aarch64_add_offset): Likewise.
+	(aarch64_sme_vq_immediate): Likewise.  Make public.
+	(aarch64_sve_addpl_factor_p): New function.
+	(aarch64_sve_addvl_addpl_immediate_p): Use
+	aarch64_sve_rdvl_addvl_factor_p and aarch64_sve_addpl_factor_p.
+	(aarch64_addsvl_addspl_immediate_p): New function.
+	(aarch64_output_addsvl_addspl): Likewise.
+	(aarch64_cannot_force_const_mem): Return true for RDSVL immediates.
+	(aarch64_classify_index): Handle .Q scaling for VNx1TImode.
+	(aarch64_classify_address): Likewise for vnum offsets.
+	(aarch64_output_sme_zero_za): New function.
+	(aarch64_sme_ldr_vnum_offset_p): Likewise.
+	* config/aarch64/predicates.md (aarch64_addsvl_addspl_immediate):
+	New predicate.
+	(aarch64_pluslong_operand): Include it for SME.
+	* config/aarch64/constraints.md (Ucj, Uav): New constraints.
+	* config/aarch64/iterators.md (VNx1TI_ONLY): New mode iterator.
+	(SME_ZA_I, SME_ZA_SDI, SME_ZA_SDF_I, SME_MOP_BHI): Likewise.
+	(SME_MOP_HSDF): Likewise.
+	(UNSPEC_SME_ADDHA, UNSPEC_SME_ADDVA, UNSPEC_SME_FMOPA)
+	(UNSPEC_SME_FMOPS, UNSPEC_SME_LD1_HOR, UNSPEC_SME_LD1_VER)
+	(UNSPEC_SME_READ_HOR, UNSPEC_SME_READ_VER, UNSPEC_SME_SMOPA)
+	(UNSPEC_SME_SMOPS, UNSPEC_SME_ST1_HOR, UNSPEC_SME_ST1_VER)
+	(UNSPEC_SME_SUMOPA, UNSPEC_SME_SUMOPS, UNSPEC_SME_UMOPA)
+	(UNSPEC_SME_UMOPS, UNSPEC_SME_USMOPA, UNSPEC_SME_USMOPS)
+	(UNSPEC_SME_WRITE_HOR, UNSPEC_SME_WRITE_VER): New unspecs.
+	(elem_bits): Handle x2 and x4 structure modes, plus VNx1TI.
+	(Vetype, Vesize, VPRED): Handle VNx1TI.
+	(b): New mode attribute.
+	(SME_LD1, SME_READ, SME_ST1, SME_WRITE, SME_BINARY_SDI, SME_INT_MOP)
+	(SME_FP_MOP): New int iterators.
+	(optab): Handle SME unspecs.
+	(hv): New int attribute.
+	* config/aarch64/aarch64.md (*add3_aarch64): Handle ADDSVL
+	and ADDSPL.
+	* config/aarch64/aarch64-sme.md (UNSPEC_SME_LDR): New unspec.
+	(@aarch64_sme_, @aarch64_sme__plus)
+	(aarch64_sme_ldr0, @aarch64_sme_ldrn): New patterns.
+	(UNSPEC_SME_STR): New unspec.
+	(@aarch64_sme_, @aarch64_sme__plus)
+	(aarch64_sme_str0, @aarch64_sme_strn): New patterns.
+	(@aarch64_sme_): Likewise.
+	(*aarch64_sme__plus): Likewise.
+	(@aarch64_sme_): Likewise.
+	(@aarch64_sme_): Likewise.
+	(*aarch64_sme__plus): Likewise.
+	(@aarch64_sme_): Likewise.
+	(UNSPEC_SME_ZERO): New unspec.
+	(aarch64_sme_zero): New pattern.
+	(@aarch64_sme_): Likewise.
+	(@aarch64_sme_): Likewise.
+	(@aarch64_sme_): Likewise.
+	* config/aarch64/aarch64-sve-builtins.def: Add ZA type suffixes.
+	Include aarch64-sve-builtins-sme.def.
+	(DEF_SME_ZA_FUNCTION): New macro.
+	* config/aarch64/aarch64-sve-builtins.h (CP_READ_ZA): New call
+	property.
+	(CP_WRITE_ZA): Likewise.
+	(PRED_za_m): New predication type.
+	(type_suffix_index): Handle DEF_SME_ZA_SUFFIX.
+	(type_suffix_info): Add vector_p and za_p fields.
+	(function_instance::num_za_tiles): New member function.
+	(function_builder::get_attributes): Add an aarch64_feature_flags
+	argument.
+	(function_expander::get_contiguous_base): Take a base argument
+	number, a vnum argument number, and an argument that indicates
+	whether the vnum parameter is a factor of the SME vector length
+	or the prevailing vector length.
+	(function_expander::add_integer_operand): Take a poly_int64.
+	(sve_switcher::sve_switcher): Take a base set of flags.
+	(sme_switcher): New class.
+	(scalar_types): Add a null entry for NUM_VECTOR_TYPES.
+	* config/aarch64/aarch64-sve-builtins.cc: Include
+	aarch64-sve-builtins-sme.h.
+	(pred_suffixes): Add an entry for PRED_za_m.
+	(type_suffixes): Initialize vector_p and za_p.  Handle ZA suffixes.
+	(TYPES_all_za, TYPES_d_za, TYPES_za_bhsd_data, TYPES_za_all_data)
+	(TYPES_za_s_integer, TYPES_za_d_integer, TYPES_mop_base)
+	(TYPES_mop_base_signed, TYPES_mop_base_unsigned, TYPES_mop_i16i64)
+	(TYPES_mop_i16i64_signed, TYPES_mop_i16i64_unsigned, TYPES_za): New
+	type suffix macros.
+	(preds_m, preds_za_m): New predication lists.
+	(function_groups): Handle DEF_SME_ZA_FUNCTION.
+	(scalar_types): Add an entry for NUM_VECTOR_TYPES.
+	(find_type_suffix_for_scalar_type): Check positively for vectors
+	rather than negatively for predicates.
+	(check_required_extensions): Handle PSTATE.SM and PSTATE.ZA
+	requirements.
+	(report_out_of_range): Handle the case where the minimum and
+	maximum are the same.
+	(function_instance::reads_global_state_p): Return true for functions
+	that read ZA.
+	(function_instance::modifies_global_state_p): Return true for functions
+	that write to ZA.
+	(sve_switcher::sve_switcher): Add a base flags argument.
+	(function_builder::get_name): Handle "__arm_" prefixes.
+	(add_attribute): Add an overload that takes a namespaces.
+	(add_shared_state_attribute): New function.
+	(function_builder::get_attributes): Take the required feature flags
+	as argument.  Add streaming and ZA attributes where appropriate.
+	(function_builder::add_unique_function): Update calls accordingly.
+	(function_resolver::check_gp_argument): Assert that the predication
+	isn't ZA _m predication.
+	(function_checker::function_checker): Don't bias the argument
+	number for ZA _m predication.
+	(function_expander::get_contiguous_base): Add arguments that
+	specify the base argument number, the vnum argument number,
+	and an argument that indicates whether the vnum parameter is
+	a factor of the SME vector length or the prevailing vector length.
+	Handle the SME case.
+	(function_expander::add_input_operand): Handle pmode_register_operand.
+	(function_expander::add_integer_operand): Take a poly_int64.
+	(init_builtins): Call handle_arm_sme_h for LTO.
+	(handle_arm_sve_h): Skip SME intrinsics.
+	(handle_arm_sme_h): New function.
+	* config/aarch64/aarch64-sve-builtins-functions.h
+	(read_write_za, write_za): New classes.
+	(unspec_based_sme_function, za_arith_function): New using aliases.
+	(quiet_za_arith_function): Likewise.
+	* config/aarch64/aarch64-sve-builtins-shapes.h
+	(binary_za_int_m, binary_za_m, binary_za_uint_m, bool_inherent)
+	(inherent_za, inherent_mask_za, ldr_za, load_za, read_za_m, store_za)
+	(str_za, unary_za_m, write_za_m): Declare.
+	* config/aarch64/aarch64-sve-builtins-shapes.cc (apply_predication):
+	Expect za_m functions to have an existing governing predicate.
+	(binary_za_m_base, binary_za_int_m_def, binary_za_m_def): New classes.
+	(binary_za_uint_m_def, bool_inherent_def, inherent_za_def): Likewise.
+	(inherent_mask_za_def, ldr_za_def, load_za_def, read_za_m_def)
+	(store_za_def, str_za_def, unary_za_m_def, write_za_m_def): Likewise.
+	* config/aarch64/arm_sme.h: New file.
+	* config/aarch64/aarch64-sve-builtins-sme.h: Likewise.
+	* config/aarch64/aarch64-sve-builtins-sme.cc: Likewise.
+	* config/aarch64/aarch64-sve-builtins-sme.def: Likewise.
+	* config/aarch64/t-aarch64 (aarch64-sve-builtins.o): Depend on
+	aarch64-sve-builtins-sme.def and aarch64-sve-builtins-sme.h.
+	(aarch64-sve-builtins-sme.o): New rule.
+
+gcc/testsuite/
+	* lib/target-supports.exp: Add sme and sme-i16i64 features.
+	* gcc.target/aarch64/pragma_cpp_predefs_4.c: Test __ARM_FEATURE_SME*
+	macros.
+	* gcc.target/aarch64/sve/acle/asm/test_sve_acle.h: Allow functions
+	to be marked as __arm_streaming, __arm_streaming_compatible, and
+	__arm_inout("za").
+	* g++.target/aarch64/sve/acle/general-c++/func_redef_4.c: Mark the
+	function as __arm_streaming_compatible.
+	* g++.target/aarch64/sve/acle/general-c++/func_redef_5.c: Likewise.
+	* g++.target/aarch64/sve/acle/general-c++/func_redef_7.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/func_redef_4.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/func_redef_5.c: Likewise.
+	* g++.target/aarch64/sme/aarch64-sme-acle-asm.exp: New test harness.
+	* gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/binary_za_int_m_1.c: New test.
+	* gcc.target/aarch64/sve/acle/general-c/binary_za_m_1.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/binary_za_m_2.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/binary_za_uint_m_1.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/read_za_m_1.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/unary_za_m_1.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/write_za_m_1.c: Likewise.
+---
+ gcc/config.gcc                                |   4 +-
+ gcc/config/aarch64/aarch64-c.cc               |   6 +
+ .../aarch64/aarch64-option-extensions.def     |   4 +
+ gcc/config/aarch64/aarch64-protos.h           |   8 +-
+ gcc/config/aarch64/aarch64-sme.md             | 373 +++++++++++++++
+ .../aarch64/aarch64-sve-builtins-functions.h  |  64 +++
+ .../aarch64/aarch64-sve-builtins-shapes.cc    | 306 +++++++++++-
+ .../aarch64/aarch64-sve-builtins-shapes.h     |  13 +
+ .../aarch64/aarch64-sve-builtins-sme.cc       | 412 +++++++++++++++++
+ .../aarch64/aarch64-sve-builtins-sme.def      |  76 +++
+ gcc/config/aarch64/aarch64-sve-builtins-sme.h |  57 +++
+ gcc/config/aarch64/aarch64-sve-builtins.cc    | 336 ++++++++++++--
+ gcc/config/aarch64/aarch64-sve-builtins.def   |  28 ++
+ gcc/config/aarch64/aarch64-sve-builtins.h     |  46 +-
+ gcc/config/aarch64/aarch64.cc                 | 140 +++++-
+ gcc/config/aarch64/aarch64.h                  |  15 +
+ gcc/config/aarch64/aarch64.md                 |  13 +-
+ gcc/config/aarch64/arm_sme.h                  |  45 ++
+ gcc/config/aarch64/constraints.md             |   9 +
+ gcc/config/aarch64/iterators.md               |  94 +++-
+ gcc/config/aarch64/predicates.md              |   8 +-
+ gcc/config/aarch64/t-aarch64                  |  17 +-
+ gcc/doc/invoke.texi                           |   4 +
+ .../aarch64/sme/aarch64-sme-acle-asm.exp      |  82 ++++
+ .../sve/acle/general-c++/func_redef_4.c       |   3 +-
+ .../sve/acle/general-c++/func_redef_5.c       |   1 +
+ .../sve/acle/general-c++/func_redef_7.c       |   1 +
+ .../gcc.target/aarch64/pragma_cpp_predefs_4.c |  38 ++
+ .../aarch64/sme/aarch64-sme-acle-asm.exp      |  81 ++++
+ .../aarch64/sme/acle-asm/addha_za32.c         |  48 ++
+ .../aarch64/sme/acle-asm/addha_za64.c         |  50 ++
+ .../aarch64/sme/acle-asm/addva_za32.c         |  48 ++
+ .../aarch64/sme/acle-asm/addva_za64.c         |  50 ++
+ .../aarch64/sme/acle-asm/arm_has_sme_sc.c     |  25 +
+ .../sme/acle-asm/arm_in_streaming_mode_ns.c   |  11 +
+ .../sme/acle-asm/arm_in_streaming_mode_s.c    |  11 +
+ .../sme/acle-asm/arm_in_streaming_mode_sc.c   |  26 ++
+ .../gcc.target/aarch64/sme/acle-asm/cntsb_s.c | 310 +++++++++++++
+ .../aarch64/sme/acle-asm/cntsb_sc.c           |  12 +
+ .../gcc.target/aarch64/sme/acle-asm/cntsd_s.c | 277 +++++++++++
+ .../aarch64/sme/acle-asm/cntsd_sc.c           |  13 +
+ .../gcc.target/aarch64/sme/acle-asm/cntsh_s.c | 279 +++++++++++
+ .../aarch64/sme/acle-asm/cntsh_sc.c           |  13 +
+ .../gcc.target/aarch64/sme/acle-asm/cntsw_s.c | 278 +++++++++++
+ .../aarch64/sme/acle-asm/cntsw_sc.c           |  13 +
+ .../aarch64/sme/acle-asm/ld1_hor_vnum_za128.c |  77 ++++
+ .../aarch64/sme/acle-asm/ld1_hor_vnum_za16.c  | 123 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_vnum_za32.c  | 123 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_vnum_za64.c  | 112 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_vnum_za8.c   | 112 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_za128.c      |  83 ++++
+ .../aarch64/sme/acle-asm/ld1_hor_za16.c       | 126 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_za32.c       | 125 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_za64.c       | 105 +++++
+ .../aarch64/sme/acle-asm/ld1_hor_za8.c        |  95 ++++
+ .../aarch64/sme/acle-asm/ld1_ver_vnum_za128.c |  77 ++++
+ .../aarch64/sme/acle-asm/ld1_ver_vnum_za16.c  | 123 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_vnum_za32.c  | 123 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_vnum_za64.c  | 112 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_vnum_za8.c   | 112 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_za128.c      |  83 ++++
+ .../aarch64/sme/acle-asm/ld1_ver_za16.c       | 126 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_za32.c       | 125 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_za64.c       | 105 +++++
+ .../aarch64/sme/acle-asm/ld1_ver_za8.c        |  95 ++++
+ .../aarch64/sme/acle-asm/ldr_vnum_za_s.c      | 147 ++++++
+ .../aarch64/sme/acle-asm/ldr_vnum_za_sc.c     | 148 ++++++
+ .../aarch64/sme/acle-asm/ldr_za_s.c           | 124 +++++
+ .../aarch64/sme/acle-asm/ldr_za_sc.c          |  71 +++
+ .../aarch64/sme/acle-asm/mopa_za32.c          | 102 ++++
+ .../aarch64/sme/acle-asm/mopa_za64.c          |  70 +++
+ .../aarch64/sme/acle-asm/mops_za32.c          | 102 ++++
+ .../aarch64/sme/acle-asm/mops_za64.c          |  70 +++
+ .../aarch64/sme/acle-asm/read_hor_za128.c     | 435 ++++++++++++++++++
+ .../aarch64/sme/acle-asm/read_hor_za16.c      | 207 +++++++++
+ .../aarch64/sme/acle-asm/read_hor_za32.c      | 196 ++++++++
+ .../aarch64/sme/acle-asm/read_hor_za64.c      | 186 ++++++++
+ .../aarch64/sme/acle-asm/read_hor_za8.c       | 125 +++++
+ .../aarch64/sme/acle-asm/read_ver_za128.c     | 435 ++++++++++++++++++
+ .../aarch64/sme/acle-asm/read_ver_za16.c      | 207 +++++++++
+ .../aarch64/sme/acle-asm/read_ver_za32.c      | 196 ++++++++
+ .../aarch64/sme/acle-asm/read_ver_za64.c      | 186 ++++++++
+ .../aarch64/sme/acle-asm/read_ver_za8.c       | 125 +++++
+ .../aarch64/sme/acle-asm/st1_hor_vnum_za128.c |  77 ++++
+ .../aarch64/sme/acle-asm/st1_hor_vnum_za16.c  | 123 +++++
+ .../aarch64/sme/acle-asm/st1_hor_vnum_za32.c  | 123 +++++
+ .../aarch64/sme/acle-asm/st1_hor_vnum_za64.c  | 112 +++++
+ .../aarch64/sme/acle-asm/st1_hor_vnum_za8.c   | 112 +++++
+ .../aarch64/sme/acle-asm/st1_hor_za128.c      |  83 ++++
+ .../aarch64/sme/acle-asm/st1_hor_za16.c       | 126 +++++
+ .../aarch64/sme/acle-asm/st1_hor_za32.c       | 125 +++++
+ .../aarch64/sme/acle-asm/st1_hor_za64.c       | 105 +++++
+ .../aarch64/sme/acle-asm/st1_hor_za8.c        |  95 ++++
+ .../aarch64/sme/acle-asm/st1_ver_vnum_za128.c |  77 ++++
+ .../aarch64/sme/acle-asm/st1_ver_vnum_za16.c  | 123 +++++
+ .../aarch64/sme/acle-asm/st1_ver_vnum_za32.c  | 123 +++++
+ .../aarch64/sme/acle-asm/st1_ver_vnum_za64.c  | 112 +++++
+ .../aarch64/sme/acle-asm/st1_ver_vnum_za8.c   | 112 +++++
+ .../aarch64/sme/acle-asm/st1_ver_za128.c      |  83 ++++
+ .../aarch64/sme/acle-asm/st1_ver_za16.c       | 126 +++++
+ .../aarch64/sme/acle-asm/st1_ver_za32.c       | 125 +++++
+ .../aarch64/sme/acle-asm/st1_ver_za64.c       | 105 +++++
+ .../aarch64/sme/acle-asm/st1_ver_za8.c        |  95 ++++
+ .../aarch64/sme/acle-asm/str_vnum_za_s.c      | 147 ++++++
+ .../aarch64/sme/acle-asm/str_vnum_za_sc.c     | 148 ++++++
+ .../aarch64/sme/acle-asm/str_za_s.c           | 124 +++++
+ .../aarch64/sme/acle-asm/str_za_sc.c          |  71 +++
+ .../aarch64/sme/acle-asm/sumopa_za32.c        |  30 ++
+ .../aarch64/sme/acle-asm/sumopa_za64.c        |  32 ++
+ .../aarch64/sme/acle-asm/sumops_za32.c        |  30 ++
+ .../aarch64/sme/acle-asm/sumops_za64.c        |  32 ++
+ .../aarch64/sme/acle-asm/test_sme_acle.h      |  62 +++
+ .../aarch64/sme/acle-asm/undef_za.c           |  33 ++
+ .../aarch64/sme/acle-asm/usmopa_za32.c        |  30 ++
+ .../aarch64/sme/acle-asm/usmopa_za64.c        |  32 ++
+ .../aarch64/sme/acle-asm/usmops_za32.c        |  30 ++
+ .../aarch64/sme/acle-asm/usmops_za64.c        |  32 ++
+ .../aarch64/sme/acle-asm/write_hor_za128.c    | 193 ++++++++
+ .../aarch64/sme/acle-asm/write_hor_za16.c     | 133 ++++++
+ .../aarch64/sme/acle-asm/write_hor_za32.c     | 143 ++++++
+ .../aarch64/sme/acle-asm/write_hor_za64.c     | 133 ++++++
+ .../aarch64/sme/acle-asm/write_hor_za8.c      |  93 ++++
+ .../aarch64/sme/acle-asm/write_ver_za128.c    | 193 ++++++++
+ .../aarch64/sme/acle-asm/write_ver_za16.c     | 133 ++++++
+ .../aarch64/sme/acle-asm/write_ver_za32.c     | 143 ++++++
+ .../aarch64/sme/acle-asm/write_ver_za64.c     | 133 ++++++
+ .../aarch64/sme/acle-asm/write_ver_za8.c      |  93 ++++
+ .../aarch64/sme/acle-asm/zero_mask_za.c       | 130 ++++++
+ .../gcc.target/aarch64/sme/acle-asm/zero_za.c |  11 +
+ .../aarch64/sve/acle/asm/test_sve_acle.h      |  14 +-
+ .../sve/acle/general-c/binary_za_int_m_1.c    |  50 ++
+ .../sve/acle/general-c/binary_za_m_1.c        |  49 ++
+ .../sve/acle/general-c/binary_za_m_2.c        |  11 +
+ .../sve/acle/general-c/binary_za_uint_m_1.c   |  50 ++
+ .../aarch64/sve/acle/general-c/func_redef_4.c |   3 +-
+ .../aarch64/sve/acle/general-c/func_redef_5.c |   1 +
+ .../aarch64/sve/acle/general-c/read_za_m_1.c  |  48 ++
+ .../aarch64/sve/acle/general-c/unary_za_m_1.c |  49 ++
+ .../aarch64/sve/acle/general-c/write_za_m_1.c |  48 ++
+ gcc/testsuite/lib/target-supports.exp         |   3 +-
+ 140 files changed, 13816 insertions(+), 78 deletions(-)
+ create mode 100644 gcc/config/aarch64/aarch64-sve-builtins-sme.cc
+ create mode 100644 gcc/config/aarch64/aarch64-sve-builtins-sme.def
+ create mode 100644 gcc/config/aarch64/aarch64-sve-builtins-sme.h
+ create mode 100644 gcc/config/aarch64/arm_sme.h
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/aarch64-sme-acle-asm.exp
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_has_sme_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_ns.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_s.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_sc.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/test_sme_acle.h
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/undef_za.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za128.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za16.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za32.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za64.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_mask_za.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_za.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_int_m_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_uint_m_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/read_za_m_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_za_m_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/write_za_m_1.c
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index da66603cd..19b21a280 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -325,11 +325,11 @@ m32c*-*-*)
+         ;;
+ aarch64*-*-*)
+ 	cpu_type=aarch64
+-	extra_headers="arm_fp16.h arm_neon.h arm_bf16.h arm_acle.h arm_sve.h"
++	extra_headers="arm_fp16.h arm_neon.h arm_bf16.h arm_acle.h arm_sve.h arm_sme.h"
+ 	c_target_objs="aarch64-c.o"
+ 	cxx_target_objs="aarch64-c.o"
+ 	d_target_objs="aarch64-d.o"
+-	extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o aarch64-cc-fusion.o"
++	extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o aarch64-sve-builtins-sme.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o aarch64-cc-fusion.o"
+ 	target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.cc \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
+ 	target_has_targetm_common=yes
+ 	;;
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 76c20848f..cb8a6c2fc 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -250,6 +250,10 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ 			"__ARM_FEATURE_LS64", pfile);
+   aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile);
+ 
++  aarch64_def_or_undef (TARGET_SME, "__ARM_FEATURE_SME", pfile);
++  aarch64_def_or_undef (TARGET_SME_I16I64, "__ARM_FEATURE_SME_I16I64", pfile);
++  aarch64_def_or_undef (TARGET_SME_F64F64, "__ARM_FEATURE_SME_F64F64", pfile);
++
+   /* Not for ACLE, but required to keep "float.h" correct if we switch
+      target between implementations that do or do not support ARMv8.2-A
+      16-bit floating-point extensions.  */
+@@ -347,6 +351,8 @@ aarch64_pragma_aarch64 (cpp_reader *)
+   const char *name = TREE_STRING_POINTER (x);
+   if (strcmp (name, "arm_sve.h") == 0)
+     aarch64_sve::handle_arm_sve_h ();
++  else if (strcmp (name, "arm_sme.h") == 0)
++    aarch64_sve::handle_arm_sme_h ();
+   else if (strcmp (name, "arm_neon.h") == 0)
+     handle_arm_neon_h ();
+   else if (strcmp (name, "arm_acle.h") == 0)
+diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
+index faee64a79..98854dbce 100644
+--- a/gcc/config/aarch64/aarch64-option-extensions.def
++++ b/gcc/config/aarch64/aarch64-option-extensions.def
+@@ -151,4 +151,8 @@ AARCH64_OPT_EXTENSION("mops", MOPS, (), (), (), "")
+ 
+ AARCH64_OPT_EXTENSION("sme", SME, (BF16, SVE2), (), (), "sme")
+ 
++AARCH64_OPT_EXTENSION("sme-i16i64", SME_I16I64, (SME), (), (), "")
++
++AARCH64_OPT_EXTENSION("sme-f64f64", SME_F64F64, (SME), (), (), "")
++
+ #undef AARCH64_OPT_EXTENSION
+diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
+index 0883ddd1a..81900fa83 100644
+--- a/gcc/config/aarch64/aarch64-protos.h
++++ b/gcc/config/aarch64/aarch64-protos.h
+@@ -809,7 +809,11 @@ bool aarch64_sve_vector_inc_dec_immediate_p (rtx);
+ int aarch64_add_offset_temporaries (rtx);
+ void aarch64_split_add_offset (scalar_int_mode, rtx, rtx, rtx, rtx, rtx);
+ bool aarch64_rdsvl_immediate_p (const_rtx);
++rtx aarch64_sme_vq_immediate (machine_mode mode, HOST_WIDE_INT,
++			      aarch64_feature_flags);
+ char *aarch64_output_rdsvl (const_rtx);
++bool aarch64_addsvl_addspl_immediate_p (const_rtx);
++char *aarch64_output_addsvl_addspl (rtx);
+ bool aarch64_mov_operand_p (rtx, machine_mode);
+ rtx aarch64_reverse_mask (machine_mode, unsigned int);
+ bool aarch64_offset_7bit_signed_scaled_p (machine_mode, poly_int64);
+@@ -853,6 +857,7 @@ int aarch64_movk_shift (const wide_int_ref &, const wide_int_ref &);
+ bool aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT);
+ bool aarch64_use_return_insn_p (void);
+ const char *aarch64_output_casesi (rtx *);
++const char *aarch64_output_sme_zero_za (rtx);
+ 
+ arm_pcs aarch64_tlsdesc_abi_id ();
+ enum aarch64_symbol_type aarch64_classify_symbol (rtx, HOST_WIDE_INT);
+@@ -867,7 +872,6 @@ int aarch64_uxt_size (int, HOST_WIDE_INT);
+ int aarch64_vec_fpconst_pow_of_2 (rtx);
+ rtx aarch64_eh_return_handler_rtx (void);
+ rtx aarch64_mask_from_zextract_ops (rtx, rtx);
+-const char *aarch64_output_move_struct (rtx *operands);
+ rtx aarch64_return_addr_rtx (void);
+ rtx aarch64_return_addr (int, rtx);
+ rtx aarch64_simd_gen_const_vector_dup (machine_mode, HOST_WIDE_INT);
+@@ -881,6 +885,7 @@ bool aarch64_sve_ldnf1_operand_p (rtx);
+ bool aarch64_sve_ldr_operand_p (rtx);
+ bool aarch64_sve_prefetch_operand_p (rtx, machine_mode);
+ bool aarch64_sve_struct_memory_operand_p (rtx);
++bool aarch64_sme_ldr_vnum_offset_p (rtx, rtx);
+ rtx aarch64_simd_vect_par_cnst_half (machine_mode, int, bool);
+ rtx aarch64_gen_stepped_int_parallel (unsigned int, int, int);
+ bool aarch64_stepped_int_parallel_p (rtx, int);
+@@ -1000,6 +1005,7 @@ void handle_arm_neon_h (void);
+ namespace aarch64_sve {
+   void init_builtins ();
+   void handle_arm_sve_h ();
++  void handle_arm_sme_h ();
+   tree builtin_decl (unsigned, bool);
+   bool builtin_type_p (const_tree);
+   bool builtin_type_p (const_tree, unsigned int *, unsigned int *);
+diff --git a/gcc/config/aarch64/aarch64-sme.md b/gcc/config/aarch64/aarch64-sme.md
+index d4973098e..da0745f65 100644
+--- a/gcc/config/aarch64/aarch64-sme.md
++++ b/gcc/config/aarch64/aarch64-sme.md
+@@ -24,6 +24,19 @@
+ ;; ---- Test current state
+ ;; ---- PSTATE.SM management
+ ;; ---- PSTATE.ZA management
++;;
++;; == Loads, stores and moves
++;; ---- Single-vector loads
++;; ---- Single-vector stores
++;; ---- Single-vector moves
++;; ---- Zeroing
++;;
++;; == Binary arithmetic
++;; ---- Binary arithmetic on ZA tile
++;;
++;; == Ternary arithmetic
++;; ---- [INT] Sum of outer products
++;; ---- [FP] Sum of outer products
+ 
+ ;; =========================================================================
+ ;; == State management
+@@ -456,3 +469,363 @@
+     DONE;
+   }
+ )
++
++;; =========================================================================
++;; == Loads, stores and moves
++;; =========================================================================
++
++;; -------------------------------------------------------------------------
++;; ---- Single-vector loads
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - LD1
++;; - LDR
++;; -------------------------------------------------------------------------
++
++(define_c_enum "unspec" [
++  UNSPEC_SME_LDR
++])
++
++(define_insn "@aarch64_sme_"
++  [(set (reg:SME_ZA_I ZA_REGNUM)
++	(unspec:SME_ZA_I
++	  [(reg:SME_ZA_I ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand:SI 1 "register_operand" "Ucj")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:SME_ZA_I 3 "aarch64_sve_ldff1_operand" "Utf")]
++	  SME_LD1))]
++  "TARGET_STREAMING_SME"
++  "ld1\t{ za%0.[%w1, 0] }, %2/z, %3"
++)
++
++(define_insn "@aarch64_sme__plus"
++  [(set (reg:SME_ZA_I ZA_REGNUM)
++	(unspec:SME_ZA_I
++	  [(reg:SME_ZA_I ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (plus:SI (match_operand:SI 1 "register_operand" "Ucj")
++		    (match_operand:SI 2 "const_int_operand"))
++	   (match_operand: 3 "register_operand" "Upl")
++	   (match_operand:SME_ZA_I 4 "aarch64_sve_ldff1_operand" "Utf")]
++	  SME_LD1))]
++  "TARGET_STREAMING_SME
++   && UINTVAL (operands[2]) < 128 / "
++  "ld1\t{ za%0.[%w1, %2] }, %3/z, %4"
++)
++
++(define_insn "aarch64_sme_ldr0"
++  [(set (reg:VNx16QI ZA_REGNUM)
++	(unspec:VNx16QI
++	  [(reg:VNx16QI ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:SI 0 "register_operand" "Ucj")
++	   (mem:VNx16QI (match_operand 1 "pmode_register_operand" "rk"))]
++	  UNSPEC_SME_LDR))]
++  "TARGET_SME"
++  "ldr\tza[%w0, 0], [%1, #0, mul vl]"
++)
++
++(define_insn "@aarch64_sme_ldrn"
++  [(set (reg:VNx16QI ZA_REGNUM)
++	(unspec:VNx16QI
++	  [(reg:VNx16QI ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (plus:SI (match_operand:SI 0 "register_operand" "Ucj")
++		    (match_operand:SI 1 "const_int_operand"))
++	   (mem:VNx16QI
++	     (plus:P (match_operand:P 2 "register_operand" "rk")
++		     (match_operand:P 3 "aarch64_mov_operand")))]
++	  UNSPEC_SME_LDR))]
++  "TARGET_SME
++   && aarch64_sme_ldr_vnum_offset_p (operands[1], operands[3])"
++  "ldr\tza[%w0, %1], [%2, #%1, mul vl]"
++)
++
++;; -------------------------------------------------------------------------
++;; ---- Single-vector stores
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - ST1
++;; - STR
++;; -------------------------------------------------------------------------
++
++(define_c_enum "unspec" [
++  UNSPEC_SME_STR
++])
++
++(define_insn "@aarch64_sme_"
++  [(set (match_operand:SME_ZA_I 0 "aarch64_sve_ldff1_operand" "+Utf")
++	(unspec:SME_ZA_I
++	  [(reg:SME_ZA_I ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_dup 0)
++	   (match_operand:DI 1 "const_int_operand")
++	   (match_operand:SI 2 "register_operand" "Ucj")
++	   (match_operand: 3 "register_operand" "Upl")]
++	  SME_ST1))]
++  "TARGET_STREAMING_SME"
++  "st1\t{ za%1.[%w2, 0] }, %3, %0"
++)
++
++(define_insn "@aarch64_sme__plus"
++  [(set (match_operand:SME_ZA_I 0 "aarch64_sve_ldff1_operand" "+Utf")
++	(unspec:SME_ZA_I
++	  [(reg:SME_ZA_I ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_dup 0)
++	   (match_operand:DI 1 "const_int_operand")
++	   (plus:SI (match_operand:SI 2 "register_operand" "Ucj")
++		    (match_operand:SI 3 "const_int_operand"))
++	   (match_operand: 4 "register_operand" "Upl")]
++	  SME_ST1))]
++  "TARGET_STREAMING_SME
++   && UINTVAL (operands[3]) < 128 / "
++  "st1\t{ za%1.[%w2, %3] }, %4, %0"
++)
++
++(define_insn "aarch64_sme_str0"
++  [(set (mem:VNx16QI (match_operand 1 "pmode_register_operand" "rk"))
++	(unspec:VNx16QI
++	  [(reg:VNx16QI ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (mem:VNx16QI (match_dup 1))
++	   (match_operand:SI 0 "register_operand" "Ucj")]
++	  UNSPEC_SME_STR))]
++  "TARGET_SME"
++  "str\tza[%w0, 0], [%1, #0, mul vl]"
++)
++
++(define_insn "@aarch64_sme_strn"
++  [(set (mem:VNx16QI
++	  (plus:P (match_operand:P 2 "register_operand" "rk")
++		  (match_operand:P 3 "aarch64_mov_operand")))
++	(unspec:VNx16QI
++	  [(reg:VNx16QI ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (mem:VNx16QI (plus:P (match_dup 2) (match_dup 3)))
++	   (plus:SI (match_operand:SI 0 "register_operand" "Ucj")
++		    (match_operand:SI 1 "const_int_operand"))]
++	  UNSPEC_SME_STR))]
++  "TARGET_SME
++   && aarch64_sme_ldr_vnum_offset_p (operands[1], operands[3])"
++  "str\tza[%w0, %1], [%2, #%1, mul vl]"
++)
++
++;; -------------------------------------------------------------------------
++;; ---- Single-vector moves
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - MOVA
++;; -------------------------------------------------------------------------
++
++(define_insn "@aarch64_sme_"
++  [(set (match_operand:SVE_FULL 0 "register_operand" "=w")
++	(unspec:SVE_FULL
++	  [(reg: ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:SVE_FULL 1 "register_operand" "0")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:DI 3 "const_int_operand")
++	   (match_operand:SI 4 "register_operand" "Ucj")]
++	  SME_READ))]
++  "TARGET_STREAMING_SME"
++  "mova\t%0., %2/m, za%3.[%w4, 0]"
++)
++
++(define_insn "*aarch64_sme__plus"
++  [(set (match_operand:SVE_FULL 0 "register_operand" "=w")
++	(unspec:SVE_FULL
++	  [(reg: ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:SVE_FULL 1 "register_operand" "0")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:DI 3 "const_int_operand")
++	   (plus:SI (match_operand:SI 4 "register_operand" "Ucj")
++		    (match_operand:SI 5 "const_int_operand"))]
++	  SME_READ))]
++  "TARGET_STREAMING_SME
++   && UINTVAL (operands[5]) < 128 / "
++  "mova\t%0., %2/m, za%3.[%w4, %5]"
++)
++
++(define_insn "@aarch64_sme_"
++  [(set (match_operand:SVE_FULL 0 "register_operand" "=w")
++	(unspec:SVE_FULL
++	  [(reg:VNx1TI_ONLY ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:SVE_FULL 1 "register_operand" "0")
++	   (match_operand:VNx2BI 2 "register_operand" "Upl")
++	   (match_operand:DI 3 "const_int_operand")
++	   (match_operand:SI 4 "register_operand" "Ucj")]
++	  SME_READ))]
++  "TARGET_STREAMING_SME"
++  "mova\t%0.q, %2/m, za%3.q[%w4, 0]"
++)
++
++(define_insn "@aarch64_sme_"
++  [(set (reg: ZA_REGNUM)
++	(unspec:
++	  [(reg:SVE_FULL ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand:SI 1 "register_operand" "Ucj")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:SVE_FULL 3 "register_operand" "w")]
++	  SME_WRITE))]
++  "TARGET_STREAMING_SME"
++  "mova\tza%0.[%w1, 0], %2/m, %3."
++)
++
++(define_insn "*aarch64_sme__plus"
++  [(set (reg: ZA_REGNUM)
++	(unspec:
++	  [(reg:SVE_FULL ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (plus:SI (match_operand:SI 1 "register_operand" "Ucj")
++		    (match_operand:SI 2 "const_int_operand"))
++	   (match_operand: 3 "register_operand" "Upl")
++	   (match_operand:SVE_FULL 4 "register_operand" "w")]
++	  SME_WRITE))]
++  "TARGET_STREAMING_SME
++   && UINTVAL (operands[2]) < 128 / "
++  "mova\tza%0.[%w1, %2], %3/m, %4."
++)
++
++(define_insn "@aarch64_sme_"
++  [(set (reg:VNx1TI_ONLY ZA_REGNUM)
++	(unspec:VNx1TI_ONLY
++	  [(reg:VNx1TI_ONLY ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand:SI 1 "register_operand" "Ucj")
++	   (match_operand:VNx2BI 2 "register_operand" "Upl")
++	   (match_operand:SVE_FULL 3 "register_operand" "w")]
++	  SME_WRITE))]
++  "TARGET_STREAMING_SME"
++  "mova\tza%0.q[%w1, 0], %2/m, %3.q"
++)
++
++;; -------------------------------------------------------------------------
++;; ---- Zeroing
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - ZERO
++;; -------------------------------------------------------------------------
++
++(define_c_enum "unspec" [UNSPEC_SME_ZERO])
++
++(define_insn "aarch64_sme_zero_za"
++  [(set (reg:VNx16QI ZA_REGNUM)
++	(unspec:VNx16QI [(reg:VNx16QI ZA_REGNUM)
++			 (reg:DI SME_STATE_REGNUM)
++			 (match_operand:DI 0 "const_int_operand")]
++			UNSPEC_SME_ZERO))]
++  "TARGET_SME"
++  {
++    return aarch64_output_sme_zero_za (operands[0]);
++  }
++)
++
++;; =========================================================================
++;; == Binary arithmetic
++;; =========================================================================
++
++;; -------------------------------------------------------------------------
++;; ---- Binary arithmetic on ZA tile
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - ADDHA
++;; - ADDVA
++;; -------------------------------------------------------------------------
++
++(define_insn "@aarch64_sme_"
++  [(set (reg:SME_ZA_SDI ZA_REGNUM)
++	(unspec:SME_ZA_SDI
++	  [(reg:SME_ZA_SDI ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand: 1 "register_operand" "Upl")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:SME_ZA_SDI 3 "register_operand" "w")]
++	  SME_BINARY_SDI))]
++  "TARGET_STREAMING_SME"
++  "\tza%0., %1/m, %2/m, %3."
++)
++
++;; =========================================================================
++;; == Ternary arithmetic
++;; =========================================================================
++
++;; -------------------------------------------------------------------------
++;; ---- [INT] Sum of outer products
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - SMOPA
++;; - SMOPS
++;; - SUMOPA
++;; - SUMOPS
++;; - UMOPA
++;; - UMOPS
++;; - USMOPA
++;; - USMOPS
++;; -------------------------------------------------------------------------
++
++(define_insn "@aarch64_sme_"
++  [(set (reg:VNx4SI_ONLY ZA_REGNUM)
++	(unspec:VNx4SI_ONLY
++	  [(reg:VNx4SI_ONLY ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand: 1 "register_operand" "Upl")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:VNx16QI_ONLY 3 "register_operand" "w")
++	   (match_operand:VNx16QI_ONLY 4 "register_operand" "w")]
++	  SME_INT_MOP))]
++  "TARGET_STREAMING_SME"
++  "\tza%0.s, %1/m, %2/m, %3.b, %4.b"
++)
++
++(define_insn "@aarch64_sme_"
++  [(set (reg:VNx2DI_ONLY ZA_REGNUM)
++	(unspec:VNx2DI_ONLY
++	  [(reg:VNx2DI_ONLY ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand: 1 "register_operand" "Upl")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:VNx8HI_ONLY 3 "register_operand" "w")
++	   (match_operand:VNx8HI_ONLY 4 "register_operand" "w")]
++	  SME_INT_MOP))]
++  "TARGET_STREAMING_SME && TARGET_SME_I16I64"
++  "\tza%0.d, %1/m, %2/m, %3.h, %4.h"
++)
++
++;; -------------------------------------------------------------------------
++;; ---- [FP] Sum of outer products
++;; -------------------------------------------------------------------------
++;; Includes:
++;; - BFMOPA
++;; - BFMOPS
++;; - FMOPA
++;; - FMOPS
++;; -------------------------------------------------------------------------
++
++(define_insn "@aarch64_sme_"
++  [(set (reg:SME_ZA_SDF_I ZA_REGNUM)
++	(unspec:SME_ZA_SDF_I
++	  [(reg:SME_ZA_SDF_I ZA_REGNUM)
++	   (reg:DI SME_STATE_REGNUM)
++	   (match_operand:DI 0 "const_int_operand")
++	   (match_operand: 1 "register_operand" "Upl")
++	   (match_operand: 2 "register_operand" "Upl")
++	   (match_operand:SME_MOP_HSDF 3 "register_operand" "w")
++	   (match_operand:SME_MOP_HSDF 4 "register_operand" "w")]
++	  SME_FP_MOP))]
++  "TARGET_STREAMING_SME
++   && ( == 32) == ( <= 32)"
++  "\tza%0., %1/m, %2/m, %3., %4."
++)
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+index f5fa4030c..9dfce5c0e 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+@@ -50,6 +50,27 @@ public:
+   }
+ };
+ 
++/* Wrap T, which is derived from function_base, and indicate that it
++   additionally has the call properties in PROPERTIES.  */
++template
++class add_call_properties : public T
++{
++public:
++  using T::T;
++
++  unsigned int
++  call_properties (const function_instance &fi) const override
++  {
++    return T::call_properties (fi) | PROPERTIES;
++  }
++};
++
++template
++using read_write_za = add_call_properties;
++
++template
++using write_za = add_call_properties;
++
+ /* A function_base that sometimes or always operates on tuples of
+    vectors.  */
+ class multi_vector_function : public function_base
+@@ -383,6 +404,49 @@ typedef unspec_based_function_exact_insn
+ typedef unspec_based_function_exact_insn
+   unspec_based_sub_lane_function;
+ 
++/* General SME unspec-based functions, parameterized on the vector mode.  */
++class sme_1mode_function : public read_write_za
++{
++public:
++  using parent = read_write_za;
++
++  CONSTEXPR sme_1mode_function (int unspec_for_sint, int unspec_for_uint,
++				int unspec_for_fp)
++    : parent (unspec_for_sint, unspec_for_uint, unspec_for_fp, 1)
++  {}
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    auto icode = code_for_aarch64_sme (unspec_for (e), e.tuple_mode (1));
++    return e.use_exact_insn (icode);
++  }
++};
++
++/* General SME unspec-based functions, parameterized on both the ZA mode
++   and the vector mode.  */
++template
++class sme_2mode_function_t : public read_write_za
++{
++public:
++  using parent = read_write_za;
++
++  CONSTEXPR sme_2mode_function_t (int unspec_for_sint, int unspec_for_uint,
++				  int unspec_for_fp)
++    : parent (unspec_for_sint, unspec_for_uint, unspec_for_fp, 1)
++  {}
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    insn_code icode = CODE (unspec_for (e), e.vector_mode (0),
++			    e.tuple_mode (1));
++    return e.use_exact_insn (icode);
++  }
++};
++
++using sme_2mode_function = sme_2mode_function_t;
++
+ /* A function that acts like unspec_based_function_exact_insn
+    when operating on integers, but that expands to an (fma ...)-style
+    aarch64_sve* operation when applied to floats.  */
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index c536949ba..bdde849c8 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -59,7 +59,10 @@ static void
+ apply_predication (const function_instance &instance, tree return_type,
+ 		   vec &argument_types)
+ {
+-  if (instance.pred != PRED_none)
++  /* There are currently no SME ZA instructions that have both merging and
++     unpredicated forms, so for simplicity, the predicates are always included
++     in the original format string.  */
++  if (instance.pred != PRED_none && instance.pred != PRED_za_m)
+     {
+       argument_types.quick_insert (0, get_svbool_t ());
+       /* For unary merge operations, the first argument is a vector with
+@@ -589,6 +592,33 @@ struct binary_imm_long_base : public overloaded_base<0>
+   }
+ };
+ 
++/* Base class for binary_za_m and similar shapes.  */
++template
++struct binary_za_m_base : public overloaded_base<1>
++{
++  tree
++  resolve (function_resolver &r) const override
++  {
++    type_suffix_index type;
++    if (!r.check_num_arguments (5)
++	|| !r.require_integer_immediate (0)
++	|| !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
++	|| !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
++	|| (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES
++	|| !r.require_derived_vector_type (4, 3, type, TCLASS, BITS))
++      return error_mark_node;
++
++    return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
++  }
++};
++
+ /* Base class for inc_dec and inc_dec_pat.  */
+ struct inc_dec_base : public overloaded_base<0>
+ {
+@@ -1576,6 +1606,68 @@ struct binary_wide_opt_n_def : public overloaded_base<0>
+ };
+ SHAPE (binary_wide_opt_n)
+ 
++/* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, svx_t,
++			svx_t)
++
++   where the first argument is a ZA tile.  */
++struct binary_za_int_m_def : public binary_za_m_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    build_all (b, "_,su64,vp,vp,t1,ts1", group, MODE_none);
++  }
++};
++SHAPE (binary_za_int_m)
++
++/* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, svx_t,
++			svx_t)
++
++   where the first argument is a ZA tile.  */
++struct binary_za_m_def : public binary_za_m_base<>
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    /* Allow the overloaded form to be specified seperately, with just
++       a single suffix.  This is necessary for the 64-bit SME MOP intrinsics,
++       which have some forms dependent on FEAT_SME_I16I64 and some forms
++       dependent on FEAT_SME_F64F64.  The resolver needs to be defined
++       for base SME.  */
++    if (group.types[0][1] != NUM_TYPE_SUFFIXES)
++      build_all (b, "_,su64,vp,vp,t1,t1", group, MODE_none);
++  }
++};
++SHAPE (binary_za_m)
++
++/* void svfoo_t0[_t1]_g(uint64_t, svbool_t, svbool_t, svx_t,
++			svx_t)
++
++   where the first argument is a ZA tile.  */
++struct binary_za_uint_m_def : public binary_za_m_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    build_all (b, "_,su64,vp,vp,t1,tu1", group, MODE_none);
++  }
++};
++SHAPE (binary_za_uint_m)
++
++/* bool svfoo().  */
++struct bool_inherent_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "sp", group, MODE_none);
++  }
++};
++SHAPE (bool_inherent)
++
+ /* sv_t svfoo[_t0](sv_t, sv_t)
+    _t svfoo[_n_t0](_t, sv_t).  */
+ struct clast_def : public overloaded_base<0>
+@@ -2055,6 +2147,51 @@ struct inherent_b_def : public overloaded_base<0>
+ };
+ SHAPE (inherent_b)
+ 
++/* void svfoo_t0().  */
++struct inherent_za_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "_", group, MODE_none);
++  }
++};
++SHAPE (inherent_za)
++
++/* void svfoo_t0(uint64_t)
++
++   where the argument is an integer constant that specifies an 8-bit mask.  */
++struct inherent_mask_za_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "_,su64", group, MODE_none);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    return c.require_immediate_range (0, 0, 255);
++  }
++};
++SHAPE (inherent_mask_za)
++
++/* void svfoo_t0(uint32_t, const void *)
++   void svfoo_vnum_t0(uint32_t, const void *, int64_t)
++
++   where the first argument is a variable ZA slice.  */
++struct ldr_za_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "_,su32,al", group, MODE_none);
++    build_all (b, "_,su32,al,ss64", group, MODE_vnum);
++  }
++};
++SHAPE (ldr_za)
++
+ /* sv[xN]_t svfoo[_t0](const _t *)
+    sv[xN]_t svfoo_vnum[_t0](const _t *, int64_t).  */
+ struct load_def : public load_contiguous_base
+@@ -2265,6 +2402,27 @@ struct load_replicate_def : public load_contiguous_base
+ };
+ SHAPE (load_replicate)
+ 
++/* void svfoo_t0(uint64_t, uint32_t, svbool_t, const void *)
++   void svfoo_vnum_t0(uint64_t, uint32_t, svbool_t, const void *, int64_t)
++
++   where the first two fields form a (ZA tile, slice) pair.  */
++struct load_za_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "_,su64,su32,vp,al", group, MODE_none);
++    build_all (b, "_,su64,su32,vp,al,ss64", group, MODE_vnum);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
++  }
++};
++SHAPE (load_za)
++
+ /* svbool_t svfoo(enum svpattern).  */
+ struct pattern_pred_def : public nonoverloaded_base
+ {
+@@ -2359,6 +2517,48 @@ struct rdffr_def : public nonoverloaded_base
+ };
+ SHAPE (rdffr)
+ 
++/* sv_t svfoo_t0[_t1](uint64_t, uint32_t)
++
++   where the first two fields form a (ZA tile, slice) pair.  */
++struct read_za_m_def : public overloaded_base<1>
++{
++  bool
++  has_merge_argument_p (const function_instance &, unsigned int) const override
++  {
++    return true;
++  }
++
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    build_all (b, "t1,su64,su32", group, MODE_none);
++  }
++
++  tree
++  resolve (function_resolver &r) const override
++  {
++    gcc_assert (r.pred == PRED_m);
++    type_suffix_index type;
++    if (!r.check_num_arguments (4)
++	|| (type = r.infer_vector_type (0)) == NUM_TYPE_SUFFIXES
++	|| !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
++	|| !r.require_integer_immediate (2)
++	|| !r.require_scalar_type (3, "uint32_t"))
++      return error_mark_node;
++
++    return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    gcc_assert (c.pred == PRED_m);
++    return c.require_immediate_range (1, 0, c.num_za_tiles () - 1);
++  }
++};
++SHAPE (read_za_m)
++
+ /* _t svfoo[_t0](sv_t).  */
+ struct reduction_def : public overloaded_base<0>
+ {
+@@ -2727,6 +2927,42 @@ struct store_scatter_offset_restricted_def : public store_scatter_base
+ };
+ SHAPE (store_scatter_offset_restricted)
+ 
++/* void svfoo_t0(uint64_t, uint32_t, svbool_t, void *)
++   void svfoo_vnum_t0(uint64_t, uint32_t, svbool_t, void *, int64_t)
++
++   where the first two fields form a (ZA tile, slice) pair.  */
++struct store_za_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "_,su64,su32,vp,as", group, MODE_none);
++    build_all (b, "_,su64,su32,vp,as,ss64", group, MODE_vnum);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
++  }
++};
++SHAPE (store_za)
++
++/* void svfoo_t0(uint32_t, void *)
++   void svfoo_vnum_t0(uint32_t, void *, int64_t)
++
++   where the first argument is a variable ZA slice.  */
++struct str_za_def : public nonoverloaded_base
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    build_all (b, "_,su32,as", group, MODE_none);
++    build_all (b, "_,su32,as,ss64", group, MODE_vnum);
++  }
++};
++SHAPE (str_za)
++
+ /* sv_t svfoo[_t0](svxN_t, sv_t).  */
+ struct tbl_tuple_def : public overloaded_base<0>
+ {
+@@ -3487,4 +3723,72 @@ struct unary_widen_def : public overloaded_base<0>
+ };
+ SHAPE (unary_widen)
+ 
++/* void svfoo_t0[_t1](uint64_t, svbool_t, svbool_t, sv_t)
++
++   where the first argument is a ZA tile.  */
++struct unary_za_m_def : public overloaded_base<1>
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    build_all (b, "_,su64,vp,vp,t1", group, MODE_none);
++  }
++
++  tree
++  resolve (function_resolver &r) const override
++  {
++    type_suffix_index type;
++    if (!r.check_num_arguments (4)
++	|| !r.require_integer_immediate (0)
++	|| !r.require_vector_type (1, VECTOR_TYPE_svbool_t)
++	|| !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
++	|| (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES)
++      return error_mark_node;
++
++    return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
++  }
++};
++SHAPE (unary_za_m)
++
++/* void svfoo_t0[_t1](uint64_t, uint32_t, svbool_t, sv_t)
++
++   where the first two fields form a (ZA tile, slice) pair.  */
++struct write_za_m_def : public overloaded_base<1>
++{
++  void
++  build (function_builder &b, const function_group_info &group) const override
++  {
++    b.add_overloaded_functions (group, MODE_none);
++    build_all (b, "_,su64,su32,vp,t1", group, MODE_none);
++  }
++
++  tree
++  resolve (function_resolver &r) const override
++  {
++    type_suffix_index type;
++    if (!r.check_num_arguments (4)
++	|| !r.require_integer_immediate (0)
++	|| !r.require_scalar_type (1, "uint32_t")
++	|| !r.require_vector_type (2, VECTOR_TYPE_svbool_t)
++	|| (type = r.infer_vector_type (3)) == NUM_TYPE_SUFFIXES)
++      return error_mark_node;
++
++    return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
++  }
++
++  bool
++  check (function_checker &c) const override
++  {
++    return c.require_immediate_range (0, 0, c.num_za_tiles () - 1);
++  }
++};
++SHAPE (write_za_m)
++
+ }
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
+index 2b06152d4..9c1f44bdc 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
+@@ -93,6 +93,10 @@ namespace aarch64_sve
+     extern const function_shape *const binary_uint64_opt_n;
+     extern const function_shape *const binary_wide;
+     extern const function_shape *const binary_wide_opt_n;
++    extern const function_shape *const binary_za_int_m;
++    extern const function_shape *const binary_za_m;
++    extern const function_shape *const binary_za_uint_m;
++    extern const function_shape *const bool_inherent;
+     extern const function_shape *const clast;
+     extern const function_shape *const compare;
+     extern const function_shape *const compare_opt_n;
+@@ -114,6 +118,9 @@ namespace aarch64_sve
+     extern const function_shape *const inc_dec_pred_scalar;
+     extern const function_shape *const inherent;
+     extern const function_shape *const inherent_b;
++    extern const function_shape *const inherent_za;
++    extern const function_shape *const inherent_mask_za;
++    extern const function_shape *const ldr_za;
+     extern const function_shape *const load;
+     extern const function_shape *const load_ext;
+     extern const function_shape *const load_ext_gather_index;
+@@ -124,6 +131,7 @@ namespace aarch64_sve
+     extern const function_shape *const load_gather_sv_restricted;
+     extern const function_shape *const load_gather_vs;
+     extern const function_shape *const load_replicate;
++    extern const function_shape *const load_za;
+     extern const function_shape *const mmla;
+     extern const function_shape *const pattern_pred;
+     extern const function_shape *const prefetch;
+@@ -131,6 +139,7 @@ namespace aarch64_sve
+     extern const function_shape *const prefetch_gather_offset;
+     extern const function_shape *const ptest;
+     extern const function_shape *const rdffr;
++    extern const function_shape *const read_za_m;
+     extern const function_shape *const reduction;
+     extern const function_shape *const reduction_wide;
+     extern const function_shape *const reinterpret;
+@@ -148,6 +157,8 @@ namespace aarch64_sve
+     extern const function_shape *const store_scatter_index_restricted;
+     extern const function_shape *const store_scatter_offset;
+     extern const function_shape *const store_scatter_offset_restricted;
++    extern const function_shape *const store_za;
++    extern const function_shape *const str_za;
+     extern const function_shape *const tbl_tuple;
+     extern const function_shape *const ternary_bfloat;
+     extern const function_shape *const ternary_bfloat_lane;
+@@ -186,6 +197,8 @@ namespace aarch64_sve
+     extern const function_shape *const unary_to_uint;
+     extern const function_shape *const unary_uint;
+     extern const function_shape *const unary_widen;
++    extern const function_shape *const unary_za_m;
++    extern const function_shape *const write_za_m;
+   }
+ }
+ 
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sme.cc b/gcc/config/aarch64/aarch64-sve-builtins-sme.cc
+new file mode 100644
+index 000000000..e1df6ce0d
+--- /dev/null
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sme.cc
+@@ -0,0 +1,412 @@
++/* ACLE support for AArch64 SME.
++   Copyright (C) 2023 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
++   .  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "tree.h"
++#include "rtl.h"
++#include "tm_p.h"
++#include "memmodel.h"
++#include "insn-codes.h"
++#include "optabs.h"
++#include "recog.h"
++#include "expr.h"
++#include "basic-block.h"
++#include "function.h"
++#include "fold-const.h"
++#include "gimple.h"
++#include "gimple-iterator.h"
++#include "gimplify.h"
++#include "explow.h"
++#include "emit-rtl.h"
++#include "aarch64-sve-builtins.h"
++#include "aarch64-sve-builtins-shapes.h"
++#include "aarch64-sve-builtins-base.h"
++#include "aarch64-sve-builtins-sme.h"
++#include "aarch64-sve-builtins-functions.h"
++
++using namespace aarch64_sve;
++
++namespace {
++
++class load_store_za_base : public function_base
++{
++public:
++  tree
++  memory_scalar_type (const function_instance &) const override
++  {
++    return void_type_node;
++  }
++};
++
++class read_write_za_base : public function_base
++{
++public:
++  constexpr read_write_za_base (int unspec) : m_unspec (unspec) {}
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    auto za_mode = e.vector_mode (0);
++    auto z_mode = e.vector_mode (1);
++    auto icode = (za_mode == VNx1TImode
++		  ? code_for_aarch64_sme (m_unspec, za_mode, z_mode)
++		  : code_for_aarch64_sme (m_unspec, z_mode, z_mode));
++    return e.use_exact_insn (icode);
++  }
++
++  int m_unspec;
++};
++
++using load_za_base = add_call_properties;
++
++using store_za_base = add_call_properties;
++
++/* E is a load or store intrinsic that accesses a ZA slice of mode MEM_MODE.
++   The intrinsic has a vnum parameter at index ARGNO.  Return true if the
++   vnum argument is a constant that is a valid ZA offset for the underlying
++   instruction.  */
++
++static bool
++has_in_range_vnum_arg (function_expander &e, machine_mode mem_mode,
++		       unsigned int argno)
++{
++  return (e.mode_suffix_id == MODE_vnum
++	  && CONST_INT_P (e.args[argno])
++	  && UINTVAL (e.args[argno]) < 16 / GET_MODE_UNIT_SIZE (mem_mode));
++}
++
++/* E is a ZA load or store intrinsic that uses instruction ICODE.  Add a
++   32-bit operand that gives the total ZA slice.  (The instruction hard-codes
++   the constant offset to 0, so there is no operand for that.)
++
++   Argument ARGNO is the intrinsic's slice argument.  If the intrinsic is
++   a _vnum intrinsic, argument VNUM_ARGNO is the intrinsic's vnum operand,
++   which must be added to the slice argument.  */
++
++static void
++add_load_store_slice_operand (function_expander &e, insn_code icode,
++			      unsigned int argno, unsigned int vnum_argno)
++{
++  rtx base = e.args[argno];
++  if (e.mode_suffix_id == MODE_vnum)
++    {
++      rtx vnum = lowpart_subreg (SImode, e.args[vnum_argno], DImode);
++      base = simplify_gen_binary (PLUS, SImode, base, vnum);
++    }
++  e.add_input_operand (icode, base);
++}
++
++/* Add a memory operand for ZA LD1 or ST1 intrinsic E.  BASE_ARGNO is
++   the index of the base argument.  */
++
++static void
++add_load_store_operand (function_expander &e, unsigned int base_argno)
++{
++  auto mode = e.vector_mode (0);
++  rtx base = e.get_contiguous_base (mode, base_argno, base_argno + 1,
++				    AARCH64_FL_SM_ON);
++  auto mem = gen_rtx_MEM (mode, force_reg (Pmode, base));
++  set_mem_align (mem, BITS_PER_UNIT);
++  e.add_fixed_operand (mem);
++}
++
++/* Expand ZA LDR or STR intrinsic E.  There are two underlying instructions:
++
++   - BASE_CODE has a zero ZA slice offset
++   - VNUM_CODE has a constant operand for the ZA slice offset.  */
++
++static rtx
++expand_ldr_str_za (function_expander &e, insn_code base_code,
++		   insn_code vnum_code)
++{
++  if (has_in_range_vnum_arg (e, VNx16QImode, 2))
++    {
++      rtx mem_offset = aarch64_sme_vq_immediate (Pmode,
++						 UINTVAL (e.args[2]) * 16,
++						 AARCH64_ISA_MODE);
++      e.add_input_operand (vnum_code, e.args[0]);
++      e.add_input_operand (vnum_code, e.args[2]);
++      e.add_input_operand (vnum_code, e.args[1]);
++      e.add_input_operand (vnum_code, mem_offset);
++      return e.generate_insn (vnum_code);
++    }
++  else
++    {
++      rtx base = e.get_contiguous_base (VNx16QImode, 1, 2, AARCH64_FL_SM_ON);
++      add_load_store_slice_operand (e, base_code, 0, 2);
++      e.add_input_operand (base_code, base);
++      return e.generate_insn (base_code);
++    }
++}
++
++/* Expand ZA LD1 or ST1 intrinsic E.  UNSPEC is the load or store unspec.
++   IS_LOAD is true if E is a load, false if it is a store.  */
++
++static rtx
++expand_ld1_st1 (function_expander &e, int unspec, bool is_load)
++{
++  bool is_vnum = has_in_range_vnum_arg (e, e.vector_mode (0), 4);
++  auto icode = (is_vnum
++		? code_for_aarch64_sme_plus (unspec, e.vector_mode (0))
++		: code_for_aarch64_sme (unspec, e.vector_mode (0)));
++  if (!is_load)
++    add_load_store_operand (e, 3);
++  e.add_input_operand (icode, e.args[0]);
++  if (is_vnum)
++    {
++      e.add_input_operand (icode, e.args[1]);
++      e.add_input_operand (icode, e.args[4]);
++    }
++  else
++    add_load_store_slice_operand (e, icode, 1, 4);
++  e.add_input_operand (icode, e.args[2]);
++  if (is_load)
++    add_load_store_operand (e, 3);
++  return e.generate_insn (icode);
++}
++
++class arm_has_sme_impl : public function_base
++{
++  gimple *
++  fold (gimple_folder &f) const override
++  {
++    if (TARGET_SME)
++      return f.fold_to_cstu (1);
++    return nullptr;
++  }
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    if (TARGET_SME)
++      return const1_rtx;
++    emit_insn (gen_aarch64_get_sme_state ());
++    return expand_simple_binop (DImode, LSHIFTRT,
++				gen_rtx_REG (DImode, R0_REGNUM),
++				gen_int_mode (63, QImode),
++				e.possible_target, true, OPTAB_LIB_WIDEN);
++  }
++};
++
++class arm_in_streaming_mode_impl : public function_base
++{
++  gimple *
++  fold (gimple_folder &f) const override
++  {
++    if (TARGET_STREAMING)
++      return f.fold_to_cstu (1);
++    if (TARGET_NON_STREAMING)
++      return f.fold_to_cstu (0);
++    return nullptr;
++  }
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    if (TARGET_STREAMING)
++      return const1_rtx;
++
++    if (TARGET_NON_STREAMING)
++      return const0_rtx;
++
++    rtx reg;
++    if (TARGET_SME)
++      {
++	reg = gen_reg_rtx (DImode);
++	emit_insn (gen_aarch64_read_svcr (reg));
++      }
++    else
++      {
++	emit_insn (gen_aarch64_get_sme_state ());
++	reg = gen_rtx_REG (DImode, R0_REGNUM);
++      }
++    return expand_simple_binop (DImode, AND, reg, gen_int_mode (1, DImode),
++				e.possible_target, true, OPTAB_LIB_WIDEN);
++  }
++};
++
++/* Implements svcnts[bhwd].  */
++class svcnts_bhwd_impl : public function_base
++{
++public:
++  constexpr svcnts_bhwd_impl (machine_mode ref_mode) : m_ref_mode (ref_mode) {}
++
++  unsigned int
++  get_shift () const
++  {
++    return exact_log2 (GET_MODE_UNIT_SIZE (m_ref_mode));
++  }
++
++  gimple *
++  fold (gimple_folder &f) const override
++  {
++    if (TARGET_STREAMING)
++      return f.fold_to_cstu (GET_MODE_NUNITS (m_ref_mode));
++    return nullptr;
++  }
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    rtx cntsb = aarch64_sme_vq_immediate (DImode, 16, AARCH64_ISA_MODE);
++    auto shift = get_shift ();
++    if (!shift)
++      return cntsb;
++
++    return expand_simple_binop (DImode, LSHIFTRT, cntsb,
++				gen_int_mode (shift, QImode),
++				e.possible_target, true, OPTAB_LIB_WIDEN);
++  }
++
++  /* The mode of the vector associated with the [bhwd] suffix.  */
++  machine_mode m_ref_mode;
++};
++
++class svld1_za_impl : public load_za_base
++{
++public:
++  constexpr svld1_za_impl (int unspec) : m_unspec (unspec) {}
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    return expand_ld1_st1 (e, m_unspec, true);
++  }
++
++  int m_unspec;
++};
++
++class svldr_za_impl : public load_za_base
++{
++public:
++  rtx
++  expand (function_expander &e) const override
++  {
++    return expand_ldr_str_za (e, CODE_FOR_aarch64_sme_ldr0,
++			      code_for_aarch64_sme_ldrn (Pmode));
++  }
++};
++
++using svread_za_tile_impl = add_call_properties;
++
++class svst1_za_impl : public store_za_base
++{
++public:
++  constexpr svst1_za_impl (int unspec) : m_unspec (unspec) {}
++
++  rtx
++  expand (function_expander &e) const override
++  {
++    return expand_ld1_st1 (e, m_unspec, false);
++  }
++
++  int m_unspec;
++};
++
++class svstr_za_impl : public store_za_base
++{
++public:
++  rtx
++  expand (function_expander &e) const override
++  {
++    return expand_ldr_str_za (e, CODE_FOR_aarch64_sme_str0,
++			      code_for_aarch64_sme_strn (Pmode));
++  }
++};
++
++class svundef_za_impl : public write_za
++{
++public:
++  rtx
++  expand (function_expander &) const override
++  {
++    rtx target = gen_rtx_REG (VNx16QImode, ZA_REGNUM);
++    emit_clobber (copy_rtx (target));
++    return const0_rtx;
++  }
++};
++
++using svwrite_za_tile_impl = add_call_properties;
++
++class svzero_mask_za_impl : public write_za
++{
++public:
++  rtx
++  expand (function_expander &e) const override
++  {
++    return e.use_exact_insn (CODE_FOR_aarch64_sme_zero_za);
++  }
++};
++
++class svzero_za_impl : public write_za
++{
++public:
++  rtx
++  expand (function_expander &) const override
++  {
++    emit_insn (gen_aarch64_sme_zero_za (gen_int_mode (0xff, SImode)));
++    return const0_rtx;
++  }
++};
++
++} /* end anonymous namespace */
++
++namespace aarch64_sve {
++
++FUNCTION (arm_has_sme, arm_has_sme_impl, )
++FUNCTION (arm_in_streaming_mode, arm_in_streaming_mode_impl, )
++FUNCTION (svaddha_za, sme_1mode_function, (UNSPEC_SME_ADDHA,
++					   UNSPEC_SME_ADDHA, -1))
++FUNCTION (svaddva_za, sme_1mode_function, (UNSPEC_SME_ADDVA,
++					  UNSPEC_SME_ADDVA, -1))
++FUNCTION (svcntsb, svcnts_bhwd_impl, (VNx16QImode))
++FUNCTION (svcntsd, svcnts_bhwd_impl, (VNx2DImode))
++FUNCTION (svcntsh, svcnts_bhwd_impl, (VNx8HImode))
++FUNCTION (svcntsw, svcnts_bhwd_impl, (VNx4SImode))
++FUNCTION (svld1_hor_za, svld1_za_impl, (UNSPEC_SME_LD1_HOR))
++FUNCTION (svld1_ver_za, svld1_za_impl, (UNSPEC_SME_LD1_VER))
++FUNCTION (svldr_za, svldr_za_impl, )
++FUNCTION (svmopa_za, sme_2mode_function, (UNSPEC_SME_SMOPA, UNSPEC_SME_UMOPA,
++					  UNSPEC_SME_FMOPA))
++FUNCTION (svmops_za, sme_2mode_function, (UNSPEC_SME_SMOPS, UNSPEC_SME_UMOPS,
++					  UNSPEC_SME_FMOPS))
++FUNCTION (svread_hor_za, svread_za_tile_impl, (UNSPEC_SME_READ_HOR))
++FUNCTION (svread_ver_za, svread_za_tile_impl, (UNSPEC_SME_READ_VER))
++FUNCTION (svst1_hor_za, svst1_za_impl, (UNSPEC_SME_ST1_HOR))
++FUNCTION (svst1_ver_za, svst1_za_impl, (UNSPEC_SME_ST1_VER))
++FUNCTION (svstr_za, svstr_za_impl, )
++FUNCTION (svsumopa_za, sme_2mode_function, (UNSPEC_SME_SUMOPA, -1, -1))
++FUNCTION (svsumops_za, sme_2mode_function, (UNSPEC_SME_SUMOPS, -1, -1))
++FUNCTION (svundef_za, svundef_za_impl, )
++FUNCTION (svusmopa_za, sme_2mode_function, (-1, UNSPEC_SME_USMOPA, -1))
++FUNCTION (svusmops_za, sme_2mode_function, (-1, UNSPEC_SME_USMOPS, -1))
++FUNCTION (svwrite_hor_za, svwrite_za_tile_impl, (UNSPEC_SME_WRITE_HOR))
++FUNCTION (svwrite_ver_za, svwrite_za_tile_impl, (UNSPEC_SME_WRITE_VER))
++FUNCTION (svzero_mask_za, svzero_mask_za_impl, )
++FUNCTION (svzero_za, svzero_za_impl, )
++
++} /* end namespace aarch64_sve */
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sme.def b/gcc/config/aarch64/aarch64-sve-builtins-sme.def
+new file mode 100644
+index 000000000..5bdcc93f4
+--- /dev/null
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sme.def
+@@ -0,0 +1,76 @@
++/* ACLE support for AArch64 SME.
++   Copyright (C) 2023 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
++   .  */
++
++#define REQUIRED_EXTENSIONS 0
++DEF_SVE_FUNCTION (arm_has_sme, bool_inherent, none, none)
++DEF_SVE_FUNCTION (arm_in_streaming_mode, bool_inherent, none, none)
++#undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS AARCH64_FL_SME
++DEF_SVE_FUNCTION (svcntsb, count_inherent, none, none)
++DEF_SVE_FUNCTION (svcntsd, count_inherent, none, none)
++DEF_SVE_FUNCTION (svcntsh, count_inherent, none, none)
++DEF_SVE_FUNCTION (svcntsw, count_inherent, none, none)
++DEF_SME_ZA_FUNCTION (svldr, ldr_za, za, none)
++DEF_SME_ZA_FUNCTION (svstr, str_za, za, none)
++DEF_SME_ZA_FUNCTION (svundef, inherent_za, za, none)
++DEF_SME_ZA_FUNCTION (svzero, inherent_za, za, none)
++DEF_SME_ZA_FUNCTION (svzero_mask, inherent_mask_za, za, none)
++#undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS AARCH64_FL_SME | AARCH64_FL_SM_ON
++DEF_SME_ZA_FUNCTION (svaddha, unary_za_m, za_s_integer, za_m)
++DEF_SME_ZA_FUNCTION (svaddva, unary_za_m, za_s_integer, za_m)
++DEF_SME_ZA_FUNCTION (svld1_hor, load_za, all_za, none)
++DEF_SME_ZA_FUNCTION (svld1_ver, load_za, all_za, none)
++DEF_SME_ZA_FUNCTION (svmopa, binary_za_m, mop_base, za_m)
++DEF_SME_ZA_FUNCTION (svmopa, binary_za_m, d_za, za_m)
++DEF_SME_ZA_FUNCTION (svmops, binary_za_m, mop_base, za_m)
++DEF_SME_ZA_FUNCTION (svmops, binary_za_m, d_za, za_m)
++DEF_SME_ZA_FUNCTION (svread_hor, read_za_m, za_all_data, m)
++DEF_SME_ZA_FUNCTION (svread_ver, read_za_m, za_all_data, m)
++DEF_SME_ZA_FUNCTION (svst1_hor, store_za, all_za, none)
++DEF_SME_ZA_FUNCTION (svst1_ver, store_za, all_za, none)
++DEF_SME_ZA_FUNCTION (svsumopa, binary_za_uint_m, mop_base_signed, za_m)
++DEF_SME_ZA_FUNCTION (svsumops, binary_za_uint_m, mop_base_signed, za_m)
++DEF_SME_ZA_FUNCTION (svusmopa, binary_za_int_m, mop_base_unsigned, za_m)
++DEF_SME_ZA_FUNCTION (svusmops, binary_za_int_m, mop_base_unsigned, za_m)
++DEF_SME_ZA_FUNCTION (svwrite_hor, write_za_m, za_all_data, za_m)
++DEF_SME_ZA_FUNCTION (svwrite_ver, write_za_m, za_all_data, za_m)
++#undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SME \
++			     | AARCH64_FL_SME_I16I64 \
++			     | AARCH64_FL_SM_ON)
++DEF_SME_ZA_FUNCTION (svaddha, unary_za_m, za_d_integer, za_m)
++DEF_SME_ZA_FUNCTION (svaddva, unary_za_m, za_d_integer, za_m)
++DEF_SME_ZA_FUNCTION (svmopa, binary_za_m, mop_i16i64, za_m)
++DEF_SME_ZA_FUNCTION (svmops, binary_za_m, mop_i16i64, za_m)
++DEF_SME_ZA_FUNCTION (svsumopa, binary_za_uint_m, mop_i16i64_signed, za_m)
++DEF_SME_ZA_FUNCTION (svsumops, binary_za_uint_m, mop_i16i64_signed, za_m)
++DEF_SME_ZA_FUNCTION (svusmopa, binary_za_int_m, mop_i16i64_unsigned, za_m)
++DEF_SME_ZA_FUNCTION (svusmops, binary_za_int_m, mop_i16i64_unsigned, za_m)
++#undef REQUIRED_EXTENSIONS
++
++#define REQUIRED_EXTENSIONS (AARCH64_FL_SME \
++			     | AARCH64_FL_SME_F64F64 \
++			     | AARCH64_FL_SM_ON)
++DEF_SME_ZA_FUNCTION (svmopa, binary_za_m, za_d_float, za_m)
++DEF_SME_ZA_FUNCTION (svmops, binary_za_m, za_d_float, za_m)
++#undef REQUIRED_EXTENSIONS
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sme.h b/gcc/config/aarch64/aarch64-sve-builtins-sme.h
+new file mode 100644
+index 000000000..acfed7700
+--- /dev/null
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sme.h
+@@ -0,0 +1,57 @@
++/* ACLE support for AArch64 SME.
++   Copyright (C) 2023 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
++   .  */
++
++#ifndef GCC_AARCH64_SVE_BUILTINS_SME_H
++#define GCC_AARCH64_SVE_BUILTINS_SME_H
++
++namespace aarch64_sve
++{
++  namespace functions
++  {
++    extern const function_base *const arm_has_sme;
++    extern const function_base *const arm_in_streaming_mode;
++    extern const function_base *const svaddha_za;
++    extern const function_base *const svaddva_za;
++    extern const function_base *const svcntsb;
++    extern const function_base *const svcntsd;
++    extern const function_base *const svcntsh;
++    extern const function_base *const svcntsw;
++    extern const function_base *const svld1_hor_za;
++    extern const function_base *const svld1_ver_za;
++    extern const function_base *const svldr_za;
++    extern const function_base *const svmopa_za;
++    extern const function_base *const svmops_za;
++    extern const function_base *const svread_hor_za;
++    extern const function_base *const svread_ver_za;
++    extern const function_base *const svst1_hor_za;
++    extern const function_base *const svst1_ver_za;
++    extern const function_base *const svstr_za;
++    extern const function_base *const svsumopa_za;
++    extern const function_base *const svsumops_za;
++    extern const function_base *const svusmopa_za;
++    extern const function_base *const svusmops_za;
++    extern const function_base *const svwrite_hor_za;
++    extern const function_base *const svwrite_ver_za;
++    extern const function_base *const svundef_za;
++    extern const function_base *const svzero_za;
++    extern const function_base *const svzero_mask_za;
++  }
++}
++
++#endif
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index 3441b4294..32971a7c8 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -51,6 +51,7 @@
+ #include "aarch64-sve-builtins.h"
+ #include "aarch64-sve-builtins-base.h"
+ #include "aarch64-sve-builtins-sve2.h"
++#include "aarch64-sve-builtins-sme.h"
+ #include "aarch64-sve-builtins-shapes.h"
+ 
+ namespace aarch64_sve {
+@@ -112,6 +113,7 @@ static const char *const pred_suffixes[NUM_PREDS + 1] = {
+   "_m",
+   "_x",
+   "_z",
++  "_m",
+   ""
+ };
+ 
+@@ -136,12 +138,28 @@ CONSTEXPR const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
+     TYPE_##CLASS == TYPE_signed || TYPE_##CLASS == TYPE_unsigned, \
+     TYPE_##CLASS == TYPE_unsigned, \
+     TYPE_##CLASS == TYPE_float, \
++    TYPE_##CLASS != TYPE_bool, \
+     TYPE_##CLASS == TYPE_bool, \
++    false, \
++    0, \
++    MODE },
++#define DEF_SME_ZA_SUFFIX(NAME, BITS, MODE) \
++  { "_" #NAME, \
++    NUM_VECTOR_TYPES, \
++    NUM_TYPE_CLASSES, \
++    BITS, \
++    BITS / BITS_PER_UNIT, \
++    false, \
++    false, \
++    false, \
++    false, \
++    false, \
++    true, \
+     0, \
+     MODE },
+ #include "aarch64-sve-builtins.def"
+   { "", NUM_VECTOR_TYPES, TYPE_bool, 0, 0, false, false, false, false,
+-    0, VOIDmode }
++    false, false, 0, VOIDmode }
+ };
+ 
+ CONSTEXPR const group_suffix_info group_suffixes[] = {
+@@ -422,6 +440,79 @@ CONSTEXPR const group_suffix_info group_suffixes[] = {
+   TYPES_while1 (D, b32), \
+   TYPES_while1 (D, b64)
+ 
++/* _za8 _za16 _za32 _za64 _za128.  */
++#define TYPES_all_za(S, D) \
++  S (za8), S (za16), S (za32), S (za64), S (za128)
++
++/* _za64.  */
++#define TYPES_d_za(S, D) \
++  S (za64)
++
++/* {   _za8 } x {             _s8  _u8 }
++
++   {  _za16 } x { _bf16 _f16 _s16 _u16 }
++
++   {  _za32 } x {       _f32 _s32 _u32 }
++
++   {  _za64 } x {       _f64 _s64 _u64 }.  */
++#define TYPES_za_bhsd_data(S, D) \
++  D (za8, s8), D (za8, u8), \
++  D (za16, bf16), D (za16, f16), D (za16, s16), D (za16, u16), \
++  D (za32, f32), D (za32, s32), D (za32, u32), \
++  D (za64, f64), D (za64, s64), D (za64, u64)
++
++/* Likewise, plus:
++
++   { _za128 } x {      _bf16           }
++		{       _f16 _f32 _f64 }
++		{ _s8   _s16 _s32 _s64 }
++		{ _u8   _u16 _u32 _u64 }.  */
++
++#define TYPES_za_all_data(S, D) \
++  TYPES_za_bhsd_data (S, D), \
++  TYPES_reinterpret1 (D, za128)
++
++/* _za32 x { _s32 _u32 }.  */
++#define TYPES_za_s_integer(S, D) \
++  D (za32, s32), D (za32, u32)
++
++
++/* _za64_f64.  */
++#define TYPES_za_d_float(S, D) \
++  D (za64, f64)
++
++/* _za64 x { _s64 _u64 }.  */
++#define TYPES_za_d_integer(S, D) \
++  D (za64, s64), D (za64, u64)
++
++/* _za32 x { _s8 _u8 _bf16 _f16 _f32 }.  */
++#define TYPES_mop_base(S, D) \
++  D (za32, s8), D (za32, u8), D (za32, bf16), D (za32, f16), D (za32, f32)
++
++/* _za32_s8.  */
++#define TYPES_mop_base_signed(S, D) \
++  D (za32, s8)
++
++/* _za32_u8.  */
++#define TYPES_mop_base_unsigned(S, D) \
++  D (za32, u8)
++
++/* _za64 x { _s16 _u16 }.  */
++#define TYPES_mop_i16i64(S, D) \
++  D (za64, s16), D (za64, u16)
++
++/* _za64_s16.  */
++#define TYPES_mop_i16i64_signed(S, D) \
++  D (za64, s16)
++
++/* _za64_u16.  */
++#define TYPES_mop_i16i64_unsigned(S, D) \
++  D (za64, u16)
++
++/* _za.  */
++#define TYPES_za(S, D) \
++  S (za)
++
+ /* Describe a pair of type suffixes in which only the first is used.  */
+ #define DEF_VECTOR_TYPE(X) { TYPE_SUFFIX_ ## X, NUM_TYPE_SUFFIXES }
+ 
+@@ -489,6 +580,19 @@ DEF_SVE_TYPES_ARRAY (cvt_narrow);
+ DEF_SVE_TYPES_ARRAY (inc_dec_n);
+ DEF_SVE_TYPES_ARRAY (reinterpret);
+ DEF_SVE_TYPES_ARRAY (while);
++DEF_SVE_TYPES_ARRAY (all_za);
++DEF_SVE_TYPES_ARRAY (d_za);
++DEF_SVE_TYPES_ARRAY (za_all_data);
++DEF_SVE_TYPES_ARRAY (za_s_integer);
++DEF_SVE_TYPES_ARRAY (za_d_float);
++DEF_SVE_TYPES_ARRAY (za_d_integer);
++DEF_SVE_TYPES_ARRAY (mop_base);
++DEF_SVE_TYPES_ARRAY (mop_base_signed);
++DEF_SVE_TYPES_ARRAY (mop_base_unsigned);
++DEF_SVE_TYPES_ARRAY (mop_i16i64);
++DEF_SVE_TYPES_ARRAY (mop_i16i64_signed);
++DEF_SVE_TYPES_ARRAY (mop_i16i64_unsigned);
++DEF_SVE_TYPES_ARRAY (za);
+ 
+ static const group_suffix_index groups_none[] = {
+   GROUP_none, NUM_GROUP_SUFFIXES
+@@ -505,6 +609,9 @@ static const predication_index preds_none[] = { PRED_none, NUM_PREDS };
+    explicit suffix.  */
+ static const predication_index preds_implicit[] = { PRED_implicit, NUM_PREDS };
+ 
++/* Used by functions that only support "_m" predication.  */
++static const predication_index preds_m[] = { PRED_m, NUM_PREDS };
++
+ /* Used by functions that allow merging and "don't care" predication,
+    but are not suitable for predicated MOVPRFX.  */
+ static const predication_index preds_mx[] = {
+@@ -536,17 +643,23 @@ static const predication_index preds_z_or_none[] = {
+ /* Used by (mostly predicate) functions that only support "_z" predication.  */
+ static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+ 
++/* Used by SME instructions that always merge into ZA.  */
++static const predication_index preds_za_m[] = { PRED_za_m, NUM_PREDS };
++
+ /* A list of all SVE ACLE functions.  */
+ static CONSTEXPR const function_group_info function_groups[] = {
+ #define DEF_SVE_FUNCTION_GS(NAME, SHAPE, TYPES, GROUPS, PREDS) \
+   { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_##GROUPS, \
+     preds_##PREDS, REQUIRED_EXTENSIONS },
++#define DEF_SME_ZA_FUNCTION_GS(NAME, SHAPE, TYPES, GROUPS, PREDS) \
++  { #NAME, &functions::NAME##_za, &shapes::SHAPE, types_##TYPES, \
++    groups_##GROUPS, preds_##PREDS, (REQUIRED_EXTENSIONS | AARCH64_FL_ZA_ON) },
+ #include "aarch64-sve-builtins.def"
+ };
+ 
+ /* The scalar type associated with each vector type.  */
+-extern GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
+-tree scalar_types[NUM_VECTOR_TYPES];
++extern GTY(()) tree scalar_types[NUM_VECTOR_TYPES + 1];
++tree scalar_types[NUM_VECTOR_TYPES + 1];
+ 
+ /* The single-predicate and single-vector types, with their built-in
+    "__SV..._t" name.  Allow an index of NUM_VECTOR_TYPES, which always
+@@ -654,7 +767,7 @@ find_type_suffix_for_scalar_type (const_tree type)
+   /* A linear search should be OK here, since the code isn't hot and
+      the number of types is only small.  */
+   for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+-    if (!type_suffixes[suffix_i].bool_p)
++    if (type_suffixes[suffix_i].vector_p)
+       {
+ 	vector_type_index vector_i = type_suffixes[suffix_i].vector_type;
+ 	if (matches_type_p (scalar_types[vector_i], type))
+@@ -745,6 +858,20 @@ check_required_extensions (location_t location, tree fndecl,
+       return false;
+     }
+ 
++  if (missing_extensions & AARCH64_FL_SM_ON)
++    {
++      error_at (location, "ACLE function %qD can only be called when"
++		" SME streaming mode is enabled", fndecl);
++      return false;
++    }
++
++  if (missing_extensions & AARCH64_FL_ZA_ON)
++    {
++      error_at (location, "ACLE function %qD can only be called from"
++		" a function that has %qs state", fndecl, "za");
++      return false;
++    }
++
+   static const struct {
+     aarch64_feature_flags flag;
+     const char *name;
+@@ -780,9 +907,13 @@ report_out_of_range (location_t location, tree fndecl, unsigned int argno,
+ 		     HOST_WIDE_INT actual, HOST_WIDE_INT min,
+ 		     HOST_WIDE_INT max)
+ {
+-  error_at (location, "passing %wd to argument %d of %qE, which expects"
+-	    " a value in the range [%wd, %wd]", actual, argno + 1, fndecl,
+-	    min, max);
++  if (min == max)
++    error_at (location, "passing %wd to argument %d of %qE, which expects"
++	      " the value %wd", actual, argno + 1, fndecl, min);
++  else
++    error_at (location, "passing %wd to argument %d of %qE, which expects"
++	      " a value in the range [%wd, %wd]", actual, argno + 1, fndecl,
++	      min, max);
+ }
+ 
+ /* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+@@ -869,7 +1000,7 @@ function_instance::reads_global_state_p () const
+     return true;
+ 
+   /* Handle direct reads of global state.  */
+-  return flags & (CP_READ_MEMORY | CP_READ_FFR);
++  return flags & (CP_READ_MEMORY | CP_READ_FFR | CP_READ_ZA);
+ }
+ 
+ /* Return true if calls to the function could modify some form of
+@@ -890,7 +1021,7 @@ function_instance::modifies_global_state_p () const
+     return true;
+ 
+   /* Handle direct modifications of global state.  */
+-  return flags & (CP_WRITE_MEMORY | CP_WRITE_FFR);
++  return flags & (CP_WRITE_MEMORY | CP_WRITE_FFR | CP_WRITE_ZA);
+ }
+ 
+ /* Return true if calls to the function could raise a signal.  */
+@@ -922,8 +1053,8 @@ registered_function_hasher::equal (value_type value, const compare_type &key)
+   return value->instance == key;
+ }
+ 
+-sve_switcher::sve_switcher ()
+-  : aarch64_simd_switcher (AARCH64_FL_F16 | AARCH64_FL_SVE)
++sve_switcher::sve_switcher (aarch64_feature_flags flags)
++  : aarch64_simd_switcher (AARCH64_FL_F16 | AARCH64_FL_SVE | flags)
+ {
+   /* Changing the ISA flags and have_regs_of_mode should be enough here.
+      We shouldn't need to pay the compile-time cost of a full target
+@@ -979,6 +1110,10 @@ char *
+ function_builder::get_name (const function_instance &instance,
+ 			    bool overloaded_p)
+ {
++  /* __arm_* functions are listed as arm_*, so that the associated GCC
++     code is not in the implementation namespace.  */
++  if (strncmp (instance.base_name, "arm_", 4) == 0)
++    append_name ("__");
+   append_name (instance.base_name);
+   if (overloaded_p)
+     switch (instance.displacement_units ())
+@@ -1016,12 +1151,72 @@ add_attribute (const char *name, tree attrs)
+   return tree_cons (get_identifier (name), NULL_TREE, attrs);
+ }
+ 
+-/* Return the appropriate function attributes for INSTANCE.  */
++/* Add attribute NS::NAME to ATTRS.  */
++static tree
++add_attribute (const char *ns, const char *name, tree value, tree attrs)
++{
++  return tree_cons (build_tree_list (get_identifier (ns),
++				     get_identifier (name)),
++		    value, attrs);
++}
++
++/* Attribute arm::NAME describes shared state that is an input if IS_IN
++   and an output if IS_OUT.  Check whether a call with call properties
++   CALL_FLAGS needs such an attribute.  Add it to in-progress attribute
++   list ATTRS if so.  Return the new attribute list.  */
++static tree
++add_shared_state_attribute (const char *name, bool is_in, bool is_out,
++			    unsigned int call_flags, tree attrs)
++{
++  struct state_flag_info
++  {
++    const char *name;
++    unsigned int read_flag;
++    unsigned int write_flag;
++  };
++  static state_flag_info state_flags[] =
++  {
++    { "za", CP_READ_ZA, CP_WRITE_ZA }
++  };
++
++  tree args = NULL_TREE;
++  for (const auto &state_flag : state_flags)
++    {
++      auto all_flags = state_flag.read_flag | state_flag.write_flag;
++      auto these_flags = ((is_in ? state_flag.read_flag : 0)
++			  | (is_out ? state_flag.write_flag : 0));
++      if ((call_flags & all_flags) == these_flags)
++	{
++	  tree value = build_string (strlen (state_flag.name) + 1,
++				     state_flag.name);
++	  args = tree_cons (NULL_TREE, value, args);
++	}
++    }
++  if (args)
++    attrs = add_attribute ("arm", name, args, attrs);
++  return attrs;
++}
++
++/* Return the appropriate function attributes for INSTANCE, which requires
++   the feature flags in REQUIRED_EXTENSIONS.  */
+ tree
+-function_builder::get_attributes (const function_instance &instance)
++function_builder::get_attributes (const function_instance &instance,
++				  aarch64_feature_flags required_extensions)
+ {
+   tree attrs = NULL_TREE;
+ 
++  if (required_extensions & AARCH64_FL_SM_ON)
++    attrs = add_attribute ("arm", "streaming", NULL_TREE, attrs);
++  else if (!(required_extensions & AARCH64_FL_SM_OFF))
++    attrs = add_attribute ("arm", "streaming_compatible", NULL_TREE, attrs);
++
++  attrs = add_shared_state_attribute ("in", true, false,
++				      instance.call_properties (), attrs);
++  attrs = add_shared_state_attribute ("out", false, true,
++				      instance.call_properties (), attrs);
++  attrs = add_shared_state_attribute ("inout", true, true,
++				      instance.call_properties (), attrs);
++
+   if (!instance.modifies_global_state_p ())
+     {
+       if (instance.reads_global_state_p ())
+@@ -1097,7 +1292,7 @@ add_unique_function (const function_instance &instance,
+   tree fntype = build_function_type_array (return_type,
+ 					   argument_types.length (),
+ 					   argument_types.address ());
+-  tree attrs = get_attributes (instance);
++  tree attrs = get_attributes (instance, required_extensions);
+   registered_function &rfn = add_function (instance, name, fntype, attrs,
+ 					   required_extensions, false, false);
+ 
+@@ -1114,7 +1309,7 @@ add_unique_function (const function_instance &instance,
+   if (strcmp (name, overload_name) != 0)
+     {
+       /* Attribute lists shouldn't be shared.  */
+-      tree attrs = get_attributes (instance);
++      tree attrs = get_attributes (instance, required_extensions);
+       bool placeholder_p = !(m_direct_overloads || force_direct_overloads);
+       add_function (instance, overload_name, fntype, attrs,
+ 		    required_extensions, false, placeholder_p);
+@@ -2283,6 +2478,7 @@ bool
+ function_resolver::check_gp_argument (unsigned int nops,
+ 				      unsigned int &i, unsigned int &nargs)
+ {
++  gcc_assert (pred != PRED_za_m);
+   i = 0;
+   if (pred != PRED_none)
+     {
+@@ -2488,9 +2684,7 @@ function_checker::function_checker (location_t location,
+ 				    unsigned int nargs, tree *args)
+   : function_call_info (location, instance, fndecl),
+     m_fntype (fntype), m_nargs (nargs), m_args (args),
+-    /* We don't have to worry about unary _m operations here, since they
+-       never have arguments that need checking.  */
+-    m_base_arg (pred != PRED_none ? 1 : 0)
++    m_base_arg (pred != PRED_none && pred != PRED_za_m ? 1 : 0)
+ {
+ }
+ 
+@@ -2889,21 +3083,51 @@ function_expander::convert_to_pmode (rtx x)
+ }
+ 
+ /* Return the base address for a contiguous load or store function.
+-   MEM_MODE is the mode of the addressed memory.  */
++   MEM_MODE is the mode of the addressed memory, BASE_ARGNO is
++   the index of the base argument, and VNUM_ARGNO is the index of
++   the vnum offset argument (if any).  VL_ISA_MODE is AARCH64_FL_SM_ON
++   if the vnum argument is a factor of the SME vector length, 0 if it
++   is a factor of the current prevailing vector length.  */
+ rtx
+-function_expander::get_contiguous_base (machine_mode mem_mode)
++function_expander::get_contiguous_base (machine_mode mem_mode,
++					unsigned int base_argno,
++					unsigned int vnum_argno,
++					aarch64_feature_flags vl_isa_mode)
+ {
+-  rtx base = convert_to_pmode (args[1]);
++  rtx base = convert_to_pmode (args[base_argno]);
+   if (mode_suffix_id == MODE_vnum)
+     {
+-      /* Use the size of the memory mode for extending loads and truncating
+-	 stores.  Use the size of a full vector for non-extending loads
+-	 and non-truncating stores (including svld[234] and svst[234]).  */
+-      poly_int64 size = ordered_min (GET_MODE_SIZE (mem_mode),
+-				     BYTES_PER_SVE_VECTOR);
+-      rtx offset = gen_int_mode (size, Pmode);
+-      offset = simplify_gen_binary (MULT, Pmode, args[2], offset);
+-      base = simplify_gen_binary (PLUS, Pmode, base, offset);
++      rtx vnum = args[vnum_argno];
++      if (vnum != const0_rtx)
++	{
++	  /* Use the size of the memory mode for extending loads and truncating
++	     stores.  Use the size of a full vector for non-extending loads
++	     and non-truncating stores (including svld[234] and svst[234]).  */
++	  poly_int64 size = ordered_min (GET_MODE_SIZE (mem_mode),
++					 BYTES_PER_SVE_VECTOR);
++	  rtx offset;
++	  if ((vl_isa_mode & AARCH64_FL_SM_ON)
++	      && !TARGET_STREAMING
++	      && !size.is_constant ())
++	    {
++	      gcc_assert (known_eq (size, BYTES_PER_SVE_VECTOR));
++	      if (CONST_INT_P (vnum) && IN_RANGE (INTVAL (vnum), -32, 31))
++		offset = aarch64_sme_vq_immediate (Pmode, INTVAL (vnum) * 16,
++						   AARCH64_ISA_MODE);
++	      else
++		{
++		  offset = aarch64_sme_vq_immediate (Pmode, 16,
++						     AARCH64_ISA_MODE);
++		  offset = simplify_gen_binary (MULT, Pmode, vnum, offset);
++		}
++	    }
++	  else
++	    {
++	      offset = gen_int_mode (size, Pmode);
++	      offset = simplify_gen_binary (MULT, Pmode, vnum, offset);
++	    }
++	  base = simplify_gen_binary (PLUS, Pmode, base, offset);
++	}
+     }
+   return base;
+ }
+@@ -2991,11 +3215,18 @@ function_expander::add_input_operand (insn_code icode, rtx x)
+   machine_mode mode = operand.mode;
+   if (mode == VOIDmode)
+     {
+-      /* The only allowable use of VOIDmode is the wildcard
+-	 aarch64_any_register_operand, which is used to avoid
+-	 combinatorial explosion in the reinterpret patterns.  */
+-      gcc_assert (operand.predicate == aarch64_any_register_operand);
+-      mode = GET_MODE (x);
++      /* The only allowable uses of VOIDmode are:
++
++	 - the wildcard aarch64_any_register_operand, which is used
++	   to avoid combinatorial explosion in the reinterpret patterns
++
++	 - pmode_register_operand, which always has mode Pmode.  */
++      if (operand.predicate == aarch64_any_register_operand)
++	mode = GET_MODE (x);
++      else if (operand.predicate == pmode_register_operand)
++	mode = Pmode;
++      else
++	gcc_unreachable ();
+     }
+   else if (!VECTOR_MODE_P (GET_MODE (x)) && VECTOR_MODE_P (mode))
+     x = expand_vector_broadcast (mode, x);
+@@ -3010,7 +3241,7 @@ function_expander::add_input_operand (insn_code icode, rtx x)
+ 
+ /* Add an integer operand with value X to the instruction.  */
+ void
+-function_expander::add_integer_operand (HOST_WIDE_INT x)
++function_expander::add_integer_operand (poly_int64 x)
+ {
+   m_ops.safe_grow (m_ops.length () + 1, true);
+   create_integer_operand (&m_ops.last (), x);
+@@ -3555,7 +3786,10 @@ init_builtins ()
+   sve_switcher sve;
+   register_builtin_types ();
+   if (in_lto_p)
+-    handle_arm_sve_h ();
++    {
++      handle_arm_sve_h ();
++      handle_arm_sme_h ();
++    }
+ }
+ 
+ /* Register vector type TYPE under its arm_sve.h name.  */
+@@ -3705,7 +3939,8 @@ handle_arm_sve_h ()
+   function_table = new hash_table (1023);
+   function_builder builder;
+   for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i)
+-    builder.register_function_group (function_groups[i]);
++    if (!(function_groups[i].required_extensions & AARCH64_FL_SME))
++      builder.register_function_group (function_groups[i]);
+ }
+ 
+ /* Return the function decl with SVE function subcode CODE, or error_mark_node
+@@ -3718,6 +3953,33 @@ builtin_decl (unsigned int code, bool)
+   return (*registered_functions)[code]->decl;
+ }
+ 
++/* Implement #pragma GCC aarch64 "arm_sme.h".  */
++void
++handle_arm_sme_h ()
++{
++  if (!function_table)
++    {
++      error ("%qs defined without first defining %qs",
++	     "arm_sme.h", "arm_sve.h");
++      return;
++    }
++
++  static bool initialized_p;
++  if (initialized_p)
++    {
++      error ("duplicate definition of %qs", "arm_sme.h");
++      return;
++    }
++  initialized_p = true;
++
++  sme_switcher sme;
++
++  function_builder builder;
++  for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i)
++    if (function_groups[i].required_extensions & AARCH64_FL_SME)
++      builder.register_function_group (function_groups[i]);
++}
++
+ /* If we're implementing manual overloading, check whether the SVE
+    function with subcode CODE is overloaded, and if so attempt to
+    determine the corresponding non-overloaded function.  The call
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def
+index be10b5ea1..69c11b1d0 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins.def
+@@ -29,6 +29,10 @@
+ #define DEF_SVE_TYPE_SUFFIX(A, B, C, D, E)
+ #endif
+ 
++#ifndef DEF_SME_ZA_SUFFIX
++#define DEF_SME_ZA_SUFFIX(A, B, C)
++#endif
++
+ #ifndef DEF_SVE_GROUP_SUFFIX
+ #define DEF_SVE_GROUP_SUFFIX(A, B, C)
+ #endif
+@@ -42,6 +46,16 @@
+   DEF_SVE_FUNCTION_GS (NAME, SHAPE, TYPES, none, PREDS)
+ #endif
+ 
++#ifndef DEF_SME_ZA_FUNCTION_GS
++#define DEF_SME_ZA_FUNCTION_GS(NAME, SHAPE, TYPES, GROUP, PREDS) \
++  DEF_SVE_FUNCTION_GS(NAME, SHAPE, TYPES, GROUP, PREDS)
++#endif
++
++#ifndef DEF_SME_ZA_FUNCTION
++#define DEF_SME_ZA_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
++  DEF_SME_ZA_FUNCTION_GS (NAME, SHAPE, TYPES, none, PREDS)
++#endif
++
+ DEF_SVE_MODE (n, none, none, none)
+ DEF_SVE_MODE (index, none, none, elements)
+ DEF_SVE_MODE (offset, none, none, bytes)
+@@ -104,16 +118,30 @@ DEF_SVE_TYPE_SUFFIX (u16, svuint16_t, unsigned, 16, VNx8HImode)
+ DEF_SVE_TYPE_SUFFIX (u32, svuint32_t, unsigned, 32, VNx4SImode)
+ DEF_SVE_TYPE_SUFFIX (u64, svuint64_t, unsigned, 64, VNx2DImode)
+ 
++/* Associate _za with bytes.  This is needed for svldr_vnum_za and
++   svstr_vnum_za, whose ZA offset can be in the range [0, 15], as for za8.  */
++DEF_SME_ZA_SUFFIX (za, 8, VNx16QImode)
++
++DEF_SME_ZA_SUFFIX (za8, 8, VNx16QImode)
++DEF_SME_ZA_SUFFIX (za16, 16, VNx8HImode)
++DEF_SME_ZA_SUFFIX (za32, 32, VNx4SImode)
++DEF_SME_ZA_SUFFIX (za64, 64, VNx2DImode)
++DEF_SME_ZA_SUFFIX (za128, 128, VNx1TImode)
++
+ DEF_SVE_GROUP_SUFFIX (x2, 0, 2)
+ DEF_SVE_GROUP_SUFFIX (x3, 0, 3)
+ DEF_SVE_GROUP_SUFFIX (x4, 0, 4)
+ 
+ #include "aarch64-sve-builtins-base.def"
+ #include "aarch64-sve-builtins-sve2.def"
++#include "aarch64-sve-builtins-sme.def"
+ 
++#undef DEF_SME_ZA_FUNCTION
+ #undef DEF_SVE_FUNCTION
++#undef DEF_SME_ZA_FUNCTION_GS
+ #undef DEF_SVE_FUNCTION_GS
+ #undef DEF_SVE_GROUP_SUFFIX
++#undef DEF_SME_ZA_SUFFIX
+ #undef DEF_SVE_TYPE_SUFFIX
+ #undef DEF_SVE_TYPE
+ #undef DEF_SVE_MODE
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index f16ac3947..6ef6bb93f 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -97,6 +97,8 @@ const unsigned int CP_PREFETCH_MEMORY = 1U << 3;
+ const unsigned int CP_WRITE_MEMORY = 1U << 4;
+ const unsigned int CP_READ_FFR = 1U << 5;
+ const unsigned int CP_WRITE_FFR = 1U << 6;
++const unsigned int CP_READ_ZA = 1U << 7;
++const unsigned int CP_WRITE_ZA = 1U << 8;
+ 
+ /* Enumerates the SVE predicate and (data) vector types, together called
+    "vector types" for brevity.  */
+@@ -142,6 +144,10 @@ enum predication_index
+   /* Zero predication: set inactive lanes of the vector result to zero.  */
+   PRED_z,
+ 
++  /* Merging predication for SME's ZA: merge into slices of the array
++     instead of overwriting the whole slices.  */
++  PRED_za_m,
++
+   NUM_PREDS
+ };
+ 
+@@ -176,6 +182,8 @@ enum type_suffix_index
+ {
+ #define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
+   TYPE_SUFFIX_ ## NAME,
++#define DEF_SME_ZA_SUFFIX(NAME, BITS, MODE) \
++  TYPE_SUFFIX_ ## NAME,
+ #include "aarch64-sve-builtins.def"
+   NUM_TYPE_SUFFIXES
+ };
+@@ -240,9 +248,13 @@ struct type_suffix_info
+   unsigned int unsigned_p : 1;
+   /* True if the suffix is for a floating-point type.  */
+   unsigned int float_p : 1;
++  /* True if the suffix is for a vector type (integer or float).  */
++  unsigned int vector_p : 1;
+   /* True if the suffix is for a boolean type.  */
+   unsigned int bool_p : 1;
+-  unsigned int spare : 12;
++  /* True if the suffix is for SME's ZA.  */
++  unsigned int za_p : 1;
++  unsigned int spare : 10;
+ 
+   /* The associated vector or predicate mode.  */
+   machine_mode vector_mode : 16;
+@@ -356,13 +368,15 @@ public:
+   tree displacement_vector_type () const;
+   units_index displacement_units () const;
+ 
++  unsigned int num_za_tiles () const;
++
+   const type_suffix_info &type_suffix (unsigned int) const;
+   const group_suffix_info &group_suffix () const;
+ 
+   tree scalar_type (unsigned int) const;
+   tree vector_type (unsigned int) const;
+   tree tuple_type (unsigned int) const;
+-  unsigned int elements_per_vq (unsigned int i) const;
++  unsigned int elements_per_vq (unsigned int) const;
+   machine_mode vector_mode (unsigned int) const;
+   machine_mode tuple_mode (unsigned int) const;
+   machine_mode gp_mode (unsigned int) const;
+@@ -401,7 +415,7 @@ private:
+ 
+   char *get_name (const function_instance &, bool);
+ 
+-  tree get_attributes (const function_instance &);
++  tree get_attributes (const function_instance &, aarch64_feature_flags);
+ 
+   registered_function &add_function (const function_instance &,
+ 				     const char *, tree, tree,
+@@ -605,7 +619,8 @@ public:
+   bool overlaps_input_p (rtx);
+ 
+   rtx convert_to_pmode (rtx);
+-  rtx get_contiguous_base (machine_mode);
++  rtx get_contiguous_base (machine_mode, unsigned int = 1, unsigned int = 2,
++			   aarch64_feature_flags = 0);
+   rtx get_fallback_value (machine_mode, unsigned int,
+ 			  unsigned int, unsigned int &);
+   rtx get_reg_target ();
+@@ -613,7 +628,7 @@ public:
+ 
+   void add_output_operand (insn_code);
+   void add_input_operand (insn_code, rtx);
+-  void add_integer_operand (HOST_WIDE_INT);
++  void add_integer_operand (poly_int64);
+   void add_mem_operand (machine_mode, rtx);
+   void add_address_operand (rtx);
+   void add_fixed_operand (rtx);
+@@ -738,7 +753,7 @@ public:
+ class sve_switcher : public aarch64_simd_switcher
+ {
+ public:
+-  sve_switcher ();
++  sve_switcher (aarch64_feature_flags = 0);
+   ~sve_switcher ();
+ 
+ private:
+@@ -746,11 +761,18 @@ private:
+   bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
+ };
+ 
++/* Extends sve_switch enough for defining arm_sme.h.  */
++class sme_switcher : public sve_switcher
++{
++public:
++  sme_switcher () : sve_switcher (AARCH64_FL_SME) {}
++};
++
+ extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
+ extern const mode_suffix_info mode_suffixes[MODE_none + 1];
+ extern const group_suffix_info group_suffixes[NUM_GROUP_SUFFIXES];
+ 
+-extern tree scalar_types[NUM_VECTOR_TYPES];
++extern tree scalar_types[NUM_VECTOR_TYPES + 1];
+ extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+ extern tree acle_svpattern;
+ extern tree acle_svprfop;
+@@ -883,6 +905,16 @@ function_instance::displacement_vector_type () const
+   return acle_vector_types[0][mode_suffix ().displacement_vector_type];
+ }
+ 
++/* Return the number of ZA tiles associated with the _za suffix
++   (which is always the first type suffix).  */
++inline unsigned int
++function_instance::num_za_tiles () const
++{
++  auto &suffix = type_suffix (0);
++  gcc_checking_assert (suffix.za_p);
++  return suffix.element_bytes;
++}
++
+ /* If the function takes a vector or scalar displacement, return the units
+    in which the displacement is measured, otherwise return UNITS_none.  */
+ inline units_index
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 112dfeabb..113784e31 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -6160,15 +6160,26 @@ aarch64_output_sve_scalar_inc_dec (rtx offset)
+ }
+ 
+ /* Return true if a single RDVL instruction can multiply FACTOR by the
+-   number of 128-bit quadwords in an SVE vector.  */
++   number of 128-bit quadwords in an SVE vector.  This is also the
++   range of ADDVL.  */
+ 
+ static bool
+-aarch64_sve_rdvl_factor_p (HOST_WIDE_INT factor)
++aarch64_sve_rdvl_addvl_factor_p (HOST_WIDE_INT factor)
+ {
+   return (multiple_p (factor, 16)
+ 	  && IN_RANGE (factor, -32 * 16, 31 * 16));
+ }
+ 
++/* Return true if ADDPL can be used to add FACTOR multiplied by the number
++   of quadwords in an SVE vector.  */
++
++static bool
++aarch64_sve_addpl_factor_p (HOST_WIDE_INT factor)
++{
++  return (multiple_p (factor, 2)
++	  && IN_RANGE (factor, -32 * 2, 31 * 2));
++}
++
+ /* Return true if we can move VALUE into a register using a single
+    RDVL instruction.  */
+ 
+@@ -6176,7 +6187,7 @@ static bool
+ aarch64_sve_rdvl_immediate_p (poly_int64 value)
+ {
+   HOST_WIDE_INT factor = value.coeffs[0];
+-  return value.coeffs[1] == factor && aarch64_sve_rdvl_factor_p (factor);
++  return value.coeffs[1] == factor && aarch64_sve_rdvl_addvl_factor_p (factor);
+ }
+ 
+ /* Likewise for rtx X.  */
+@@ -6212,10 +6223,8 @@ aarch64_sve_addvl_addpl_immediate_p (poly_int64 value)
+   HOST_WIDE_INT factor = value.coeffs[0];
+   if (factor == 0 || value.coeffs[1] != factor)
+     return false;
+-  /* FACTOR counts VG / 2, so a value of 2 is one predicate width
+-     and a value of 16 is one vector width.  */
+-  return (((factor & 15) == 0 && IN_RANGE (factor, -32 * 16, 31 * 16))
+-	  || ((factor & 1) == 0 && IN_RANGE (factor, -32 * 2, 31 * 2)));
++  return (aarch64_sve_rdvl_addvl_factor_p (factor)
++	  || aarch64_sve_addpl_factor_p (factor));
+ }
+ 
+ /* Likewise for rtx X.  */
+@@ -6315,11 +6324,11 @@ aarch64_output_sve_vector_inc_dec (const char *operands, rtx x)
+    number of 128-bit quadwords in an SME vector.  ISA_MODE is the
+    ISA mode in which the calculation is being performed.  */
+ 
+-static rtx
++rtx
+ aarch64_sme_vq_immediate (machine_mode mode, HOST_WIDE_INT factor,
+ 			  aarch64_feature_flags isa_mode)
+ {
+-  gcc_assert (aarch64_sve_rdvl_factor_p (factor));
++  gcc_assert (aarch64_sve_rdvl_addvl_factor_p (factor));
+   if (isa_mode & AARCH64_FL_SM_ON)
+     /* We're in streaming mode, so we can use normal poly-int values.  */
+     return gen_int_mode ({ factor, factor }, mode);
+@@ -6362,7 +6371,7 @@ aarch64_rdsvl_immediate_p (const_rtx x)
+ {
+   HOST_WIDE_INT factor;
+   return (aarch64_sme_vq_unspec_p (x, &factor)
+-	  && aarch64_sve_rdvl_factor_p (factor));
++	  && aarch64_sve_rdvl_addvl_factor_p (factor));
+ }
+ 
+ /* Return the asm string for an RDSVL instruction that calculates X,
+@@ -6379,6 +6388,38 @@ aarch64_output_rdsvl (const_rtx x)
+   return buffer;
+ }
+ 
++/* Return true if X is a constant that can be added using ADDSVL or ADDSPL.  */
++
++bool
++aarch64_addsvl_addspl_immediate_p (const_rtx x)
++{
++  HOST_WIDE_INT factor;
++  return (aarch64_sme_vq_unspec_p (x, &factor)
++	  && (aarch64_sve_rdvl_addvl_factor_p (factor)
++	      || aarch64_sve_addpl_factor_p (factor)));
++}
++
++/* X is a constant that satisfies aarch64_addsvl_addspl_immediate_p.
++   Return the asm string for the associated instruction.  */
++
++char *
++aarch64_output_addsvl_addspl (rtx x)
++{
++  static char buffer[sizeof ("addspl\t%x0, %x1, #-") + 3 * sizeof (int)];
++  HOST_WIDE_INT factor;
++  if (!aarch64_sme_vq_unspec_p (x, &factor))
++    gcc_unreachable ();
++  if (aarch64_sve_rdvl_addvl_factor_p (factor))
++    snprintf (buffer, sizeof (buffer), "addsvl\t%%x0, %%x1, #%d",
++	      (int) factor / 16);
++  else if (aarch64_sve_addpl_factor_p (factor))
++    snprintf (buffer, sizeof (buffer), "addspl\t%%x0, %%x1, #%d",
++	      (int) factor / 2);
++  else
++    gcc_unreachable ();
++  return buffer;
++}
++
+ /* Multipliers for repeating bitmasks of width 32, 16, 8, 4, and 2.  */
+ 
+ static const unsigned HOST_WIDE_INT bitmask_imm_mul[] =
+@@ -6965,7 +7006,7 @@ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+ 	{
+ 	  /* Try to use an unshifted CNT[BHWD] or RDVL.  */
+ 	  if (aarch64_sve_cnt_factor_p (factor)
+-	      || aarch64_sve_rdvl_factor_p (factor))
++	      || aarch64_sve_rdvl_addvl_factor_p (factor))
+ 	    {
+ 	      val = gen_int_mode (poly_int64 (factor, factor), mode);
+ 	      shift = 0;
+@@ -12185,7 +12226,7 @@ aarch64_classify_index (struct aarch64_address_info *info, rtx x,
+       && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))])
+     index = SUBREG_REG (index);
+ 
+-  if (aarch64_sve_data_mode_p (mode))
++  if (aarch64_sve_data_mode_p (mode) || mode == VNx1TImode)
+     {
+       if (type != ADDRESS_REG_REG
+ 	  || (1 << shift) != GET_MODE_UNIT_SIZE (mode))
+@@ -12288,7 +12329,8 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 			    && ((vec_flags == 0
+ 				 && known_lt (GET_MODE_SIZE (mode), 16))
+ 				|| vec_flags == VEC_ADVSIMD
+-				|| vec_flags & VEC_SVE_DATA));
++				|| vec_flags & VEC_SVE_DATA
++				|| mode == VNx1TImode));
+ 
+   /* 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
+@@ -12407,7 +12449,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
+ 	  /* Make "m" use the LD1 offset range for SVE data modes, so
+ 	     that pre-RTL optimizers like ivopts will work to that
+ 	     instead of the wider LDR/STR range.  */
+-	  if (vec_flags == VEC_SVE_DATA)
++	  if (vec_flags == VEC_SVE_DATA || mode == VNx1TImode)
+ 	    return (type == ADDR_QUERY_M
+ 		    ? offset_4bit_signed_scaled_p (mode, offset)
+ 		    : offset_9bit_signed_scaled_p (mode, offset));
+@@ -14750,6 +14792,51 @@ aarch64_output_casesi (rtx *operands)
+   return "";
+ }
+ 
++/* Return the asm string for an SME ZERO instruction whose 8-bit mask
++   operand is MASK.  */
++const char *
++aarch64_output_sme_zero_za (rtx mask)
++{
++  auto mask_val = UINTVAL (mask);
++  if (mask_val == 0)
++    return "zero\t{}";
++
++  if (mask_val == 0xff)
++    return "zero\t{ za }";
++
++  static constexpr std::pair tiles[] = {
++    { 0xff, 'b' },
++    { 0x55, 'h' },
++    { 0x11, 's' },
++    { 0x01, 'd' }
++  };
++  /* The last entry in the list has the form "za7.d }", but that's the
++     same length as "za7.d, ".  */
++  static char buffer[sizeof("zero\t{ ") + sizeof ("za7.d, ") * 8 + 1];
++  unsigned int i = 0;
++  i += snprintf (buffer + i, sizeof (buffer) - i, "zero\t");
++  const char *prefix = "{ ";
++  for (auto &tile : tiles)
++    {
++      auto tile_mask = tile.first;
++      unsigned int tile_index = 0;
++      while (tile_mask < 0x100)
++	{
++	  if ((mask_val & tile_mask) == tile_mask)
++	    {
++	      i += snprintf (buffer + i, sizeof (buffer) - i, "%sza%d.%c",
++			     prefix, tile_index, tile.second);
++	      prefix = ", ";
++	      mask_val &= ~tile_mask;
++	    }
++	  tile_mask <<= 1;
++	  tile_index += 1;
++	}
++    }
++  gcc_assert (mask_val == 0 && i + 3 <= sizeof (buffer));
++  snprintf (buffer + i, sizeof (buffer) - i, " }");
++  return buffer;
++}
+ 
+ /* Return size in bits of an arithmetic operand which is shifted/scaled and
+    masked such that it is suitable for a UXTB, UXTH, or UXTW extend
+@@ -23756,6 +23843,31 @@ aarch64_sve_struct_memory_operand_p (rtx op)
+ 	  && offset_4bit_signed_scaled_p (SVE_BYTE_MODE, last));
+ }
+ 
++/* Return true if OFFSET is a constant integer and if VNUM is
++   OFFSET * the number of bytes in an SVE vector.  This is the requirement
++   that exists in SME LDR and STR instructions, where the VL offset must
++   equal the ZA slice offset.  */
++bool
++aarch64_sme_ldr_vnum_offset_p (rtx offset, rtx vnum)
++{
++  if (!CONST_INT_P (offset) || !IN_RANGE (INTVAL (offset), 0, 15))
++    return false;
++
++  if (TARGET_STREAMING)
++    {
++      poly_int64 const_vnum;
++      return (poly_int_rtx_p (vnum, &const_vnum)
++	      && known_eq (const_vnum,
++			   INTVAL (offset) * BYTES_PER_SVE_VECTOR));
++    }
++  else
++    {
++      HOST_WIDE_INT factor;
++      return (aarch64_sme_vq_unspec_p (vnum, &factor)
++	      && factor == INTVAL (offset) * 16);
++    }
++}
++
+ /* Emit a register copy from operand to operand, taking care not to
+    early-clobber source registers in the process.
+ 
+diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
+index 8b21faf34..50fdf2f50 100644
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -207,6 +207,7 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ /* Macros to test ISA flags.  */
+ 
+ #define AARCH64_ISA_SM_OFF         (aarch64_isa_flags & AARCH64_FL_SM_OFF)
++#define AARCH64_ISA_SM_ON          (aarch64_isa_flags & AARCH64_FL_SM_ON)
+ #define AARCH64_ISA_ZA_ON          (aarch64_isa_flags & AARCH64_FL_ZA_ON)
+ #define AARCH64_ISA_MODE           (aarch64_isa_flags & AARCH64_FL_ISA_MODES)
+ #define AARCH64_ISA_CRC            (aarch64_isa_flags & AARCH64_FL_CRC)
+@@ -224,6 +225,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ #define AARCH64_ISA_SVE2_SHA3	   (aarch64_isa_flags & AARCH64_FL_SVE2_SHA3)
+ #define AARCH64_ISA_SVE2_SM4	   (aarch64_isa_flags & AARCH64_FL_SVE2_SM4)
+ #define AARCH64_ISA_SME		   (aarch64_isa_flags & AARCH64_FL_SME)
++#define AARCH64_ISA_SME_I16I64	   (aarch64_isa_flags & AARCH64_FL_SME_I16I64)
++#define AARCH64_ISA_SME_F64F64	   (aarch64_isa_flags & AARCH64_FL_SME_F64F64)
+ #define AARCH64_ISA_V8_3A	   (aarch64_isa_flags & AARCH64_FL_V8_3A)
+ #define AARCH64_ISA_DOTPROD	   (aarch64_isa_flags & AARCH64_FL_DOTPROD)
+ #define AARCH64_ISA_AES	           (aarch64_isa_flags & AARCH64_FL_AES)
+@@ -256,6 +259,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+ /* The current function is a normal non-streaming function.  */
+ #define TARGET_NON_STREAMING (AARCH64_ISA_SM_OFF)
+ 
++/* The current function has a streaming body.  */
++#define TARGET_STREAMING (AARCH64_ISA_SM_ON)
++
+ /* The current function has a streaming-compatible body.  */
+ #define TARGET_STREAMING_COMPATIBLE \
+   ((aarch64_isa_flags & AARCH64_FL_SM_STATE) == 0)
+@@ -316,6 +322,15 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF;
+    imply anything about the state of PSTATE.SM.  */
+ #define TARGET_SME (AARCH64_ISA_SME)
+ 
++/* Streaming-mode SME instructions.  */
++#define TARGET_STREAMING_SME (TARGET_STREAMING && TARGET_SME)
++
++/* The FEAT_SME_I16I64 extension to SME, enabled through +sme-i16i64.  */
++#define TARGET_SME_I16I64 (AARCH64_ISA_SME_I16I64)
++
++/* The FEAT_SME_F64F64 extension to SME, enabled through +sme-f64f64.  */
++#define TARGET_SME_F64F64 (AARCH64_ISA_SME_F64F64)
++
+ /* ARMv8.3-A features.  */
+ #define TARGET_ARMV8_3	(AARCH64_ISA_V8_3A)
+ 
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index 05a7c6675..6b4341866 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -2147,10 +2147,10 @@
+ 
+ (define_insn "*add3_aarch64"
+   [(set
+-    (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,r,rk")
++    (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,r,rk,rk")
+     (plus:GPI
+-     (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,0,rk")
+-     (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav")))]
++     (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,0,rk,rk")
++     (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav,UaV")))]
+   ""
+   "@
+   add\\t%0, %1, %2
+@@ -2159,10 +2159,11 @@
+   sub\\t%0, %1, #%n2
+   #
+   * return aarch64_output_sve_scalar_inc_dec (operands[2]);
+-  * return aarch64_output_sve_addvl_addpl (operands[2]);"
++  * return aarch64_output_sve_addvl_addpl (operands[2]);
++  * return aarch64_output_addsvl_addspl (operands[2]);"
+   ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
+-  [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm,alu_imm")
+-   (set_attr "arch" "*,*,simd,*,*,sve,sve")]
++  [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm,alu_imm,alu_imm")
++   (set_attr "arch" "*,*,simd,*,*,sve,sve,sme")]
+ )
+ 
+ ;; zero_extend version of above
+diff --git a/gcc/config/aarch64/arm_sme.h b/gcc/config/aarch64/arm_sme.h
+new file mode 100644
+index 000000000..5ddd49f57
+--- /dev/null
++++ b/gcc/config/aarch64/arm_sme.h
+@@ -0,0 +1,45 @@
++/* AArch64 SME intrinsics include file.
++   Copyright (C) 2023 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
++   .  */
++
++#ifndef _ARM_SME_H_
++#define _ARM_SME_H_
++
++#include 
++#pragma GCC aarch64 "arm_sme.h"
++
++void __arm_za_disable(void) __arm_streaming_compatible;
++
++void *__arm_sc_memcpy(void *, const void *, __SIZE_TYPE__)
++  __arm_streaming_compatible;
++
++void *__arm_sc_memmove(void *, const void *, __SIZE_TYPE__)
++  __arm_streaming_compatible;
++
++void *__arm_sc_memset(void *, int, __SIZE_TYPE__)
++  __arm_streaming_compatible;
++
++void *__arm_sc_memchr(void *, int, __SIZE_TYPE__)
++  __arm_streaming_compatible;
++
++#endif
+diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
+index 88fb9a07c..2da423779 100644
+--- a/gcc/config/aarch64/constraints.md
++++ b/gcc/config/aarch64/constraints.md
+@@ -21,6 +21,9 @@
+ (define_register_constraint "k" "STACK_REG"
+   "@internal The stack register.")
+ 
++(define_register_constraint "Ucj" "W12_W15_REGS"
++  "@internal r12-r15, which can be used to index ZA.")
++
+ (define_register_constraint "Ucs" "TAILCALL_ADDR_REGS"
+   "@internal Registers suitable for an indirect tail call")
+ 
+@@ -74,6 +77,12 @@
+    a single ADDVL or ADDPL."
+  (match_operand 0 "aarch64_sve_addvl_addpl_immediate"))
+ 
++(define_constraint "UaV"
++  "@internal
++   A constraint that matches a VG-based constant that can be added by
++   a single ADDSVL or ADDSPL."
++ (match_operand 0 "aarch64_addsvl_addspl_immediate"))
++
+ (define_constraint "Uat"
+   "@internal
+    A constraint that matches a VG-based constant that can be added by
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index b616f5c9a..152d28f6b 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -450,6 +450,7 @@
+ (define_mode_iterator VNx4SF_ONLY [VNx4SF])
+ (define_mode_iterator VNx2DI_ONLY [VNx2DI])
+ (define_mode_iterator VNx2DF_ONLY [VNx2DF])
++(define_mode_iterator VNx1TI_ONLY [VNx1TI])
+ 
+ ;; All fully-packed SVE vector modes.
+ (define_mode_iterator SVE_FULL [VNx16QI VNx8HI VNx4SI VNx2DI
+@@ -608,6 +609,17 @@
+ ;; Bfloat16 modes to which V4SF can be converted
+ (define_mode_iterator V4SF_TO_BF [V4BF V8BF])
+ 
++;; The modes used to represent different ZA access sizes.
++(define_mode_iterator SME_ZA_I [VNx16QI VNx8HI VNx4SI VNx2DI VNx1TI])
++(define_mode_iterator SME_ZA_SDI [VNx4SI (VNx2DI "TARGET_SME_I16I64")])
++
++(define_mode_iterator SME_ZA_SDF_I [VNx4SI (VNx2DI "TARGET_SME_F64F64")])
++
++;; The modes for which outer product instructions are supported.
++(define_mode_iterator SME_MOP_BHI [VNx16QI (VNx8HI "TARGET_SME_I16I64")])
++(define_mode_iterator SME_MOP_HSDF [VNx8BF VNx8HF VNx4SF
++				    (VNx2DF "TARGET_SME_F64F64")])
++
+ ;; ------------------------------------------------------------------
+ ;; Unspec enumerations for Advance SIMD. These could well go into
+ ;; aarch64.md but for their use in int_iterators here.
+@@ -986,6 +998,28 @@
+     UNSPEC_BFCVTN2     ; Used in aarch64-simd.md.
+     UNSPEC_BFCVT       ; Used in aarch64-simd.md.
+     UNSPEC_FCVTXN	; Used in aarch64-simd.md.
++
++    ;; All used in aarch64-sme.md
++    UNSPEC_SME_ADDHA
++    UNSPEC_SME_ADDVA
++    UNSPEC_SME_FMOPA
++    UNSPEC_SME_FMOPS
++    UNSPEC_SME_LD1_HOR
++    UNSPEC_SME_LD1_VER
++    UNSPEC_SME_READ_HOR
++    UNSPEC_SME_READ_VER
++    UNSPEC_SME_SMOPA
++    UNSPEC_SME_SMOPS
++    UNSPEC_SME_ST1_HOR
++    UNSPEC_SME_ST1_VER
++    UNSPEC_SME_SUMOPA
++    UNSPEC_SME_SUMOPS
++    UNSPEC_SME_UMOPA
++    UNSPEC_SME_UMOPS
++    UNSPEC_SME_USMOPA
++    UNSPEC_SME_USMOPS
++    UNSPEC_SME_WRITE_HOR
++    UNSPEC_SME_WRITE_VER
+ ])
+ 
+ ;; ------------------------------------------------------------------
+@@ -1115,9 +1149,15 @@
+ ;; element.
+ (define_mode_attr elem_bits [(VNx16BI "8") (VNx8BI "16")
+ 			     (VNx4BI "32") (VNx2BI "64")
+-			     (VNx16QI "8") (VNx8HI "16")
+-			     (VNx4SI "32") (VNx2DI "64")
+-			     (VNx8HF "16") (VNx4SF "32") (VNx2DF "64")])
++			     (VNx16QI "8") (VNx32QI "8") (VNx64QI "8")
++			     (VNx8HI "16") (VNx16HI "16") (VNx32HI "16")
++			     (VNx8HF "16") (VNx16HF "16") (VNx32HF "16")
++			     (VNx8BF "16") (VNx16BF "16") (VNx32BF "16")
++			     (VNx4SI "32") (VNx8SI "32") (VNx16SI "32")
++			     (VNx4SF "32") (VNx8SF "32") (VNx16SF "32")
++			     (VNx2DI "64") (VNx4DI "64") (VNx8DI "64")
++			     (VNx2DF "64") (VNx4DF "64") (VNx8DF "64")
++			     (VNx1TI "128")])
+ 
+ ;; The number of bits in a vector container.
+ (define_mode_attr container_bits [(VNx16QI "8")
+@@ -1243,6 +1283,7 @@
+ 			  (VNx4SF "s") (VNx2SF "s")
+ 			  (VNx2DI "d")
+ 			  (VNx2DF "d")
++			  (VNx1TI "q")
+ 			  (BF "h") (V4BF "h") (V8BF "h")
+ 			  (HF "h")
+ 			  (SF "s") (DF "d")
+@@ -1261,6 +1302,7 @@
+ 			  (VNx4SF "w") (VNx2SF "w")
+ 			  (VNx2DI "d")
+ 			  (VNx2DF "d")
++			  (VNx1TI "q")
+ 			  (VNx32QI "b") (VNx48QI "b") (VNx64QI "b")
+ 			  (VNx16HI "h") (VNx24HI "h") (VNx32HI "h")
+ 			  (VNx16HF "h") (VNx24HF "h") (VNx32HF "h")
+@@ -2052,6 +2094,7 @@
+ 			 (VNx4SF "VNx4BI") (VNx2SF "VNx2BI")
+ 			 (VNx2DI "VNx2BI")
+ 			 (VNx2DF "VNx2BI")
++			 (VNx1TI "VNx2BI")
+ 			 (VNx32QI "VNx16BI")
+ 			 (VNx16HI "VNx8BI") (VNx16HF "VNx8BI")
+ 			 (VNx16BF "VNx8BI")
+@@ -2132,6 +2175,8 @@
+ ;; The constraint to use for an SVE FCMLA lane index.
+ (define_mode_attr sve_lane_pair_con [(VNx8HF "y") (VNx4SF "x")])
+ 
++(define_mode_attr b [(VNx8BF "b") (VNx8HF "") (VNx4SF "") (VNx2DF "")])
++
+ ;; -------------------------------------------------------------------
+ ;; Code Iterators
+ ;; -------------------------------------------------------------------
+@@ -3159,6 +3204,20 @@
+ (define_int_iterator FCMUL_OP [UNSPEC_FCMUL
+ 			       UNSPEC_FCMUL_CONJ])
+ 
++(define_int_iterator SME_LD1 [UNSPEC_SME_LD1_HOR UNSPEC_SME_LD1_VER])
++(define_int_iterator SME_READ [UNSPEC_SME_READ_HOR UNSPEC_SME_READ_VER])
++(define_int_iterator SME_ST1 [UNSPEC_SME_ST1_HOR UNSPEC_SME_ST1_VER])
++(define_int_iterator SME_WRITE [UNSPEC_SME_WRITE_HOR UNSPEC_SME_WRITE_VER])
++
++(define_int_iterator SME_BINARY_SDI [UNSPEC_SME_ADDHA UNSPEC_SME_ADDVA])
++
++(define_int_iterator SME_INT_MOP [UNSPEC_SME_SMOPA UNSPEC_SME_SMOPS
++				  UNSPEC_SME_SUMOPA UNSPEC_SME_SUMOPS
++				  UNSPEC_SME_UMOPA UNSPEC_SME_UMOPS
++				  UNSPEC_SME_USMOPA UNSPEC_SME_USMOPS])
++
++(define_int_iterator SME_FP_MOP [UNSPEC_SME_FMOPA UNSPEC_SME_FMOPS])
++
+ ;; Iterators for atomic operations.
+ 
+ (define_int_iterator ATOMIC_LDOP
+@@ -3231,6 +3290,26 @@
+ 			(UNSPEC_PMULLT "pmullt")
+ 			(UNSPEC_PMULLT_PAIR "pmullt_pair")
+ 			(UNSPEC_SMATMUL "smatmul")
++			(UNSPEC_SME_ADDHA "addha")
++			(UNSPEC_SME_ADDVA "addva")
++			(UNSPEC_SME_FMOPA "fmopa")
++			(UNSPEC_SME_FMOPS "fmops")
++			(UNSPEC_SME_LD1_HOR "ld1_hor")
++			(UNSPEC_SME_LD1_VER "ld1_ver")
++			(UNSPEC_SME_READ_HOR "read_hor")
++			(UNSPEC_SME_READ_VER "read_ver")
++			(UNSPEC_SME_SMOPA "smopa")
++			(UNSPEC_SME_SMOPS "smops")
++			(UNSPEC_SME_ST1_HOR "st1_hor")
++			(UNSPEC_SME_ST1_VER "st1_ver")
++			(UNSPEC_SME_SUMOPA "sumopa")
++			(UNSPEC_SME_SUMOPS "sumops")
++			(UNSPEC_SME_UMOPA "umopa")
++			(UNSPEC_SME_UMOPS "umops")
++			(UNSPEC_SME_USMOPA "usmopa")
++			(UNSPEC_SME_USMOPS "usmops")
++			(UNSPEC_SME_WRITE_HOR "write_hor")
++			(UNSPEC_SME_WRITE_VER "write_ver")
+ 			(UNSPEC_SQCADD90 "sqcadd90")
+ 			(UNSPEC_SQCADD270 "sqcadd270")
+ 			(UNSPEC_SQRDCMLAH "sqrdcmlah")
+@@ -4000,6 +4079,15 @@
+ (define_int_attr unspec [(UNSPEC_WHILERW "UNSPEC_WHILERW")
+ 			 (UNSPEC_WHILEWR "UNSPEC_WHILEWR")])
+ 
++(define_int_attr hv [(UNSPEC_SME_LD1_HOR "h")
++		     (UNSPEC_SME_LD1_VER "v")
++		     (UNSPEC_SME_READ_HOR "h")
++		     (UNSPEC_SME_READ_VER "v")
++		     (UNSPEC_SME_ST1_HOR "h")
++		     (UNSPEC_SME_ST1_VER "v")
++		     (UNSPEC_SME_WRITE_HOR "h")
++		     (UNSPEC_SME_WRITE_VER "v")])
++
+ ;; Iterators and attributes for fpcr fpsr getter setters
+ 
+ (define_int_iterator GET_FPSCR
+diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
+index 1b8496c07..3ec9e9103 100644
+--- a/gcc/config/aarch64/predicates.md
++++ b/gcc/config/aarch64/predicates.md
+@@ -212,11 +212,17 @@
+   (and (match_code "const_poly_int")
+        (match_test "aarch64_add_offset_temporaries (op) == 1")))
+ 
++(define_predicate "aarch64_addsvl_addspl_immediate"
++  (and (match_code "const")
++       (match_test "aarch64_addsvl_addspl_immediate_p (op)")))
++
+ (define_predicate "aarch64_pluslong_operand"
+   (ior (match_operand 0 "register_operand")
+        (match_operand 0 "aarch64_pluslong_immediate")
+        (and (match_test "TARGET_SVE")
+-	    (match_operand 0 "aarch64_sve_plus_immediate"))))
++	    (match_operand 0 "aarch64_sve_plus_immediate"))
++       (and (match_test "TARGET_SME")
++	    (match_operand 0 "aarch64_addsvl_addspl_immediate"))))
+ 
+ (define_predicate "aarch64_pluslong_or_poly_operand"
+   (ior (match_operand 0 "aarch64_pluslong_operand")
+diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
+index 49731ba92..be60cc003 100644
+--- a/gcc/config/aarch64/t-aarch64
++++ b/gcc/config/aarch64/t-aarch64
+@@ -63,6 +63,7 @@ aarch64-sve-builtins.o: $(srcdir)/config/aarch64/aarch64-sve-builtins.cc \
+   $(srcdir)/config/aarch64/aarch64-sve-builtins.def \
+   $(srcdir)/config/aarch64/aarch64-sve-builtins-base.def \
+   $(srcdir)/config/aarch64/aarch64-sve-builtins-sve2.def \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-sme.def \
+   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+   $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) \
+   $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+@@ -72,7 +73,8 @@ aarch64-sve-builtins.o: $(srcdir)/config/aarch64/aarch64-sve-builtins.cc \
+   $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+   $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h \
+   $(srcdir)/config/aarch64/aarch64-sve-builtins-base.h \
+-  $(srcdir)/config/aarch64/aarch64-sve-builtins-sve2.h
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-sve2.h \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-sme.h
+ 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ 		$(srcdir)/config/aarch64/aarch64-sve-builtins.cc
+ 
+@@ -113,6 +115,19 @@ aarch64-sve-builtins-sve2.o: \
+ 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ 		$(srcdir)/config/aarch64/aarch64-sve-builtins-sve2.cc
+ 
++aarch64-sve-builtins-sme.o: \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-sme.cc \
++  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
++  $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) \
++  $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
++  gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-sme.h \
++  $(srcdir)/config/aarch64/aarch64-sve-builtins-functions.h
++	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
++		$(srcdir)/config/aarch64/aarch64-sve-builtins-sme.cc
++
+ aarch64-builtin-iterators.h: $(srcdir)/config/aarch64/geniterators.sh \
+ 	$(srcdir)/config/aarch64/iterators.md
+ 	$(SHELL) $(srcdir)/config/aarch64/geniterators.sh \
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 2420b05d9..47fff9c90 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -19480,6 +19480,10 @@ Enable the Flag Manipulation instructions Extension.
+ Enable the Pointer Authentication Extension.
+ @item sme
+ Enable the Scalable Matrix Extension.
++@item sme-i16i64
++Enable the FEAT_SME_I16I64 extension to SME.
++@item sme-f64f64
++Enable the FEAT_SME_F64F64 extension to SME.
+ 
+ @end table
+ 
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme-acle-asm.exp b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme-acle-asm.exp
+new file mode 100644
+index 000000000..a9ed3a195
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/aarch64-sme-acle-asm.exp
+@@ -0,0 +1,82 @@
++#  Assembly-based regression-test driver for the SME ACLE.
++#  Copyright (C) 2009-2023 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
++#  .  */
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Exit immediately if this isn't an AArch64 target.
++if {![istarget aarch64*-*-*] } {
++    return
++}
++
++# Load support procs.
++load_lib g++-dg.exp
++
++# Initialize `dg'.
++dg-init
++
++# Force SME if we're not testing it already.
++if { [check_effective_target_aarch64_sme] } {
++    set sme_flags ""
++} else {
++    set sme_flags "-march=armv9-a+sme"
++}
++
++# Turn off any codegen tweaks by default that may affect expected assembly.
++# Tests relying on those should turn them on explicitly.
++set sme_flags "$sme_flags -mtune=generic -moverride=tune=none"
++
++global gcc_runtest_parallelize_limit_minor
++if { [info exists gcc_runtest_parallelize_limit_minor] } {
++    set old_limit_minor $gcc_runtest_parallelize_limit_minor
++    set gcc_runtest_parallelize_limit_minor 1
++}
++
++torture-init
++set-torture-options {
++    "-std=c++11 -O0 -g"
++    "-std=c++14 -O1 -g"
++    "-std=c++17 -Og -g"
++    "-std=c++23 -Os -g"
++    "-std=gnu++11 -O2 -fno-schedule-insns -fno-schedule-insns2 -DCHECK_ASM --save-temps"
++    "-std=gnu++23 -Ofast -g"
++} {
++    "-DTEST_FULL"
++    "-DTEST_OVERLOADS"
++}
++
++# Main loop.
++set gcc_subdir [string replace $subdir 0 2 gcc]
++set files [glob -nocomplain $srcdir/$gcc_subdir/acle-asm/*.c]
++set save-dg-do-what-default ${dg-do-what-default}
++if { [check_effective_target_aarch64_asm_sme-i16i64_ok] } {
++    set dg-do-what-default assemble
++} else {
++    set dg-do-what-default compile
++}
++gcc-dg-runtest [lsort $files] "" "$sme_flags -fno-ipa-icf"
++set dg-do-what-default ${save-dg-do-what-default}
++
++torture-finish
++
++if { [info exists gcc_runtest_parallelize_limit_minor] } {
++    set gcc_runtest_parallelize_limit_minor $old_limit_minor
++}
++
++# All done.
++dg-finish
+diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c
+index 9591e3d01..f2f922d4f 100644
+--- a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c
++++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c
+@@ -4,6 +4,7 @@
+    to be diagnosed.  Any attempt to call the function before including
+    arm_sve.h will lead to a link failure.  (Same for taking its address,
+    etc.)  */
+-extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t);
++extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t)
++   __arm_streaming_compatible;
+ 
+ #pragma GCC aarch64 "arm_sve.h"
+diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c
+index f87201984..f24ef002c 100644
+--- a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c
++++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c
+@@ -2,6 +2,7 @@
+ 
+ __SVUint8_t
+ svadd_u8_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
++  __arm_streaming_compatible
+ {
+   return x;
+ }
+diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c
+index 1f2e4bf66..6752ea11e 100644
+--- a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c
++++ b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c
+@@ -2,6 +2,7 @@
+ 
+ __SVUint8_t
+ svadd_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
++  __arm_streaming_compatible
+ {
+   return x;
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
+index 0e6461fa4..23ebe5e4f 100644
+--- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
++++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_4.c
+@@ -45,3 +45,41 @@
+ #ifdef __ARM_FEATURE_SVE2_SHA3
+ #error Foo
+ #endif
++
++#pragma GCC target "+sme"
++#ifndef __ARM_FEATURE_SME
++#error Foo
++#endif
++
++#pragma GCC target "+sme+nofp"
++#ifdef __ARM_FEATURE_SME
++#error Foo
++#endif
++
++#pragma GCC target "+sme+nosimd"
++#ifdef __ARM_FEATURE_SME
++#error Foo
++#endif
++
++#pragma GCC target "+sme+nobf16"
++#ifdef __ARM_FEATURE_SME
++#error Foo
++#endif
++
++#pragma GCC target "+nothing+sme"
++#ifdef __ARM_FEATURE_SME_I16I64
++#error Foo
++#endif
++#ifdef __ARM_FEATURE_SME_F64F64
++#error Foo
++#endif
++
++#pragma GCC target "+sme-i16i64"
++#ifndef __ARM_FEATURE_SME_I16I64
++#error Foo
++#endif
++
++#pragma GCC target "+sme-f64f64"
++#ifndef __ARM_FEATURE_SME_F64F64
++#error Foo
++#endif
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp
+new file mode 100644
+index 000000000..e2d002f26
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp
+@@ -0,0 +1,81 @@
++#  Assembly-based regression-test driver for the SME ACLE.
++#  Copyright (C) 2009-2023 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
++#  .  */
++
++# GCC testsuite that uses the `dg.exp' driver.
++
++# Exit immediately if this isn't an AArch64 target.
++if {![istarget aarch64*-*-*] } {
++    return
++}
++
++# Load support procs.
++load_lib gcc-dg.exp
++
++# Initialize `dg'.
++dg-init
++
++# Force SME if we're not testing it already.
++if { [check_effective_target_aarch64_sme] } {
++    set sme_flags ""
++} else {
++    set sme_flags "-march=armv9-a+sme"
++}
++
++# Turn off any codegen tweaks by default that may affect expected assembly.
++# Tests relying on those should turn them on explicitly.
++set sme_flags "$sme_flags -mtune=generic -moverride=tune=none"
++
++global gcc_runtest_parallelize_limit_minor
++if { [info exists gcc_runtest_parallelize_limit_minor] } {
++    set old_limit_minor $gcc_runtest_parallelize_limit_minor
++    set gcc_runtest_parallelize_limit_minor 1
++}
++
++torture-init
++set-torture-options {
++    "-std=c90 -O0 -g"
++    "-std=c99 -Og -g"
++    "-std=c11 -Os -g"
++    "-std=c23 -O2 -fno-schedule-insns -fno-schedule-insns2 -DCHECK_ASM --save-temps"
++    "-std=gnu90 -O3 -g"
++    "-std=gnu23 -Ofast -g"
++} {
++    "-DTEST_FULL"
++    "-DTEST_OVERLOADS"
++}
++
++# Main loop.
++set files [glob -nocomplain $srcdir/$subdir/acle-asm/*.c]
++set save-dg-do-what-default ${dg-do-what-default}
++if { [check_effective_target_aarch64_asm_sme-i16i64_ok] } {
++    set dg-do-what-default assemble
++} else {
++    set dg-do-what-default compile
++}
++gcc-dg-runtest [lsort $files] "" "$sme_flags -fno-ipa-icf"
++set dg-do-what-default ${save-dg-do-what-default}
++
++torture-finish
++
++if { [info exists gcc_runtest_parallelize_limit_minor] } {
++    set gcc_runtest_parallelize_limit_minor $old_limit_minor
++}
++
++# All done.
++dg-finish
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za32.c
+new file mode 100644
+index 000000000..8dee40145
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za32.c
+@@ -0,0 +1,48 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** addha_za32_s32_0_p0_p1_z0:
++**	addha	za0\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za32_s32_0_p0_p1_z0, svint32_t,
++		 svaddha_za32_s32_m (0, p0, p1, z0),
++		 svaddha_za32_m (0, p0, p1, z0))
++
++/*
++** addha_za32_s32_0_p1_p0_z1:
++**	addha	za0\.s, p1/m, p0/m, z1\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za32_s32_0_p1_p0_z1, svint32_t,
++		 svaddha_za32_s32_m (0, p1, p0, z1),
++		 svaddha_za32_m (0, p1, p0, z1))
++
++/*
++** addha_za32_s32_1_p0_p1_z0:
++**	addha	za1\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za32_s32_1_p0_p1_z0, svint32_t,
++		 svaddha_za32_s32_m (1, p0, p1, z0),
++		 svaddha_za32_m (1, p0, p1, z0))
++
++/*
++** addha_za32_s32_3_p0_p1_z0:
++**	addha	za3\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za32_s32_3_p0_p1_z0, svint32_t,
++		 svaddha_za32_s32_m (3, p0, p1, z0),
++		 svaddha_za32_m (3, p0, p1, z0))
++
++/*
++** addha_za32_u32_0_p0_p1_z0:
++**	addha	za0\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za32_u32_0_p0_p1_z0, svuint32_t,
++		 svaddha_za32_u32_m (0, p0, p1, z0),
++		 svaddha_za32_m (0, p0, p1, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za64.c
+new file mode 100644
+index 000000000..363ff1aab
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addha_za64.c
+@@ -0,0 +1,50 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** addha_za64_s64_0_p0_p1_z0:
++**	addha	za0\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za64_s64_0_p0_p1_z0, svint64_t,
++		 svaddha_za64_s64_m (0, p0, p1, z0),
++		 svaddha_za64_m (0, p0, p1, z0))
++
++/*
++** addha_za64_s64_0_p1_p0_z1:
++**	addha	za0\.d, p1/m, p0/m, z1\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za64_s64_0_p1_p0_z1, svint64_t,
++		 svaddha_za64_s64_m (0, p1, p0, z1),
++		 svaddha_za64_m (0, p1, p0, z1))
++
++/*
++** addha_za64_s64_1_p0_p1_z0:
++**	addha	za1\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za64_s64_1_p0_p1_z0, svint64_t,
++		 svaddha_za64_s64_m (1, p0, p1, z0),
++		 svaddha_za64_m (1, p0, p1, z0))
++
++/*
++** addha_za64_s64_7_p0_p1_z0:
++**	addha	za7\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za64_s64_7_p0_p1_z0, svint64_t,
++		 svaddha_za64_s64_m (7, p0, p1, z0),
++		 svaddha_za64_m (7, p0, p1, z0))
++
++/*
++** addha_za64_u64_0_p0_p1_z0:
++**	addha	za0\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addha_za64_u64_0_p0_p1_z0, svuint64_t,
++		 svaddha_za64_u64_m (0, p0, p1, z0),
++		 svaddha_za64_m (0, p0, p1, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za32.c
+new file mode 100644
+index 000000000..0de019ac8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za32.c
+@@ -0,0 +1,48 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** addva_za32_s32_0_p0_p1_z0:
++**	addva	za0\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za32_s32_0_p0_p1_z0, svint32_t,
++		 svaddva_za32_s32_m (0, p0, p1, z0),
++		 svaddva_za32_m (0, p0, p1, z0))
++
++/*
++** addva_za32_s32_0_p1_p0_z1:
++**	addva	za0\.s, p1/m, p0/m, z1\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za32_s32_0_p1_p0_z1, svint32_t,
++		 svaddva_za32_s32_m (0, p1, p0, z1),
++		 svaddva_za32_m (0, p1, p0, z1))
++
++/*
++** addva_za32_s32_1_p0_p1_z0:
++**	addva	za1\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za32_s32_1_p0_p1_z0, svint32_t,
++		 svaddva_za32_s32_m (1, p0, p1, z0),
++		 svaddva_za32_m (1, p0, p1, z0))
++
++/*
++** addva_za32_s32_3_p0_p1_z0:
++**	addva	za3\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za32_s32_3_p0_p1_z0, svint32_t,
++		 svaddva_za32_s32_m (3, p0, p1, z0),
++		 svaddva_za32_m (3, p0, p1, z0))
++
++/*
++** addva_za32_u32_0_p0_p1_z0:
++**	addva	za0\.s, p0/m, p1/m, z0\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za32_u32_0_p0_p1_z0, svuint32_t,
++		 svaddva_za32_u32_m (0, p0, p1, z0),
++		 svaddva_za32_m (0, p0, p1, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za64.c
+new file mode 100644
+index 000000000..d83d4e03c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/addva_za64.c
+@@ -0,0 +1,50 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** addva_za64_s64_0_p0_p1_z0:
++**	addva	za0\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za64_s64_0_p0_p1_z0, svint64_t,
++		 svaddva_za64_s64_m (0, p0, p1, z0),
++		 svaddva_za64_m (0, p0, p1, z0))
++
++/*
++** addva_za64_s64_0_p1_p0_z1:
++**	addva	za0\.d, p1/m, p0/m, z1\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za64_s64_0_p1_p0_z1, svint64_t,
++		 svaddva_za64_s64_m (0, p1, p0, z1),
++		 svaddva_za64_m (0, p1, p0, z1))
++
++/*
++** addva_za64_s64_1_p0_p1_z0:
++**	addva	za1\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za64_s64_1_p0_p1_z0, svint64_t,
++		 svaddva_za64_s64_m (1, p0, p1, z0),
++		 svaddva_za64_m (1, p0, p1, z0))
++
++/*
++** addva_za64_s64_7_p0_p1_z0:
++**	addva	za7\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za64_s64_7_p0_p1_z0, svint64_t,
++		 svaddva_za64_s64_m (7, p0, p1, z0),
++		 svaddva_za64_m (7, p0, p1, z0))
++
++/*
++** addva_za64_u64_0_p0_p1_z0:
++**	addva	za0\.d, p0/m, p1/m, z0\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (addva_za64_u64_0_p0_p1_z0, svuint64_t,
++		 svaddva_za64_u64_m (0, p0, p1, z0),
++		 svaddva_za64_m (0, p0, p1, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_has_sme_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_has_sme_sc.c
+new file mode 100644
+index 000000000..e37793f9e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_has_sme_sc.c
+@@ -0,0 +1,25 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++#pragma GCC target "+nosme"
++
++/*
++** test_nosme:
++**	...
++**	bl	__arm_sme_state
++**	lsr	x0, x0, #?63
++**	...
++*/
++PROTO (test_nosme, int, ()) { return __arm_has_sme (); }
++
++#pragma GCC target "+sme"
++
++/*
++** test_sme:
++**	mov	w0, #?1
++**	ret
++*/
++PROTO (test_sme, int, ()) { return __arm_has_sme (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_ns.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_ns.c
+new file mode 100644
+index 000000000..ba475d67b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_ns.c
+@@ -0,0 +1,11 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define NON_STREAMING
++#include "test_sme_acle.h"
++
++/*
++** test_sme:
++**	mov	w0, #?0
++**	ret
++*/
++PROTO (test_sme, int, ()) { return __arm_in_streaming_mode (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_s.c
+new file mode 100644
+index 000000000..b88d47921
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_s.c
+@@ -0,0 +1,11 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** test_sme:
++**	mov	w0, #?1
++**	ret
++*/
++PROTO (test_sme, int, ()) { return __arm_in_streaming_mode (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_sc.c
+new file mode 100644
+index 000000000..fb3588a64
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/arm_in_streaming_mode_sc.c
+@@ -0,0 +1,26 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++#pragma GCC target "+nosme"
++
++/*
++** test_nosme:
++**	...
++**	bl	__arm_sme_state
++**	and	w0, w0, #?1
++**	...
++*/
++PROTO (test_nosme, int, ()) { return __arm_in_streaming_mode (); }
++
++#pragma GCC target "+sme"
++
++/*
++** test_sme:
++**	mrs	x([0-9]+), svcr
++**	and	w0, w\1, #?1
++**	ret
++*/
++PROTO (test_sme, int, ()) { return __arm_in_streaming_mode (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_s.c
+new file mode 100644
+index 000000000..0a8de45be
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_s.c
+@@ -0,0 +1,310 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntb_1:
++**	cntb	x0
++**	ret
++*/
++PROTO (cntb_1, uint64_t, ()) { return svcntsb (); }
++
++/*
++** cntb_2:
++**	cntb	x0, all, mul #2
++**	ret
++*/
++PROTO (cntb_2, uint64_t, ()) { return svcntsb () * 2; }
++
++/*
++** cntb_3:
++**	cntb	x0, all, mul #3
++**	ret
++*/
++PROTO (cntb_3, uint64_t, ()) { return svcntsb () * 3; }
++
++/*
++** cntb_4:
++**	cntb	x0, all, mul #4
++**	ret
++*/
++PROTO (cntb_4, uint64_t, ()) { return svcntsb () * 4; }
++
++/*
++** cntb_8:
++**	cntb	x0, all, mul #8
++**	ret
++*/
++PROTO (cntb_8, uint64_t, ()) { return svcntsb () * 8; }
++
++/*
++** cntb_15:
++**	cntb	x0, all, mul #15
++**	ret
++*/
++PROTO (cntb_15, uint64_t, ()) { return svcntsb () * 15; }
++
++/*
++** cntb_16:
++**	cntb	x0, all, mul #16
++**	ret
++*/
++PROTO (cntb_16, uint64_t, ()) { return svcntsb () * 16; }
++
++/*
++** cntb_17:
++**	rdvl	x0, #17
++**	ret
++*/
++PROTO (cntb_17, uint64_t, ()) { return svcntsb () * 17; }
++
++/*
++** cntb_31:
++**	rdvl	x0, #31
++**	ret
++*/
++PROTO (cntb_31, uint64_t, ()) { return svcntsb () * 31; }
++
++/*
++** cntb_32:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
++**	ret
++*/
++PROTO (cntb_32, uint64_t, ()) { return svcntsb () * 32; }
++
++/* Other sequences would be OK.  */
++/*
++** cntb_33:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
++**	incb	x0
++**	ret
++*/
++PROTO (cntb_33, uint64_t, ()) { return svcntsb () * 33; }
++
++/*
++** cntb_64:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 6
++**	ret
++*/
++PROTO (cntb_64, uint64_t, ()) { return svcntsb () * 64; }
++
++/*
++** cntb_128:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 7
++**	ret
++*/
++PROTO (cntb_128, uint64_t, ()) { return svcntsb () * 128; }
++
++/* Other sequences would be OK.  */
++/*
++** cntb_129:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 7
++**	incb	x0
++**	ret
++*/
++PROTO (cntb_129, uint64_t, ()) { return svcntsb () * 129; }
++
++/*
++** cntb_m1:
++**	rdvl	x0, #-1
++**	ret
++*/
++PROTO (cntb_m1, uint64_t, ()) { return -svcntsb (); }
++
++/*
++** cntb_m13:
++**	rdvl	x0, #-13
++**	ret
++*/
++PROTO (cntb_m13, uint64_t, ()) { return -svcntsb () * 13; }
++
++/*
++** cntb_m15:
++**	rdvl	x0, #-15
++**	ret
++*/
++PROTO (cntb_m15, uint64_t, ()) { return -svcntsb () * 15; }
++
++/*
++** cntb_m16:
++**	rdvl	x0, #-16
++**	ret
++*/
++PROTO (cntb_m16, uint64_t, ()) { return -svcntsb () * 16; }
++
++/*
++** cntb_m17:
++**	rdvl	x0, #-17
++**	ret
++*/
++PROTO (cntb_m17, uint64_t, ()) { return -svcntsb () * 17; }
++
++/*
++** cntb_m32:
++**	rdvl	x0, #-32
++**	ret
++*/
++PROTO (cntb_m32, uint64_t, ()) { return -svcntsb () * 32; }
++
++/*
++** cntb_m33:
++**	rdvl	x0, #-32
++**	decb	x0
++**	ret
++*/
++PROTO (cntb_m33, uint64_t, ()) { return -svcntsb () * 33; }
++
++/*
++** cntb_m34:
++**	rdvl	(x[0-9]+), #-17
++**	lsl	x0, \1, #?1
++**	ret
++*/
++PROTO (cntb_m34, uint64_t, ()) { return -svcntsb () * 34; }
++
++/*
++** cntb_m64:
++**	rdvl	(x[0-9]+), #-1
++**	lsl	x0, \1, #?6
++**	ret
++*/
++PROTO (cntb_m64, uint64_t, ()) { return -svcntsb () * 64; }
++
++/*
++** incb_1:
++**	incb	x0
++**	ret
++*/
++PROTO (incb_1, uint64_t, (uint64_t x0)) { return x0 + svcntsb (); }
++
++/*
++** incb_2:
++**	incb	x0, all, mul #2
++**	ret
++*/
++PROTO (incb_2, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 2; }
++
++/*
++** incb_3:
++**	incb	x0, all, mul #3
++**	ret
++*/
++PROTO (incb_3, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 3; }
++
++/*
++** incb_4:
++**	incb	x0, all, mul #4
++**	ret
++*/
++PROTO (incb_4, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 4; }
++
++/*
++** incb_8:
++**	incb	x0, all, mul #8
++**	ret
++*/
++PROTO (incb_8, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 8; }
++
++/*
++** incb_15:
++**	incb	x0, all, mul #15
++**	ret
++*/
++PROTO (incb_15, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 15; }
++
++/*
++** incb_16:
++**	incb	x0, all, mul #16
++**	ret
++*/
++PROTO (incb_16, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 16; }
++
++/*
++** incb_17:
++**	addvl	x0, x0, #17
++**	ret
++*/
++PROTO (incb_17, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 17; }
++
++/*
++** incb_31:
++**	addvl	x0, x0, #31
++**	ret
++*/
++PROTO (incb_31, uint64_t, (uint64_t x0)) { return x0 + svcntsb () * 31; }
++
++/*
++** decb_1:
++**	decb	x0
++**	ret
++*/
++PROTO (decb_1, uint64_t, (uint64_t x0)) { return x0 - svcntsb (); }
++
++/*
++** decb_2:
++**	decb	x0, all, mul #2
++**	ret
++*/
++PROTO (decb_2, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 2; }
++
++/*
++** decb_3:
++**	decb	x0, all, mul #3
++**	ret
++*/
++PROTO (decb_3, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 3; }
++
++/*
++** decb_4:
++**	decb	x0, all, mul #4
++**	ret
++*/
++PROTO (decb_4, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 4; }
++
++/*
++** decb_8:
++**	decb	x0, all, mul #8
++**	ret
++*/
++PROTO (decb_8, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 8; }
++
++/*
++** decb_15:
++**	decb	x0, all, mul #15
++**	ret
++*/
++PROTO (decb_15, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 15; }
++
++/*
++** decb_16:
++**	decb	x0, all, mul #16
++**	ret
++*/
++PROTO (decb_16, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 16; }
++
++/*
++** decb_17:
++**	addvl	x0, x0, #-17
++**	ret
++*/
++PROTO (decb_17, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 17; }
++
++/*
++** decb_31:
++**	addvl	x0, x0, #-31
++**	ret
++*/
++PROTO (decb_31, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 31; }
++
++/*
++** decb_32:
++**	addvl	x0, x0, #-32
++**	ret
++*/
++PROTO (decb_32, uint64_t, (uint64_t x0)) { return x0 - svcntsb () * 32; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_sc.c
+new file mode 100644
+index 000000000..9ee4c8afc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsb_sc.c
+@@ -0,0 +1,12 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntsb:
++**	rdsvl	x0, #1
++**	ret
++*/
++PROTO (cntsb, uint64_t, ()) { return svcntsb (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_s.c
+new file mode 100644
+index 000000000..3bf9498e9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_s.c
+@@ -0,0 +1,277 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntd_1:
++**	cntd	x0
++**	ret
++*/
++PROTO (cntd_1, uint64_t, ()) { return svcntsd (); }
++
++/*
++** cntd_2:
++**	cntw	x0
++**	ret
++*/
++PROTO (cntd_2, uint64_t, ()) { return svcntsd () * 2; }
++
++/*
++** cntd_3:
++**	cntd	x0, all, mul #3
++**	ret
++*/
++PROTO (cntd_3, uint64_t, ()) { return svcntsd () * 3; }
++
++/*
++** cntd_4:
++**	cnth	x0
++**	ret
++*/
++PROTO (cntd_4, uint64_t, ()) { return svcntsd () * 4; }
++
++/*
++** cntd_8:
++**	cntb	x0
++**	ret
++*/
++PROTO (cntd_8, uint64_t, ()) { return svcntsd () * 8; }
++
++/*
++** cntd_15:
++**	cntd	x0, all, mul #15
++**	ret
++*/
++PROTO (cntd_15, uint64_t, ()) { return svcntsd () * 15; }
++
++/*
++** cntd_16:
++**	cntb	x0, all, mul #2
++**	ret
++*/
++PROTO (cntd_16, uint64_t, ()) { return svcntsd () * 16; }
++
++/* Other sequences would be OK.  */
++/*
++** cntd_17:
++**	rdvl	(x[0-9]+), #17
++**	asr	x0, \1, 3
++**	ret
++*/
++PROTO (cntd_17, uint64_t, ()) { return svcntsd () * 17; }
++
++/*
++** cntd_32:
++**	cntb	x0, all, mul #4
++**	ret
++*/
++PROTO (cntd_32, uint64_t, ()) { return svcntsd () * 32; }
++
++/*
++** cntd_64:
++**	cntb	x0, all, mul #8
++**	ret
++*/
++PROTO (cntd_64, uint64_t, ()) { return svcntsd () * 64; }
++
++/*
++** cntd_128:
++**	cntb	x0, all, mul #16
++**	ret
++*/
++PROTO (cntd_128, uint64_t, ()) { return svcntsd () * 128; }
++
++/*
++** cntd_m1:
++**	cntd	(x[0-9]+)
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cntd_m1, uint64_t, ()) { return -svcntsd (); }
++
++/*
++** cntd_m13:
++**	cntd	(x[0-9]+), all, mul #13
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cntd_m13, uint64_t, ()) { return -svcntsd () * 13; }
++
++/*
++** cntd_m15:
++**	cntd	(x[0-9]+), all, mul #15
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cntd_m15, uint64_t, ()) { return -svcntsd () * 15; }
++
++/*
++** cntd_m16:
++**	rdvl	x0, #-2
++**	ret
++*/
++PROTO (cntd_m16, uint64_t, ()) { return -svcntsd () * 16; }
++
++/* Other sequences would be OK.  */
++/*
++** cntd_m17:
++**	rdvl	(x[0-9]+), #-17
++**	asr	x0, \1, 3
++**	ret
++*/
++PROTO (cntd_m17, uint64_t, ()) { return -svcntsd () * 17; }
++
++/*
++** incd_1:
++**	incd	x0
++**	ret
++*/
++PROTO (incd_1, uint64_t, (uint64_t x0)) { return x0 + svcntsd (); }
++
++/*
++** incd_2:
++**	incw	x0
++**	ret
++*/
++PROTO (incd_2, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 2; }
++
++/*
++** incd_3:
++**	incd	x0, all, mul #3
++**	ret
++*/
++PROTO (incd_3, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 3; }
++
++/*
++** incd_4:
++**	inch	x0
++**	ret
++*/
++PROTO (incd_4, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 4; }
++
++/*
++** incd_7:
++**	incd	x0, all, mul #7
++**	ret
++*/
++PROTO (incd_7, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 7; }
++
++/*
++** incd_8:
++**	incb	x0
++**	ret
++*/
++PROTO (incd_8, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 8; }
++
++/*
++** incd_9:
++**	incd	x0, all, mul #9
++**	ret
++*/
++PROTO (incd_9, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 9; }
++
++/*
++** incd_15:
++**	incd	x0, all, mul #15
++**	ret
++*/
++PROTO (incd_15, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 15; }
++
++/*
++** incd_16:
++**	incb	x0, all, mul #2
++**	ret
++*/
++PROTO (incd_16, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 16; }
++
++/*
++** incd_18:
++**	incw	x0, all, mul #9
++**	ret
++*/
++PROTO (incd_18, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 18; }
++
++/*
++** incd_30:
++**	incw	x0, all, mul #15
++**	ret
++*/
++PROTO (incd_30, uint64_t, (uint64_t x0)) { return x0 + svcntsd () * 30; }
++
++/*
++** decd_1:
++**	decd	x0
++**	ret
++*/
++PROTO (decd_1, uint64_t, (uint64_t x0)) { return x0 - svcntsd (); }
++
++/*
++** decd_2:
++**	decw	x0
++**	ret
++*/
++PROTO (decd_2, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 2; }
++
++/*
++** decd_3:
++**	decd	x0, all, mul #3
++**	ret
++*/
++PROTO (decd_3, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 3; }
++
++/*
++** decd_4:
++**	dech	x0
++**	ret
++*/
++PROTO (decd_4, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 4; }
++
++/*
++** decd_7:
++**	decd	x0, all, mul #7
++**	ret
++*/
++PROTO (decd_7, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 7; }
++
++/*
++** decd_8:
++**	decb	x0
++**	ret
++*/
++PROTO (decd_8, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 8; }
++
++/*
++** decd_9:
++**	decd	x0, all, mul #9
++**	ret
++*/
++PROTO (decd_9, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 9; }
++
++/*
++** decd_15:
++**	decd	x0, all, mul #15
++**	ret
++*/
++PROTO (decd_15, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 15; }
++
++/*
++** decd_16:
++**	decb	x0, all, mul #2
++**	ret
++*/
++PROTO (decd_16, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 16; }
++
++/*
++** decd_18:
++**	decw	x0, all, mul #9
++**	ret
++*/
++PROTO (decd_18, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 18; }
++
++/*
++** decd_30:
++**	decw	x0, all, mul #15
++**	ret
++*/
++PROTO (decd_30, uint64_t, (uint64_t x0)) { return x0 - svcntsd () * 30; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_sc.c
+new file mode 100644
+index 000000000..90fb374ba
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsd_sc.c
+@@ -0,0 +1,13 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntsd:
++**	rdsvl	(x[0-9])+, #1
++**	lsr	x0, \1, #?3
++**	ret
++*/
++PROTO (cntsd, uint64_t, ()) { return svcntsd (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_s.c
+new file mode 100644
+index 000000000..021c39a14
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_s.c
+@@ -0,0 +1,279 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cnth_1:
++**	cnth	x0
++**	ret
++*/
++PROTO (cnth_1, uint64_t, ()) { return svcntsh (); }
++
++/*
++** cnth_2:
++**	cntb	x0
++**	ret
++*/
++PROTO (cnth_2, uint64_t, ()) { return svcntsh () * 2; }
++
++/*
++** cnth_3:
++**	cnth	x0, all, mul #3
++**	ret
++*/
++PROTO (cnth_3, uint64_t, ()) { return svcntsh () * 3; }
++
++/*
++** cnth_4:
++**	cntb	x0, all, mul #2
++**	ret
++*/
++PROTO (cnth_4, uint64_t, ()) { return svcntsh () * 4; }
++
++/*
++** cnth_8:
++**	cntb	x0, all, mul #4
++**	ret
++*/
++PROTO (cnth_8, uint64_t, ()) { return svcntsh () * 8; }
++
++/*
++** cnth_15:
++**	cnth	x0, all, mul #15
++**	ret
++*/
++PROTO (cnth_15, uint64_t, ()) { return svcntsh () * 15; }
++
++/*
++** cnth_16:
++**	cntb	x0, all, mul #8
++**	ret
++*/
++PROTO (cnth_16, uint64_t, ()) { return svcntsh () * 16; }
++
++/* Other sequences would be OK.  */
++/*
++** cnth_17:
++**	rdvl	(x[0-9]+), #17
++**	asr	x0, \1, 1
++**	ret
++*/
++PROTO (cnth_17, uint64_t, ()) { return svcntsh () * 17; }
++
++/*
++** cnth_32:
++**	cntb	x0, all, mul #16
++**	ret
++*/
++PROTO (cnth_32, uint64_t, ()) { return svcntsh () * 32; }
++
++/*
++** cnth_64:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
++**	ret
++*/
++PROTO (cnth_64, uint64_t, ()) { return svcntsh () * 64; }
++
++/*
++** cnth_128:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 6
++**	ret
++*/
++PROTO (cnth_128, uint64_t, ()) { return svcntsh () * 128; }
++
++/*
++** cnth_m1:
++**	cnth	(x[0-9]+)
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cnth_m1, uint64_t, ()) { return -svcntsh (); }
++
++/*
++** cnth_m13:
++**	cnth	(x[0-9]+), all, mul #13
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cnth_m13, uint64_t, ()) { return -svcntsh () * 13; }
++
++/*
++** cnth_m15:
++**	cnth	(x[0-9]+), all, mul #15
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cnth_m15, uint64_t, ()) { return -svcntsh () * 15; }
++
++/*
++** cnth_m16:
++**	rdvl	x0, #-8
++**	ret
++*/
++PROTO (cnth_m16, uint64_t, ()) { return -svcntsh () * 16; }
++
++/* Other sequences would be OK.  */
++/*
++** cnth_m17:
++**	rdvl	(x[0-9]+), #-17
++**	asr	x0, \1, 1
++**	ret
++*/
++PROTO (cnth_m17, uint64_t, ()) { return -svcntsh () * 17; }
++
++/*
++** inch_1:
++**	inch	x0
++**	ret
++*/
++PROTO (inch_1, uint64_t, (uint64_t x0)) { return x0 + svcntsh (); }
++
++/*
++** inch_2:
++**	incb	x0
++**	ret
++*/
++PROTO (inch_2, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 2; }
++
++/*
++** inch_3:
++**	inch	x0, all, mul #3
++**	ret
++*/
++PROTO (inch_3, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 3; }
++
++/*
++** inch_4:
++**	incb	x0, all, mul #2
++**	ret
++*/
++PROTO (inch_4, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 4; }
++
++/*
++** inch_7:
++**	inch	x0, all, mul #7
++**	ret
++*/
++PROTO (inch_7, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 7; }
++
++/*
++** inch_8:
++**	incb	x0, all, mul #4
++**	ret
++*/
++PROTO (inch_8, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 8; }
++
++/*
++** inch_9:
++**	inch	x0, all, mul #9
++**	ret
++*/
++PROTO (inch_9, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 9; }
++
++/*
++** inch_15:
++**	inch	x0, all, mul #15
++**	ret
++*/
++PROTO (inch_15, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 15; }
++
++/*
++** inch_16:
++**	incb	x0, all, mul #8
++**	ret
++*/
++PROTO (inch_16, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 16; }
++
++/*
++** inch_18:
++**	incb	x0, all, mul #9
++**	ret
++*/
++PROTO (inch_18, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 18; }
++
++/*
++** inch_30:
++**	incb	x0, all, mul #15
++**	ret
++*/
++PROTO (inch_30, uint64_t, (uint64_t x0)) { return x0 + svcntsh () * 30; }
++
++/*
++** dech_1:
++**	dech	x0
++**	ret
++*/
++PROTO (dech_1, uint64_t, (uint64_t x0)) { return x0 - svcntsh (); }
++
++/*
++** dech_2:
++**	decb	x0
++**	ret
++*/
++PROTO (dech_2, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 2; }
++
++/*
++** dech_3:
++**	dech	x0, all, mul #3
++**	ret
++*/
++PROTO (dech_3, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 3; }
++
++/*
++** dech_4:
++**	decb	x0, all, mul #2
++**	ret
++*/
++PROTO (dech_4, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 4; }
++
++/*
++** dech_7:
++**	dech	x0, all, mul #7
++**	ret
++*/
++PROTO (dech_7, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 7; }
++
++/*
++** dech_8:
++**	decb	x0, all, mul #4
++**	ret
++*/
++PROTO (dech_8, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 8; }
++
++/*
++** dech_9:
++**	dech	x0, all, mul #9
++**	ret
++*/
++PROTO (dech_9, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 9; }
++
++/*
++** dech_15:
++**	dech	x0, all, mul #15
++**	ret
++*/
++PROTO (dech_15, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 15; }
++
++/*
++** dech_16:
++**	decb	x0, all, mul #8
++**	ret
++*/
++PROTO (dech_16, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 16; }
++
++/*
++** dech_18:
++**	decb	x0, all, mul #9
++**	ret
++*/
++PROTO (dech_18, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 18; }
++
++/*
++** dech_30:
++**	decb	x0, all, mul #15
++**	ret
++*/
++PROTO (dech_30, uint64_t, (uint64_t x0)) { return x0 - svcntsh () * 30; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_sc.c
+new file mode 100644
+index 000000000..9f6c85208
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsh_sc.c
+@@ -0,0 +1,13 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntsh:
++**	rdsvl	(x[0-9])+, #1
++**	lsr	x0, \1, #?1
++**	ret
++*/
++PROTO (cntsh, uint64_t, ()) { return svcntsh (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_s.c
+new file mode 100644
+index 000000000..c421e1b8e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_s.c
+@@ -0,0 +1,278 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntw_1:
++**	cntw	x0
++**	ret
++*/
++PROTO (cntw_1, uint64_t, ()) { return svcntsw (); }
++
++/*
++** cntw_2:
++**	cnth	x0
++**	ret
++*/
++PROTO (cntw_2, uint64_t, ()) { return svcntsw () * 2; }
++
++/*
++** cntw_3:
++**	cntw	x0, all, mul #3
++**	ret
++*/
++PROTO (cntw_3, uint64_t, ()) { return svcntsw () * 3; }
++
++/*
++** cntw_4:
++**	cntb	x0
++**	ret
++*/
++PROTO (cntw_4, uint64_t, ()) { return svcntsw () * 4; }
++
++/*
++** cntw_8:
++**	cntb	x0, all, mul #2
++**	ret
++*/
++PROTO (cntw_8, uint64_t, ()) { return svcntsw () * 8; }
++
++/*
++** cntw_15:
++**	cntw	x0, all, mul #15
++**	ret
++*/
++PROTO (cntw_15, uint64_t, ()) { return svcntsw () * 15; }
++
++/*
++** cntw_16:
++**	cntb	x0, all, mul #4
++**	ret
++*/
++PROTO (cntw_16, uint64_t, ()) { return svcntsw () * 16; }
++
++/* Other sequences would be OK.  */
++/*
++** cntw_17:
++**	rdvl	(x[0-9]+), #17
++**	asr	x0, \1, 2
++**	ret
++*/
++PROTO (cntw_17, uint64_t, ()) { return svcntsw () * 17; }
++
++/*
++** cntw_32:
++**	cntb	x0, all, mul #8
++**	ret
++*/
++PROTO (cntw_32, uint64_t, ()) { return svcntsw () * 32; }
++
++/*
++** cntw_64:
++**	cntb	x0, all, mul #16
++**	ret
++*/
++PROTO (cntw_64, uint64_t, ()) { return svcntsw () * 64; }
++
++/*
++** cntw_128:
++**	cntb	(x[0-9]+)
++**	lsl	x0, \1, 5
++**	ret
++*/
++PROTO (cntw_128, uint64_t, ()) { return svcntsw () * 128; }
++
++/*
++** cntw_m1:
++**	cntw	(x[0-9]+)
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cntw_m1, uint64_t, ()) { return -svcntsw (); }
++
++/*
++** cntw_m13:
++**	cntw	(x[0-9]+), all, mul #13
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cntw_m13, uint64_t, ()) { return -svcntsw () * 13; }
++
++/*
++** cntw_m15:
++**	cntw	(x[0-9]+), all, mul #15
++**	neg	x0, \1
++**	ret
++*/
++PROTO (cntw_m15, uint64_t, ()) { return -svcntsw () * 15; }
++
++/*
++** cntw_m16:
++**	rdvl	(x[0-9]+), #-4
++**	ret
++*/
++PROTO (cntw_m16, uint64_t, ()) { return -svcntsw () * 16; }
++
++/* Other sequences would be OK.  */
++/*
++** cntw_m17:
++**	rdvl	(x[0-9]+), #-17
++**	asr	x0, \1, 2
++**	ret
++*/
++PROTO (cntw_m17, uint64_t, ()) { return -svcntsw () * 17; }
++
++/*
++** incw_1:
++**	incw	x0
++**	ret
++*/
++PROTO (incw_1, uint64_t, (uint64_t x0)) { return x0 + svcntsw (); }
++
++/*
++** incw_2:
++**	inch	x0
++**	ret
++*/
++PROTO (incw_2, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 2; }
++
++/*
++** incw_3:
++**	incw	x0, all, mul #3
++**	ret
++*/
++PROTO (incw_3, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 3; }
++
++/*
++** incw_4:
++**	incb	x0
++**	ret
++*/
++PROTO (incw_4, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 4; }
++
++/*
++** incw_7:
++**	incw	x0, all, mul #7
++**	ret
++*/
++PROTO (incw_7, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 7; }
++
++/*
++** incw_8:
++**	incb	x0, all, mul #2
++**	ret
++*/
++PROTO (incw_8, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 8; }
++
++/*
++** incw_9:
++**	incw	x0, all, mul #9
++**	ret
++*/
++PROTO (incw_9, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 9; }
++
++/*
++** incw_15:
++**	incw	x0, all, mul #15
++**	ret
++*/
++PROTO (incw_15, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 15; }
++
++/*
++** incw_16:
++**	incb	x0, all, mul #4
++**	ret
++*/
++PROTO (incw_16, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 16; }
++
++/*
++** incw_18:
++**	inch	x0, all, mul #9
++**	ret
++*/
++PROTO (incw_18, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 18; }
++
++/*
++** incw_30:
++**	inch	x0, all, mul #15
++**	ret
++*/
++PROTO (incw_30, uint64_t, (uint64_t x0)) { return x0 + svcntsw () * 30; }
++
++/*
++** decw_1:
++**	decw	x0
++**	ret
++*/
++PROTO (decw_1, uint64_t, (uint64_t x0)) { return x0 - svcntsw (); }
++
++/*
++** decw_2:
++**	dech	x0
++**	ret
++*/
++PROTO (decw_2, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 2; }
++
++/*
++** decw_3:
++**	decw	x0, all, mul #3
++**	ret
++*/
++PROTO (decw_3, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 3; }
++
++/*
++** decw_4:
++**	decb	x0
++**	ret
++*/
++PROTO (decw_4, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 4; }
++
++/*
++** decw_7:
++**	decw	x0, all, mul #7
++**	ret
++*/
++PROTO (decw_7, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 7; }
++
++/*
++** decw_8:
++**	decb	x0, all, mul #2
++**	ret
++*/
++PROTO (decw_8, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 8; }
++
++/*
++** decw_9:
++**	decw	x0, all, mul #9
++**	ret
++*/
++PROTO (decw_9, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 9; }
++
++/*
++** decw_15:
++**	decw	x0, all, mul #15
++**	ret
++*/
++PROTO (decw_15, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 15; }
++
++/*
++** decw_16:
++**	decb	x0, all, mul #4
++**	ret
++*/
++PROTO (decw_16, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 16; }
++
++/*
++** decw_18:
++**	dech	x0, all, mul #9
++**	ret
++*/
++PROTO (decw_18, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 18; }
++
++/*
++** decw_30:
++**	dech	x0, all, mul #15
++**	ret
++*/
++PROTO (decw_30, uint64_t, (uint64_t x0)) { return x0 - svcntsw () * 30; }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_sc.c
+new file mode 100644
+index 000000000..75ca937c4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/cntsw_sc.c
+@@ -0,0 +1,13 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#define NO_SHARED_ZA
++#include "test_sme_acle.h"
++
++/*
++** cntsw:
++**	rdsvl	(x[0-9])+, #1
++**	lsr	x0, \1, #?2
++**	ret
++*/
++PROTO (cntsw, uint64_t, ()) { return svcntsw (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za128.c
+new file mode 100644
+index 000000000..fbbeb4f12
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za128.c
+@@ -0,0 +1,77 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za128_0_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1q	{ za0h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_0_0_0,
++	      svld1_hor_vnum_za128 (0, 0, p0, x1, 0),
++	      svld1_hor_vnum_za128 (0, 0, p0, x1, 0))
++
++/*
++** ld1_vnum_za128_7_1_0:
++**	mov	(w1[2-5]), #?1
++**	ld1q	{ za7h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_7_1_0,
++	      svld1_hor_vnum_za128 (7, 1, p0, x1, 0),
++	      svld1_hor_vnum_za128 (7, 1, p0, x1, 0))
++
++/*
++** ld1_vnum_za128_11_1_5:
++**	incb	x1, all, mul #5
++**	mov	(w1[2-5]), #?6
++**	ld1q	{ za11h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_11_1_5,
++	      svld1_hor_vnum_za128 (11, 1, p0, x1, 5),
++	      svld1_hor_vnum_za128 (11, 1, p0, x1, 5))
++
++/*
++** ld1_vnum_za128_3_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za3h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_3_w0_0,
++	      svld1_hor_vnum_za128 (3, w0, p0, x1, 0),
++	      svld1_hor_vnum_za128 (3, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za128_5_w0_0:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1q	{ za5h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_5_w0_0,
++	      svld1_hor_vnum_za128 (5, w0, p0, x1, 13),
++	      svld1_hor_vnum_za128 (5, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za128_11_w0_0:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1q	{ za11h\.q\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_11_w0_0,
++	      svld1_hor_vnum_za128 (11, w0, p0, x1, x2),
++	      svld1_hor_vnum_za128 (11, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za128_15_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	ld1q	{ za15h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_15_w0p1_0,
++	      svld1_hor_vnum_za128 (15, w0 + 1, p0, x1, 0),
++	      svld1_hor_vnum_za128 (15, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za16.c
+new file mode 100644
+index 000000000..30e7a71ed
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za16.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za16_1_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1h	{ za1h\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_0_1,
++	      svld1_hor_vnum_za16 (1, 0, p0, x1, 1),
++	      svld1_hor_vnum_za16 (1, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za16_1_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1h	{ za1h\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_1_1,
++	      svld1_hor_vnum_za16 (1, 1, p0, x1, 1),
++	      svld1_hor_vnum_za16 (1, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za16_0_0_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?8
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_0_8,
++	      svld1_hor_vnum_za16 (0, 0, p0, x1, 8),
++	      svld1_hor_vnum_za16 (0, 0, p0, x1, 8))
++
++/*
++** ld1_vnum_za16_0_1_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?9
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_1_8,
++	      svld1_hor_vnum_za16 (0, 1, p0, x1, 8),
++	      svld1_hor_vnum_za16 (0, 1, p0, x1, 8))
++
++/*
++** ld1_vnum_za16_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_0,
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, 0),
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za16_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0h\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_1,
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, 1),
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za16_0_w0_7:
++**	incb	x1, all, mul #7
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0h\.h\[\1, 7\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_7,
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, 7),
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, 7))
++
++/*
++** ld1_vnum_za16_1_w0_8:
++**	incb	x1, all, mul #8
++**	add	(w1[2-5]), w0, #?8
++**	ld1h	{ za1h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_w0_8,
++	      svld1_hor_vnum_za16 (1, w0, p0, x1, 8),
++	      svld1_hor_vnum_za16 (1, w0, p0, x1, 8))
++
++/*
++** ld1_vnum_za16_1_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1h	{ za1h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_w0_13,
++	      svld1_hor_vnum_za16 (1, w0, p0, x1, 13),
++	      svld1_hor_vnum_za16 (1, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za16_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1h	{ za0h\.h\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_x2,
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, x2),
++	      svld1_hor_vnum_za16 (0, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za16_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1h\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_w0p1_0,
++	      svld1_hor_vnum_za16 (1, w0 + 1, p0, x1, 0),
++	      svld1_hor_vnum_za16 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za32.c
+new file mode 100644
+index 000000000..49ffaede8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za32.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za32_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1w	{ za3h\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_3_0_1,
++	      svld1_hor_vnum_za32 (3, 0, p0, x1, 1),
++	      svld1_hor_vnum_za32 (3, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za32_2_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1w	{ za2h\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_2_1_1,
++	      svld1_hor_vnum_za32 (2, 1, p0, x1, 1),
++	      svld1_hor_vnum_za32 (2, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za32_0_0_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?4
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_0_4,
++	      svld1_hor_vnum_za32 (0, 0, p0, x1, 4),
++	      svld1_hor_vnum_za32 (0, 0, p0, x1, 4))
++
++/*
++** ld1_vnum_za32_2_1_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?5
++**	ld1w	{ za2h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_2_1_4,
++	      svld1_hor_vnum_za32 (2, 1, p0, x1, 4),
++	      svld1_hor_vnum_za32 (2, 1, p0, x1, 4))
++
++/*
++** ld1_vnum_za32_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_0,
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, 0),
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za32_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0h\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_1,
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, 1),
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za32_0_w0_3:
++**	incb	x1, all, mul #3
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0h\.s\[\1, 3\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_3,
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, 3),
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, 3))
++
++/*
++** ld1_vnum_za32_1_w0_4:
++**	incb	x1, all, mul #4
++**	add	(w1[2-5]), w0, #?4
++**	ld1w	{ za1h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_1_w0_4,
++	      svld1_hor_vnum_za32 (1, w0, p0, x1, 4),
++	      svld1_hor_vnum_za32 (1, w0, p0, x1, 4))
++
++/*
++** ld1_vnum_za32_3_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1w	{ za3h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_3_w0_13,
++	      svld1_hor_vnum_za32 (3, w0, p0, x1, 13),
++	      svld1_hor_vnum_za32 (3, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za32_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1w	{ za0h\.s\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_x2,
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, x2),
++	      svld1_hor_vnum_za32 (0, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za32_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za1h\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_1_w0p1_0,
++	      svld1_hor_vnum_za32 (1, w0 + 1, p0, x1, 0),
++	      svld1_hor_vnum_za32 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za64.c
+new file mode 100644
+index 000000000..df09b1c81
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za64.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za64_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1d	{ za3h\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_3_0_1,
++	      svld1_hor_vnum_za64 (3, 0, p0, x1, 1),
++	      svld1_hor_vnum_za64 (3, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za64_7_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1d	{ za7h\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_7_1_1,
++	      svld1_hor_vnum_za64 (7, 1, p0, x1, 1),
++	      svld1_hor_vnum_za64 (7, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za64_0_0_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?2
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_0_0_2,
++	      svld1_hor_vnum_za64 (0, 0, p0, x1, 2),
++	      svld1_hor_vnum_za64 (0, 0, p0, x1, 2))
++
++/*
++** ld1_vnum_za64_5_1_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?3
++**	ld1d	{ za5h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_5_1_2,
++	      svld1_hor_vnum_za64 (5, 1, p0, x1, 2),
++	      svld1_hor_vnum_za64 (5, 1, p0, x1, 2))
++
++/*
++** ld1_vnum_za64_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_0_w0_0,
++	      svld1_hor_vnum_za64 (0, w0, p0, x1, 0),
++	      svld1_hor_vnum_za64 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za64_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0h\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_0_w0_1,
++	      svld1_hor_vnum_za64 (0, w0, p0, x1, 1),
++	      svld1_hor_vnum_za64 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za64_6_w0_2:
++**	incb	x1, all, mul #2
++**	add	(w1[2-5]), w0, #?2
++**	ld1d	{ za6h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_6_w0_2,
++	      svld1_hor_vnum_za64 (6, w0, p0, x1, 2),
++	      svld1_hor_vnum_za64 (6, w0, p0, x1, 2))
++
++/*
++** ld1_vnum_za64_2_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1d	{ za2h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_2_w0_13,
++	      svld1_hor_vnum_za64 (2, w0, p0, x1, 13),
++	      svld1_hor_vnum_za64 (2, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za64_4_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1d	{ za4h\.d\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_4_w0_x2,
++	      svld1_hor_vnum_za64 (4, w0, p0, x1, x2),
++	      svld1_hor_vnum_za64 (4, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za64_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za1h\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_1_w0p1_0,
++	      svld1_hor_vnum_za64 (1, w0 + 1, p0, x1, 0),
++	      svld1_hor_vnum_za64 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za8.c
+new file mode 100644
+index 000000000..c42931d3e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_vnum_za8.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za8_0_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1b	{ za0h\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_0_1,
++	      svld1_hor_vnum_za8 (0, 0, p0, x1, 1),
++	      svld1_hor_vnum_za8 (0, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za8_0_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1b	{ za0h\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_1_1,
++	      svld1_hor_vnum_za8 (0, 1, p0, x1, 1),
++	      svld1_hor_vnum_za8 (0, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za8_0_0_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?16
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_0_16,
++	      svld1_hor_vnum_za8 (0, 0, p0, x1, 16),
++	      svld1_hor_vnum_za8 (0, 0, p0, x1, 16))
++
++/*
++** ld1_vnum_za8_0_1_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?17
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_1_16,
++	      svld1_hor_vnum_za8 (0, 1, p0, x1, 16),
++	      svld1_hor_vnum_za8 (0, 1, p0, x1, 16))
++
++/*
++** ld1_vnum_za8_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_0,
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 0),
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za8_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_1,
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 1),
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za8_0_w0_15:
++**	incb	x1, all, mul #15
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 15\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_15,
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 15),
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 15))
++
++/*
++** ld1_vnum_za8_0_w0_16:
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_16,
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 16),
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, 16))
++
++/*
++** ld1_vnum_za8_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	mul	(x[0-9]+), (?:\1, x2|x2, \1)
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1b	{ za0h\.b\[\3, 0\] }, p0/z, \[x1, \2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_x2,
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, x2),
++	      svld1_hor_vnum_za8 (0, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za8_0_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0p1_0,
++	      svld1_hor_vnum_za8 (0, w0 + 1, p0, x1, 0),
++	      svld1_hor_vnum_za8 (0, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za128.c
+new file mode 100644
+index 000000000..2c6292217
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za128.c
+@@ -0,0 +1,83 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za128_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1q	{ za0h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_0,
++	      svld1_hor_za128 (0, 0, p0, x1),
++	      svld1_hor_za128 (0, 0, p0, x1))
++
++/*
++** ld1_za128_0_1:
++**	mov	(w1[2-5]), #?1
++**	ld1q	{ za0h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_1,
++	      svld1_hor_za128 (0, 1, p0, x1),
++	      svld1_hor_za128 (0, 1, p0, x1))
++
++/*
++** ld1_za128_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za0h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_w0,
++	      svld1_hor_za128 (0, w0, p0, x1),
++	      svld1_hor_za128 (0, w0, p0, x1))
++
++/*
++** ld1_za128_0_w0_p1:
++**	add	(w1[2-5]), w0, #?1
++**	ld1q	{ za0h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_w0_p1,
++	      svld1_hor_za128 (0, w0 + 1, p0, x1),
++	      svld1_hor_za128 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za128_7_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za7h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_7_w0,
++	      svld1_hor_za128 (7, w0, p0, x1),
++	      svld1_hor_za128 (7, w0, p0, x1))
++
++/*
++** ld1_za128_13_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za13h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_13_w0,
++	      svld1_hor_za128 (13, w0, p0, x1),
++	      svld1_hor_za128 (13, w0, p0, x1))
++
++/*
++** ld1_za128_15_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za15h\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_15_w0,
++	      svld1_hor_za128 (15, w0, p0, x1),
++	      svld1_hor_za128 (15, w0, p0, x1))
++
++/*
++** ld1_za128_9_w0_index:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za9h\.q\[\1, 0\] }, p0/z, \[x1, x2, lsl #?4\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_9_w0_index,
++	      svld1_hor_za128 (9, w0, p0, x1 + x2 * 16),
++	      svld1_hor_za128 (9, w0, p0, x1 + x2 * 16))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za16.c
+new file mode 100644
+index 000000000..3570bea61
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za16.c
+@@ -0,0 +1,126 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za16_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_0,
++	      svld1_hor_za16 (0, 0, p0, x1),
++	      svld1_hor_za16 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 7.  */
++/*
++** ld1_za16_0_7:
++**	mov	(w1[2-5]), #?7
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_7,
++	      svld1_hor_za16 (0, 7, p0, x1),
++	      svld1_hor_za16 (0, 7, p0, x1))
++
++/*
++** ld1_za16_0_8:
++**	mov	(w1[2-5]), #?8
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_8,
++	      svld1_hor_za16 (0, 8, p0, x1),
++	      svld1_hor_za16 (0, 8, p0, x1))
++
++/*
++** ld1_za16_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0,
++	      svld1_hor_za16 (0, w0, p0, x1),
++	      svld1_hor_za16 (0, w0, p0, x1))
++
++/*
++** ld1_za16_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0h\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_p1,
++	      svld1_hor_za16 (0, w0 + 1, p0, x1),
++	      svld1_hor_za16 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za16_0_w0_p7:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0h\.h\[\1, 7\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_p7,
++	      svld1_hor_za16 (0, w0 + 7, p0, x1),
++	      svld1_hor_za16 (0, w0 + 7, p0, x1))
++
++/*
++** ld1_za16_1_w0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0,
++	      svld1_hor_za16 (1, w0, p0, x1),
++	      svld1_hor_za16 (1, w0, p0, x1))
++
++
++/*
++** ld1_za16_1_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1h\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0_p1,
++	      svld1_hor_za16 (1, w0 + 1, p0, x1),
++	      svld1_hor_za16 (1, w0 + 1, p0, x1))
++
++/*
++** ld1_za16_1_w0_p7:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1h\.h\[\1, 7\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0_p7,
++	      svld1_hor_za16 (1, w0 + 7, p0, x1),
++	      svld1_hor_za16 (1, w0 + 7, p0, x1))
++
++/*
++** ld1_za16_1_w0_p5_index:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1h\.h\[\1, 5\] }, p0/z, \[x1, x2, lsl #?1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0_p5_index,
++	      svld1_hor_za16 (1, w0 + 5, p0, x1 + x2 * 2),
++	      svld1_hor_za16 (1, w0 + 5, p0, x1 + x2 * 2))
++
++/*
++** ld1_za16_0_w0_p8:
++**	add	(w1[2-5]), w0, #?8
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_p8,
++	      svld1_hor_za16 (0, w0 + 8, p0, x1),
++	      svld1_hor_za16 (0, w0 + 8, p0, x1))
++
++/*
++** ld1_za16_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1h	{ za0h\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_m1,
++	      svld1_hor_za16 (0, w0 - 1, p0, x1),
++	      svld1_hor_za16 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za32.c
+new file mode 100644
+index 000000000..a8f6606bd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za32.c
+@@ -0,0 +1,125 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za32_0_0:
++**	mov	(w1[2-5]), (?:w0|#?0)
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_0,
++	      svld1_hor_za32 (0, 0, p0, x1),
++	      svld1_hor_za32 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 3.  */
++/*
++** ld1_za32_0_3:
++**	mov	(w1[2-5]), #?3
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_3,
++	      svld1_hor_za32 (0, 3, p0, x1),
++	      svld1_hor_za32 (0, 3, p0, x1))
++
++/*
++** ld1_za32_0_4:
++**	mov	(w1[2-5]), #?4
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_4,
++	      svld1_hor_za32 (0, 4, p0, x1),
++	      svld1_hor_za32 (0, 4, p0, x1))
++
++/*
++** ld1_za32_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0,
++	      svld1_hor_za32 (0, w0, p0, x1),
++	      svld1_hor_za32 (0, w0, p0, x1))
++
++/*
++** ld1_za32_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0h\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_p1,
++	      svld1_hor_za32 (0, w0 + 1, p0, x1),
++	      svld1_hor_za32 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za32_0_w0_p3:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0h\.s\[\1, 3\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_p3,
++	      svld1_hor_za32 (0, w0 + 3, p0, x1),
++	      svld1_hor_za32 (0, w0 + 3, p0, x1))
++
++/*
++** ld1_za32_3_w0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za3h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_3_w0,
++	      svld1_hor_za32 (3, w0, p0, x1),
++	      svld1_hor_za32 (3, w0, p0, x1))
++
++/*
++** ld1_za32_3_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za3h\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_3_w0_p1,
++	      svld1_hor_za32 (3, w0 + 1, p0, x1),
++	      svld1_hor_za32 (3, w0 + 1, p0, x1))
++
++/*
++** ld1_za32_3_w0_p3:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za3h\.s\[\1, 3\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_3_w0_p3,
++	      svld1_hor_za32 (3, w0 + 3, p0, x1),
++	      svld1_hor_za32 (3, w0 + 3, p0, x1))
++
++/*
++** ld1_za32_1_w0_p2_index:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za1h\.s\[\1, 2\] }, p0/z, \[x1, x2, lsl #?2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_1_w0_p2_index,
++	      svld1_hor_za32 (1, w0 + 2, p0, x1 + x2 * 4),
++	      svld1_hor_za32 (1, w0 + 2, p0, x1 + x2 * 4))
++
++/*
++** ld1_za32_0_w0_p4:
++**	add	(w1[2-5]), w0, #?4
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_p4,
++	      svld1_hor_za32 (0, w0 + 4, p0, x1),
++	      svld1_hor_za32 (0, w0 + 4, p0, x1))
++
++/*
++** ld1_za32_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1w	{ za0h\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_m1,
++	      svld1_hor_za32 (0, w0 - 1, p0, x1),
++	      svld1_hor_za32 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za64.c
+new file mode 100644
+index 000000000..f4573eb71
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za64.c
+@@ -0,0 +1,105 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za64_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_0,
++	      svld1_hor_za64 (0, 0, p0, x1),
++	      svld1_hor_za64 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 1.  */
++/*
++** ld1_za64_0_1:
++**	mov	(w1[2-5]), #?1
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_1,
++	      svld1_hor_za64 (0, 1, p0, x1),
++	      svld1_hor_za64 (0, 1, p0, x1))
++
++/*
++** ld1_za64_0_2:
++**	mov	(w1[2-5]), #?2
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_2,
++	      svld1_hor_za64 (0, 2, p0, x1),
++	      svld1_hor_za64 (0, 2, p0, x1))
++
++/*
++** ld1_za64_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0,
++	      svld1_hor_za64 (0, w0, p0, x1),
++	      svld1_hor_za64 (0, w0, p0, x1))
++
++/*
++** ld1_za64_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0h\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0_p1,
++	      svld1_hor_za64 (0, w0 + 1, p0, x1),
++	      svld1_hor_za64 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za64_7_w0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za7h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_7_w0,
++	      svld1_hor_za64 (7, w0, p0, x1),
++	      svld1_hor_za64 (7, w0, p0, x1))
++
++/*
++** ld1_za64_7_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za7h\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_7_w0_p1,
++	      svld1_hor_za64 (7, w0 + 1, p0, x1),
++	      svld1_hor_za64 (7, w0 + 1, p0, x1))
++
++/*
++** ld1_za64_5_w0_p1_index:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za5h\.d\[\1, 1\] }, p0/z, \[x1, x2, lsl #?3\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_5_w0_p1_index,
++	      svld1_hor_za64 (5, w0 + 1, p0, x1 + x2 * 8),
++	      svld1_hor_za64 (5, w0 + 1, p0, x1 + x2 * 8))
++
++/*
++** ld1_za64_0_w0_p2:
++**	add	(w1[2-5]), w0, #?2
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0_p2,
++	      svld1_hor_za64 (0, w0 + 2, p0, x1),
++	      svld1_hor_za64 (0, w0 + 2, p0, x1))
++
++/*
++** ld1_za64_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1d	{ za0h\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0_m1,
++	      svld1_hor_za64 (0, w0 - 1, p0, x1),
++	      svld1_hor_za64 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za8.c
+new file mode 100644
+index 000000000..eef0927cd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_hor_za8.c
+@@ -0,0 +1,95 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za8_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_0,
++	      svld1_hor_za8 (0, 0, p0, x1),
++	      svld1_hor_za8 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 15.  */
++/*
++** ld1_za8_0_15:
++**	mov	(w1[2-5]), #?15
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_15,
++	      svld1_hor_za8 (0, 15, p0, x1),
++	      svld1_hor_za8 (0, 15, p0, x1))
++
++/*
++** ld1_za8_0_16:
++**	mov	(w1[2-5]), #?16
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_16,
++	      svld1_hor_za8 (0, 16, p0, x1),
++	      svld1_hor_za8 (0, 16, p0, x1))
++
++/*
++** ld1_za8_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0,
++	      svld1_hor_za8 (0, w0, p0, x1),
++	      svld1_hor_za8 (0, w0, p0, x1))
++
++/*
++** ld1_za8_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p1,
++	      svld1_hor_za8 (0, w0 + 1, p0, x1),
++	      svld1_hor_za8 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za8_0_w0_p15:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 15\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p15,
++	      svld1_hor_za8 (0, w0 + 15, p0, x1),
++	      svld1_hor_za8 (0, w0 + 15, p0, x1))
++
++/*
++** ld1_za8_0_w0_p13_index:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0h\.b\[\1, 15\] }, p0/z, \[x1, x2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p13_index,
++	      svld1_hor_za8 (0, w0 + 15, p0, x1 + x2),
++	      svld1_hor_za8 (0, w0 + 15, p0, x1 + x2))
++
++/*
++** ld1_za8_0_w0_p16:
++**	add	(w1[2-5]), w0, #?16
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p16,
++	      svld1_hor_za8 (0, w0 + 16, p0, x1),
++	      svld1_hor_za8 (0, w0 + 16, p0, x1))
++
++/*
++** ld1_za8_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1b	{ za0h\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_m1,
++	      svld1_hor_za8 (0, w0 - 1, p0, x1),
++	      svld1_hor_za8 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za128.c
+new file mode 100644
+index 000000000..e90da4b33
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za128.c
+@@ -0,0 +1,77 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za128_0_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1q	{ za0v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_0_0_0,
++	      svld1_ver_vnum_za128 (0, 0, p0, x1, 0),
++	      svld1_ver_vnum_za128 (0, 0, p0, x1, 0))
++
++/*
++** ld1_vnum_za128_7_1_0:
++**	mov	(w1[2-5]), #?1
++**	ld1q	{ za7v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_7_1_0,
++	      svld1_ver_vnum_za128 (7, 1, p0, x1, 0),
++	      svld1_ver_vnum_za128 (7, 1, p0, x1, 0))
++
++/*
++** ld1_vnum_za128_11_1_5:
++**	incb	x1, all, mul #5
++**	mov	(w1[2-5]), #?6
++**	ld1q	{ za11v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_11_1_5,
++	      svld1_ver_vnum_za128 (11, 1, p0, x1, 5),
++	      svld1_ver_vnum_za128 (11, 1, p0, x1, 5))
++
++/*
++** ld1_vnum_za128_3_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za3v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_3_w0_0,
++	      svld1_ver_vnum_za128 (3, w0, p0, x1, 0),
++	      svld1_ver_vnum_za128 (3, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za128_5_w0_0:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1q	{ za5v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_5_w0_0,
++	      svld1_ver_vnum_za128 (5, w0, p0, x1, 13),
++	      svld1_ver_vnum_za128 (5, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za128_11_w0_0:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1q	{ za11v\.q\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_11_w0_0,
++	      svld1_ver_vnum_za128 (11, w0, p0, x1, x2),
++	      svld1_ver_vnum_za128 (11, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za128_15_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	ld1q	{ za15v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za128_15_w0p1_0,
++	      svld1_ver_vnum_za128 (15, w0 + 1, p0, x1, 0),
++	      svld1_ver_vnum_za128 (15, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za16.c
+new file mode 100644
+index 000000000..7868cf4ea
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za16.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za16_1_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1h	{ za1v\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_0_1,
++	      svld1_ver_vnum_za16 (1, 0, p0, x1, 1),
++	      svld1_ver_vnum_za16 (1, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za16_1_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1h	{ za1v\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_1_1,
++	      svld1_ver_vnum_za16 (1, 1, p0, x1, 1),
++	      svld1_ver_vnum_za16 (1, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za16_0_0_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?8
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_0_8,
++	      svld1_ver_vnum_za16 (0, 0, p0, x1, 8),
++	      svld1_ver_vnum_za16 (0, 0, p0, x1, 8))
++
++/*
++** ld1_vnum_za16_0_1_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?9
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_1_8,
++	      svld1_ver_vnum_za16 (0, 1, p0, x1, 8),
++	      svld1_ver_vnum_za16 (0, 1, p0, x1, 8))
++
++/*
++** ld1_vnum_za16_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_0,
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, 0),
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za16_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0v\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_1,
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, 1),
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za16_0_w0_7:
++**	incb	x1, all, mul #7
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0v\.h\[\1, 7\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_7,
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, 7),
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, 7))
++
++/*
++** ld1_vnum_za16_1_w0_8:
++**	incb	x1, all, mul #8
++**	add	(w1[2-5]), w0, #?8
++**	ld1h	{ za1v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_w0_8,
++	      svld1_ver_vnum_za16 (1, w0, p0, x1, 8),
++	      svld1_ver_vnum_za16 (1, w0, p0, x1, 8))
++
++/*
++** ld1_vnum_za16_1_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1h	{ za1v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_w0_13,
++	      svld1_ver_vnum_za16 (1, w0, p0, x1, 13),
++	      svld1_ver_vnum_za16 (1, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za16_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1h	{ za0v\.h\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_0_w0_x2,
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, x2),
++	      svld1_ver_vnum_za16 (0, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za16_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1v\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za16_1_w0p1_0,
++	      svld1_ver_vnum_za16 (1, w0 + 1, p0, x1, 0),
++	      svld1_ver_vnum_za16 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za32.c
+new file mode 100644
+index 000000000..053b60140
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za32.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za32_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1w	{ za3v\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_3_0_1,
++	      svld1_ver_vnum_za32 (3, 0, p0, x1, 1),
++	      svld1_ver_vnum_za32 (3, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za32_2_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1w	{ za2v\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_2_1_1,
++	      svld1_ver_vnum_za32 (2, 1, p0, x1, 1),
++	      svld1_ver_vnum_za32 (2, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za32_0_0_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?4
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_0_4,
++	      svld1_ver_vnum_za32 (0, 0, p0, x1, 4),
++	      svld1_ver_vnum_za32 (0, 0, p0, x1, 4))
++
++/*
++** ld1_vnum_za32_2_1_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?5
++**	ld1w	{ za2v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_2_1_4,
++	      svld1_ver_vnum_za32 (2, 1, p0, x1, 4),
++	      svld1_ver_vnum_za32 (2, 1, p0, x1, 4))
++
++/*
++** ld1_vnum_za32_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_0,
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, 0),
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za32_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0v\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_1,
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, 1),
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za32_0_w0_3:
++**	incb	x1, all, mul #3
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0v\.s\[\1, 3\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_3,
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, 3),
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, 3))
++
++/*
++** ld1_vnum_za32_1_w0_4:
++**	incb	x1, all, mul #4
++**	add	(w1[2-5]), w0, #?4
++**	ld1w	{ za1v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_1_w0_4,
++	      svld1_ver_vnum_za32 (1, w0, p0, x1, 4),
++	      svld1_ver_vnum_za32 (1, w0, p0, x1, 4))
++
++/*
++** ld1_vnum_za32_3_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1w	{ za3v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_3_w0_13,
++	      svld1_ver_vnum_za32 (3, w0, p0, x1, 13),
++	      svld1_ver_vnum_za32 (3, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za32_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1w	{ za0v\.s\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_0_w0_x2,
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, x2),
++	      svld1_ver_vnum_za32 (0, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za32_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za1v\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za32_1_w0p1_0,
++	      svld1_ver_vnum_za32 (1, w0 + 1, p0, x1, 0),
++	      svld1_ver_vnum_za32 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za64.c
+new file mode 100644
+index 000000000..d04764979
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za64.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za64_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1d	{ za3v\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_3_0_1,
++	      svld1_ver_vnum_za64 (3, 0, p0, x1, 1),
++	      svld1_ver_vnum_za64 (3, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za64_7_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1d	{ za7v\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_7_1_1,
++	      svld1_ver_vnum_za64 (7, 1, p0, x1, 1),
++	      svld1_ver_vnum_za64 (7, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za64_0_0_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?2
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_0_0_2,
++	      svld1_ver_vnum_za64 (0, 0, p0, x1, 2),
++	      svld1_ver_vnum_za64 (0, 0, p0, x1, 2))
++
++/*
++** ld1_vnum_za64_5_1_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?3
++**	ld1d	{ za5v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_5_1_2,
++	      svld1_ver_vnum_za64 (5, 1, p0, x1, 2),
++	      svld1_ver_vnum_za64 (5, 1, p0, x1, 2))
++
++/*
++** ld1_vnum_za64_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_0_w0_0,
++	      svld1_ver_vnum_za64 (0, w0, p0, x1, 0),
++	      svld1_ver_vnum_za64 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za64_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0v\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_0_w0_1,
++	      svld1_ver_vnum_za64 (0, w0, p0, x1, 1),
++	      svld1_ver_vnum_za64 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za64_6_w0_2:
++**	incb	x1, all, mul #2
++**	add	(w1[2-5]), w0, #?2
++**	ld1d	{ za6v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_6_w0_2,
++	      svld1_ver_vnum_za64 (6, w0, p0, x1, 2),
++	      svld1_ver_vnum_za64 (6, w0, p0, x1, 2))
++
++/*
++** ld1_vnum_za64_2_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	ld1d	{ za2v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_2_w0_13,
++	      svld1_ver_vnum_za64 (2, w0, p0, x1, 13),
++	      svld1_ver_vnum_za64 (2, w0, p0, x1, 13))
++
++/*
++** ld1_vnum_za64_4_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1d	{ za4v\.d\[\3, 0\] }, p0/z, \[\2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_4_w0_x2,
++	      svld1_ver_vnum_za64 (4, w0, p0, x1, x2),
++	      svld1_ver_vnum_za64 (4, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za64_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za1v\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za64_1_w0p1_0,
++	      svld1_ver_vnum_za64 (1, w0 + 1, p0, x1, 0),
++	      svld1_ver_vnum_za64 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za8.c
+new file mode 100644
+index 000000000..e99d95e3a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_vnum_za8.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_vnum_za8_0_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1b	{ za0v\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_0_1,
++	      svld1_ver_vnum_za8 (0, 0, p0, x1, 1),
++	      svld1_ver_vnum_za8 (0, 0, p0, x1, 1))
++
++/*
++** ld1_vnum_za8_0_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	ld1b	{ za0v\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_1_1,
++	      svld1_ver_vnum_za8 (0, 1, p0, x1, 1),
++	      svld1_ver_vnum_za8 (0, 1, p0, x1, 1))
++
++/*
++** ld1_vnum_za8_0_0_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?16
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_0_16,
++	      svld1_ver_vnum_za8 (0, 0, p0, x1, 16),
++	      svld1_ver_vnum_za8 (0, 0, p0, x1, 16))
++
++/*
++** ld1_vnum_za8_0_1_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?17
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_1_16,
++	      svld1_ver_vnum_za8 (0, 1, p0, x1, 16),
++	      svld1_ver_vnum_za8 (0, 1, p0, x1, 16))
++
++/*
++** ld1_vnum_za8_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_0,
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 0),
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 0))
++
++/*
++** ld1_vnum_za8_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_1,
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 1),
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 1))
++
++/*
++** ld1_vnum_za8_0_w0_15:
++**	incb	x1, all, mul #15
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 15\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_15,
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 15),
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 15))
++
++/*
++** ld1_vnum_za8_0_w0_16:
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_16,
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 16),
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, 16))
++
++/*
++** ld1_vnum_za8_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	mul	(x[0-9]+), (?:\1, x2|x2, \1)
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	ld1b	{ za0v\.b\[\3, 0\] }, p0/z, \[x1, \2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0_x2,
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, x2),
++	      svld1_ver_vnum_za8 (0, w0, p0, x1, x2))
++
++/*
++** ld1_vnum_za8_0_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_vnum_za8_0_w0p1_0,
++	      svld1_ver_vnum_za8 (0, w0 + 1, p0, x1, 0),
++	      svld1_ver_vnum_za8 (0, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za128.c
+new file mode 100644
+index 000000000..e81f40258
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za128.c
+@@ -0,0 +1,83 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za128_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1q	{ za0v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_0,
++	      svld1_ver_za128 (0, 0, p0, x1),
++	      svld1_ver_za128 (0, 0, p0, x1))
++
++/*
++** ld1_za128_0_1:
++**	mov	(w1[2-5]), #?1
++**	ld1q	{ za0v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_1,
++	      svld1_ver_za128 (0, 1, p0, x1),
++	      svld1_ver_za128 (0, 1, p0, x1))
++
++/*
++** ld1_za128_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za0v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_w0,
++	      svld1_ver_za128 (0, w0, p0, x1),
++	      svld1_ver_za128 (0, w0, p0, x1))
++
++/*
++** ld1_za128_0_w0_p1:
++**	add	(w1[2-5]), w0, #?1
++**	ld1q	{ za0v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_0_w0_p1,
++	      svld1_ver_za128 (0, w0 + 1, p0, x1),
++	      svld1_ver_za128 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za128_7_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za7v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_7_w0,
++	      svld1_ver_za128 (7, w0, p0, x1),
++	      svld1_ver_za128 (7, w0, p0, x1))
++
++/*
++** ld1_za128_13_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za13v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_13_w0,
++	      svld1_ver_za128 (13, w0, p0, x1),
++	      svld1_ver_za128 (13, w0, p0, x1))
++
++/*
++** ld1_za128_15_w0:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za15v\.q\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_15_w0,
++	      svld1_ver_za128 (15, w0, p0, x1),
++	      svld1_ver_za128 (15, w0, p0, x1))
++
++/*
++** ld1_za128_9_w0_index:
++**	mov	(w1[2-5]), w0
++**	ld1q	{ za9v\.q\[\1, 0\] }, p0/z, \[x1, x2, lsl #?4\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za128_9_w0_index,
++	      svld1_ver_za128 (9, w0, p0, x1 + x2 * 16),
++	      svld1_ver_za128 (9, w0, p0, x1 + x2 * 16))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za16.c
+new file mode 100644
+index 000000000..0938b1eba
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za16.c
+@@ -0,0 +1,126 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za16_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_0,
++	      svld1_ver_za16 (0, 0, p0, x1),
++	      svld1_ver_za16 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 7.  */
++/*
++** ld1_za16_0_7:
++**	mov	(w1[2-5]), #?7
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_7,
++	      svld1_ver_za16 (0, 7, p0, x1),
++	      svld1_ver_za16 (0, 7, p0, x1))
++
++/*
++** ld1_za16_0_8:
++**	mov	(w1[2-5]), #?8
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_8,
++	      svld1_ver_za16 (0, 8, p0, x1),
++	      svld1_ver_za16 (0, 8, p0, x1))
++
++/*
++** ld1_za16_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0,
++	      svld1_ver_za16 (0, w0, p0, x1),
++	      svld1_ver_za16 (0, w0, p0, x1))
++
++/*
++** ld1_za16_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0v\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_p1,
++	      svld1_ver_za16 (0, w0 + 1, p0, x1),
++	      svld1_ver_za16 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za16_0_w0_p7:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za0v\.h\[\1, 7\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_p7,
++	      svld1_ver_za16 (0, w0 + 7, p0, x1),
++	      svld1_ver_za16 (0, w0 + 7, p0, x1))
++
++/*
++** ld1_za16_1_w0:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0,
++	      svld1_ver_za16 (1, w0, p0, x1),
++	      svld1_ver_za16 (1, w0, p0, x1))
++
++
++/*
++** ld1_za16_1_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1v\.h\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0_p1,
++	      svld1_ver_za16 (1, w0 + 1, p0, x1),
++	      svld1_ver_za16 (1, w0 + 1, p0, x1))
++
++/*
++** ld1_za16_1_w0_p7:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1v\.h\[\1, 7\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0_p7,
++	      svld1_ver_za16 (1, w0 + 7, p0, x1),
++	      svld1_ver_za16 (1, w0 + 7, p0, x1))
++
++/*
++** ld1_za16_1_w0_p5_index:
++**	mov	(w1[2-5]), w0
++**	ld1h	{ za1v\.h\[\1, 5\] }, p0/z, \[x1, x2, lsl #?1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_1_w0_p5_index,
++	      svld1_ver_za16 (1, w0 + 5, p0, x1 + x2 * 2),
++	      svld1_ver_za16 (1, w0 + 5, p0, x1 + x2 * 2))
++
++/*
++** ld1_za16_0_w0_p8:
++**	add	(w1[2-5]), w0, #?8
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_p8,
++	      svld1_ver_za16 (0, w0 + 8, p0, x1),
++	      svld1_ver_za16 (0, w0 + 8, p0, x1))
++
++/*
++** ld1_za16_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1h	{ za0v\.h\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za16_0_w0_m1,
++	      svld1_ver_za16 (0, w0 - 1, p0, x1),
++	      svld1_ver_za16 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za32.c
+new file mode 100644
+index 000000000..bb9d93184
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za32.c
+@@ -0,0 +1,125 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za32_0_0:
++**	mov	(w1[2-5]), (?:w0|#?0)
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_0,
++	      svld1_ver_za32 (0, 0, p0, x1),
++	      svld1_ver_za32 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 3.  */
++/*
++** ld1_za32_0_3:
++**	mov	(w1[2-5]), #?3
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_3,
++	      svld1_ver_za32 (0, 3, p0, x1),
++	      svld1_ver_za32 (0, 3, p0, x1))
++
++/*
++** ld1_za32_0_4:
++**	mov	(w1[2-5]), #?4
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_4,
++	      svld1_ver_za32 (0, 4, p0, x1),
++	      svld1_ver_za32 (0, 4, p0, x1))
++
++/*
++** ld1_za32_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0,
++	      svld1_ver_za32 (0, w0, p0, x1),
++	      svld1_ver_za32 (0, w0, p0, x1))
++
++/*
++** ld1_za32_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0v\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_p1,
++	      svld1_ver_za32 (0, w0 + 1, p0, x1),
++	      svld1_ver_za32 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za32_0_w0_p3:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za0v\.s\[\1, 3\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_p3,
++	      svld1_ver_za32 (0, w0 + 3, p0, x1),
++	      svld1_ver_za32 (0, w0 + 3, p0, x1))
++
++/*
++** ld1_za32_3_w0:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za3v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_3_w0,
++	      svld1_ver_za32 (3, w0, p0, x1),
++	      svld1_ver_za32 (3, w0, p0, x1))
++
++/*
++** ld1_za32_3_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za3v\.s\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_3_w0_p1,
++	      svld1_ver_za32 (3, w0 + 1, p0, x1),
++	      svld1_ver_za32 (3, w0 + 1, p0, x1))
++
++/*
++** ld1_za32_3_w0_p3:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za3v\.s\[\1, 3\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_3_w0_p3,
++	      svld1_ver_za32 (3, w0 + 3, p0, x1),
++	      svld1_ver_za32 (3, w0 + 3, p0, x1))
++
++/*
++** ld1_za32_1_w0_p2_index:
++**	mov	(w1[2-5]), w0
++**	ld1w	{ za1v\.s\[\1, 2\] }, p0/z, \[x1, x2, lsl #?2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_1_w0_p2_index,
++	      svld1_ver_za32 (1, w0 + 2, p0, x1 + x2 * 4),
++	      svld1_ver_za32 (1, w0 + 2, p0, x1 + x2 * 4))
++
++/*
++** ld1_za32_0_w0_p4:
++**	add	(w1[2-5]), w0, #?4
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_p4,
++	      svld1_ver_za32 (0, w0 + 4, p0, x1),
++	      svld1_ver_za32 (0, w0 + 4, p0, x1))
++
++/*
++** ld1_za32_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1w	{ za0v\.s\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za32_0_w0_m1,
++	      svld1_ver_za32 (0, w0 - 1, p0, x1),
++	      svld1_ver_za32 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za64.c
+new file mode 100644
+index 000000000..58d73ad06
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za64.c
+@@ -0,0 +1,105 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za64_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_0,
++	      svld1_ver_za64 (0, 0, p0, x1),
++	      svld1_ver_za64 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 1.  */
++/*
++** ld1_za64_0_1:
++**	mov	(w1[2-5]), #?1
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_1,
++	      svld1_ver_za64 (0, 1, p0, x1),
++	      svld1_ver_za64 (0, 1, p0, x1))
++
++/*
++** ld1_za64_0_2:
++**	mov	(w1[2-5]), #?2
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_2,
++	      svld1_ver_za64 (0, 2, p0, x1),
++	      svld1_ver_za64 (0, 2, p0, x1))
++
++/*
++** ld1_za64_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0,
++	      svld1_ver_za64 (0, w0, p0, x1),
++	      svld1_ver_za64 (0, w0, p0, x1))
++
++/*
++** ld1_za64_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za0v\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0_p1,
++	      svld1_ver_za64 (0, w0 + 1, p0, x1),
++	      svld1_ver_za64 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za64_7_w0:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za7v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_7_w0,
++	      svld1_ver_za64 (7, w0, p0, x1),
++	      svld1_ver_za64 (7, w0, p0, x1))
++
++/*
++** ld1_za64_7_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za7v\.d\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_7_w0_p1,
++	      svld1_ver_za64 (7, w0 + 1, p0, x1),
++	      svld1_ver_za64 (7, w0 + 1, p0, x1))
++
++/*
++** ld1_za64_5_w0_p1_index:
++**	mov	(w1[2-5]), w0
++**	ld1d	{ za5v\.d\[\1, 1\] }, p0/z, \[x1, x2, lsl #?3\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_5_w0_p1_index,
++	      svld1_ver_za64 (5, w0 + 1, p0, x1 + x2 * 8),
++	      svld1_ver_za64 (5, w0 + 1, p0, x1 + x2 * 8))
++
++/*
++** ld1_za64_0_w0_p2:
++**	add	(w1[2-5]), w0, #?2
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0_p2,
++	      svld1_ver_za64 (0, w0 + 2, p0, x1),
++	      svld1_ver_za64 (0, w0 + 2, p0, x1))
++
++/*
++** ld1_za64_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1d	{ za0v\.d\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za64_0_w0_m1,
++	      svld1_ver_za64 (0, w0 - 1, p0, x1),
++	      svld1_ver_za64 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za8.c
+new file mode 100644
+index 000000000..38211b211
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ld1_ver_za8.c
+@@ -0,0 +1,95 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ld1_za8_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_0,
++	      svld1_ver_za8 (0, 0, p0, x1),
++	      svld1_ver_za8 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 15.  */
++/*
++** ld1_za8_0_15:
++**	mov	(w1[2-5]), #?15
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_15,
++	      svld1_ver_za8 (0, 15, p0, x1),
++	      svld1_ver_za8 (0, 15, p0, x1))
++
++/*
++** ld1_za8_0_16:
++**	mov	(w1[2-5]), #?16
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_16,
++	      svld1_ver_za8 (0, 16, p0, x1),
++	      svld1_ver_za8 (0, 16, p0, x1))
++
++/*
++** ld1_za8_0_w0:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0,
++	      svld1_ver_za8 (0, w0, p0, x1),
++	      svld1_ver_za8 (0, w0, p0, x1))
++
++/*
++** ld1_za8_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 1\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p1,
++	      svld1_ver_za8 (0, w0 + 1, p0, x1),
++	      svld1_ver_za8 (0, w0 + 1, p0, x1))
++
++/*
++** ld1_za8_0_w0_p15:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 15\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p15,
++	      svld1_ver_za8 (0, w0 + 15, p0, x1),
++	      svld1_ver_za8 (0, w0 + 15, p0, x1))
++
++/*
++** ld1_za8_0_w0_p13_index:
++**	mov	(w1[2-5]), w0
++**	ld1b	{ za0v\.b\[\1, 15\] }, p0/z, \[x1, x2\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p13_index,
++	      svld1_ver_za8 (0, w0 + 15, p0, x1 + x2),
++	      svld1_ver_za8 (0, w0 + 15, p0, x1 + x2))
++
++/*
++** ld1_za8_0_w0_p16:
++**	add	(w1[2-5]), w0, #?16
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_p16,
++	      svld1_ver_za8 (0, w0 + 16, p0, x1),
++	      svld1_ver_za8 (0, w0 + 16, p0, x1))
++
++/*
++** ld1_za8_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	ld1b	{ za0v\.b\[\1, 0\] }, p0/z, \[x1\]
++**	ret
++*/
++TEST_LOAD_ZA (ld1_za8_0_w0_m1,
++	      svld1_ver_za8 (0, w0 - 1, p0, x1),
++	      svld1_ver_za8 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_s.c
+new file mode 100644
+index 000000000..90495d080
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_s.c
+@@ -0,0 +1,147 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ldr_vnum_za_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_0_0,
++	      svldr_vnum_za (0, x1, 0),
++	      svldr_vnum_za (0, x1, 0))
++
++/*
++** ldr_vnum_za_0_1:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ldr	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_0_1,
++	      svldr_vnum_za (0, x1, 1),
++	      svldr_vnum_za (0, x1, 1))
++
++/*
++** ldr_vnum_za_1_0:
++**	mov	(w1[2-5]), #?1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_1_0,
++	      svldr_vnum_za (1, x1, 0),
++	      svldr_vnum_za (1, x1, 0))
++
++/*
++** ldr_vnum_za_1_2:
++**	mov	(w1[2-5]), #?1
++**	ldr	za\[\1, 2\], \[x1(?:, #2, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_1_2,
++	      svldr_vnum_za (1, x1, 2),
++	      svldr_vnum_za (1, x1, 2))
++
++/*
++** ldr_vnum_za_w0_0:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_0,
++	      svldr_vnum_za (w0, x1, 0),
++	      svldr_vnum_za (w0, x1, 0))
++
++/*
++** ldr_vnum_za_w0_1:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_1,
++	      svldr_vnum_za (w0, x1, 1),
++	      svldr_vnum_za (w0, x1, 1))
++
++/*
++** ldr_vnum_za_w0_13:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 13\], \[x1, #13, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_13,
++	      svldr_vnum_za (w0, x1, 13),
++	      svldr_vnum_za (w0, x1, 13))
++
++/*
++** ldr_vnum_za_w0_15:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 15\], \[x1, #15, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_15,
++	      svldr_vnum_za (w0, x1, 15),
++	      svldr_vnum_za (w0, x1, 15))
++
++/*
++** ldr_vnum_za_w0_16:
++** (
++**	add	(w1[2-5]), w0, #?16
++**	incb	x1, all, mul #16
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	ldr	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_16,
++	      svldr_vnum_za (w0, x1, 16),
++	      svldr_vnum_za (w0, x1, 16))
++
++/*
++** ldr_vnum_za_w0_m1:
++** (
++**	sub	(w1[2-5]), w0, #?1
++**	decb	x1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	decb	x1
++**	sub	(w1[2-5]), w0, #?1
++**	ldr	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_m1,
++	      svldr_vnum_za (w0, x1, -1),
++	      svldr_vnum_za (w0, x1, -1))
++
++/*
++** ldr_vnum_za_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0p1_0,
++	      svldr_vnum_za (w0 + 1, x1, 0),
++	      svldr_vnum_za (w0 + 1, x1, 0))
++
++/*
++** ldr_vnum_za_w0m1_1:
++**	sub	(w1[2-5]), w0, #?1
++**	ldr	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0m1_1,
++	      svldr_vnum_za (w0 - 1, x1, 1),
++	      svldr_vnum_za (w0 - 1, x1, 1))
++
++/*
++** ldr_vnum_za_w0p2_3:
++**	add	(w1[2-5]), w0, #?2
++**	ldr	za\[\1, 3\], \[x1(?:, #3, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0p2_3,
++	      svldr_vnum_za (w0 + 2, x1, 3),
++	      svldr_vnum_za (w0 + 2, x1, 3))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_sc.c
+new file mode 100644
+index 000000000..dfc2d139f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_vnum_za_sc.c
+@@ -0,0 +1,148 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** ldr_vnum_za_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_0_0,
++	      svldr_vnum_za (0, x1, 0),
++	      svldr_vnum_za (0, x1, 0))
++
++/*
++** ldr_vnum_za_0_1:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ldr	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_0_1,
++	      svldr_vnum_za (0, x1, 1),
++	      svldr_vnum_za (0, x1, 1))
++
++/*
++** ldr_vnum_za_1_0:
++**	mov	(w1[2-5]), #?1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_1_0,
++	      svldr_vnum_za (1, x1, 0),
++	      svldr_vnum_za (1, x1, 0))
++
++/*
++** ldr_vnum_za_1_2:
++**	mov	(w1[2-5]), #?1
++**	ldr	za\[\1, 2\], \[x1(?:, #2, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_1_2,
++	      svldr_vnum_za (1, x1, 2),
++	      svldr_vnum_za (1, x1, 2))
++
++/*
++** ldr_vnum_za_w0_0:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_0,
++	      svldr_vnum_za (w0, x1, 0),
++	      svldr_vnum_za (w0, x1, 0))
++
++/*
++** ldr_vnum_za_w0_1:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_1,
++	      svldr_vnum_za (w0, x1, 1),
++	      svldr_vnum_za (w0, x1, 1))
++
++/*
++** ldr_vnum_za_w0_13:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 13\], \[x1, #13, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_13,
++	      svldr_vnum_za (w0, x1, 13),
++	      svldr_vnum_za (w0, x1, 13))
++
++/*
++** ldr_vnum_za_w0_15:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 15\], \[x1, #15, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_15,
++	      svldr_vnum_za (w0, x1, 15),
++	      svldr_vnum_za (w0, x1, 15))
++
++/*
++** ldr_vnum_za_w0_16:
++** (
++**	add	(w1[2-5]), w0, #?16
++**	addsvl	(x[0-9]+), x1, #16
++**	ldr	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	addsvl	(x[0-9]+), x1, #16
++**	add	(w1[2-5]), w0, #?16
++**	ldr	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_16,
++	      svldr_vnum_za (w0, x1, 16),
++	      svldr_vnum_za (w0, x1, 16))
++
++/*
++** ldr_vnum_za_w0_m1:
++** (
++**	sub	(w1[2-5]), w0, #?1
++**	addsvl	(x[0-9]+), x1, #-1
++**	ldr	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	addsvl	(x[0-9]+), x1, #-1
++**	sub	(w1[2-5]), w0, #?1
++**	ldr	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0_m1,
++	      svldr_vnum_za (w0, x1, -1),
++	      svldr_vnum_za (w0, x1, -1))
++
++/*
++** ldr_vnum_za_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0p1_0,
++	      svldr_vnum_za (w0 + 1, x1, 0),
++	      svldr_vnum_za (w0 + 1, x1, 0))
++
++/*
++** ldr_vnum_za_w0m1_1:
++**	sub	(w1[2-5]), w0, #?1
++**	ldr	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0m1_1,
++	      svldr_vnum_za (w0 - 1, x1, 1),
++	      svldr_vnum_za (w0 - 1, x1, 1))
++
++/*
++** ldr_vnum_za_w0p2_3:
++**	add	(w1[2-5]), w0, #?2
++**	ldr	za\[\1, 3\], \[x1(?:, #3, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_vnum_za_w0p2_3,
++	      svldr_vnum_za (w0 + 2, x1, 3),
++	      svldr_vnum_za (w0 + 2, x1, 3))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_s.c
+new file mode 100644
+index 000000000..313b3239a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_s.c
+@@ -0,0 +1,124 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** ldr_za_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_0,
++	      svldr_za (0, x1),
++	      svldr_za (0, x1))
++
++/*
++** ldr_za_1:
++**	mov	(w1[2-5]), #?1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_1,
++	      svldr_za (1, x1),
++	      svldr_za (1, x1))
++
++/*
++** ldr_za_w0:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0,
++	      svldr_za (w0, x1),
++	      svldr_za (w0, x1))
++
++/*
++** ldr_za_w0_1_vnum:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0_1_vnum,
++	      svldr_za (w0 + 1, x1 + svcntsb ()),
++	      svldr_za (w0 + 1, x1 + svcntsb ()))
++
++/*
++** ldr_za_w0_13_vnum:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 13\], \[x1, #13, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0_13_vnum,
++	      svldr_za (w0 + 13, x1 + svcntsb () * 13),
++	      svldr_za (w0 + 13, x1 + svcntsb () * 13))
++
++/*
++** ldr_za_w0_15_vnum:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 15\], \[x1, #15, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0_15_vnum,
++	      svldr_za (w0 + 15, x1 + svcntsb () * 15),
++	      svldr_za (w0 + 15, x1 + svcntsb () * 15))
++
++/*
++** ldr_za_w0_16_vnum:
++** (
++**	add	(w1[2-5]), w0, #?16
++**	incb	x1, all, mul #16
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	ldr	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0_16_vnum,
++	      svldr_za (w0 + 16, x1 + svcntsb () * 16),
++	      svldr_za (w0 + 16, x1 + svcntsb () * 16))
++
++/*
++** ldr_za_w0_m1_vnum:
++** (
++**	sub	(w1[2-5]), w0, #?1
++**	decb	x1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	decb	x1
++**	sub	(w1[2-5]), w0, #?1
++**	ldr	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0_m1_vnum,
++	      svldr_za (w0 - 1, x1 - svcntsb ()),
++	      svldr_za (w0 - 1, x1 - svcntsb ()))
++
++/*
++** ldr_za_w0p2:
++**	add	(w1[2-5]), w0, #?2
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0p2,
++	      svldr_za (w0 + 2, x1),
++	      svldr_za (w0 + 2, x1))
++
++/*
++** ldr_za_offset:
++** (
++**	mov	(w1[2-5]), w0
++**	add	(x[0-9]+), x1, #?1
++**	ldr	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	add	(x[0-9]+), x1, #?1
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_offset,
++	      svldr_za (w0, x1 + 1),
++	      svldr_za (w0, x1 + 1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_sc.c
+new file mode 100644
+index 000000000..a27be7671
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/ldr_za_sc.c
+@@ -0,0 +1,71 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** ldr_za_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_0,
++	      svldr_za (0, x1),
++	      svldr_za (0, x1))
++
++/*
++** ldr_za_1:
++**	mov	(w1[2-5]), #?1
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_1,
++	      svldr_za (1, x1),
++	      svldr_za (1, x1))
++
++/*
++** ldr_za_w0:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0,
++	      svldr_za (w0, x1),
++	      svldr_za (w0, x1))
++
++/*
++** ldr_za_w0_1_vnum:
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0_1_vnum,
++	      svldr_za (w0 + 1, x1 + svcntsb ()),
++	      svldr_za (w0 + 1, x1 + svcntsb ()))
++
++/*
++** ldr_za_w0p2:
++**	add	(w1[2-5]), w0, #?2
++**	ldr	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_w0p2,
++	      svldr_za (w0 + 2, x1),
++	      svldr_za (w0 + 2, x1))
++
++/*
++** ldr_za_offset:
++** (
++**	mov	(w1[2-5]), w0
++**	add	(x[0-9]+), x1, #?1
++**	ldr	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	add	(x[0-9]+), x1, #?1
++**	mov	(w1[2-5]), w0
++**	ldr	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_LOAD_ZA (ldr_za_offset,
++	      svldr_za (w0, x1 + 1),
++	      svldr_za (w0, x1 + 1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za32.c
+new file mode 100644
+index 000000000..480de2c7f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za32.c
+@@ -0,0 +1,102 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** mopa_za32_s8_0_p0_p1_z0_z1:
++**	smopa	za0\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_s8_0_p0_p1_z0_z1, svint8_t,
++		 svmopa_za32_s8_m (0, p0, p1, z0, z1),
++		 svmopa_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za32_s8_0_p1_p0_z1_z0:
++**	smopa	za0\.s, p1/m, p0/m, z1\.b, z0\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_s8_0_p1_p0_z1_z0, svint8_t,
++		 svmopa_za32_s8_m (0, p1, p0, z1, z0),
++		 svmopa_za32_m (0, p1, p0, z1, z0))
++
++/*
++** mopa_za32_s8_3_p0_p1_z0_z1:
++**	smopa	za3\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_s8_3_p0_p1_z0_z1, svint8_t,
++		 svmopa_za32_s8_m (3, p0, p1, z0, z1),
++		 svmopa_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mopa_za32_u8_0_p0_p1_z0_z1:
++**	umopa	za0\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_u8_0_p0_p1_z0_z1, svuint8_t,
++		 svmopa_za32_u8_m (0, p0, p1, z0, z1),
++		 svmopa_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za32_u8_3_p0_p1_z0_z1:
++**	umopa	za3\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_u8_3_p0_p1_z0_z1, svuint8_t,
++		 svmopa_za32_u8_m (3, p0, p1, z0, z1),
++		 svmopa_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mopa_za32_bf16_0_p0_p1_z0_z1:
++**	bfmopa	za0\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_bf16_0_p0_p1_z0_z1, svbfloat16_t,
++		 svmopa_za32_bf16_m (0, p0, p1, z0, z1),
++		 svmopa_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za32_bf16_3_p0_p1_z0_z1:
++**	bfmopa	za3\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_bf16_3_p0_p1_z0_z1, svbfloat16_t,
++		 svmopa_za32_bf16_m (3, p0, p1, z0, z1),
++		 svmopa_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mopa_za32_f16_0_p0_p1_z0_z1:
++**	fmopa	za0\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_f16_0_p0_p1_z0_z1, svfloat16_t,
++		 svmopa_za32_f16_m (0, p0, p1, z0, z1),
++		 svmopa_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za32_f16_3_p0_p1_z0_z1:
++**	fmopa	za3\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_f16_3_p0_p1_z0_z1, svfloat16_t,
++		 svmopa_za32_f16_m (3, p0, p1, z0, z1),
++		 svmopa_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mopa_za32_f32_0_p0_p1_z0_z1:
++**	fmopa	za0\.s, p0/m, p1/m, z0\.s, z1\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_f32_0_p0_p1_z0_z1, svfloat32_t,
++		 svmopa_za32_f32_m (0, p0, p1, z0, z1),
++		 svmopa_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za32_f32_3_p0_p1_z0_z1:
++**	fmopa	za3\.s, p0/m, p1/m, z0\.s, z1\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za32_f32_3_p0_p1_z0_z1, svfloat32_t,
++		 svmopa_za32_f32_m (3, p0, p1, z0, z1),
++		 svmopa_za32_m (3, p0, p1, z0, z1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za64.c
+new file mode 100644
+index 000000000..f523b9605
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mopa_za64.c
+@@ -0,0 +1,70 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** mopa_za64_s16_0_p0_p1_z0_z1:
++**	smopa	za0\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_s16_0_p0_p1_z0_z1, svint16_t,
++		 svmopa_za64_s16_m (0, p0, p1, z0, z1),
++		 svmopa_za64_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za64_s16_0_p1_p0_z1_z0:
++**	smopa	za0\.d, p1/m, p0/m, z1\.h, z0\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_s16_0_p1_p0_z1_z0, svint16_t,
++		 svmopa_za64_s16_m (0, p1, p0, z1, z0),
++		 svmopa_za64_m (0, p1, p0, z1, z0))
++
++/*
++** mopa_za64_s16_7_p0_p1_z0_z1:
++**	smopa	za7\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_s16_7_p0_p1_z0_z1, svint16_t,
++		 svmopa_za64_s16_m (7, p0, p1, z0, z1),
++		 svmopa_za64_m (7, p0, p1, z0, z1))
++
++/*
++** mopa_za64_u16_0_p0_p1_z0_z1:
++**	umopa	za0\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_u16_0_p0_p1_z0_z1, svuint16_t,
++		 svmopa_za64_u16_m (0, p0, p1, z0, z1),
++		 svmopa_za64_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za64_u16_7_p0_p1_z0_z1:
++**	umopa	za7\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_u16_7_p0_p1_z0_z1, svuint16_t,
++		 svmopa_za64_u16_m (7, p0, p1, z0, z1),
++		 svmopa_za64_m (7, p0, p1, z0, z1))
++
++#pragma GCC target "+nosme-i16i64+sme-f64f64"
++
++/*
++** mopa_za64_f64_0_p0_p1_z0_z1:
++**	fmopa	za0\.d, p0/m, p1/m, z0\.d, z1\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_f64_0_p0_p1_z0_z1, svfloat64_t,
++		 svmopa_za64_f64_m (0, p0, p1, z0, z1),
++		 svmopa_za64_m (0, p0, p1, z0, z1))
++
++/*
++** mopa_za64_f64_7_p0_p1_z0_z1:
++**	fmopa	za7\.d, p0/m, p1/m, z0\.d, z1\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (mopa_za64_f64_7_p0_p1_z0_z1, svfloat64_t,
++		 svmopa_za64_f64_m (7, p0, p1, z0, z1),
++		 svmopa_za64_m (7, p0, p1, z0, z1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za32.c
+new file mode 100644
+index 000000000..63c2b80fd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za32.c
+@@ -0,0 +1,102 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** mops_za32_s8_0_p0_p1_z0_z1:
++**	smops	za0\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_s8_0_p0_p1_z0_z1, svint8_t,
++		 svmops_za32_s8_m (0, p0, p1, z0, z1),
++		 svmops_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za32_s8_0_p1_p0_z1_z0:
++**	smops	za0\.s, p1/m, p0/m, z1\.b, z0\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_s8_0_p1_p0_z1_z0, svint8_t,
++		 svmops_za32_s8_m (0, p1, p0, z1, z0),
++		 svmops_za32_m (0, p1, p0, z1, z0))
++
++/*
++** mops_za32_s8_3_p0_p1_z0_z1:
++**	smops	za3\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_s8_3_p0_p1_z0_z1, svint8_t,
++		 svmops_za32_s8_m (3, p0, p1, z0, z1),
++		 svmops_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mops_za32_u8_0_p0_p1_z0_z1:
++**	umops	za0\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_u8_0_p0_p1_z0_z1, svuint8_t,
++		 svmops_za32_u8_m (0, p0, p1, z0, z1),
++		 svmops_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za32_u8_3_p0_p1_z0_z1:
++**	umops	za3\.s, p0/m, p1/m, z0\.b, z1\.b
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_u8_3_p0_p1_z0_z1, svuint8_t,
++		 svmops_za32_u8_m (3, p0, p1, z0, z1),
++		 svmops_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mops_za32_bf16_0_p0_p1_z0_z1:
++**	bfmops	za0\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_bf16_0_p0_p1_z0_z1, svbfloat16_t,
++		 svmops_za32_bf16_m (0, p0, p1, z0, z1),
++		 svmops_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za32_bf16_3_p0_p1_z0_z1:
++**	bfmops	za3\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_bf16_3_p0_p1_z0_z1, svbfloat16_t,
++		 svmops_za32_bf16_m (3, p0, p1, z0, z1),
++		 svmops_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mops_za32_f16_0_p0_p1_z0_z1:
++**	fmops	za0\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_f16_0_p0_p1_z0_z1, svfloat16_t,
++		 svmops_za32_f16_m (0, p0, p1, z0, z1),
++		 svmops_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za32_f16_3_p0_p1_z0_z1:
++**	fmops	za3\.s, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_f16_3_p0_p1_z0_z1, svfloat16_t,
++		 svmops_za32_f16_m (3, p0, p1, z0, z1),
++		 svmops_za32_m (3, p0, p1, z0, z1))
++
++/*
++** mops_za32_f32_0_p0_p1_z0_z1:
++**	fmops	za0\.s, p0/m, p1/m, z0\.s, z1\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_f32_0_p0_p1_z0_z1, svfloat32_t,
++		 svmops_za32_f32_m (0, p0, p1, z0, z1),
++		 svmops_za32_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za32_f32_3_p0_p1_z0_z1:
++**	fmops	za3\.s, p0/m, p1/m, z0\.s, z1\.s
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za32_f32_3_p0_p1_z0_z1, svfloat32_t,
++		 svmops_za32_f32_m (3, p0, p1, z0, z1),
++		 svmops_za32_m (3, p0, p1, z0, z1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za64.c
+new file mode 100644
+index 000000000..bc04c3cf7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/mops_za64.c
+@@ -0,0 +1,70 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** mops_za64_s16_0_p0_p1_z0_z1:
++**	smops	za0\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_s16_0_p0_p1_z0_z1, svint16_t,
++		 svmops_za64_s16_m (0, p0, p1, z0, z1),
++		 svmops_za64_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za64_s16_0_p1_p0_z1_z0:
++**	smops	za0\.d, p1/m, p0/m, z1\.h, z0\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_s16_0_p1_p0_z1_z0, svint16_t,
++		 svmops_za64_s16_m (0, p1, p0, z1, z0),
++		 svmops_za64_m (0, p1, p0, z1, z0))
++
++/*
++** mops_za64_s16_7_p0_p1_z0_z1:
++**	smops	za7\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_s16_7_p0_p1_z0_z1, svint16_t,
++		 svmops_za64_s16_m (7, p0, p1, z0, z1),
++		 svmops_za64_m (7, p0, p1, z0, z1))
++
++/*
++** mops_za64_u16_0_p0_p1_z0_z1:
++**	umops	za0\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_u16_0_p0_p1_z0_z1, svuint16_t,
++		 svmops_za64_u16_m (0, p0, p1, z0, z1),
++		 svmops_za64_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za64_u16_7_p0_p1_z0_z1:
++**	umops	za7\.d, p0/m, p1/m, z0\.h, z1\.h
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_u16_7_p0_p1_z0_z1, svuint16_t,
++		 svmops_za64_u16_m (7, p0, p1, z0, z1),
++		 svmops_za64_m (7, p0, p1, z0, z1))
++
++#pragma GCC target "+nosme-i16i64+sme-f64f64"
++
++/*
++** mops_za64_f64_0_p0_p1_z0_z1:
++**	fmops	za0\.d, p0/m, p1/m, z0\.d, z1\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_f64_0_p0_p1_z0_z1, svfloat64_t,
++		 svmops_za64_f64_m (0, p0, p1, z0, z1),
++		 svmops_za64_m (0, p0, p1, z0, z1))
++
++/*
++** mops_za64_f64_7_p0_p1_z0_z1:
++**	fmops	za7\.d, p0/m, p1/m, z0\.d, z1\.d
++**	ret
++*/
++TEST_UNIFORM_ZA (mops_za64_f64_7_p0_p1_z0_z1, svfloat64_t,
++		 svmops_za64_f64_m (7, p0, p1, z0, z1),
++		 svmops_za64_m (7, p0, p1, z0, z1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za128.c
+new file mode 100644
+index 000000000..c8eef3b16
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za128.c
+@@ -0,0 +1,435 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za128_s8_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_0_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 0, 0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, 0))
++
++/*
++** read_za128_s8_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_1_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 0, 1),
++	      z0 = svread_hor_za128_m (z0, p0, 0, 1))
++
++/*
++** read_za128_s8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s8_0_w0p1_tied:
++**	add	(w1[2-5]), w0, #?1
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0p1_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za128_s8_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0m1_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za128_s8_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za1h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_1_w0_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 1, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 1, w0))
++
++/*
++** read_za128_s8_15_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za15h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_15_w0_tied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z0, p0, 15, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 15, w0))
++
++/*
++** read_za128_s8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0_untied, svint8_t,
++	      z0 = svread_hor_za128_s8_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u8_0_w0_tied, svuint8_t,
++	      z0 = svread_hor_za128_u8_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u8_0_w0_untied, svuint8_t,
++	      z0 = svread_hor_za128_u8_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_s16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s16_0_w0_tied, svint16_t,
++	      z0 = svread_hor_za128_s16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s16_0_w0_untied, svint16_t,
++	      z0 = svread_hor_za128_s16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u16_0_w0_tied, svuint16_t,
++	      z0 = svread_hor_za128_u16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u16_0_w0_untied, svuint16_t,
++	      z0 = svread_hor_za128_u16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_f16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_f16_0_w0_tied, svfloat16_t,
++	      z0 = svread_hor_za128_f16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_f16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_f16_0_w0_untied, svfloat16_t,
++	      z0 = svread_hor_za128_f16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_bf16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_bf16_0_w0_tied, svbfloat16_t,
++	      z0 = svread_hor_za128_bf16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_bf16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_bf16_0_w0_untied, svbfloat16_t,
++	      z0 = svread_hor_za128_bf16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_s32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s32_0_w0_tied, svint32_t,
++	      z0 = svread_hor_za128_s32_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s32_0_w0_untied, svint32_t,
++	      z0 = svread_hor_za128_s32_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u32_0_w0_tied, svuint32_t,
++	      z0 = svread_hor_za128_u32_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u32_0_w0_untied, svuint32_t,
++	      z0 = svread_hor_za128_u32_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_f32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_f32_0_w0_tied, svfloat32_t,
++	      z0 = svread_hor_za128_f32_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_f32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_f32_0_w0_untied, svfloat32_t,
++	      z0 = svread_hor_za128_f32_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_s64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s64_0_w0_tied, svint64_t,
++	      z0 = svread_hor_za128_s64_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s64_0_w0_untied, svint64_t,
++	      z0 = svread_hor_za128_s64_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u64_0_w0_tied, svuint64_t,
++	      z0 = svread_hor_za128_u64_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u64_0_w0_untied, svuint64_t,
++	      z0 = svread_hor_za128_u64_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_f64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_f64_0_w0_tied, svfloat64_t,
++	      z0 = svread_hor_za128_f64_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_f64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0h\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0h\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0h\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_f64_0_w0_untied, svfloat64_t,
++	      z0 = svread_hor_za128_f64_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za128_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za16.c
+new file mode 100644
+index 000000000..2e0a96591
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za16.c
+@@ -0,0 +1,207 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za16_s16_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_0_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, 0),
++	      z0 = svread_hor_za16_m (z0, p0, 0, 0))
++
++/*
++** read_za16_s16_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_1_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, 1),
++	      z0 = svread_hor_za16_m (z0, p0, 0, 1))
++
++/*
++** read_za16_s16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_s16_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0p1_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za16_s16_0_w0p7_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 7\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0p7_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, w0 + 7),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0 + 7))
++
++/*
++** read_za16_s16_0_w0p8_tied:
++**	add	(w1[2-5]), w0, #?8
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0p8_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, w0 + 8),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0 + 8))
++
++/*
++** read_za16_s16_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0m1_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za16_s16_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za1h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_1_w0_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 1, w0),
++	      z0 = svread_hor_za16_m (z0, p0, 1, w0))
++
++/*
++** read_za16_s16_1_w0p7_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za1h\.h\[\1, 7\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_1_w0p7_tied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z0, p0, 1, w0 + 7),
++	      z0 = svread_hor_za16_m (z0, p0, 1, w0 + 7))
++
++/*
++** read_za16_s16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0h\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0_untied, svint16_t,
++	      z0 = svread_hor_za16_s16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z1, p0, 0, w0))
++
++/*
++** read_za16_u16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_u16_0_w0_tied, svuint16_t,
++	      z0 = svread_hor_za16_u16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_u16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0h\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_u16_0_w0_untied, svuint16_t,
++	      z0 = svread_hor_za16_u16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z1, p0, 0, w0))
++
++/*
++** read_za16_f16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_f16_0_w0_tied, svfloat16_t,
++	      z0 = svread_hor_za16_f16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_f16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0h\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_f16_0_w0_untied, svfloat16_t,
++	      z0 = svread_hor_za16_f16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z1, p0, 0, w0))
++
++/*
++** read_za16_bf16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_bf16_0_w0_tied, svbfloat16_t,
++	      z0 = svread_hor_za16_bf16_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_bf16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0h\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0h\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0h\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_bf16_0_w0_untied, svbfloat16_t,
++	      z0 = svread_hor_za16_bf16_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za16_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za32.c
+new file mode 100644
+index 000000000..d111b60a7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za32.c
+@@ -0,0 +1,196 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za32_s32_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_0_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, 0),
++	      z0 = svread_hor_za32_m (z0, p0, 0, 0))
++
++/*
++** read_za32_s32_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_1_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, 1),
++	      z0 = svread_hor_za32_m (z0, p0, 0, 1))
++
++/*
++** read_za32_s32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0))
++
++/*
++** read_za32_s32_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0p1_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za32_s32_0_w0p3_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 3\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0p3_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, w0 + 3),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0 + 3))
++
++/*
++** read_za32_s32_0_w0p4_tied:
++**	add	(w1[2-5]), w0, #?4
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0p4_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, w0 + 4),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0 + 4))
++
++/*
++** read_za32_s32_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0m1_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za32_s32_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za1h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_1_w0_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 1, w0),
++	      z0 = svread_hor_za32_m (z0, p0, 1, w0))
++
++/*
++** read_za32_s32_1_w0p3_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za1h\.s\[\1, 3\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_1_w0p3_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 1, w0 + 3),
++	      z0 = svread_hor_za32_m (z0, p0, 1, w0 + 3))
++
++/*
++** read_za32_s32_3_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za3h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_3_w0_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 3, w0),
++	      z0 = svread_hor_za32_m (z0, p0, 3, w0))
++
++/*
++** read_za32_s32_3_w0p3_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za3h\.s\[\1, 3\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_3_w0p3_tied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z0, p0, 3, w0 + 3),
++	      z0 = svread_hor_za32_m (z0, p0, 3, w0 + 3))
++
++/*
++** read_za32_s32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.s, p0/m, za0h\.s\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0_untied, svint32_t,
++	      z0 = svread_hor_za32_s32_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za32_m (z1, p0, 0, w0))
++
++/*
++** read_za32_u32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_u32_0_w0_tied, svuint32_t,
++	      z0 = svread_hor_za32_u32_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0))
++
++/*
++** read_za32_u32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.s, p0/m, za0h\.s\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za32_u32_0_w0_untied, svuint32_t,
++	      z0 = svread_hor_za32_u32_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za32_m (z1, p0, 0, w0))
++
++/*
++** read_za32_f32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_f32_0_w0_tied, svfloat32_t,
++	      z0 = svread_hor_za32_f32_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za32_m (z0, p0, 0, w0))
++
++/*
++** read_za32_f32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.s, p0/m, za0h\.s\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0h\.s\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.s, p0/m, za0h\.s\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za32_f32_0_w0_untied, svfloat32_t,
++	      z0 = svread_hor_za32_f32_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za32_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za64.c
+new file mode 100644
+index 000000000..b75c531a5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za64.c
+@@ -0,0 +1,186 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za64_s64_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_0_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 0, 0),
++	      z0 = svread_hor_za64_m (z0, p0, 0, 0))
++
++/*
++** read_za64_s64_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_1_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 0, 1),
++	      z0 = svread_hor_za64_m (z0, p0, 0, 1))
++
++/*
++** read_za64_s64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za64_m (z0, p0, 0, w0))
++
++/*
++** read_za64_s64_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0p1_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_hor_za64_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za64_s64_0_w0p2_tied:
++**	add	(w1[2-5]), w0, #?2
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0p2_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 0, w0 + 2),
++	      z0 = svread_hor_za64_m (z0, p0, 0, w0 + 2))
++
++/*
++** read_za64_s64_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0m1_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_hor_za64_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za64_s64_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za1h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_1_w0_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 1, w0),
++	      z0 = svread_hor_za64_m (z0, p0, 1, w0))
++
++/*
++** read_za64_s64_1_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za1h\.d\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_1_w0p1_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 1, w0 + 1),
++	      z0 = svread_hor_za64_m (z0, p0, 1, w0 + 1))
++
++/*
++** read_za64_s64_7_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za7h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_7_w0_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 7, w0),
++	      z0 = svread_hor_za64_m (z0, p0, 7, w0))
++
++/*
++** read_za64_s64_7_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za7h\.d\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_7_w0p1_tied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z0, p0, 7, w0 + 1),
++	      z0 = svread_hor_za64_m (z0, p0, 7, w0 + 1))
++
++/*
++** read_za64_s64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.d, p0/m, za0h\.d\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0_untied, svint64_t,
++	      z0 = svread_hor_za64_s64_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za64_m (z1, p0, 0, w0))
++
++/*
++** read_za64_u64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_u64_0_w0_tied, svuint64_t,
++	      z0 = svread_hor_za64_u64_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za64_m (z0, p0, 0, w0))
++
++/*
++** read_za64_u64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.d, p0/m, za0h\.d\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za64_u64_0_w0_untied, svuint64_t,
++	      z0 = svread_hor_za64_u64_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za64_m (z1, p0, 0, w0))
++
++/*
++** read_za64_f64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_f64_0_w0_tied, svfloat64_t,
++	      z0 = svread_hor_za64_f64_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za64_m (z0, p0, 0, w0))
++
++/*
++** read_za64_f64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.d, p0/m, za0h\.d\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0h\.d\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.d, p0/m, za0h\.d\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za64_f64_0_w0_untied, svfloat64_t,
++	      z0 = svread_hor_za64_f64_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za64_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za8.c
+new file mode 100644
+index 000000000..0ad5a953f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_hor_za8.c
+@@ -0,0 +1,125 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za8_s8_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_0_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, 0),
++	      z0 = svread_hor_za8_m (z0, p0, 0, 0))
++
++/*
++** read_za8_s8_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_1_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, 1),
++	      z0 = svread_hor_za8_m (z0, p0, 0, 1))
++
++/*
++** read_za8_s8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za8_m (z0, p0, 0, w0))
++
++/*
++** read_za8_s8_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0p1_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_hor_za8_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za8_s8_0_w0p15_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 15\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0p15_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, w0 + 15),
++	      z0 = svread_hor_za8_m (z0, p0, 0, w0 + 15))
++
++/*
++** read_za8_s8_0_w0p16_tied:
++**	add	(w1[2-5]), w0, #?16
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0p16_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, w0 + 16),
++	      z0 = svread_hor_za8_m (z0, p0, 0, w0 + 16))
++
++/*
++** read_za8_s8_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0m1_tied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_hor_za8_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za8_s8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0h\.b\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.b, p0/m, za0h\.b\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0_untied, svint8_t,
++	      z0 = svread_hor_za8_s8_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za8_m (z1, p0, 0, w0))
++
++/*
++** read_za8_u8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_u8_0_w0_tied, svuint8_t,
++	      z0 = svread_hor_za8_u8_m (z0, p0, 0, w0),
++	      z0 = svread_hor_za8_m (z0, p0, 0, w0))
++
++/*
++** read_za8_u8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.b, p0/m, za0h\.b\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0h\.b\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.b, p0/m, za0h\.b\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za8_u8_0_w0_untied, svuint8_t,
++	      z0 = svread_hor_za8_u8_m (z1, p0, 0, w0),
++	      z0 = svread_hor_za8_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za128.c
+new file mode 100644
+index 000000000..93d5d60ea
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za128.c
+@@ -0,0 +1,435 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za128_s8_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_0_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 0, 0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, 0))
++
++/*
++** read_za128_s8_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_1_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 0, 1),
++	      z0 = svread_ver_za128_m (z0, p0, 0, 1))
++
++/*
++** read_za128_s8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s8_0_w0p1_tied:
++**	add	(w1[2-5]), w0, #?1
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0p1_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za128_s8_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0m1_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za128_s8_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za1v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_1_w0_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 1, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 1, w0))
++
++/*
++** read_za128_s8_15_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za15v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_15_w0_tied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z0, p0, 15, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 15, w0))
++
++/*
++** read_za128_s8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s8_0_w0_untied, svint8_t,
++	      z0 = svread_ver_za128_s8_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u8_0_w0_tied, svuint8_t,
++	      z0 = svread_ver_za128_u8_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u8_0_w0_untied, svuint8_t,
++	      z0 = svread_ver_za128_u8_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_s16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s16_0_w0_tied, svint16_t,
++	      z0 = svread_ver_za128_s16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s16_0_w0_untied, svint16_t,
++	      z0 = svread_ver_za128_s16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u16_0_w0_tied, svuint16_t,
++	      z0 = svread_ver_za128_u16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u16_0_w0_untied, svuint16_t,
++	      z0 = svread_ver_za128_u16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_f16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_f16_0_w0_tied, svfloat16_t,
++	      z0 = svread_ver_za128_f16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_f16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_f16_0_w0_untied, svfloat16_t,
++	      z0 = svread_ver_za128_f16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_bf16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_bf16_0_w0_tied, svbfloat16_t,
++	      z0 = svread_ver_za128_bf16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_bf16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_bf16_0_w0_untied, svbfloat16_t,
++	      z0 = svread_ver_za128_bf16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_s32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s32_0_w0_tied, svint32_t,
++	      z0 = svread_ver_za128_s32_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s32_0_w0_untied, svint32_t,
++	      z0 = svread_ver_za128_s32_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u32_0_w0_tied, svuint32_t,
++	      z0 = svread_ver_za128_u32_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u32_0_w0_untied, svuint32_t,
++	      z0 = svread_ver_za128_u32_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_f32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_f32_0_w0_tied, svfloat32_t,
++	      z0 = svread_ver_za128_f32_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_f32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_f32_0_w0_untied, svfloat32_t,
++	      z0 = svread_ver_za128_f32_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_s64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_s64_0_w0_tied, svint64_t,
++	      z0 = svread_ver_za128_s64_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_s64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_s64_0_w0_untied, svint64_t,
++	      z0 = svread_ver_za128_s64_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_u64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_u64_0_w0_tied, svuint64_t,
++	      z0 = svread_ver_za128_u64_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_u64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_u64_0_w0_untied, svuint64_t,
++	      z0 = svread_ver_za128_u64_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
++
++/*
++** read_za128_f64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za128_f64_0_w0_tied, svfloat64_t,
++	      z0 = svread_ver_za128_f64_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z0, p0, 0, w0))
++
++/*
++** read_za128_f64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.q, p0/m, za0v\.q\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.q, p0/m, za0v\.q\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.q, p0/m, za0v\.q\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za128_f64_0_w0_untied, svfloat64_t,
++	      z0 = svread_ver_za128_f64_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za128_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za16.c
+new file mode 100644
+index 000000000..d0353dce6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za16.c
+@@ -0,0 +1,207 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za16_s16_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_0_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, 0),
++	      z0 = svread_ver_za16_m (z0, p0, 0, 0))
++
++/*
++** read_za16_s16_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_1_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, 1),
++	      z0 = svread_ver_za16_m (z0, p0, 0, 1))
++
++/*
++** read_za16_s16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_s16_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0p1_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za16_s16_0_w0p7_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 7\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0p7_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, w0 + 7),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0 + 7))
++
++/*
++** read_za16_s16_0_w0p8_tied:
++**	add	(w1[2-5]), w0, #?8
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0p8_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, w0 + 8),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0 + 8))
++
++/*
++** read_za16_s16_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0m1_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za16_s16_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za1v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_1_w0_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 1, w0),
++	      z0 = svread_ver_za16_m (z0, p0, 1, w0))
++
++/*
++** read_za16_s16_1_w0p7_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za1v\.h\[\1, 7\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_1_w0p7_tied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z0, p0, 1, w0 + 7),
++	      z0 = svread_ver_za16_m (z0, p0, 1, w0 + 7))
++
++/*
++** read_za16_s16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0v\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_s16_0_w0_untied, svint16_t,
++	      z0 = svread_ver_za16_s16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z1, p0, 0, w0))
++
++/*
++** read_za16_u16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_u16_0_w0_tied, svuint16_t,
++	      z0 = svread_ver_za16_u16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_u16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0v\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_u16_0_w0_untied, svuint16_t,
++	      z0 = svread_ver_za16_u16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z1, p0, 0, w0))
++
++/*
++** read_za16_f16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_f16_0_w0_tied, svfloat16_t,
++	      z0 = svread_ver_za16_f16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_f16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0v\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_f16_0_w0_untied, svfloat16_t,
++	      z0 = svread_ver_za16_f16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z1, p0, 0, w0))
++
++/*
++** read_za16_bf16_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za16_bf16_0_w0_tied, svbfloat16_t,
++	      z0 = svread_ver_za16_bf16_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z0, p0, 0, w0))
++
++/*
++** read_za16_bf16_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.h, p0/m, za0v\.h\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.h, p0/m, za0v\.h\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.h, p0/m, za0v\.h\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za16_bf16_0_w0_untied, svbfloat16_t,
++	      z0 = svread_ver_za16_bf16_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za16_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za32.c
+new file mode 100644
+index 000000000..362e818ee
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za32.c
+@@ -0,0 +1,196 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za32_s32_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_0_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, 0),
++	      z0 = svread_ver_za32_m (z0, p0, 0, 0))
++
++/*
++** read_za32_s32_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_1_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, 1),
++	      z0 = svread_ver_za32_m (z0, p0, 0, 1))
++
++/*
++** read_za32_s32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0))
++
++/*
++** read_za32_s32_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0p1_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za32_s32_0_w0p3_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 3\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0p3_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, w0 + 3),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0 + 3))
++
++/*
++** read_za32_s32_0_w0p4_tied:
++**	add	(w1[2-5]), w0, #?4
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0p4_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, w0 + 4),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0 + 4))
++
++/*
++** read_za32_s32_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0m1_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za32_s32_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za1v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_1_w0_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 1, w0),
++	      z0 = svread_ver_za32_m (z0, p0, 1, w0))
++
++/*
++** read_za32_s32_1_w0p3_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za1v\.s\[\1, 3\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_1_w0p3_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 1, w0 + 3),
++	      z0 = svread_ver_za32_m (z0, p0, 1, w0 + 3))
++
++/*
++** read_za32_s32_3_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za3v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_3_w0_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 3, w0),
++	      z0 = svread_ver_za32_m (z0, p0, 3, w0))
++
++/*
++** read_za32_s32_3_w0p3_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za3v\.s\[\1, 3\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_3_w0p3_tied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z0, p0, 3, w0 + 3),
++	      z0 = svread_ver_za32_m (z0, p0, 3, w0 + 3))
++
++/*
++** read_za32_s32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.s, p0/m, za0v\.s\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za32_s32_0_w0_untied, svint32_t,
++	      z0 = svread_ver_za32_s32_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za32_m (z1, p0, 0, w0))
++
++/*
++** read_za32_u32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_u32_0_w0_tied, svuint32_t,
++	      z0 = svread_ver_za32_u32_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0))
++
++/*
++** read_za32_u32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.s, p0/m, za0v\.s\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za32_u32_0_w0_untied, svuint32_t,
++	      z0 = svread_ver_za32_u32_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za32_m (z1, p0, 0, w0))
++
++/*
++** read_za32_f32_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za32_f32_0_w0_tied, svfloat32_t,
++	      z0 = svread_ver_za32_f32_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za32_m (z0, p0, 0, w0))
++
++/*
++** read_za32_f32_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.s, p0/m, za0v\.s\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.s, p0/m, za0v\.s\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.s, p0/m, za0v\.s\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za32_f32_0_w0_untied, svfloat32_t,
++	      z0 = svread_ver_za32_f32_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za32_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za64.c
+new file mode 100644
+index 000000000..dba3c6ffa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za64.c
+@@ -0,0 +1,186 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za64_s64_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_0_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 0, 0),
++	      z0 = svread_ver_za64_m (z0, p0, 0, 0))
++
++/*
++** read_za64_s64_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_1_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 0, 1),
++	      z0 = svread_ver_za64_m (z0, p0, 0, 1))
++
++/*
++** read_za64_s64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za64_m (z0, p0, 0, w0))
++
++/*
++** read_za64_s64_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0p1_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_ver_za64_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za64_s64_0_w0p2_tied:
++**	add	(w1[2-5]), w0, #?2
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0p2_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 0, w0 + 2),
++	      z0 = svread_ver_za64_m (z0, p0, 0, w0 + 2))
++
++/*
++** read_za64_s64_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0m1_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_ver_za64_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za64_s64_1_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za1v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_1_w0_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 1, w0),
++	      z0 = svread_ver_za64_m (z0, p0, 1, w0))
++
++/*
++** read_za64_s64_1_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za1v\.d\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_1_w0p1_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 1, w0 + 1),
++	      z0 = svread_ver_za64_m (z0, p0, 1, w0 + 1))
++
++/*
++** read_za64_s64_7_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za7v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_7_w0_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 7, w0),
++	      z0 = svread_ver_za64_m (z0, p0, 7, w0))
++
++/*
++** read_za64_s64_7_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za7v\.d\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_7_w0p1_tied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z0, p0, 7, w0 + 1),
++	      z0 = svread_ver_za64_m (z0, p0, 7, w0 + 1))
++
++/*
++** read_za64_s64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.d, p0/m, za0v\.d\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za64_s64_0_w0_untied, svint64_t,
++	      z0 = svread_ver_za64_s64_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za64_m (z1, p0, 0, w0))
++
++/*
++** read_za64_u64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_u64_0_w0_tied, svuint64_t,
++	      z0 = svread_ver_za64_u64_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za64_m (z0, p0, 0, w0))
++
++/*
++** read_za64_u64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.d, p0/m, za0v\.d\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za64_u64_0_w0_untied, svuint64_t,
++	      z0 = svread_ver_za64_u64_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za64_m (z1, p0, 0, w0))
++
++/*
++** read_za64_f64_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za64_f64_0_w0_tied, svfloat64_t,
++	      z0 = svread_ver_za64_f64_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za64_m (z0, p0, 0, w0))
++
++/*
++** read_za64_f64_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.d, p0/m, za0v\.d\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.d, p0/m, za0v\.d\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.d, p0/m, za0v\.d\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za64_f64_0_w0_untied, svfloat64_t,
++	      z0 = svread_ver_za64_f64_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za64_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za8.c
+new file mode 100644
+index 000000000..87564d1fa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/read_ver_za8.c
+@@ -0,0 +1,125 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** read_za8_s8_0_0_tied:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_0_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, 0),
++	      z0 = svread_ver_za8_m (z0, p0, 0, 0))
++
++/*
++** read_za8_s8_0_1_tied:
++**	mov	(w1[2-5]), #?1
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_1_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, 1),
++	      z0 = svread_ver_za8_m (z0, p0, 0, 1))
++
++/*
++** read_za8_s8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za8_m (z0, p0, 0, w0))
++
++/*
++** read_za8_s8_0_w0p1_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 1\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0p1_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, w0 + 1),
++	      z0 = svread_ver_za8_m (z0, p0, 0, w0 + 1))
++
++/*
++** read_za8_s8_0_w0p15_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 15\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0p15_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, w0 + 15),
++	      z0 = svread_ver_za8_m (z0, p0, 0, w0 + 15))
++
++/*
++** read_za8_s8_0_w0p16_tied:
++**	add	(w1[2-5]), w0, #?16
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0p16_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, w0 + 16),
++	      z0 = svread_ver_za8_m (z0, p0, 0, w0 + 16))
++
++/*
++** read_za8_s8_0_w0m1_tied:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0m1_tied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z0, p0, 0, w0 - 1),
++	      z0 = svread_ver_za8_m (z0, p0, 0, w0 - 1))
++
++/*
++** read_za8_s8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0v\.b\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.b, p0/m, za0v\.b\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za8_s8_0_w0_untied, svint8_t,
++	      z0 = svread_ver_za8_s8_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za8_m (z1, p0, 0, w0))
++
++/*
++** read_za8_u8_0_w0_tied:
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++**	ret
++*/
++TEST_READ_ZA (read_za8_u8_0_w0_tied, svuint8_t,
++	      z0 = svread_ver_za8_u8_m (z0, p0, 0, w0),
++	      z0 = svread_ver_za8_m (z0, p0, 0, w0))
++
++/*
++** read_za8_u8_0_w0_untied:
++** (
++**	mov	(w1[2-5]), w0
++**	mov	z0\.d, z1\.d
++**	mova	z0\.b, p0/m, za0v\.b\[\1, 0\]
++** |
++**	mov	z0\.d, z1\.d
++**	mov	(w1[2-5]), w0
++**	mova	z0\.b, p0/m, za0v\.b\[\2, 0\]
++** |
++**	mov	(w1[2-5]), w0
++**	mova	z1\.b, p0/m, za0v\.b\[\3, 0\]
++**	mov	z0\.d, z1\.d
++** )
++**	ret
++*/
++TEST_READ_ZA (read_za8_u8_0_w0_untied, svuint8_t,
++	      z0 = svread_ver_za8_u8_m (z1, p0, 0, w0),
++	      z0 = svread_ver_za8_m (z1, p0, 0, w0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za128.c
+new file mode 100644
+index 000000000..057b6f21e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za128.c
+@@ -0,0 +1,77 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za128_0_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1q	{ za0h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_0_0_0,
++	       svst1_hor_vnum_za128 (0, 0, p0, x1, 0),
++	       svst1_hor_vnum_za128 (0, 0, p0, x1, 0))
++
++/*
++** st1_vnum_za128_7_1_0:
++**	mov	(w1[2-5]), #?1
++**	st1q	{ za7h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_7_1_0,
++	       svst1_hor_vnum_za128 (7, 1, p0, x1, 0),
++	       svst1_hor_vnum_za128 (7, 1, p0, x1, 0))
++
++/*
++** st1_vnum_za128_11_1_5:
++**	incb	x1, all, mul #5
++**	mov	(w1[2-5]), #?6
++**	st1q	{ za11h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_11_1_5,
++	       svst1_hor_vnum_za128 (11, 1, p0, x1, 5),
++	       svst1_hor_vnum_za128 (11, 1, p0, x1, 5))
++
++/*
++** st1_vnum_za128_3_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za3h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_3_w0_0,
++	       svst1_hor_vnum_za128 (3, w0, p0, x1, 0),
++	       svst1_hor_vnum_za128 (3, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za128_5_w0_0:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1q	{ za5h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_5_w0_0,
++	       svst1_hor_vnum_za128 (5, w0, p0, x1, 13),
++	       svst1_hor_vnum_za128 (5, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za128_11_w0_0:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1q	{ za11h\.q\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_11_w0_0,
++	       svst1_hor_vnum_za128 (11, w0, p0, x1, x2),
++	       svst1_hor_vnum_za128 (11, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za128_15_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	st1q	{ za15h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_15_w0p1_0,
++	       svst1_hor_vnum_za128 (15, w0 + 1, p0, x1, 0),
++	       svst1_hor_vnum_za128 (15, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za16.c
+new file mode 100644
+index 000000000..0b57dda0a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za16.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za16_1_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1h	{ za1h\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_0_1,
++	       svst1_hor_vnum_za16 (1, 0, p0, x1, 1),
++	       svst1_hor_vnum_za16 (1, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za16_1_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1h	{ za1h\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_1_1,
++	       svst1_hor_vnum_za16 (1, 1, p0, x1, 1),
++	       svst1_hor_vnum_za16 (1, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za16_0_0_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?8
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_0_8,
++	       svst1_hor_vnum_za16 (0, 0, p0, x1, 8),
++	       svst1_hor_vnum_za16 (0, 0, p0, x1, 8))
++
++/*
++** st1_vnum_za16_0_1_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?9
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_1_8,
++	       svst1_hor_vnum_za16 (0, 1, p0, x1, 8),
++	       svst1_hor_vnum_za16 (0, 1, p0, x1, 8))
++
++/*
++** st1_vnum_za16_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_0,
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, 0),
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za16_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0h\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_1,
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, 1),
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za16_0_w0_7:
++**	incb	x1, all, mul #7
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0h\.h\[\1, 7\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_7,
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, 7),
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, 7))
++
++/*
++** st1_vnum_za16_1_w0_8:
++**	incb	x1, all, mul #8
++**	add	(w1[2-5]), w0, #?8
++**	st1h	{ za1h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_w0_8,
++	       svst1_hor_vnum_za16 (1, w0, p0, x1, 8),
++	       svst1_hor_vnum_za16 (1, w0, p0, x1, 8))
++
++/*
++** st1_vnum_za16_1_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1h	{ za1h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_w0_13,
++	       svst1_hor_vnum_za16 (1, w0, p0, x1, 13),
++	       svst1_hor_vnum_za16 (1, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za16_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1h	{ za0h\.h\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_x2,
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, x2),
++	       svst1_hor_vnum_za16 (0, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za16_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1h\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_w0p1_0,
++	       svst1_hor_vnum_za16 (1, w0 + 1, p0, x1, 0),
++	       svst1_hor_vnum_za16 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za32.c
+new file mode 100644
+index 000000000..d4381182f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za32.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za32_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1w	{ za3h\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_3_0_1,
++	       svst1_hor_vnum_za32 (3, 0, p0, x1, 1),
++	       svst1_hor_vnum_za32 (3, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za32_2_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1w	{ za2h\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_2_1_1,
++	       svst1_hor_vnum_za32 (2, 1, p0, x1, 1),
++	       svst1_hor_vnum_za32 (2, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za32_0_0_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?4
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_0_4,
++	       svst1_hor_vnum_za32 (0, 0, p0, x1, 4),
++	       svst1_hor_vnum_za32 (0, 0, p0, x1, 4))
++
++/*
++** st1_vnum_za32_2_1_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?5
++**	st1w	{ za2h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_2_1_4,
++	       svst1_hor_vnum_za32 (2, 1, p0, x1, 4),
++	       svst1_hor_vnum_za32 (2, 1, p0, x1, 4))
++
++/*
++** st1_vnum_za32_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_0,
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, 0),
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za32_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0h\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_1,
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, 1),
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za32_0_w0_3:
++**	incb	x1, all, mul #3
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0h\.s\[\1, 3\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_3,
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, 3),
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, 3))
++
++/*
++** st1_vnum_za32_1_w0_4:
++**	incb	x1, all, mul #4
++**	add	(w1[2-5]), w0, #?4
++**	st1w	{ za1h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_1_w0_4,
++	       svst1_hor_vnum_za32 (1, w0, p0, x1, 4),
++	       svst1_hor_vnum_za32 (1, w0, p0, x1, 4))
++
++/*
++** st1_vnum_za32_3_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1w	{ za3h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_3_w0_13,
++	       svst1_hor_vnum_za32 (3, w0, p0, x1, 13),
++	       svst1_hor_vnum_za32 (3, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za32_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1w	{ za0h\.s\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_x2,
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, x2),
++	       svst1_hor_vnum_za32 (0, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za32_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za1h\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_1_w0p1_0,
++	       svst1_hor_vnum_za32 (1, w0 + 1, p0, x1, 0),
++	       svst1_hor_vnum_za32 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za64.c
+new file mode 100644
+index 000000000..be6063712
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za64.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za64_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1d	{ za3h\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_3_0_1,
++	       svst1_hor_vnum_za64 (3, 0, p0, x1, 1),
++	       svst1_hor_vnum_za64 (3, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za64_7_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1d	{ za7h\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_7_1_1,
++	       svst1_hor_vnum_za64 (7, 1, p0, x1, 1),
++	       svst1_hor_vnum_za64 (7, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za64_0_0_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?2
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_0_0_2,
++	       svst1_hor_vnum_za64 (0, 0, p0, x1, 2),
++	       svst1_hor_vnum_za64 (0, 0, p0, x1, 2))
++
++/*
++** st1_vnum_za64_5_1_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?3
++**	st1d	{ za5h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_5_1_2,
++	       svst1_hor_vnum_za64 (5, 1, p0, x1, 2),
++	       svst1_hor_vnum_za64 (5, 1, p0, x1, 2))
++
++/*
++** st1_vnum_za64_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_0_w0_0,
++	       svst1_hor_vnum_za64 (0, w0, p0, x1, 0),
++	       svst1_hor_vnum_za64 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za64_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0h\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_0_w0_1,
++	       svst1_hor_vnum_za64 (0, w0, p0, x1, 1),
++	       svst1_hor_vnum_za64 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za64_6_w0_2:
++**	incb	x1, all, mul #2
++**	add	(w1[2-5]), w0, #?2
++**	st1d	{ za6h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_6_w0_2,
++	       svst1_hor_vnum_za64 (6, w0, p0, x1, 2),
++	       svst1_hor_vnum_za64 (6, w0, p0, x1, 2))
++
++/*
++** st1_vnum_za64_2_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1d	{ za2h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_2_w0_13,
++	       svst1_hor_vnum_za64 (2, w0, p0, x1, 13),
++	       svst1_hor_vnum_za64 (2, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za64_4_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1d	{ za4h\.d\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_4_w0_x2,
++	       svst1_hor_vnum_za64 (4, w0, p0, x1, x2),
++	       svst1_hor_vnum_za64 (4, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za64_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za1h\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_1_w0p1_0,
++	       svst1_hor_vnum_za64 (1, w0 + 1, p0, x1, 0),
++	       svst1_hor_vnum_za64 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za8.c
+new file mode 100644
+index 000000000..eed41d25e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_vnum_za8.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za8_0_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1b	{ za0h\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_0_1,
++	       svst1_hor_vnum_za8 (0, 0, p0, x1, 1),
++	       svst1_hor_vnum_za8 (0, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za8_0_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1b	{ za0h\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_1_1,
++	       svst1_hor_vnum_za8 (0, 1, p0, x1, 1),
++	       svst1_hor_vnum_za8 (0, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za8_0_0_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?16
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_0_16,
++	       svst1_hor_vnum_za8 (0, 0, p0, x1, 16),
++	       svst1_hor_vnum_za8 (0, 0, p0, x1, 16))
++
++/*
++** st1_vnum_za8_0_1_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?17
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_1_16,
++	       svst1_hor_vnum_za8 (0, 1, p0, x1, 16),
++	       svst1_hor_vnum_za8 (0, 1, p0, x1, 16))
++
++/*
++** st1_vnum_za8_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_0,
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 0),
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za8_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_1,
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 1),
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za8_0_w0_15:
++**	incb	x1, all, mul #15
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 15\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_15,
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 15),
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 15))
++
++/*
++** st1_vnum_za8_0_w0_16:
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_16,
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 16),
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, 16))
++
++/*
++** st1_vnum_za8_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	mul	(x[0-9]+), (?:\1, x2|x2, \1)
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1b	{ za0h\.b\[\3, 0\] }, p0, \[x1, \2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_x2,
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, x2),
++	       svst1_hor_vnum_za8 (0, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za8_0_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0p1_0,
++	       svst1_hor_vnum_za8 (0, w0 + 1, p0, x1, 0),
++	       svst1_hor_vnum_za8 (0, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za128.c
+new file mode 100644
+index 000000000..5f3d613d5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za128.c
+@@ -0,0 +1,83 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za128_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1q	{ za0h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_0,
++	       svst1_hor_za128 (0, 0, p0, x1),
++	       svst1_hor_za128 (0, 0, p0, x1))
++
++/*
++** st1_za128_0_1:
++**	mov	(w1[2-5]), #?1
++**	st1q	{ za0h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_1,
++	       svst1_hor_za128 (0, 1, p0, x1),
++	       svst1_hor_za128 (0, 1, p0, x1))
++
++/*
++** st1_za128_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za0h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_w0,
++	       svst1_hor_za128 (0, w0, p0, x1),
++	       svst1_hor_za128 (0, w0, p0, x1))
++
++/*
++** st1_za128_0_w0_p1:
++**	add	(w1[2-5]), w0, #?1
++**	st1q	{ za0h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_w0_p1,
++	       svst1_hor_za128 (0, w0 + 1, p0, x1),
++	       svst1_hor_za128 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za128_7_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za7h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_7_w0,
++	       svst1_hor_za128 (7, w0, p0, x1),
++	       svst1_hor_za128 (7, w0, p0, x1))
++
++/*
++** st1_za128_13_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za13h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_13_w0,
++	       svst1_hor_za128 (13, w0, p0, x1),
++	       svst1_hor_za128 (13, w0, p0, x1))
++
++/*
++** st1_za128_15_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za15h\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_15_w0,
++	       svst1_hor_za128 (15, w0, p0, x1),
++	       svst1_hor_za128 (15, w0, p0, x1))
++
++/*
++** st1_za128_9_w0_index:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za9h\.q\[\1, 0\] }, p0, \[x1, x2, lsl #?4\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_9_w0_index,
++	       svst1_hor_za128 (9, w0, p0, x1 + x2 * 16),
++	       svst1_hor_za128 (9, w0, p0, x1 + x2 * 16))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za16.c
+new file mode 100644
+index 000000000..206306b23
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za16.c
+@@ -0,0 +1,126 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za16_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_0,
++	       svst1_hor_za16 (0, 0, p0, x1),
++	       svst1_hor_za16 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 7.  */
++/*
++** st1_za16_0_7:
++**	mov	(w1[2-5]), #?7
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_7,
++	       svst1_hor_za16 (0, 7, p0, x1),
++	       svst1_hor_za16 (0, 7, p0, x1))
++
++/*
++** st1_za16_0_8:
++**	mov	(w1[2-5]), #?8
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_8,
++	       svst1_hor_za16 (0, 8, p0, x1),
++	       svst1_hor_za16 (0, 8, p0, x1))
++
++/*
++** st1_za16_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0,
++	       svst1_hor_za16 (0, w0, p0, x1),
++	       svst1_hor_za16 (0, w0, p0, x1))
++
++/*
++** st1_za16_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0h\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_p1,
++	       svst1_hor_za16 (0, w0 + 1, p0, x1),
++	       svst1_hor_za16 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za16_0_w0_p7:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0h\.h\[\1, 7\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_p7,
++	       svst1_hor_za16 (0, w0 + 7, p0, x1),
++	       svst1_hor_za16 (0, w0 + 7, p0, x1))
++
++/*
++** st1_za16_1_w0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0,
++	       svst1_hor_za16 (1, w0, p0, x1),
++	       svst1_hor_za16 (1, w0, p0, x1))
++
++
++/*
++** st1_za16_1_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1h\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0_p1,
++	       svst1_hor_za16 (1, w0 + 1, p0, x1),
++	       svst1_hor_za16 (1, w0 + 1, p0, x1))
++
++/*
++** st1_za16_1_w0_p7:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1h\.h\[\1, 7\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0_p7,
++	       svst1_hor_za16 (1, w0 + 7, p0, x1),
++	       svst1_hor_za16 (1, w0 + 7, p0, x1))
++
++/*
++** st1_za16_1_w0_p5_index:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1h\.h\[\1, 5\] }, p0, \[x1, x2, lsl #?1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0_p5_index,
++	       svst1_hor_za16 (1, w0 + 5, p0, x1 + x2 * 2),
++	       svst1_hor_za16 (1, w0 + 5, p0, x1 + x2 * 2))
++
++/*
++** st1_za16_0_w0_p8:
++**	add	(w1[2-5]), w0, #?8
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_p8,
++	       svst1_hor_za16 (0, w0 + 8, p0, x1),
++	       svst1_hor_za16 (0, w0 + 8, p0, x1))
++
++/*
++** st1_za16_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1h	{ za0h\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_m1,
++	       svst1_hor_za16 (0, w0 - 1, p0, x1),
++	       svst1_hor_za16 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za32.c
+new file mode 100644
+index 000000000..ed9b2b2e9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za32.c
+@@ -0,0 +1,125 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za32_0_0:
++**	mov	(w1[2-5]), (?:w0|#?0)
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_0,
++	       svst1_hor_za32 (0, 0, p0, x1),
++	       svst1_hor_za32 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 3.  */
++/*
++** st1_za32_0_3:
++**	mov	(w1[2-5]), #?3
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_3,
++	       svst1_hor_za32 (0, 3, p0, x1),
++	       svst1_hor_za32 (0, 3, p0, x1))
++
++/*
++** st1_za32_0_4:
++**	mov	(w1[2-5]), #?4
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_4,
++	       svst1_hor_za32 (0, 4, p0, x1),
++	       svst1_hor_za32 (0, 4, p0, x1))
++
++/*
++** st1_za32_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0,
++	       svst1_hor_za32 (0, w0, p0, x1),
++	       svst1_hor_za32 (0, w0, p0, x1))
++
++/*
++** st1_za32_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0h\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_p1,
++	       svst1_hor_za32 (0, w0 + 1, p0, x1),
++	       svst1_hor_za32 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za32_0_w0_p3:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0h\.s\[\1, 3\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_p3,
++	       svst1_hor_za32 (0, w0 + 3, p0, x1),
++	       svst1_hor_za32 (0, w0 + 3, p0, x1))
++
++/*
++** st1_za32_3_w0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za3h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_3_w0,
++	       svst1_hor_za32 (3, w0, p0, x1),
++	       svst1_hor_za32 (3, w0, p0, x1))
++
++/*
++** st1_za32_3_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za3h\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_3_w0_p1,
++	       svst1_hor_za32 (3, w0 + 1, p0, x1),
++	       svst1_hor_za32 (3, w0 + 1, p0, x1))
++
++/*
++** st1_za32_3_w0_p3:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za3h\.s\[\1, 3\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_3_w0_p3,
++	       svst1_hor_za32 (3, w0 + 3, p0, x1),
++	       svst1_hor_za32 (3, w0 + 3, p0, x1))
++
++/*
++** st1_za32_1_w0_p2_index:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za1h\.s\[\1, 2\] }, p0, \[x1, x2, lsl #?2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_1_w0_p2_index,
++	       svst1_hor_za32 (1, w0 + 2, p0, x1 + x2 * 4),
++	       svst1_hor_za32 (1, w0 + 2, p0, x1 + x2 * 4))
++
++/*
++** st1_za32_0_w0_p4:
++**	add	(w1[2-5]), w0, #?4
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_p4,
++	       svst1_hor_za32 (0, w0 + 4, p0, x1),
++	       svst1_hor_za32 (0, w0 + 4, p0, x1))
++
++/*
++** st1_za32_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1w	{ za0h\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_m1,
++	       svst1_hor_za32 (0, w0 - 1, p0, x1),
++	       svst1_hor_za32 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za64.c
+new file mode 100644
+index 000000000..3600f5b8f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za64.c
+@@ -0,0 +1,105 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za64_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_0,
++	       svst1_hor_za64 (0, 0, p0, x1),
++	       svst1_hor_za64 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 1.  */
++/*
++** st1_za64_0_1:
++**	mov	(w1[2-5]), #?1
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_1,
++	       svst1_hor_za64 (0, 1, p0, x1),
++	       svst1_hor_za64 (0, 1, p0, x1))
++
++/*
++** st1_za64_0_2:
++**	mov	(w1[2-5]), #?2
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_2,
++	       svst1_hor_za64 (0, 2, p0, x1),
++	       svst1_hor_za64 (0, 2, p0, x1))
++
++/*
++** st1_za64_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0,
++	       svst1_hor_za64 (0, w0, p0, x1),
++	       svst1_hor_za64 (0, w0, p0, x1))
++
++/*
++** st1_za64_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0h\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0_p1,
++	       svst1_hor_za64 (0, w0 + 1, p0, x1),
++	       svst1_hor_za64 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za64_7_w0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za7h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_7_w0,
++	       svst1_hor_za64 (7, w0, p0, x1),
++	       svst1_hor_za64 (7, w0, p0, x1))
++
++/*
++** st1_za64_7_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za7h\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_7_w0_p1,
++	       svst1_hor_za64 (7, w0 + 1, p0, x1),
++	       svst1_hor_za64 (7, w0 + 1, p0, x1))
++
++/*
++** st1_za64_5_w0_p1_index:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za5h\.d\[\1, 1\] }, p0, \[x1, x2, lsl #?3\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_5_w0_p1_index,
++	       svst1_hor_za64 (5, w0 + 1, p0, x1 + x2 * 8),
++	       svst1_hor_za64 (5, w0 + 1, p0, x1 + x2 * 8))
++
++/*
++** st1_za64_0_w0_p2:
++**	add	(w1[2-5]), w0, #?2
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0_p2,
++	       svst1_hor_za64 (0, w0 + 2, p0, x1),
++	       svst1_hor_za64 (0, w0 + 2, p0, x1))
++
++/*
++** st1_za64_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1d	{ za0h\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0_m1,
++	       svst1_hor_za64 (0, w0 - 1, p0, x1),
++	       svst1_hor_za64 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za8.c
+new file mode 100644
+index 000000000..9026fae9e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_hor_za8.c
+@@ -0,0 +1,95 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za8_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_0,
++	       svst1_hor_za8 (0, 0, p0, x1),
++	       svst1_hor_za8 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 15.  */
++/*
++** st1_za8_0_15:
++**	mov	(w1[2-5]), #?15
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_15,
++	       svst1_hor_za8 (0, 15, p0, x1),
++	       svst1_hor_za8 (0, 15, p0, x1))
++
++/*
++** st1_za8_0_16:
++**	mov	(w1[2-5]), #?16
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_16,
++	       svst1_hor_za8 (0, 16, p0, x1),
++	       svst1_hor_za8 (0, 16, p0, x1))
++
++/*
++** st1_za8_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0,
++	       svst1_hor_za8 (0, w0, p0, x1),
++	       svst1_hor_za8 (0, w0, p0, x1))
++
++/*
++** st1_za8_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p1,
++	       svst1_hor_za8 (0, w0 + 1, p0, x1),
++	       svst1_hor_za8 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za8_0_w0_p15:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 15\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p15,
++	       svst1_hor_za8 (0, w0 + 15, p0, x1),
++	       svst1_hor_za8 (0, w0 + 15, p0, x1))
++
++/*
++** st1_za8_0_w0_p13_index:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0h\.b\[\1, 15\] }, p0, \[x1, x2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p13_index,
++	       svst1_hor_za8 (0, w0 + 15, p0, x1 + x2),
++	       svst1_hor_za8 (0, w0 + 15, p0, x1 + x2))
++
++/*
++** st1_za8_0_w0_p16:
++**	add	(w1[2-5]), w0, #?16
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p16,
++	       svst1_hor_za8 (0, w0 + 16, p0, x1),
++	       svst1_hor_za8 (0, w0 + 16, p0, x1))
++
++/*
++** st1_za8_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1b	{ za0h\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_m1,
++	       svst1_hor_za8 (0, w0 - 1, p0, x1),
++	       svst1_hor_za8 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za128.c
+new file mode 100644
+index 000000000..210687a48
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za128.c
+@@ -0,0 +1,77 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za128_0_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1q	{ za0v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_0_0_0,
++	       svst1_ver_vnum_za128 (0, 0, p0, x1, 0),
++	       svst1_ver_vnum_za128 (0, 0, p0, x1, 0))
++
++/*
++** st1_vnum_za128_7_1_0:
++**	mov	(w1[2-5]), #?1
++**	st1q	{ za7v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_7_1_0,
++	       svst1_ver_vnum_za128 (7, 1, p0, x1, 0),
++	       svst1_ver_vnum_za128 (7, 1, p0, x1, 0))
++
++/*
++** st1_vnum_za128_11_1_5:
++**	incb	x1, all, mul #5
++**	mov	(w1[2-5]), #?6
++**	st1q	{ za11v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_11_1_5,
++	       svst1_ver_vnum_za128 (11, 1, p0, x1, 5),
++	       svst1_ver_vnum_za128 (11, 1, p0, x1, 5))
++
++/*
++** st1_vnum_za128_3_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za3v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_3_w0_0,
++	       svst1_ver_vnum_za128 (3, w0, p0, x1, 0),
++	       svst1_ver_vnum_za128 (3, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za128_5_w0_0:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1q	{ za5v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_5_w0_0,
++	       svst1_ver_vnum_za128 (5, w0, p0, x1, 13),
++	       svst1_ver_vnum_za128 (5, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za128_11_w0_0:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1q	{ za11v\.q\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_11_w0_0,
++	       svst1_ver_vnum_za128 (11, w0, p0, x1, x2),
++	       svst1_ver_vnum_za128 (11, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za128_15_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	st1q	{ za15v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za128_15_w0p1_0,
++	       svst1_ver_vnum_za128 (15, w0 + 1, p0, x1, 0),
++	       svst1_ver_vnum_za128 (15, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za16.c
+new file mode 100644
+index 000000000..f75a22402
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za16.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za16_1_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1h	{ za1v\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_0_1,
++	       svst1_ver_vnum_za16 (1, 0, p0, x1, 1),
++	       svst1_ver_vnum_za16 (1, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za16_1_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1h	{ za1v\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_1_1,
++	       svst1_ver_vnum_za16 (1, 1, p0, x1, 1),
++	       svst1_ver_vnum_za16 (1, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za16_0_0_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?8
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_0_8,
++	       svst1_ver_vnum_za16 (0, 0, p0, x1, 8),
++	       svst1_ver_vnum_za16 (0, 0, p0, x1, 8))
++
++/*
++** st1_vnum_za16_0_1_8:
++**	incb	x1, all, mul #8
++**	mov	(w1[2-5]), #?9
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_1_8,
++	       svst1_ver_vnum_za16 (0, 1, p0, x1, 8),
++	       svst1_ver_vnum_za16 (0, 1, p0, x1, 8))
++
++/*
++** st1_vnum_za16_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_0,
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, 0),
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za16_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0v\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_1,
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, 1),
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za16_0_w0_7:
++**	incb	x1, all, mul #7
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0v\.h\[\1, 7\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_7,
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, 7),
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, 7))
++
++/*
++** st1_vnum_za16_1_w0_8:
++**	incb	x1, all, mul #8
++**	add	(w1[2-5]), w0, #?8
++**	st1h	{ za1v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_w0_8,
++	       svst1_ver_vnum_za16 (1, w0, p0, x1, 8),
++	       svst1_ver_vnum_za16 (1, w0, p0, x1, 8))
++
++/*
++** st1_vnum_za16_1_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1h	{ za1v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_w0_13,
++	       svst1_ver_vnum_za16 (1, w0, p0, x1, 13),
++	       svst1_ver_vnum_za16 (1, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za16_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1h	{ za0v\.h\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_0_w0_x2,
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, x2),
++	       svst1_ver_vnum_za16 (0, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za16_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1v\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za16_1_w0p1_0,
++	       svst1_ver_vnum_za16 (1, w0 + 1, p0, x1, 0),
++	       svst1_ver_vnum_za16 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za32.c
+new file mode 100644
+index 000000000..45db67a9f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za32.c
+@@ -0,0 +1,123 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za32_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1w	{ za3v\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_3_0_1,
++	       svst1_ver_vnum_za32 (3, 0, p0, x1, 1),
++	       svst1_ver_vnum_za32 (3, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za32_2_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1w	{ za2v\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_2_1_1,
++	       svst1_ver_vnum_za32 (2, 1, p0, x1, 1),
++	       svst1_ver_vnum_za32 (2, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za32_0_0_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?4
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_0_4,
++	       svst1_ver_vnum_za32 (0, 0, p0, x1, 4),
++	       svst1_ver_vnum_za32 (0, 0, p0, x1, 4))
++
++/*
++** st1_vnum_za32_2_1_4:
++**	incb	x1, all, mul #4
++**	mov	(w1[2-5]), #?5
++**	st1w	{ za2v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_2_1_4,
++	       svst1_ver_vnum_za32 (2, 1, p0, x1, 4),
++	       svst1_ver_vnum_za32 (2, 1, p0, x1, 4))
++
++/*
++** st1_vnum_za32_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_0,
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, 0),
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za32_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0v\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_1,
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, 1),
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za32_0_w0_3:
++**	incb	x1, all, mul #3
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0v\.s\[\1, 3\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_3,
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, 3),
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, 3))
++
++/*
++** st1_vnum_za32_1_w0_4:
++**	incb	x1, all, mul #4
++**	add	(w1[2-5]), w0, #?4
++**	st1w	{ za1v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_1_w0_4,
++	       svst1_ver_vnum_za32 (1, w0, p0, x1, 4),
++	       svst1_ver_vnum_za32 (1, w0, p0, x1, 4))
++
++/*
++** st1_vnum_za32_3_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1w	{ za3v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_3_w0_13,
++	       svst1_ver_vnum_za32 (3, w0, p0, x1, 13),
++	       svst1_ver_vnum_za32 (3, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za32_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1w	{ za0v\.s\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_0_w0_x2,
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, x2),
++	       svst1_ver_vnum_za32 (0, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za32_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za1v\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za32_1_w0p1_0,
++	       svst1_ver_vnum_za32 (1, w0 + 1, p0, x1, 0),
++	       svst1_ver_vnum_za32 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za64.c
+new file mode 100644
+index 000000000..bd061fc61
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za64.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za64_3_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1d	{ za3v\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_3_0_1,
++	       svst1_ver_vnum_za64 (3, 0, p0, x1, 1),
++	       svst1_ver_vnum_za64 (3, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za64_7_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1d	{ za7v\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_7_1_1,
++	       svst1_ver_vnum_za64 (7, 1, p0, x1, 1),
++	       svst1_ver_vnum_za64 (7, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za64_0_0_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?2
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_0_0_2,
++	       svst1_ver_vnum_za64 (0, 0, p0, x1, 2),
++	       svst1_ver_vnum_za64 (0, 0, p0, x1, 2))
++
++/*
++** st1_vnum_za64_5_1_2:
++**	incb	x1, all, mul #2
++**	mov	(w1[2-5]), #?3
++**	st1d	{ za5v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_5_1_2,
++	       svst1_ver_vnum_za64 (5, 1, p0, x1, 2),
++	       svst1_ver_vnum_za64 (5, 1, p0, x1, 2))
++
++/*
++** st1_vnum_za64_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_0_w0_0,
++	       svst1_ver_vnum_za64 (0, w0, p0, x1, 0),
++	       svst1_ver_vnum_za64 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za64_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0v\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_0_w0_1,
++	       svst1_ver_vnum_za64 (0, w0, p0, x1, 1),
++	       svst1_ver_vnum_za64 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za64_6_w0_2:
++**	incb	x1, all, mul #2
++**	add	(w1[2-5]), w0, #?2
++**	st1d	{ za6v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_6_w0_2,
++	       svst1_ver_vnum_za64 (6, w0, p0, x1, 2),
++	       svst1_ver_vnum_za64 (6, w0, p0, x1, 2))
++
++/*
++** st1_vnum_za64_2_w0_13:
++**	incb	x1, all, mul #13
++**	add	(w1[2-5]), w0, #?13
++**	st1d	{ za2v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_2_w0_13,
++	       svst1_ver_vnum_za64 (2, w0, p0, x1, 13),
++	       svst1_ver_vnum_za64 (2, w0, p0, x1, 13))
++
++/*
++** st1_vnum_za64_4_w0_x2:
++**	cntb	(x[0-9]+)
++**	madd	(x[0-9]+), (?:\1, x2|x2, \1), x1
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1d	{ za4v\.d\[\3, 0\] }, p0, \[\2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_4_w0_x2,
++	       svst1_ver_vnum_za64 (4, w0, p0, x1, x2),
++	       svst1_ver_vnum_za64 (4, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za64_1_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za1v\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za64_1_w0p1_0,
++	       svst1_ver_vnum_za64 (1, w0 + 1, p0, x1, 0),
++	       svst1_ver_vnum_za64 (1, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za8.c
+new file mode 100644
+index 000000000..b15a7eb08
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_vnum_za8.c
+@@ -0,0 +1,112 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_vnum_za8_0_0_1:
++**	incb	x1
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1b	{ za0v\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_0_1,
++	       svst1_ver_vnum_za8 (0, 0, p0, x1, 1),
++	       svst1_ver_vnum_za8 (0, 0, p0, x1, 1))
++
++/*
++** st1_vnum_za8_0_1_1:
++**	incb	x1
++**	mov	(w1[2-5]), #?1
++**	st1b	{ za0v\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_1_1,
++	       svst1_ver_vnum_za8 (0, 1, p0, x1, 1),
++	       svst1_ver_vnum_za8 (0, 1, p0, x1, 1))
++
++/*
++** st1_vnum_za8_0_0_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?16
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_0_16,
++	       svst1_ver_vnum_za8 (0, 0, p0, x1, 16),
++	       svst1_ver_vnum_za8 (0, 0, p0, x1, 16))
++
++/*
++** st1_vnum_za8_0_1_16:
++**	incb	x1, all, mul #16
++**	mov	(w1[2-5]), #?17
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_1_16,
++	       svst1_ver_vnum_za8 (0, 1, p0, x1, 16),
++	       svst1_ver_vnum_za8 (0, 1, p0, x1, 16))
++
++/*
++** st1_vnum_za8_0_w0_0:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_0,
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 0),
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 0))
++
++/*
++** st1_vnum_za8_0_w0_1:
++**	incb	x1
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_1,
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 1),
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 1))
++
++/*
++** st1_vnum_za8_0_w0_15:
++**	incb	x1, all, mul #15
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 15\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_15,
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 15),
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 15))
++
++/*
++** st1_vnum_za8_0_w0_16:
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_16,
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 16),
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, 16))
++
++/*
++** st1_vnum_za8_0_w0_x2:
++**	cntb	(x[0-9]+)
++**	mul	(x[0-9]+), (?:\1, x2|x2, \1)
++**	add	(w1[2-5]), (?:w0, w2|w2, w0)
++**	st1b	{ za0v\.b\[\3, 0\] }, p0, \[x1, \2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0_x2,
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, x2),
++	       svst1_ver_vnum_za8 (0, w0, p0, x1, x2))
++
++/*
++** st1_vnum_za8_0_w0p1_0:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_vnum_za8_0_w0p1_0,
++	       svst1_ver_vnum_za8 (0, w0 + 1, p0, x1, 0),
++	       svst1_ver_vnum_za8 (0, w0 + 1, p0, x1, 0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za128.c
+new file mode 100644
+index 000000000..7be6d5a5f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za128.c
+@@ -0,0 +1,83 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za128_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1q	{ za0v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_0,
++	       svst1_ver_za128 (0, 0, p0, x1),
++	       svst1_ver_za128 (0, 0, p0, x1))
++
++/*
++** st1_za128_0_1:
++**	mov	(w1[2-5]), #?1
++**	st1q	{ za0v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_1,
++	       svst1_ver_za128 (0, 1, p0, x1),
++	       svst1_ver_za128 (0, 1, p0, x1))
++
++/*
++** st1_za128_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za0v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_w0,
++	       svst1_ver_za128 (0, w0, p0, x1),
++	       svst1_ver_za128 (0, w0, p0, x1))
++
++/*
++** st1_za128_0_w0_p1:
++**	add	(w1[2-5]), w0, #?1
++**	st1q	{ za0v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_0_w0_p1,
++	       svst1_ver_za128 (0, w0 + 1, p0, x1),
++	       svst1_ver_za128 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za128_7_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za7v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_7_w0,
++	       svst1_ver_za128 (7, w0, p0, x1),
++	       svst1_ver_za128 (7, w0, p0, x1))
++
++/*
++** st1_za128_13_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za13v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_13_w0,
++	       svst1_ver_za128 (13, w0, p0, x1),
++	       svst1_ver_za128 (13, w0, p0, x1))
++
++/*
++** st1_za128_15_w0:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za15v\.q\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_15_w0,
++	       svst1_ver_za128 (15, w0, p0, x1),
++	       svst1_ver_za128 (15, w0, p0, x1))
++
++/*
++** st1_za128_9_w0_index:
++**	mov	(w1[2-5]), w0
++**	st1q	{ za9v\.q\[\1, 0\] }, p0, \[x1, x2, lsl #?4\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za128_9_w0_index,
++	       svst1_ver_za128 (9, w0, p0, x1 + x2 * 16),
++	       svst1_ver_za128 (9, w0, p0, x1 + x2 * 16))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za16.c
+new file mode 100644
+index 000000000..1bbf12a14
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za16.c
+@@ -0,0 +1,126 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za16_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_0,
++	       svst1_ver_za16 (0, 0, p0, x1),
++	       svst1_ver_za16 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 7.  */
++/*
++** st1_za16_0_7:
++**	mov	(w1[2-5]), #?7
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_7,
++	       svst1_ver_za16 (0, 7, p0, x1),
++	       svst1_ver_za16 (0, 7, p0, x1))
++
++/*
++** st1_za16_0_8:
++**	mov	(w1[2-5]), #?8
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_8,
++	       svst1_ver_za16 (0, 8, p0, x1),
++	       svst1_ver_za16 (0, 8, p0, x1))
++
++/*
++** st1_za16_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0,
++	       svst1_ver_za16 (0, w0, p0, x1),
++	       svst1_ver_za16 (0, w0, p0, x1))
++
++/*
++** st1_za16_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0v\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_p1,
++	       svst1_ver_za16 (0, w0 + 1, p0, x1),
++	       svst1_ver_za16 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za16_0_w0_p7:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za0v\.h\[\1, 7\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_p7,
++	       svst1_ver_za16 (0, w0 + 7, p0, x1),
++	       svst1_ver_za16 (0, w0 + 7, p0, x1))
++
++/*
++** st1_za16_1_w0:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0,
++	       svst1_ver_za16 (1, w0, p0, x1),
++	       svst1_ver_za16 (1, w0, p0, x1))
++
++
++/*
++** st1_za16_1_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1v\.h\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0_p1,
++	       svst1_ver_za16 (1, w0 + 1, p0, x1),
++	       svst1_ver_za16 (1, w0 + 1, p0, x1))
++
++/*
++** st1_za16_1_w0_p7:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1v\.h\[\1, 7\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0_p7,
++	       svst1_ver_za16 (1, w0 + 7, p0, x1),
++	       svst1_ver_za16 (1, w0 + 7, p0, x1))
++
++/*
++** st1_za16_1_w0_p5_index:
++**	mov	(w1[2-5]), w0
++**	st1h	{ za1v\.h\[\1, 5\] }, p0, \[x1, x2, lsl #?1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_1_w0_p5_index,
++	       svst1_ver_za16 (1, w0 + 5, p0, x1 + x2 * 2),
++	       svst1_ver_za16 (1, w0 + 5, p0, x1 + x2 * 2))
++
++/*
++** st1_za16_0_w0_p8:
++**	add	(w1[2-5]), w0, #?8
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_p8,
++	       svst1_ver_za16 (0, w0 + 8, p0, x1),
++	       svst1_ver_za16 (0, w0 + 8, p0, x1))
++
++/*
++** st1_za16_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1h	{ za0v\.h\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za16_0_w0_m1,
++	       svst1_ver_za16 (0, w0 - 1, p0, x1),
++	       svst1_ver_za16 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za32.c
+new file mode 100644
+index 000000000..9809e9708
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za32.c
+@@ -0,0 +1,125 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za32_0_0:
++**	mov	(w1[2-5]), (?:w0|#?0)
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_0,
++	       svst1_ver_za32 (0, 0, p0, x1),
++	       svst1_ver_za32 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 3.  */
++/*
++** st1_za32_0_3:
++**	mov	(w1[2-5]), #?3
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_3,
++	       svst1_ver_za32 (0, 3, p0, x1),
++	       svst1_ver_za32 (0, 3, p0, x1))
++
++/*
++** st1_za32_0_4:
++**	mov	(w1[2-5]), #?4
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_4,
++	       svst1_ver_za32 (0, 4, p0, x1),
++	       svst1_ver_za32 (0, 4, p0, x1))
++
++/*
++** st1_za32_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0,
++	       svst1_ver_za32 (0, w0, p0, x1),
++	       svst1_ver_za32 (0, w0, p0, x1))
++
++/*
++** st1_za32_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0v\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_p1,
++	       svst1_ver_za32 (0, w0 + 1, p0, x1),
++	       svst1_ver_za32 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za32_0_w0_p3:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za0v\.s\[\1, 3\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_p3,
++	       svst1_ver_za32 (0, w0 + 3, p0, x1),
++	       svst1_ver_za32 (0, w0 + 3, p0, x1))
++
++/*
++** st1_za32_3_w0:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za3v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_3_w0,
++	       svst1_ver_za32 (3, w0, p0, x1),
++	       svst1_ver_za32 (3, w0, p0, x1))
++
++/*
++** st1_za32_3_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za3v\.s\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_3_w0_p1,
++	       svst1_ver_za32 (3, w0 + 1, p0, x1),
++	       svst1_ver_za32 (3, w0 + 1, p0, x1))
++
++/*
++** st1_za32_3_w0_p3:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za3v\.s\[\1, 3\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_3_w0_p3,
++	       svst1_ver_za32 (3, w0 + 3, p0, x1),
++	       svst1_ver_za32 (3, w0 + 3, p0, x1))
++
++/*
++** st1_za32_1_w0_p2_index:
++**	mov	(w1[2-5]), w0
++**	st1w	{ za1v\.s\[\1, 2\] }, p0, \[x1, x2, lsl #?2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_1_w0_p2_index,
++	       svst1_ver_za32 (1, w0 + 2, p0, x1 + x2 * 4),
++	       svst1_ver_za32 (1, w0 + 2, p0, x1 + x2 * 4))
++
++/*
++** st1_za32_0_w0_p4:
++**	add	(w1[2-5]), w0, #?4
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_p4,
++	       svst1_ver_za32 (0, w0 + 4, p0, x1),
++	       svst1_ver_za32 (0, w0 + 4, p0, x1))
++
++/*
++** st1_za32_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1w	{ za0v\.s\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za32_0_w0_m1,
++	       svst1_ver_za32 (0, w0 - 1, p0, x1),
++	       svst1_ver_za32 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za64.c
+new file mode 100644
+index 000000000..0e93f4da3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za64.c
+@@ -0,0 +1,105 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za64_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_0,
++	       svst1_ver_za64 (0, 0, p0, x1),
++	       svst1_ver_za64 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 1.  */
++/*
++** st1_za64_0_1:
++**	mov	(w1[2-5]), #?1
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_1,
++	       svst1_ver_za64 (0, 1, p0, x1),
++	       svst1_ver_za64 (0, 1, p0, x1))
++
++/*
++** st1_za64_0_2:
++**	mov	(w1[2-5]), #?2
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_2,
++	       svst1_ver_za64 (0, 2, p0, x1),
++	       svst1_ver_za64 (0, 2, p0, x1))
++
++/*
++** st1_za64_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0,
++	       svst1_ver_za64 (0, w0, p0, x1),
++	       svst1_ver_za64 (0, w0, p0, x1))
++
++/*
++** st1_za64_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za0v\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0_p1,
++	       svst1_ver_za64 (0, w0 + 1, p0, x1),
++	       svst1_ver_za64 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za64_7_w0:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za7v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_7_w0,
++	       svst1_ver_za64 (7, w0, p0, x1),
++	       svst1_ver_za64 (7, w0, p0, x1))
++
++/*
++** st1_za64_7_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za7v\.d\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_7_w0_p1,
++	       svst1_ver_za64 (7, w0 + 1, p0, x1),
++	       svst1_ver_za64 (7, w0 + 1, p0, x1))
++
++/*
++** st1_za64_5_w0_p1_index:
++**	mov	(w1[2-5]), w0
++**	st1d	{ za5v\.d\[\1, 1\] }, p0, \[x1, x2, lsl #?3\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_5_w0_p1_index,
++	       svst1_ver_za64 (5, w0 + 1, p0, x1 + x2 * 8),
++	       svst1_ver_za64 (5, w0 + 1, p0, x1 + x2 * 8))
++
++/*
++** st1_za64_0_w0_p2:
++**	add	(w1[2-5]), w0, #?2
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0_p2,
++	       svst1_ver_za64 (0, w0 + 2, p0, x1),
++	       svst1_ver_za64 (0, w0 + 2, p0, x1))
++
++/*
++** st1_za64_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1d	{ za0v\.d\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za64_0_w0_m1,
++	       svst1_ver_za64 (0, w0 - 1, p0, x1),
++	       svst1_ver_za64 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za8.c
+new file mode 100644
+index 000000000..c76b5c28b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/st1_ver_za8.c
+@@ -0,0 +1,95 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** st1_za8_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_0,
++	       svst1_ver_za8 (0, 0, p0, x1),
++	       svst1_ver_za8 (0, 0, p0, x1))
++
++/* It would also be OK (and perhaps better) to move 0 into a register
++   and use an offset of 15.  */
++/*
++** st1_za8_0_15:
++**	mov	(w1[2-5]), #?15
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_15,
++	       svst1_ver_za8 (0, 15, p0, x1),
++	       svst1_ver_za8 (0, 15, p0, x1))
++
++/*
++** st1_za8_0_16:
++**	mov	(w1[2-5]), #?16
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_16,
++	       svst1_ver_za8 (0, 16, p0, x1),
++	       svst1_ver_za8 (0, 16, p0, x1))
++
++/*
++** st1_za8_0_w0:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0,
++	       svst1_ver_za8 (0, w0, p0, x1),
++	       svst1_ver_za8 (0, w0, p0, x1))
++
++/*
++** st1_za8_0_w0_p1:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 1\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p1,
++	       svst1_ver_za8 (0, w0 + 1, p0, x1),
++	       svst1_ver_za8 (0, w0 + 1, p0, x1))
++
++/*
++** st1_za8_0_w0_p15:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 15\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p15,
++	       svst1_ver_za8 (0, w0 + 15, p0, x1),
++	       svst1_ver_za8 (0, w0 + 15, p0, x1))
++
++/*
++** st1_za8_0_w0_p13_index:
++**	mov	(w1[2-5]), w0
++**	st1b	{ za0v\.b\[\1, 15\] }, p0, \[x1, x2\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p13_index,
++	       svst1_ver_za8 (0, w0 + 15, p0, x1 + x2),
++	       svst1_ver_za8 (0, w0 + 15, p0, x1 + x2))
++
++/*
++** st1_za8_0_w0_p16:
++**	add	(w1[2-5]), w0, #?16
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_p16,
++	       svst1_ver_za8 (0, w0 + 16, p0, x1),
++	       svst1_ver_za8 (0, w0 + 16, p0, x1))
++
++/*
++** st1_za8_0_w0_m1:
++**	sub	(w1[2-5]), w0, #?1
++**	st1b	{ za0v\.b\[\1, 0\] }, p0, \[x1\]
++**	ret
++*/
++TEST_STORE_ZA (st1_za8_0_w0_m1,
++	       svst1_ver_za8 (0, w0 - 1, p0, x1),
++	       svst1_ver_za8 (0, w0 - 1, p0, x1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_s.c
+new file mode 100644
+index 000000000..3ef7e0c09
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_s.c
+@@ -0,0 +1,147 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** str_vnum_za_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_0_0,
++	       svstr_vnum_za (0, x1, 0),
++	       svstr_vnum_za (0, x1, 0))
++
++/*
++** str_vnum_za_0_1:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_0_1,
++	       svstr_vnum_za (0, x1, 1),
++	       svstr_vnum_za (0, x1, 1))
++
++/*
++** str_vnum_za_1_0:
++**	mov	(w1[2-5]), #?1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_1_0,
++	       svstr_vnum_za (1, x1, 0),
++	       svstr_vnum_za (1, x1, 0))
++
++/*
++** str_vnum_za_1_2:
++**	mov	(w1[2-5]), #?1
++**	str	za\[\1, 2\], \[x1(?:, #2, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_1_2,
++	       svstr_vnum_za (1, x1, 2),
++	       svstr_vnum_za (1, x1, 2))
++
++/*
++** str_vnum_za_w0_0:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_0,
++	       svstr_vnum_za (w0, x1, 0),
++	       svstr_vnum_za (w0, x1, 0))
++
++/*
++** str_vnum_za_w0_1:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_1,
++	       svstr_vnum_za (w0, x1, 1),
++	       svstr_vnum_za (w0, x1, 1))
++
++/*
++** str_vnum_za_w0_13:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 13\], \[x1, #13, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_13,
++	       svstr_vnum_za (w0, x1, 13),
++	       svstr_vnum_za (w0, x1, 13))
++
++/*
++** str_vnum_za_w0_15:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 15\], \[x1, #15, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_15,
++	       svstr_vnum_za (w0, x1, 15),
++	       svstr_vnum_za (w0, x1, 15))
++
++/*
++** str_vnum_za_w0_16:
++** (
++**	add	(w1[2-5]), w0, #?16
++**	incb	x1, all, mul #16
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	str	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_16,
++	       svstr_vnum_za (w0, x1, 16),
++	       svstr_vnum_za (w0, x1, 16))
++
++/*
++** str_vnum_za_w0_m1:
++** (
++**	sub	(w1[2-5]), w0, #?1
++**	decb	x1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	decb	x1
++**	sub	(w1[2-5]), w0, #?1
++**	str	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_m1,
++	       svstr_vnum_za (w0, x1, -1),
++	       svstr_vnum_za (w0, x1, -1))
++
++/*
++** str_vnum_za_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0p1_0,
++	       svstr_vnum_za (w0 + 1, x1, 0),
++	       svstr_vnum_za (w0 + 1, x1, 0))
++
++/*
++** str_vnum_za_w0m1_1:
++**	sub	(w1[2-5]), w0, #?1
++**	str	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0m1_1,
++	       svstr_vnum_za (w0 - 1, x1, 1),
++	       svstr_vnum_za (w0 - 1, x1, 1))
++
++/*
++** str_vnum_za_w0p2_3:
++**	add	(w1[2-5]), w0, #?2
++**	str	za\[\1, 3\], \[x1(?:, #3, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0p2_3,
++	       svstr_vnum_za (w0 + 2, x1, 3),
++	       svstr_vnum_za (w0 + 2, x1, 3))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_sc.c
+new file mode 100644
+index 000000000..7cd09e67c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_vnum_za_sc.c
+@@ -0,0 +1,148 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** str_vnum_za_0_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_0_0,
++	       svstr_vnum_za (0, x1, 0),
++	       svstr_vnum_za (0, x1, 0))
++
++/*
++** str_vnum_za_0_1:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_0_1,
++	       svstr_vnum_za (0, x1, 1),
++	       svstr_vnum_za (0, x1, 1))
++
++/*
++** str_vnum_za_1_0:
++**	mov	(w1[2-5]), #?1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_1_0,
++	       svstr_vnum_za (1, x1, 0),
++	       svstr_vnum_za (1, x1, 0))
++
++/*
++** str_vnum_za_1_2:
++**	mov	(w1[2-5]), #?1
++**	str	za\[\1, 2\], \[x1(?:, #2, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_1_2,
++	       svstr_vnum_za (1, x1, 2),
++	       svstr_vnum_za (1, x1, 2))
++
++/*
++** str_vnum_za_w0_0:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_0,
++	       svstr_vnum_za (w0, x1, 0),
++	       svstr_vnum_za (w0, x1, 0))
++
++/*
++** str_vnum_za_w0_1:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_1,
++	       svstr_vnum_za (w0, x1, 1),
++	       svstr_vnum_za (w0, x1, 1))
++
++/*
++** str_vnum_za_w0_13:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 13\], \[x1, #13, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_13,
++	       svstr_vnum_za (w0, x1, 13),
++	       svstr_vnum_za (w0, x1, 13))
++
++/*
++** str_vnum_za_w0_15:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 15\], \[x1, #15, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_15,
++	       svstr_vnum_za (w0, x1, 15),
++	       svstr_vnum_za (w0, x1, 15))
++
++/*
++** str_vnum_za_w0_16:
++** (
++**	add	(w1[2-5]), w0, #?16
++**	addsvl	(x[0-9]+), x1, #16
++**	str	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	addsvl	(x[0-9]+), x1, #16
++**	add	(w1[2-5]), w0, #?16
++**	str	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_16,
++	       svstr_vnum_za (w0, x1, 16),
++	       svstr_vnum_za (w0, x1, 16))
++
++/*
++** str_vnum_za_w0_m1:
++** (
++**	sub	(w1[2-5]), w0, #?1
++**	addsvl	(x[0-9]+), x1, #-1
++**	str	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	addsvl	(x[0-9]+), x1, #-1
++**	sub	(w1[2-5]), w0, #?1
++**	str	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0_m1,
++	       svstr_vnum_za (w0, x1, -1),
++	       svstr_vnum_za (w0, x1, -1))
++
++/*
++** str_vnum_za_w0p1_0:
++**	add	(w1[2-5]), w0, #?1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0p1_0,
++	       svstr_vnum_za (w0 + 1, x1, 0),
++	       svstr_vnum_za (w0 + 1, x1, 0))
++
++/*
++** str_vnum_za_w0m1_1:
++**	sub	(w1[2-5]), w0, #?1
++**	str	za\[\1, 1\], \[x1(?:, #1, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0m1_1,
++	       svstr_vnum_za (w0 - 1, x1, 1),
++	       svstr_vnum_za (w0 - 1, x1, 1))
++
++/*
++** str_vnum_za_w0p2_3:
++**	add	(w1[2-5]), w0, #?2
++**	str	za\[\1, 3\], \[x1(?:, #3, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_vnum_za_w0p2_3,
++	       svstr_vnum_za (w0 + 2, x1, 3),
++	       svstr_vnum_za (w0 + 2, x1, 3))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_s.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_s.c
+new file mode 100644
+index 000000000..4d953c596
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_s.c
+@@ -0,0 +1,124 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** str_za_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_0,
++	       svstr_za (0, x1),
++	       svstr_za (0, x1))
++
++/*
++** str_za_1:
++**	mov	(w1[2-5]), #?1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_1,
++	       svstr_za (1, x1),
++	       svstr_za (1, x1))
++
++/*
++** str_za_w0:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0,
++	       svstr_za (w0, x1),
++	       svstr_za (w0, x1))
++
++/*
++** str_za_w0_1_vnum:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0_1_vnum,
++	       svstr_za (w0 + 1, x1 + svcntsb ()),
++	       svstr_za (w0 + 1, x1 + svcntsb ()))
++
++/*
++** str_za_w0_13_vnum:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 13\], \[x1, #13, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0_13_vnum,
++	       svstr_za (w0 + 13, x1 + svcntsb () * 13),
++	       svstr_za (w0 + 13, x1 + svcntsb () * 13))
++
++/*
++** str_za_w0_15_vnum:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 15\], \[x1, #15, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0_15_vnum,
++	       svstr_za (w0 + 15, x1 + svcntsb () * 15),
++	       svstr_za (w0 + 15, x1 + svcntsb () * 15))
++
++/*
++** str_za_w0_16_vnum:
++** (
++**	add	(w1[2-5]), w0, #?16
++**	incb	x1, all, mul #16
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	incb	x1, all, mul #16
++**	add	(w1[2-5]), w0, #?16
++**	str	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0_16_vnum,
++	       svstr_za (w0 + 16, x1 + svcntsb () * 16),
++	       svstr_za (w0 + 16, x1 + svcntsb () * 16))
++
++/*
++** str_za_w0_m1_vnum:
++** (
++**	sub	(w1[2-5]), w0, #?1
++**	decb	x1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++** |
++**	decb	x1
++**	sub	(w1[2-5]), w0, #?1
++**	str	za\[\2, 0\], \[x1(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0_m1_vnum,
++	       svstr_za (w0 - 1, x1 - svcntsb ()),
++	       svstr_za (w0 - 1, x1 - svcntsb ()))
++
++/*
++** str_za_w0p2:
++**	add	(w1[2-5]), w0, #?2
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0p2,
++	       svstr_za (w0 + 2, x1),
++	       svstr_za (w0 + 2, x1))
++
++/*
++** str_za_offset:
++** (
++**	mov	(w1[2-5]), w0
++**	add	(x[0-9]+), x1, #?1
++**	str	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	add	(x[0-9]+), x1, #?1
++**	mov	(w1[2-5]), w0
++**	str	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_za_offset,
++	       svstr_za (w0, x1 + 1),
++	       svstr_za (w0, x1 + 1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_sc.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_sc.c
+new file mode 100644
+index 000000000..3406055e7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/str_za_sc.c
+@@ -0,0 +1,71 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** str_za_0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_0,
++	       svstr_za (0, x1),
++	       svstr_za (0, x1))
++
++/*
++** str_za_1:
++**	mov	(w1[2-5]), #?1
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_1,
++	       svstr_za (1, x1),
++	       svstr_za (1, x1))
++
++/*
++** str_za_w0:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0,
++	       svstr_za (w0, x1),
++	       svstr_za (w0, x1))
++
++/*
++** str_za_w0_1_vnum:
++**	mov	(w1[2-5]), w0
++**	str	za\[\1, 1\], \[x1, #1, mul vl\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0_1_vnum,
++	       svstr_za (w0 + 1, x1 + svcntsb ()),
++	       svstr_za (w0 + 1, x1 + svcntsb ()))
++
++/*
++** str_za_w0p2:
++**	add	(w1[2-5]), w0, #?2
++**	str	za\[\1, 0\], \[x1(?:, #0, mul vl)?\]
++**	ret
++*/
++TEST_STORE_ZA (str_za_w0p2,
++	       svstr_za (w0 + 2, x1),
++	       svstr_za (w0 + 2, x1))
++
++/*
++** str_za_offset:
++** (
++**	mov	(w1[2-5]), w0
++**	add	(x[0-9]+), x1, #?1
++**	str	za\[\1, 0\], \[\2(?:, #0, mul vl)?\]
++** |
++**	add	(x[0-9]+), x1, #?1
++**	mov	(w1[2-5]), w0
++**	str	za\[\4, 0\], \[\3(?:, #0, mul vl)?\]
++** )
++**	ret
++*/
++TEST_STORE_ZA (str_za_offset,
++	       svstr_za (w0, x1 + 1),
++	       svstr_za (w0, x1 + 1))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za32.c
+new file mode 100644
+index 000000000..9dd66f722
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za32.c
+@@ -0,0 +1,30 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** sumopa_za32_s8_0_p0_p1_z0_z4:
++**	sumopa	za0\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (sumopa_za32_s8_0_p0_p1_z0_z4, svint8_t, svuint8_t,
++	      svsumopa_za32_s8_m (0, p0, p1, z0, z4),
++	      svsumopa_za32_m (0, p0, p1, z0, z4))
++
++/*
++** sumopa_za32_s8_0_p1_p0_z4_z0:
++**	sumopa	za0\.s, p1/m, p0/m, z4\.b, z0\.b
++**	ret
++*/
++TEST_DUAL_ZA (sumopa_za32_s8_0_p1_p0_z4_z0, svuint8_t, svint8_t,
++	      svsumopa_za32_s8_m (0, p1, p0, z4, z0),
++	      svsumopa_za32_m (0, p1, p0, z4, z0))
++
++/*
++** sumopa_za32_s8_3_p0_p1_z0_z4:
++**	sumopa	za3\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (sumopa_za32_s8_3_p0_p1_z0_z4, svint8_t, svuint8_t,
++	      svsumopa_za32_s8_m (3, p0, p1, z0, z4),
++	      svsumopa_za32_m (3, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za64.c
+new file mode 100644
+index 000000000..2a78ab85d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumopa_za64.c
+@@ -0,0 +1,32 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** sumopa_za64_s16_0_p0_p1_z0_z4:
++**	sumopa	za0\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (sumopa_za64_s16_0_p0_p1_z0_z4, svint16_t, svuint16_t,
++	      svsumopa_za64_s16_m (0, p0, p1, z0, z4),
++	      svsumopa_za64_m (0, p0, p1, z0, z4))
++
++/*
++** sumopa_za64_s16_0_p1_p0_z4_z0:
++**	sumopa	za0\.d, p1/m, p0/m, z4\.h, z0\.h
++**	ret
++*/
++TEST_DUAL_ZA (sumopa_za64_s16_0_p1_p0_z4_z0, svuint16_t, svint16_t,
++	      svsumopa_za64_s16_m (0, p1, p0, z4, z0),
++	      svsumopa_za64_m (0, p1, p0, z4, z0))
++
++/*
++** sumopa_za64_s16_7_p0_p1_z0_z4:
++**	sumopa	za7\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (sumopa_za64_s16_7_p0_p1_z0_z4, svint16_t, svuint16_t,
++	      svsumopa_za64_s16_m (7, p0, p1, z0, z4),
++	      svsumopa_za64_m (7, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za32.c
+new file mode 100644
+index 000000000..55cb92d1b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za32.c
+@@ -0,0 +1,30 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** sumops_za32_s8_0_p0_p1_z0_z4:
++**	sumops	za0\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (sumops_za32_s8_0_p0_p1_z0_z4, svint8_t, svuint8_t,
++	      svsumops_za32_s8_m (0, p0, p1, z0, z4),
++	      svsumops_za32_m (0, p0, p1, z0, z4))
++
++/*
++** sumops_za32_s8_0_p1_p0_z4_z0:
++**	sumops	za0\.s, p1/m, p0/m, z4\.b, z0\.b
++**	ret
++*/
++TEST_DUAL_ZA (sumops_za32_s8_0_p1_p0_z4_z0, svuint8_t, svint8_t,
++	      svsumops_za32_s8_m (0, p1, p0, z4, z0),
++	      svsumops_za32_m (0, p1, p0, z4, z0))
++
++/*
++** sumops_za32_s8_3_p0_p1_z0_z4:
++**	sumops	za3\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (sumops_za32_s8_3_p0_p1_z0_z4, svint8_t, svuint8_t,
++	      svsumops_za32_s8_m (3, p0, p1, z0, z4),
++	      svsumops_za32_m (3, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za64.c
+new file mode 100644
+index 000000000..910a45b29
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/sumops_za64.c
+@@ -0,0 +1,32 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** sumops_za64_s16_0_p0_p1_z0_z4:
++**	sumops	za0\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (sumops_za64_s16_0_p0_p1_z0_z4, svint16_t, svuint16_t,
++	      svsumops_za64_s16_m (0, p0, p1, z0, z4),
++	      svsumops_za64_m (0, p0, p1, z0, z4))
++
++/*
++** sumops_za64_s16_0_p1_p0_z4_z0:
++**	sumops	za0\.d, p1/m, p0/m, z4\.h, z0\.h
++**	ret
++*/
++TEST_DUAL_ZA (sumops_za64_s16_0_p1_p0_z4_z0, svuint16_t, svint16_t,
++	      svsumops_za64_s16_m (0, p1, p0, z4, z0),
++	      svsumops_za64_m (0, p1, p0, z4, z0))
++
++/*
++** sumops_za64_s16_7_p0_p1_z0_z4:
++**	sumops	za7\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (sumops_za64_s16_7_p0_p1_z0_z4, svint16_t, svuint16_t,
++	      svsumops_za64_s16_m (7, p0, p1, z0, z4),
++	      svsumops_za64_m (7, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/test_sme_acle.h b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/test_sme_acle.h
+new file mode 100644
+index 000000000..aaadab2f7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/test_sme_acle.h
+@@ -0,0 +1,62 @@
++#ifndef TEST_SME_ACLE_H
++#define TEST_SME_ACLE_H 1
++
++#if (!defined(STREAMING_COMPATIBLE) \
++     && !defined(NON_STREAMING) \
++     && !defined(STREAMING))
++#define STREAMING
++#endif
++
++#if !defined(NO_SHARED_ZA)
++#define SHARED_ZA
++#endif
++
++#include "../../sve/acle/asm/test_sve_acle.h"
++
++#include 
++
++#define TEST_LOAD_ZA(NAME, CODE1, CODE2)			\
++  PROTO (NAME, void, (svbool_t p0, int32_t w0, const char *x1,	\
++		      uint64_t x2))				\
++  {								\
++    INVOKE (CODE1, CODE2);					\
++  }
++
++#define TEST_STORE_ZA(NAME, CODE1, CODE2)			\
++  PROTO (NAME, void, (svbool_t p0, int32_t w0, char *x1,	\
++		      uint64_t x2))				\
++  {								\
++    INVOKE (CODE1, CODE2);					\
++  }
++
++#define TEST_READ_ZA(NAME, TYPE, CODE1, CODE2)			\
++  PROTO (NAME, TYPE, (TYPE z0, TYPE z1, svbool_t p0,		\
++		      int32_t w0))				\
++  {								\
++    INVOKE (CODE1, CODE2);					\
++    return z0;							\
++  }
++
++#define TEST_WRITE_ZA(NAME, TYPE, CODE1, CODE2)			\
++  PROTO (NAME, void, (TYPE z0, TYPE z1, svbool_t p0,		\
++		      int32_t w0))				\
++  {								\
++    INVOKE (CODE1, CODE2);					\
++  }
++
++#define TEST_UNIFORM_ZA(NAME, TYPE, CODE1, CODE2)		\
++  PROTO (NAME, void, (TYPE z0, TYPE z1, svbool_t p0,		\
++		      svbool_t p1))				\
++  {								\
++    INVOKE (CODE1, CODE2);					\
++  }
++
++#define TEST_DUAL_ZA(NAME, TYPE1, TYPE2, CODE1, CODE2)		\
++  PROTO (NAME, void, (TYPE1 z0, TYPE1 z1, TYPE1 z2, TYPE1 z3,	\
++		      TYPE2 z4, TYPE2 z5, TYPE2 z6, TYPE2 z7,	\
++		      svbool_t p0, svbool_t p1))		\
++  {								\
++    INVOKE (CODE1, CODE2);					\
++  }
++
++#endif
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/undef_za.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/undef_za.c
+new file mode 100644
+index 000000000..5474328fb
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/undef_za.c
+@@ -0,0 +1,33 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** undef_za_1:
++**	ret
++*/
++PROTO (undef_za_1, void, ()) { svundef_za (); }
++
++/*
++** undef_za_2:
++**	ret
++*/
++PROTO (undef_za_2, void, ())
++{
++  svzero_za ();
++  svundef_za ();
++}
++
++/*
++** undef_za_3:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	str	za\[\1, 0\], \[x0(?:, #0, mul vl)\]
++**	ret
++*/
++PROTO (undef_za_3, void, (void *ptr))
++{
++  svzero_za ();
++  svundef_za ();
++  svstr_za (0, ptr);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za32.c
+new file mode 100644
+index 000000000..bbc0b6c11
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za32.c
+@@ -0,0 +1,30 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** usmopa_za32_u8_0_p0_p1_z0_z4:
++**	usmopa	za0\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (usmopa_za32_u8_0_p0_p1_z0_z4, svuint8_t, svint8_t,
++	      svusmopa_za32_u8_m (0, p0, p1, z0, z4),
++	      svusmopa_za32_m (0, p0, p1, z0, z4))
++
++/*
++** usmopa_za32_u8_0_p1_p0_z4_z0:
++**	usmopa	za0\.s, p1/m, p0/m, z4\.b, z0\.b
++**	ret
++*/
++TEST_DUAL_ZA (usmopa_za32_u8_0_p1_p0_z4_z0, svint8_t, svuint8_t,
++	      svusmopa_za32_u8_m (0, p1, p0, z4, z0),
++	      svusmopa_za32_m (0, p1, p0, z4, z0))
++
++/*
++** usmopa_za32_u8_3_p0_p1_z0_z4:
++**	usmopa	za3\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (usmopa_za32_u8_3_p0_p1_z0_z4, svuint8_t, svint8_t,
++	      svusmopa_za32_u8_m (3, p0, p1, z0, z4),
++	      svusmopa_za32_m (3, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za64.c
+new file mode 100644
+index 000000000..64ee25bc7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmopa_za64.c
+@@ -0,0 +1,32 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** usmopa_za64_u16_0_p0_p1_z0_z4:
++**	usmopa	za0\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (usmopa_za64_u16_0_p0_p1_z0_z4, svuint16_t, svint16_t,
++	      svusmopa_za64_u16_m (0, p0, p1, z0, z4),
++	      svusmopa_za64_m (0, p0, p1, z0, z4))
++
++/*
++** usmopa_za64_u16_0_p1_p0_z4_z0:
++**	usmopa	za0\.d, p1/m, p0/m, z4\.h, z0\.h
++**	ret
++*/
++TEST_DUAL_ZA (usmopa_za64_u16_0_p1_p0_z4_z0, svint16_t, svuint16_t,
++	      svusmopa_za64_u16_m (0, p1, p0, z4, z0),
++	      svusmopa_za64_m (0, p1, p0, z4, z0))
++
++/*
++** usmopa_za64_u16_7_p0_p1_z0_z4:
++**	usmopa	za7\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (usmopa_za64_u16_7_p0_p1_z0_z4, svuint16_t, svint16_t,
++	      svusmopa_za64_u16_m (7, p0, p1, z0, z4),
++	      svusmopa_za64_m (7, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za32.c
+new file mode 100644
+index 000000000..98fd33157
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za32.c
+@@ -0,0 +1,30 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** usmops_za32_u8_0_p0_p1_z0_z4:
++**	usmops	za0\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (usmops_za32_u8_0_p0_p1_z0_z4, svuint8_t, svint8_t,
++	      svusmops_za32_u8_m (0, p0, p1, z0, z4),
++	      svusmops_za32_m (0, p0, p1, z0, z4))
++
++/*
++** usmops_za32_u8_0_p1_p0_z4_z0:
++**	usmops	za0\.s, p1/m, p0/m, z4\.b, z0\.b
++**	ret
++*/
++TEST_DUAL_ZA (usmops_za32_u8_0_p1_p0_z4_z0, svint8_t, svuint8_t,
++	      svusmops_za32_u8_m (0, p1, p0, z4, z0),
++	      svusmops_za32_m (0, p1, p0, z4, z0))
++
++/*
++** usmops_za32_u8_3_p0_p1_z0_z4:
++**	usmops	za3\.s, p0/m, p1/m, z0\.b, z4\.b
++**	ret
++*/
++TEST_DUAL_ZA (usmops_za32_u8_3_p0_p1_z0_z4, svuint8_t, svint8_t,
++	      svusmops_za32_u8_m (3, p0, p1, z0, z4),
++	      svusmops_za32_m (3, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za64.c
+new file mode 100644
+index 000000000..e20cdab41
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/usmops_za64.c
+@@ -0,0 +1,32 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++#pragma GCC target "+sme-i16i64"
++
++/*
++** usmops_za64_u16_0_p0_p1_z0_z4:
++**	usmops	za0\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (usmops_za64_u16_0_p0_p1_z0_z4, svuint16_t, svint16_t,
++	      svusmops_za64_u16_m (0, p0, p1, z0, z4),
++	      svusmops_za64_m (0, p0, p1, z0, z4))
++
++/*
++** usmops_za64_u16_0_p1_p0_z4_z0:
++**	usmops	za0\.d, p1/m, p0/m, z4\.h, z0\.h
++**	ret
++*/
++TEST_DUAL_ZA (usmops_za64_u16_0_p1_p0_z4_z0, svint16_t, svuint16_t,
++	      svusmops_za64_u16_m (0, p1, p0, z4, z0),
++	      svusmops_za64_m (0, p1, p0, z4, z0))
++
++/*
++** usmops_za64_u16_7_p0_p1_z0_z4:
++**	usmops	za7\.d, p0/m, p1/m, z0\.h, z4\.h
++**	ret
++*/
++TEST_DUAL_ZA (usmops_za64_u16_7_p0_p1_z0_z4, svuint16_t, svint16_t,
++	      svusmops_za64_u16_m (7, p0, p1, z0, z4),
++	      svusmops_za64_m (7, p0, p1, z0, z4))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za128.c
+new file mode 100644
+index 000000000..119a2535e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za128.c
+@@ -0,0 +1,193 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za128_s8_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_0_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (0, 0, p0, z0),
++	       svwrite_hor_za128_m (0, 0, p0, z0))
++
++/*
++** write_za128_s8_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_1_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (0, 1, p0, z0),
++	       svwrite_hor_za128_m (0, 1, p0, z0))
++
++/*
++** write_za128_s8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s8_0_w0p1_z0:
++**	add	(w1[2-5]), w0, #?1
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0p1_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (0, w0 + 1, p0, z0),
++	       svwrite_hor_za128_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za128_s8_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0m1_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (0, w0 - 1, p0, z0),
++	       svwrite_hor_za128_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za128_s8_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_1_w0_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (1, w0, p0, z0),
++	       svwrite_hor_za128_m (1, w0, p0, z0))
++
++/*
++** write_za128_s8_15_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za15h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_15_w0_z0, svint8_t,
++	       svwrite_hor_za128_s8_m (15, w0, p0, z0),
++	       svwrite_hor_za128_m (15, w0, p0, z0))
++
++/*
++** write_za128_s8_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z1\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0_z1, svint8_t,
++	       svwrite_hor_za128_s8_m (0, w0, p0, z1),
++	       svwrite_hor_za128_m (0, w0, p0, z1))
++
++/*
++** write_za128_u8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u8_0_w0_z0, svuint8_t,
++	       svwrite_hor_za128_u8_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s16_0_w0_z0, svint16_t,
++	       svwrite_hor_za128_s16_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_u16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u16_0_w0_z0, svuint16_t,
++	       svwrite_hor_za128_u16_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_f16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_f16_0_w0_z0, svfloat16_t,
++	       svwrite_hor_za128_f16_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_bf16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_bf16_0_w0_z0, svbfloat16_t,
++	       svwrite_hor_za128_bf16_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s32_0_w0_z0, svint32_t,
++	       svwrite_hor_za128_s32_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_u32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u32_0_w0_z0, svuint32_t,
++	       svwrite_hor_za128_u32_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_f32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_f32_0_w0_z0, svfloat32_t,
++	       svwrite_hor_za128_f32_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s64_0_w0_z0, svint64_t,
++	       svwrite_hor_za128_s64_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_u64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u64_0_w0_z0, svuint64_t,
++	       svwrite_hor_za128_u64_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_f64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_f64_0_w0_z0, svfloat64_t,
++	       svwrite_hor_za128_f64_m (0, w0, p0, z0),
++	       svwrite_hor_za128_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za16.c
+new file mode 100644
+index 000000000..c8f13f7bc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za16.c
+@@ -0,0 +1,133 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za16_s16_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_0_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, 0, p0, z0),
++	       svwrite_hor_za16_m (0, 0, p0, z0))
++
++/*
++** write_za16_s16_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_1_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, 1, p0, z0),
++	       svwrite_hor_za16_m (0, 1, p0, z0))
++
++/*
++** write_za16_s16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, w0, p0, z0),
++	       svwrite_hor_za16_m (0, w0, p0, z0))
++
++/*
++** write_za16_s16_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 1\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0p1_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, w0 + 1, p0, z0),
++	       svwrite_hor_za16_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za16_s16_0_w0p7_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 7\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0p7_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, w0 + 7, p0, z0),
++	       svwrite_hor_za16_m (0, w0 + 7, p0, z0))
++
++/*
++** write_za16_s16_0_w0p8_z0:
++**	add	(w1[2-5]), w0, #?8
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0p8_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, w0 + 8, p0, z0),
++	       svwrite_hor_za16_m (0, w0 + 8, p0, z0))
++
++/*
++** write_za16_s16_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0m1_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (0, w0 - 1, p0, z0),
++	       svwrite_hor_za16_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za16_s16_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_1_w0_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (1, w0, p0, z0),
++	       svwrite_hor_za16_m (1, w0, p0, z0))
++
++/*
++** write_za16_s16_1_w0p7_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.h\[\1, 7\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_1_w0p7_z0, svint16_t,
++	       svwrite_hor_za16_s16_m (1, w0 + 7, p0, z0),
++	       svwrite_hor_za16_m (1, w0 + 7, p0, z0))
++
++/*
++** write_za16_s16_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 0\], p0/m, z1\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0_z1, svint16_t,
++	       svwrite_hor_za16_s16_m (0, w0, p0, z1),
++	       svwrite_hor_za16_m (0, w0, p0, z1))
++
++/*
++** write_za16_u16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_u16_0_w0_z0, svuint16_t,
++	       svwrite_hor_za16_u16_m (0, w0, p0, z0),
++	       svwrite_hor_za16_m (0, w0, p0, z0))
++
++/*
++** write_za16_f16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_f16_0_w0_z0, svfloat16_t,
++	       svwrite_hor_za16_f16_m (0, w0, p0, z0),
++	       svwrite_hor_za16_m (0, w0, p0, z0))
++
++/*
++** write_za16_bf16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_bf16_0_w0_z0, svbfloat16_t,
++	       svwrite_hor_za16_bf16_m (0, w0, p0, z0),
++	       svwrite_hor_za16_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za32.c
+new file mode 100644
+index 000000000..ea2f5ae89
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za32.c
+@@ -0,0 +1,143 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za32_s32_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_0_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, 0, p0, z0),
++	       svwrite_hor_za32_m (0, 0, p0, z0))
++
++/*
++** write_za32_s32_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_1_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, 1, p0, z0),
++	       svwrite_hor_za32_m (0, 1, p0, z0))
++
++/*
++** write_za32_s32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, w0, p0, z0),
++	       svwrite_hor_za32_m (0, w0, p0, z0))
++
++/*
++** write_za32_s32_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.s\[\1, 1\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0p1_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, w0 + 1, p0, z0),
++	       svwrite_hor_za32_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za32_s32_0_w0p3_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.s\[\1, 3\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0p3_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, w0 + 3, p0, z0),
++	       svwrite_hor_za32_m (0, w0 + 3, p0, z0))
++
++/*
++** write_za32_s32_0_w0p4_z0:
++**	add	(w1[2-5]), w0, #?4
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0p4_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, w0 + 4, p0, z0),
++	       svwrite_hor_za32_m (0, w0 + 4, p0, z0))
++
++/*
++** write_za32_s32_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0m1_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (0, w0 - 1, p0, z0),
++	       svwrite_hor_za32_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za32_s32_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_1_w0_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (1, w0, p0, z0),
++	       svwrite_hor_za32_m (1, w0, p0, z0))
++
++/*
++** write_za32_s32_1_w0p3_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.s\[\1, 3\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_1_w0p3_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (1, w0 + 3, p0, z0),
++	       svwrite_hor_za32_m (1, w0 + 3, p0, z0))
++
++/*
++** write_za32_s32_3_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za3h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_3_w0_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (3, w0, p0, z0),
++	       svwrite_hor_za32_m (3, w0, p0, z0))
++
++/*
++** write_za32_s32_3_w0p3_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za3h\.s\[\1, 3\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_3_w0p3_z0, svint32_t,
++	       svwrite_hor_za32_s32_m (3, w0 + 3, p0, z0),
++	       svwrite_hor_za32_m (3, w0 + 3, p0, z0))
++
++/*
++** write_za32_s32_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.s\[\1, 0\], p0/m, z1\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0_z1, svint32_t,
++	       svwrite_hor_za32_s32_m (0, w0, p0, z1),
++	       svwrite_hor_za32_m (0, w0, p0, z1))
++
++/*
++** write_za32_u32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_u32_0_w0_z0, svuint32_t,
++	       svwrite_hor_za32_u32_m (0, w0, p0, z0),
++	       svwrite_hor_za32_m (0, w0, p0, z0))
++
++/*
++** write_za32_f32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_f32_0_w0_z0, svfloat32_t,
++	       svwrite_hor_za32_f32_m (0, w0, p0, z0),
++	       svwrite_hor_za32_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za64.c
+new file mode 100644
+index 000000000..2b0a157d2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za64.c
+@@ -0,0 +1,133 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za64_s64_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_0_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (0, 0, p0, z0),
++	       svwrite_hor_za64_m (0, 0, p0, z0))
++
++/*
++** write_za64_s64_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_1_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (0, 1, p0, z0),
++	       svwrite_hor_za64_m (0, 1, p0, z0))
++
++/*
++** write_za64_s64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (0, w0, p0, z0),
++	       svwrite_hor_za64_m (0, w0, p0, z0))
++
++/*
++** write_za64_s64_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.d\[\1, 1\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0p1_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (0, w0 + 1, p0, z0),
++	       svwrite_hor_za64_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za64_s64_0_w0p2_z0:
++**	add	(w1[2-5]), w0, #?2
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0p2_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (0, w0 + 2, p0, z0),
++	       svwrite_hor_za64_m (0, w0 + 2, p0, z0))
++
++/*
++** write_za64_s64_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0m1_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (0, w0 - 1, p0, z0),
++	       svwrite_hor_za64_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za64_s64_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_1_w0_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (1, w0, p0, z0),
++	       svwrite_hor_za64_m (1, w0, p0, z0))
++
++/*
++** write_za64_s64_1_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1h\.d\[\1, 1\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_1_w0p1_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (1, w0 + 1, p0, z0),
++	       svwrite_hor_za64_m (1, w0 + 1, p0, z0))
++
++/*
++** write_za64_s64_7_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za7h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_7_w0_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (7, w0, p0, z0),
++	       svwrite_hor_za64_m (7, w0, p0, z0))
++
++/*
++** write_za64_s64_7_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za7h\.d\[\1, 1\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_7_w0p1_z0, svint64_t,
++	       svwrite_hor_za64_s64_m (7, w0 + 1, p0, z0),
++	       svwrite_hor_za64_m (7, w0 + 1, p0, z0))
++
++/*
++** write_za64_s64_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.d\[\1, 0\], p0/m, z1\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0_z1, svint64_t,
++	       svwrite_hor_za64_s64_m (0, w0, p0, z1),
++	       svwrite_hor_za64_m (0, w0, p0, z1))
++
++/*
++** write_za64_u64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_u64_0_w0_z0, svuint64_t,
++	       svwrite_hor_za64_u64_m (0, w0, p0, z0),
++	       svwrite_hor_za64_m (0, w0, p0, z0))
++
++/*
++** write_za64_f64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_f64_0_w0_z0, svfloat64_t,
++	       svwrite_hor_za64_f64_m (0, w0, p0, z0),
++	       svwrite_hor_za64_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za8.c
+new file mode 100644
+index 000000000..683e1a64a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_hor_za8.c
+@@ -0,0 +1,93 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za8_s8_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0h\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_0_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, 0, p0, z0),
++	       svwrite_hor_za8_m (0, 0, p0, z0))
++
++/*
++** write_za8_s8_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0h\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_1_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, 1, p0, z0),
++	       svwrite_hor_za8_m (0, 1, p0, z0))
++
++/*
++** write_za8_s8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, w0, p0, z0),
++	       svwrite_hor_za8_m (0, w0, p0, z0))
++
++/*
++** write_za8_s8_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.b\[\1, 1\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0p1_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, w0 + 1, p0, z0),
++	       svwrite_hor_za8_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za8_s8_0_w0p15_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.b\[\1, 15\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0p15_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, w0 + 15, p0, z0),
++	       svwrite_hor_za8_m (0, w0 + 15, p0, z0))
++
++/*
++** write_za8_s8_0_w0p16_z0:
++**	add	(w1[2-5]), w0, #?16
++**	mova	za0h\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0p16_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, w0 + 16, p0, z0),
++	       svwrite_hor_za8_m (0, w0 + 16, p0, z0))
++
++/*
++** write_za8_s8_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0h\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0m1_z0, svint8_t,
++	       svwrite_hor_za8_s8_m (0, w0 - 1, p0, z0),
++	       svwrite_hor_za8_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za8_s8_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.b\[\1, 0\], p0/m, z1\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0_z1, svint8_t,
++	       svwrite_hor_za8_s8_m (0, w0, p0, z1),
++	       svwrite_hor_za8_m (0, w0, p0, z1))
++
++/*
++** write_za8_u8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0h\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_u8_0_w0_z0, svuint8_t,
++	       svwrite_hor_za8_u8_m (0, w0, p0, z0),
++	       svwrite_hor_za8_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za128.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za128.c
+new file mode 100644
+index 000000000..9622e99dd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za128.c
+@@ -0,0 +1,193 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za128_s8_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_0_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (0, 0, p0, z0),
++	       svwrite_ver_za128_m (0, 0, p0, z0))
++
++/*
++** write_za128_s8_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_1_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (0, 1, p0, z0),
++	       svwrite_ver_za128_m (0, 1, p0, z0))
++
++/*
++** write_za128_s8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s8_0_w0p1_z0:
++**	add	(w1[2-5]), w0, #?1
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0p1_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (0, w0 + 1, p0, z0),
++	       svwrite_ver_za128_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za128_s8_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0m1_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (0, w0 - 1, p0, z0),
++	       svwrite_ver_za128_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za128_s8_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_1_w0_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (1, w0, p0, z0),
++	       svwrite_ver_za128_m (1, w0, p0, z0))
++
++/*
++** write_za128_s8_15_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za15v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_15_w0_z0, svint8_t,
++	       svwrite_ver_za128_s8_m (15, w0, p0, z0),
++	       svwrite_ver_za128_m (15, w0, p0, z0))
++
++/*
++** write_za128_s8_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z1\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s8_0_w0_z1, svint8_t,
++	       svwrite_ver_za128_s8_m (0, w0, p0, z1),
++	       svwrite_ver_za128_m (0, w0, p0, z1))
++
++/*
++** write_za128_u8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u8_0_w0_z0, svuint8_t,
++	       svwrite_ver_za128_u8_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s16_0_w0_z0, svint16_t,
++	       svwrite_ver_za128_s16_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_u16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u16_0_w0_z0, svuint16_t,
++	       svwrite_ver_za128_u16_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_f16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_f16_0_w0_z0, svfloat16_t,
++	       svwrite_ver_za128_f16_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_bf16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_bf16_0_w0_z0, svbfloat16_t,
++	       svwrite_ver_za128_bf16_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s32_0_w0_z0, svint32_t,
++	       svwrite_ver_za128_s32_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_u32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u32_0_w0_z0, svuint32_t,
++	       svwrite_ver_za128_u32_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_f32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_f32_0_w0_z0, svfloat32_t,
++	       svwrite_ver_za128_f32_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_s64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_s64_0_w0_z0, svint64_t,
++	       svwrite_ver_za128_s64_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_u64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_u64_0_w0_z0, svuint64_t,
++	       svwrite_ver_za128_u64_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
++
++/*
++** write_za128_f64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.q\[\1, 0\], p0/m, z0\.q
++**	ret
++*/
++TEST_WRITE_ZA (write_za128_f64_0_w0_z0, svfloat64_t,
++	       svwrite_ver_za128_f64_m (0, w0, p0, z0),
++	       svwrite_ver_za128_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za16.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za16.c
+new file mode 100644
+index 000000000..5430f2307
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za16.c
+@@ -0,0 +1,133 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za16_s16_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_0_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, 0, p0, z0),
++	       svwrite_ver_za16_m (0, 0, p0, z0))
++
++/*
++** write_za16_s16_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_1_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, 1, p0, z0),
++	       svwrite_ver_za16_m (0, 1, p0, z0))
++
++/*
++** write_za16_s16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, w0, p0, z0),
++	       svwrite_ver_za16_m (0, w0, p0, z0))
++
++/*
++** write_za16_s16_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 1\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0p1_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, w0 + 1, p0, z0),
++	       svwrite_ver_za16_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za16_s16_0_w0p7_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 7\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0p7_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, w0 + 7, p0, z0),
++	       svwrite_ver_za16_m (0, w0 + 7, p0, z0))
++
++/*
++** write_za16_s16_0_w0p8_z0:
++**	add	(w1[2-5]), w0, #?8
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0p8_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, w0 + 8, p0, z0),
++	       svwrite_ver_za16_m (0, w0 + 8, p0, z0))
++
++/*
++** write_za16_s16_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0m1_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (0, w0 - 1, p0, z0),
++	       svwrite_ver_za16_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za16_s16_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_1_w0_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (1, w0, p0, z0),
++	       svwrite_ver_za16_m (1, w0, p0, z0))
++
++/*
++** write_za16_s16_1_w0p7_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.h\[\1, 7\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_1_w0p7_z0, svint16_t,
++	       svwrite_ver_za16_s16_m (1, w0 + 7, p0, z0),
++	       svwrite_ver_za16_m (1, w0 + 7, p0, z0))
++
++/*
++** write_za16_s16_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 0\], p0/m, z1\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_s16_0_w0_z1, svint16_t,
++	       svwrite_ver_za16_s16_m (0, w0, p0, z1),
++	       svwrite_ver_za16_m (0, w0, p0, z1))
++
++/*
++** write_za16_u16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_u16_0_w0_z0, svuint16_t,
++	       svwrite_ver_za16_u16_m (0, w0, p0, z0),
++	       svwrite_ver_za16_m (0, w0, p0, z0))
++
++/*
++** write_za16_f16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_f16_0_w0_z0, svfloat16_t,
++	       svwrite_ver_za16_f16_m (0, w0, p0, z0),
++	       svwrite_ver_za16_m (0, w0, p0, z0))
++
++/*
++** write_za16_bf16_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.h\[\1, 0\], p0/m, z0\.h
++**	ret
++*/
++TEST_WRITE_ZA (write_za16_bf16_0_w0_z0, svbfloat16_t,
++	       svwrite_ver_za16_bf16_m (0, w0, p0, z0),
++	       svwrite_ver_za16_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za32.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za32.c
+new file mode 100644
+index 000000000..960ce163d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za32.c
+@@ -0,0 +1,143 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za32_s32_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_0_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, 0, p0, z0),
++	       svwrite_ver_za32_m (0, 0, p0, z0))
++
++/*
++** write_za32_s32_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_1_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, 1, p0, z0),
++	       svwrite_ver_za32_m (0, 1, p0, z0))
++
++/*
++** write_za32_s32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, w0, p0, z0),
++	       svwrite_ver_za32_m (0, w0, p0, z0))
++
++/*
++** write_za32_s32_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.s\[\1, 1\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0p1_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, w0 + 1, p0, z0),
++	       svwrite_ver_za32_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za32_s32_0_w0p3_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.s\[\1, 3\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0p3_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, w0 + 3, p0, z0),
++	       svwrite_ver_za32_m (0, w0 + 3, p0, z0))
++
++/*
++** write_za32_s32_0_w0p4_z0:
++**	add	(w1[2-5]), w0, #?4
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0p4_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, w0 + 4, p0, z0),
++	       svwrite_ver_za32_m (0, w0 + 4, p0, z0))
++
++/*
++** write_za32_s32_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0m1_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (0, w0 - 1, p0, z0),
++	       svwrite_ver_za32_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za32_s32_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_1_w0_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (1, w0, p0, z0),
++	       svwrite_ver_za32_m (1, w0, p0, z0))
++
++/*
++** write_za32_s32_1_w0p3_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.s\[\1, 3\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_1_w0p3_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (1, w0 + 3, p0, z0),
++	       svwrite_ver_za32_m (1, w0 + 3, p0, z0))
++
++/*
++** write_za32_s32_3_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za3v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_3_w0_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (3, w0, p0, z0),
++	       svwrite_ver_za32_m (3, w0, p0, z0))
++
++/*
++** write_za32_s32_3_w0p3_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za3v\.s\[\1, 3\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_3_w0p3_z0, svint32_t,
++	       svwrite_ver_za32_s32_m (3, w0 + 3, p0, z0),
++	       svwrite_ver_za32_m (3, w0 + 3, p0, z0))
++
++/*
++** write_za32_s32_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.s\[\1, 0\], p0/m, z1\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_s32_0_w0_z1, svint32_t,
++	       svwrite_ver_za32_s32_m (0, w0, p0, z1),
++	       svwrite_ver_za32_m (0, w0, p0, z1))
++
++/*
++** write_za32_u32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_u32_0_w0_z0, svuint32_t,
++	       svwrite_ver_za32_u32_m (0, w0, p0, z0),
++	       svwrite_ver_za32_m (0, w0, p0, z0))
++
++/*
++** write_za32_f32_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.s\[\1, 0\], p0/m, z0\.s
++**	ret
++*/
++TEST_WRITE_ZA (write_za32_f32_0_w0_z0, svfloat32_t,
++	       svwrite_ver_za32_f32_m (0, w0, p0, z0),
++	       svwrite_ver_za32_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za64.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za64.c
+new file mode 100644
+index 000000000..962c4002e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za64.c
+@@ -0,0 +1,133 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za64_s64_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_0_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (0, 0, p0, z0),
++	       svwrite_ver_za64_m (0, 0, p0, z0))
++
++/*
++** write_za64_s64_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_1_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (0, 1, p0, z0),
++	       svwrite_ver_za64_m (0, 1, p0, z0))
++
++/*
++** write_za64_s64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (0, w0, p0, z0),
++	       svwrite_ver_za64_m (0, w0, p0, z0))
++
++/*
++** write_za64_s64_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.d\[\1, 1\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0p1_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (0, w0 + 1, p0, z0),
++	       svwrite_ver_za64_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za64_s64_0_w0p2_z0:
++**	add	(w1[2-5]), w0, #?2
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0p2_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (0, w0 + 2, p0, z0),
++	       svwrite_ver_za64_m (0, w0 + 2, p0, z0))
++
++/*
++** write_za64_s64_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0m1_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (0, w0 - 1, p0, z0),
++	       svwrite_ver_za64_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za64_s64_1_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_1_w0_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (1, w0, p0, z0),
++	       svwrite_ver_za64_m (1, w0, p0, z0))
++
++/*
++** write_za64_s64_1_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za1v\.d\[\1, 1\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_1_w0p1_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (1, w0 + 1, p0, z0),
++	       svwrite_ver_za64_m (1, w0 + 1, p0, z0))
++
++/*
++** write_za64_s64_7_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za7v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_7_w0_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (7, w0, p0, z0),
++	       svwrite_ver_za64_m (7, w0, p0, z0))
++
++/*
++** write_za64_s64_7_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za7v\.d\[\1, 1\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_7_w0p1_z0, svint64_t,
++	       svwrite_ver_za64_s64_m (7, w0 + 1, p0, z0),
++	       svwrite_ver_za64_m (7, w0 + 1, p0, z0))
++
++/*
++** write_za64_s64_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.d\[\1, 0\], p0/m, z1\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_s64_0_w0_z1, svint64_t,
++	       svwrite_ver_za64_s64_m (0, w0, p0, z1),
++	       svwrite_ver_za64_m (0, w0, p0, z1))
++
++/*
++** write_za64_u64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_u64_0_w0_z0, svuint64_t,
++	       svwrite_ver_za64_u64_m (0, w0, p0, z0),
++	       svwrite_ver_za64_m (0, w0, p0, z0))
++
++/*
++** write_za64_f64_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.d\[\1, 0\], p0/m, z0\.d
++**	ret
++*/
++TEST_WRITE_ZA (write_za64_f64_0_w0_z0, svfloat64_t,
++	       svwrite_ver_za64_f64_m (0, w0, p0, z0),
++	       svwrite_ver_za64_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za8.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za8.c
+new file mode 100644
+index 000000000..dd6182821
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/write_ver_za8.c
+@@ -0,0 +1,93 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#include "test_sme_acle.h"
++
++/*
++** write_za8_s8_0_0_z0:
++**	mov	(w1[2-5]), (?:wzr|#?0)
++**	mova	za0v\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_0_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, 0, p0, z0),
++	       svwrite_ver_za8_m (0, 0, p0, z0))
++
++/*
++** write_za8_s8_0_1_z0:
++**	mov	(w1[2-5]), #?1
++**	mova	za0v\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_1_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, 1, p0, z0),
++	       svwrite_ver_za8_m (0, 1, p0, z0))
++
++/*
++** write_za8_s8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, w0, p0, z0),
++	       svwrite_ver_za8_m (0, w0, p0, z0))
++
++/*
++** write_za8_s8_0_w0p1_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.b\[\1, 1\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0p1_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, w0 + 1, p0, z0),
++	       svwrite_ver_za8_m (0, w0 + 1, p0, z0))
++
++/*
++** write_za8_s8_0_w0p15_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.b\[\1, 15\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0p15_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, w0 + 15, p0, z0),
++	       svwrite_ver_za8_m (0, w0 + 15, p0, z0))
++
++/*
++** write_za8_s8_0_w0p16_z0:
++**	add	(w1[2-5]), w0, #?16
++**	mova	za0v\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0p16_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, w0 + 16, p0, z0),
++	       svwrite_ver_za8_m (0, w0 + 16, p0, z0))
++
++/*
++** write_za8_s8_0_w0m1_z0:
++**	sub	(w1[2-5]), w0, #?1
++**	mova	za0v\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0m1_z0, svint8_t,
++	       svwrite_ver_za8_s8_m (0, w0 - 1, p0, z0),
++	       svwrite_ver_za8_m (0, w0 - 1, p0, z0))
++
++/*
++** write_za8_s8_0_w0_z1:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.b\[\1, 0\], p0/m, z1\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_s8_0_w0_z1, svint8_t,
++	       svwrite_ver_za8_s8_m (0, w0, p0, z1),
++	       svwrite_ver_za8_m (0, w0, p0, z1))
++
++/*
++** write_za8_u8_0_w0_z0:
++**	mov	(w1[2-5]), w0
++**	mova	za0v\.b\[\1, 0\], p0/m, z0\.b
++**	ret
++*/
++TEST_WRITE_ZA (write_za8_u8_0_w0_z0, svuint8_t,
++	       svwrite_ver_za8_u8_m (0, w0, p0, z0),
++	       svwrite_ver_za8_m (0, w0, p0, z0))
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_mask_za.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_mask_za.c
+new file mode 100644
+index 000000000..9ce7331eb
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_mask_za.c
+@@ -0,0 +1,130 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** zero_mask_za_0:
++**	zero	{ *}
++**	ret
++*/
++PROTO (zero_mask_za_0, void, ()) { svzero_mask_za (0); }
++
++/*
++** zero_mask_za_01:
++**	zero	{ za0\.d }
++**	ret
++*/
++PROTO (zero_mask_za_01, void, ()) { svzero_mask_za (0x01); }
++
++/*
++** zero_mask_za_80:
++**	zero	{ za7\.d }
++**	ret
++*/
++PROTO (zero_mask_za_80, void, ()) { svzero_mask_za (0x80); }
++
++/*
++** zero_mask_za_03:
++**	zero	{ za0\.d, za1\.d }
++**	ret
++*/
++PROTO (zero_mask_za_03, void, ()) { svzero_mask_za (0x03); }
++
++/*
++** zero_mask_za_09:
++**	zero	{ za0\.d, za3\.d }
++**	ret
++*/
++PROTO (zero_mask_za_09, void, ()) { svzero_mask_za (0x09); }
++
++/*
++** zero_mask_za_0d:
++**	zero	{ za0\.d, za2\.d, za3\.d }
++**	ret
++*/
++PROTO (zero_mask_za_0d, void, ()) { svzero_mask_za (0x0d); }
++
++/*
++** zero_mask_za_3c:
++**	zero	{ za2\.d, za3\.d, za4\.d, za5\.d }
++**	ret
++*/
++PROTO (zero_mask_za_3c, void, ()) { svzero_mask_za (0x3c); }
++
++/*
++** zero_mask_za_5a:
++**	zero	{ za1\.d, za3\.d, za4\.d, za6\.d }
++**	ret
++*/
++PROTO (zero_mask_za_5a, void, ()) { svzero_mask_za (0x5a); }
++
++/*
++** zero_mask_za_11:
++**	zero	{ za0\.s }
++**	ret
++*/
++PROTO (zero_mask_za_11, void, ()) { svzero_mask_za (0x11); }
++
++/*
++** zero_mask_za_88:
++**	zero	{ za3\.s }
++**	ret
++*/
++PROTO (zero_mask_za_88, void, ()) { svzero_mask_za (0x88); }
++
++/*
++** zero_mask_za_33:
++**	zero	{ za0\.s, za1\.s }
++**	ret
++*/
++PROTO (zero_mask_za_33, void, ()) { svzero_mask_za (0x33); }
++
++/*
++** zero_mask_za_cc:
++**	zero	{ za2\.s, za3\.s }
++**	ret
++*/
++PROTO (zero_mask_za_cc, void, ()) { svzero_mask_za (0xcc); }
++
++/*
++** zero_mask_za_55:
++**	zero	{ za0\.h }
++**	ret
++*/
++PROTO (zero_mask_za_55, void, ()) { svzero_mask_za (0x55); }
++
++/*
++** zero_mask_za_aa:
++**	zero	{ za1\.h }
++**	ret
++*/
++PROTO (zero_mask_za_aa, void, ()) { svzero_mask_za (0xaa); }
++
++/*
++** zero_mask_za_ab:
++**	zero	{ za1\.h, za0\.d }
++**	ret
++*/
++PROTO (zero_mask_za_ab, void, ()) { svzero_mask_za (0xab); }
++
++/*
++** zero_mask_za_d7:
++**	zero	{ za0\.h, za1\.d, za7\.d }
++**	ret
++*/
++PROTO (zero_mask_za_d7, void, ()) { svzero_mask_za (0xd7); }
++
++/*
++** zero_mask_za_bf:
++**	zero	{ za1\.h, za0\.s, za2\.d }
++**	ret
++*/
++PROTO (zero_mask_za_bf, void, ()) { svzero_mask_za (0xbf); }
++
++/*
++** zero_mask_za_ff:
++**	zero	{ za }
++**	ret
++*/
++PROTO (zero_mask_za_ff, void, ()) { svzero_mask_za (0xff); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_za.c b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_za.c
+new file mode 100644
+index 000000000..4688d0950
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/acle-asm/zero_za.c
+@@ -0,0 +1,11 @@
++/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
++
++#define STREAMING_COMPATIBLE
++#include "test_sme_acle.h"
++
++/*
++** zero_za:
++**	zero	{ za }
++**	ret
++*/
++PROTO (zero_za, void, ()) { svzero_za (); }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
+index d8916809b..84925b9bd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
+@@ -12,11 +12,21 @@
+ #endif
+ 
+ #ifdef STREAMING_COMPATIBLE
+-#define ATTR __arm_streaming_compatible
++#define SM_ATTR __arm_streaming_compatible
++#elif defined(STREAMING)
++#define SM_ATTR __arm_streaming
+ #else
+-#define ATTR
++#define SM_ATTR
+ #endif
+ 
++#ifdef SHARED_ZA
++#define ZA_ATTR __arm_inout("za")
++#else
++#define ZA_ATTR
++#endif
++
++#define ATTR SM_ATTR ZA_ATTR
++
+ #ifdef __cplusplus
+ #define PROTO(NAME, RET, ARGS) \
+   extern "C" RET NAME ARGS ATTR; RET NAME ARGS ATTR
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_int_m_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_int_m_1.c
+new file mode 100644
+index 000000000..fce1ef1dd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_int_m_1.c
+@@ -0,0 +1,50 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
++    svint16_t s16, svuint16_t u16, svfloat16_t f16, uint32_t tile)
++  __arm_streaming __arm_inout("za")
++{
++  svusmopa_za32_m (0, pg, pg, u8); /* { dg-error {too few arguments to function 'svusmopa_za32_m'} } */
++  svusmopa_za32_m (0, pg, pg, u8, s8, 0); /* { dg-error {too many arguments to function 'svusmopa_za32_m'} } */
++  svusmopa_za32_m (tile, pg, pg, u8, s8); /* { dg-error {argument 1 of 'svusmopa_za32_m' must be an integer constant expression} } */
++  svusmopa_za32_m (-1, pg, pg, u8, s8); /* { dg-error {passing -1 to argument 1 of 'svusmopa_za32_m', which expects a value in the range \[0, 3\]} } */
++  svusmopa_za32_m (4, pg, pg, u8, s8); /* { dg-error {passing 4 to argument 1 of 'svusmopa_za32_m', which expects a value in the range \[0, 3\]} } */
++  svusmopa_za32_m (0, u8, pg, u8, s8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svusmopa_za32_m', which expects 'svbool_t'} } */
++  svusmopa_za32_m (0, pg, u8, u8, s8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svusmopa_za32_m', which expects 'svbool_t'} } */
++  svusmopa_za32_m (0, pg, pg, tile, s8); /* { dg-error {passing 'uint32_t'.* to argument 4 of 'svusmopa_za32_m', which expects an SVE type} } */
++  svusmopa_za32_m (0, pg, pg, s8, s8); /* { dg-error {'svusmopa_za32_m' has no form that takes 'svint8_t' arguments} } */
++  svusmopa_za32_m (0, pg, pg, pg, s8); /* { dg-error {'svusmopa_za32_m' has no form that takes 'svbool_t' arguments} } */
++  svusmopa_za32_m (0, pg, pg, f16, s8); /* { dg-error {'svusmopa_za32_m' has no form that takes 'svfloat16_t' arguments} } */
++  svusmopa_za32_m (0, pg, pg, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 5 of 'svusmopa_za32_m', which expects a vector of signed integers} } */
++  svusmopa_za32_m (0, pg, pg, u8, s16); /* { dg-error {arguments 4 and 5 of 'svusmopa_za32_m' must have the same element size, but the values passed here have type 'svuint8_t' and 'svint16_t' respectively} } */
++  svusmopa_za32_m (0, pg, pg, u16, s16); /* { dg-error {'svusmopa_za32_m' has no form that takes 'svuint16_t' arguments} } */
++
++  svusmopa_za64_m (0, pg, pg, u16, s16); /* { dg-error {ACLE function 'svusmopa_za64_u16_m' requires ISA extension 'sme-i16i64'} } */
++}
++
++void
++f2 (svbool_t pg, svint8_t s8, svuint8_t u8) __arm_streaming
++{
++  svusmopa_za32_m (0, pg, pg, u8, s8); /* { dg-error {ACLE function 'svusmopa_za32_u8_m' can only be called from a function that has 'za' state} } */
++}
++
++void
++f3 (svbool_t pg, svint8_t s8, svuint8_t u8) __arm_inout("za")
++{
++  svusmopa_za32_m (0, pg, pg, u8, s8); /* { dg-error {ACLE function 'svusmopa_za32_u8_m' can only be called when SME streaming mode is enabled} } */
++}
++
++#pragma GCC target ("arch=armv9-a+sme-i16i64")
++
++void
++f4 (svbool_t pg, svint16_t s16, svuint16_t u16)
++  __arm_streaming __arm_inout("za")
++{
++  svusmopa_za64_m (-1, pg, pg, u16, s16); /* { dg-error {passing -1 to argument 1 of 'svusmopa_za64_m', which expects a value in the range \[0, 7\]} } */
++  svusmopa_za64_m (8, pg, pg, u16, s16); /* { dg-error {passing 8 to argument 1 of 'svusmopa_za64_m', which expects a value in the range \[0, 7\]} } */
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_1.c
+new file mode 100644
+index 000000000..7e91a41cc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_1.c
+@@ -0,0 +1,49 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svint32_t s32,
++    svfloat16_t f16, svfloat32_t f32, svfloat64_t f64, uint32_t tile)
++  __arm_streaming __arm_inout("za")
++{
++  svmopa_za32_m (0, pg, pg, s8); /* { dg-error {too few arguments to function 'svmopa_za32_m'} } */
++  svmopa_za32_m (0, pg, pg, s8, s8, 0); /* { dg-error {too many arguments to function 'svmopa_za32_m'} } */
++  svmopa_za32_m (tile, pg, pg, s8, s8); /* { dg-error {argument 1 of 'svmopa_za32_m' must be an integer constant expression} } */
++  svmopa_za32_m (-1, pg, pg, s8, s8); /* { dg-error {passing -1 to argument 1 of 'svmopa_za32_m', which expects a value in the range \[0, 3\]} } */
++  svmopa_za32_m (4, pg, pg, s8, s8); /* { dg-error {passing 4 to argument 1 of 'svmopa_za32_m', which expects a value in the range \[0, 3\]} } */
++  svmopa_za32_m (0, u8, pg, s8, s8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svmopa_za32_m', which expects 'svbool_t'} } */
++  svmopa_za32_m (0, pg, u8, s8, s8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svmopa_za32_m', which expects 'svbool_t'} } */
++  svmopa_za32_m (0, pg, pg, tile, s8); /* { dg-error {passing 'uint32_t'.* to argument 4 of 'svmopa_za32_m', which expects an SVE type} } */
++  svmopa_za32_m (0, pg, pg, u8, s8); /* { dg-error {passing 'svint8_t'.* to argument 5 of 'svmopa_za32_m', but argument 4 had type 'svuint8_t'} } */
++  svmopa_za32_m (0, pg, pg, s8, f16); /* { dg-error {passing 'svfloat16_t'.* to argument 5 of 'svmopa_za32_m', but argument 4 had type 'svint8_t'} } */
++  svmopa_za32_m (0, pg, pg, pg, pg); /* { dg-error {'svmopa_za32_m' has no form that takes 'svbool_t' arguments} } */
++  svmopa_za32_m (0, pg, pg, s16, s16); /* { dg-error {'svmopa_za32_m' has no form that takes 'svint16_t' arguments} } */
++  svmopa_za32_m (0, pg, pg, s32, s32); /* { dg-error {'svmopa_za32_m' has no form that takes 'svint32_t' arguments} } */
++  svmopa_za32_m (0, pg, pg, f64, f64); /* { dg-error {'svmopa_za32_m' has no form that takes 'svfloat64_t' arguments} } */
++
++  svmopa_za64_m (0, pg, pg, s16, s16); /* { dg-error {ACLE function 'svmopa_za64_s16_m' requires ISA extension 'sme-i16i64'} } */
++}
++
++void
++f2 (svbool_t pg, svint8_t s8) __arm_streaming
++{
++  svmopa_za32_m (0, pg, pg, s8, s8); /* { dg-error {ACLE function 'svmopa_za32_s8_m' can only be called from a function that has 'za' state} } */
++}
++
++void
++f3 (svbool_t pg, svint8_t s8)  __arm_inout("za")
++{
++  svmopa_za32_m (0, pg, pg, s8, s8); /* { dg-error {ACLE function 'svmopa_za32_s8_m' can only be called when SME streaming mode is enabled} } */
++}
++
++#pragma GCC target ("arch=armv9-a+sme-i16i64")
++
++void
++f4 (svbool_t pg, svint16_t s16) __arm_streaming __arm_inout("za")
++{
++  svmopa_za64_m (-1, pg, pg, s16, s16); /* { dg-error {passing -1 to argument 1 of 'svmopa_za64_m', which expects a value in the range \[0, 7\]} } */
++  svmopa_za64_m (8, pg, pg, s16, s16); /* { dg-error {passing 8 to argument 1 of 'svmopa_za64_m', which expects a value in the range \[0, 7\]} } */
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_2.c
+new file mode 100644
+index 000000000..dfc1b737d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_m_2.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svfloat64_t f64) __arm_streaming __arm_inout("za")
++{
++  svmopa_za64_m (0, pg, pg, f64, f64); /* { dg-error {ACLE function 'svmopa_za64_f64_m' requires ISA extension 'sme-f64f64'} } */
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_uint_m_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_uint_m_1.c
+new file mode 100644
+index 000000000..555f95a61
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_za_uint_m_1.c
+@@ -0,0 +1,50 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
++    svint16_t s16, svuint16_t u16, svfloat16_t f16, uint32_t tile)
++  __arm_streaming __arm_inout("za")
++{
++  svsumopa_za32_m (0, pg, pg, s8); /* { dg-error {too few arguments to function 'svsumopa_za32_m'} } */
++  svsumopa_za32_m (0, pg, pg, s8, u8, 0); /* { dg-error {too many arguments to function 'svsumopa_za32_m'} } */
++  svsumopa_za32_m (tile, pg, pg, s8, u8); /* { dg-error {argument 1 of 'svsumopa_za32_m' must be an integer constant expression} } */
++  svsumopa_za32_m (-1, pg, pg, s8, u8); /* { dg-error {passing -1 to argument 1 of 'svsumopa_za32_m', which expects a value in the range \[0, 3\]} } */
++  svsumopa_za32_m (4, pg, pg, s8, u8); /* { dg-error {passing 4 to argument 1 of 'svsumopa_za32_m', which expects a value in the range \[0, 3\]} } */
++  svsumopa_za32_m (0, u8, pg, s8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svsumopa_za32_m', which expects 'svbool_t'} } */
++  svsumopa_za32_m (0, pg, u8, s8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svsumopa_za32_m', which expects 'svbool_t'} } */
++  svsumopa_za32_m (0, pg, pg, tile, s8); /* { dg-error {passing 'uint32_t'.* to argument 4 of 'svsumopa_za32_m', which expects an SVE type} } */
++  svsumopa_za32_m (0, pg, pg, u8, u8); /* { dg-error {'svsumopa_za32_m' has no form that takes 'svuint8_t' arguments} } */
++  svsumopa_za32_m (0, pg, pg, pg, u8); /* { dg-error {'svsumopa_za32_m' has no form that takes 'svbool_t' arguments} } */
++  svsumopa_za32_m (0, pg, pg, f16, u8); /* { dg-error {'svsumopa_za32_m' has no form that takes 'svfloat16_t' arguments} } */
++  svsumopa_za32_m (0, pg, pg, s8, s8); /* { dg-error {passing 'svint8_t' to argument 5 of 'svsumopa_za32_m', which expects a vector of unsigned integers} } */
++  svsumopa_za32_m (0, pg, pg, s8, u16); /* { dg-error {arguments 4 and 5 of 'svsumopa_za32_m' must have the same element size, but the values passed here have type 'svint8_t' and 'svuint16_t' respectively} } */
++  svsumopa_za32_m (0, pg, pg, s16, u16); /* { dg-error {'svsumopa_za32_m' has no form that takes 'svint16_t' arguments} } */
++
++  svsumopa_za64_m (0, pg, pg, s16, u16); /* { dg-error {ACLE function 'svsumopa_za64_s16_m' requires ISA extension 'sme-i16i64'} } */
++}
++
++void
++f2 (svbool_t pg, svint8_t s8, svuint8_t u8) __arm_streaming
++{
++  svsumopa_za32_m (0, pg, pg, s8, u8); /* { dg-error {ACLE function 'svsumopa_za32_s8_m' can only be called from a function that has 'za' state} } */
++}
++
++void
++f3 (svbool_t pg, svint8_t s8, svuint8_t u8) __arm_inout("za")
++{
++  svsumopa_za32_m (0, pg, pg, s8, u8); /* { dg-error {ACLE function 'svsumopa_za32_s8_m' can only be called when SME streaming mode is enabled} } */
++}
++
++#pragma GCC target ("arch=armv9-a+sme-i16i64")
++
++void
++f4 (svbool_t pg, svint16_t s16, svuint16_t u16)
++  __arm_streaming __arm_inout("za")
++{
++  svsumopa_za64_m (-1, pg, pg, s16, u16); /* { dg-error {passing -1 to argument 1 of 'svsumopa_za64_m', which expects a value in the range \[0, 7\]} } */
++  svsumopa_za64_m (8, pg, pg, s16, u16); /* { dg-error {passing 8 to argument 1 of 'svsumopa_za64_m', which expects a value in the range \[0, 7\]} } */
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c
+index 9591e3d01..5aa0ea671 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c
+@@ -4,6 +4,7 @@
+    to be diagnosed.  Any attempt to call the function before including
+    arm_sve.h will lead to a link failure.  (Same for taking its address,
+    etc.)  */
+-extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t);
++extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t)
++  __arm_streaming_compatible;
+ 
+ #pragma GCC aarch64 "arm_sve.h"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c
+index 85923611d..ede9a8063 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c
+@@ -8,6 +8,7 @@
+    explicit definition "wins".  This isn't supported behavior though.  */
+ __SVUint8_t
+ svadd_u8_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
++  __arm_streaming_compatible
+ {
+   return x;
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/read_za_m_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/read_za_m_1.c
+new file mode 100644
+index 000000000..421979ea0
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/read_za_m_1.c
+@@ -0,0 +1,48 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svint8_t s8, svint64_t s64, svuint8_t u8, svuint16_t u16,
++    svfloat32_t f32, uint32_t tile)
++  __arm_streaming __arm_inout("za")
++{
++  svread_hor_za8_m (s8, pg, 0); /* { dg-error {too few arguments to function 'svread_hor_za8_m'} } */
++  svread_hor_za8_m (s8, pg, 0, 0, 0); /* { dg-error {too many arguments to function 'svread_hor_za8_m'} } */
++  svread_hor_za8_m (tile, pg, 0, 0); /* { dg-error {passing 'uint32_t'.* to argument 1 of 'svread_hor_za8_m', which expects an SVE type} } */
++  svread_hor_za8_m (pg, pg, 0, 0); /* { dg-error {'svread_hor_za8_m' has no form that takes 'svbool_t' arguments} } */
++  svread_hor_za8_m (u16, pg, 0, 0); /* { dg-error {'svread_hor_za8_m' has no form that takes 'svuint16_t' arguments} } */
++  svread_hor_za8_m (s8, s8, 0, 0); /* { dg-error {passing 'svint8_t' to argument 2 of 'svread_hor_za8_m', which expects 'svbool_t'} } */
++  svread_hor_za8_m (s8, pg, tile, 0); /* { dg-error {argument 3 of 'svread_hor_za8_m' must be an integer constant expression} } */
++  svread_hor_za8_m (s8, pg, -1, 0); /* { dg-error {passing -1 to argument 3 of 'svread_hor_za8_m', which expects the value 0} } */
++  svread_hor_za8_m (s8, pg, 1, 0); /* { dg-error {passing 1 to argument 3 of 'svread_hor_za8_m', which expects the value 0} } */
++  svread_hor_za8_m (s8, pg, 0, u8); /* { dg-error {passing 'svuint8_t' to argument 4 of 'svread_hor_za8_m', which expects 'uint32_t'} } */
++
++  svread_hor_za16_m (u16, pg, -1, 0); /* { dg-error {passing -1 to argument 3 of 'svread_hor_za16_m', which expects a value in the range \[0, 1\]} } */
++  svread_hor_za16_m (u16, pg, 2, 0); /* { dg-error {passing 2 to argument 3 of 'svread_hor_za16_m', which expects a value in the range \[0, 1\]} } */
++
++  svread_hor_za32_m (f32, pg, -1, 0); /* { dg-error {passing -1 to argument 3 of 'svread_hor_za32_m', which expects a value in the range \[0, 3\]} } */
++  svread_hor_za32_m (f32, pg, 4, 0); /* { dg-error {passing 4 to argument 3 of 'svread_hor_za32_m', which expects a value in the range \[0, 3\]} } */
++
++  svread_hor_za64_m (s64, pg, -1, 0); /* { dg-error {passing -1 to argument 3 of 'svread_hor_za64_m', which expects a value in the range \[0, 7\]} } */
++  svread_hor_za64_m (s64, pg, 8, 0); /* { dg-error {passing 8 to argument 3 of 'svread_hor_za64_m', which expects a value in the range \[0, 7\]} } */
++
++  svread_hor_za128_m (s8, pg, -1, 0); /* { dg-error {passing -1 to argument 3 of 'svread_hor_za128_m', which expects a value in the range \[0, 15\]} } */
++  svread_hor_za128_m (s8, pg, 16, 0); /* { dg-error {passing 16 to argument 3 of 'svread_hor_za128_m', which expects a value in the range \[0, 15\]} } */
++  svread_hor_za128_m (f32, pg, -1, 0); /* { dg-error {passing -1 to argument 3 of 'svread_hor_za128_m', which expects a value in the range \[0, 15\]} } */
++  svread_hor_za128_m (f32, pg, 16, 0); /* { dg-error {passing 16 to argument 3 of 'svread_hor_za128_m', which expects a value in the range \[0, 15\]} } */
++}
++
++void
++f2 (svbool_t pg, svint8_t s8) __arm_streaming
++{
++  svread_hor_za8_m (s8, pg, 0, 0); /* { dg-error {ACLE function 'svread_hor_za8_s8_m' can only be called from a function that has 'za' state} } */
++}
++
++void
++f3 (svbool_t pg, svint8_t s8) __arm_inout("za")
++{
++  svread_hor_za8_m (s8, pg, 0, 0); /* { dg-error {ACLE function 'svread_hor_za8_s8_m' can only be called when SME streaming mode is enabled} } */
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_za_m_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_za_m_1.c
+new file mode 100644
+index 000000000..948ce2cb3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_za_m_1.c
+@@ -0,0 +1,49 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svuint8_t u8, svint16_t s16, svint32_t s32, svint64_t s64,
++    svfloat32_t f32, uint32_t tile)
++  __arm_streaming __arm_inout("za")
++{
++  svaddha_za32_m (0, pg, pg); /* { dg-error {too few arguments to function 'svaddha_za32_m'} } */
++  svaddha_za32_m (0, pg, pg, s32, s32); /* { dg-error {too many arguments to function 'svaddha_za32_m'} } */
++  svaddha_za32_m (tile, pg, pg, s32); /* { dg-error {argument 1 of 'svaddha_za32_m' must be an integer constant expression} } */
++  svaddha_za32_m (-1, pg, pg, s32); /* { dg-error {passing -1 to argument 1 of 'svaddha_za32_m', which expects a value in the range \[0, 3\]} } */
++  svaddha_za32_m (4, pg, pg, s32); /* { dg-error {passing 4 to argument 1 of 'svaddha_za32_m', which expects a value in the range \[0, 3\]} } */
++  svaddha_za32_m (0, u8, pg, s32); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svaddha_za32_m', which expects 'svbool_t'} } */
++  svaddha_za32_m (0, pg, u8, s32); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svaddha_za32_m', which expects 'svbool_t'} } */
++  svaddha_za32_m (0, pg, pg, tile); /* { dg-error {passing 'uint32_t'.* to argument 4 of 'svaddha_za32_m', which expects an SVE type} } */
++  svaddha_za32_m (0, pg, pg, pg); /* { dg-error {'svaddha_za32_m' has no form that takes 'svbool_t' arguments} } */
++  svaddha_za32_m (0, pg, pg, u8); /* { dg-error {'svaddha_za32_m' has no form that takes 'svuint8_t' arguments} } */
++  svaddha_za32_m (0, pg, pg, s16); /* { dg-error {'svaddha_za32_m' has no form that takes 'svint16_t' arguments} } */
++  svaddha_za32_m (0, pg, pg, f32); /* { dg-error {'svaddha_za32_m' has no form that takes 'svfloat32_t' arguments} } */
++  svaddha_za32_m (0, pg, pg, s64); /* { dg-error {'svaddha_za32_m' has no form that takes 'svint64_t' arguments} } */
++
++  svaddha_za64_m (0, pg, pg, s64); /* { dg-error {ACLE function 'svaddha_za64_s64_m' requires ISA extension 'sme-i16i64'} } */
++}
++
++void
++f2 (svbool_t pg, svint32_t s32) __arm_streaming
++{
++  svaddha_za32_m (0, pg, pg, s32); /* { dg-error {ACLE function 'svaddha_za32_s32_m' can only be called from a function that has 'za' state} } */
++}
++
++void
++f3 (svbool_t pg, svint32_t s32) __arm_inout("za")
++{
++  svaddha_za32_m (0, pg, pg, s32); /* { dg-error {ACLE function 'svaddha_za32_s32_m' can only be called when SME streaming mode is enabled} } */
++}
++
++#pragma GCC target ("arch=armv9-a+sme-i16i64")
++
++void
++f4 (svbool_t pg, svint64_t s64)
++  __arm_streaming __arm_inout("za")
++{
++  svaddha_za64_m (-1, pg, pg, s64); /* { dg-error {passing -1 to argument 1 of 'svaddha_za64_m', which expects a value in the range \[0, 7\]} } */
++  svaddha_za64_m (8, pg, pg, s64); /* { dg-error {passing 8 to argument 1 of 'svaddha_za64_m', which expects a value in the range \[0, 7\]} } */
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/write_za_m_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/write_za_m_1.c
+new file mode 100644
+index 000000000..af79c406b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/write_za_m_1.c
+@@ -0,0 +1,48 @@
++/* { dg-do compile } */
++
++#include 
++
++#pragma GCC target ("arch=armv9-a+sme")
++
++void
++f1 (svbool_t pg, svint8_t s8, svint64_t s64, svuint8_t u8, svuint16_t u16,
++    svfloat32_t f32, uint32_t tile)
++  __arm_streaming __arm_inout("za")
++{
++  svwrite_ver_za8_m (0, 0, pg); /* { dg-error {too few arguments to function 'svwrite_ver_za8_m'} } */
++  svwrite_ver_za8_m (0, 0, pg, s8, 0); /* { dg-error {too many arguments to function 'svwrite_ver_za8_m'} } */
++  svwrite_ver_za8_m (tile, 0, pg, s8); /* { dg-error {argument 1 of 'svwrite_ver_za8_m' must be an integer constant expression} } */
++  svwrite_ver_za8_m (-1, 0, pg, s8); /* { dg-error {passing -1 to argument 1 of 'svwrite_ver_za8_m', which expects the value 0} } */
++  svwrite_ver_za8_m (1, 0, pg, s8); /* { dg-error {passing 1 to argument 1 of 'svwrite_ver_za8_m', which expects the value 0} } */
++  svwrite_ver_za8_m (0, u8, pg, s8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svwrite_ver_za8_m', which expects 'uint32_t'} } */
++  svwrite_ver_za8_m (0, 0, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svwrite_ver_za8_m', which expects 'svbool_t'} } */
++  svwrite_ver_za8_m (0, 0, pg, tile); /* { dg-error {passing 'uint32_t'.* to argument 4 of 'svwrite_ver_za8_m', which expects an SVE type} } */
++  svwrite_ver_za8_m (0, 0, pg, pg); /* { dg-error {'svwrite_ver_za8_m' has no form that takes 'svbool_t' arguments} } */
++  svwrite_ver_za8_m (0, 0, pg, u16); /* { dg-error {'svwrite_ver_za8_m' has no form that takes 'svuint16_t' arguments} } */
++
++  svwrite_ver_za16_m (-1, 0, pg, u16); /* { dg-error {passing -1 to argument 1 of 'svwrite_ver_za16_m', which expects a value in the range \[0, 1\]} } */
++  svwrite_ver_za16_m (2, 0, pg, u16); /* { dg-error {passing 2 to argument 1 of 'svwrite_ver_za16_m', which expects a value in the range \[0, 1\]} } */
++
++  svwrite_ver_za32_m (-1, 0, pg, f32); /* { dg-error {passing -1 to argument 1 of 'svwrite_ver_za32_m', which expects a value in the range \[0, 3\]} } */
++  svwrite_ver_za32_m (4, 0, pg, f32); /* { dg-error {passing 4 to argument 1 of 'svwrite_ver_za32_m', which expects a value in the range \[0, 3\]} } */
++
++  svwrite_ver_za64_m (-1, 0, pg, s64); /* { dg-error {passing -1 to argument 1 of 'svwrite_ver_za64_m', which expects a value in the range \[0, 7\]} } */
++  svwrite_ver_za64_m (8, 0, pg, s64); /* { dg-error {passing 8 to argument 1 of 'svwrite_ver_za64_m', which expects a value in the range \[0, 7\]} } */
++
++  svwrite_ver_za128_m (-1, 0, pg, s8); /* { dg-error {passing -1 to argument 1 of 'svwrite_ver_za128_m', which expects a value in the range \[0, 15\]} } */
++  svwrite_ver_za128_m (16, 0, pg, s8); /* { dg-error {passing 16 to argument 1 of 'svwrite_ver_za128_m', which expects a value in the range \[0, 15\]} } */
++  svwrite_ver_za128_m (-1, 0, pg, f32); /* { dg-error {passing -1 to argument 1 of 'svwrite_ver_za128_m', which expects a value in the range \[0, 15\]} } */
++  svwrite_ver_za128_m (16, 0, pg, f32); /* { dg-error {passing 16 to argument 1 of 'svwrite_ver_za128_m', which expects a value in the range \[0, 15\]} } */
++}
++
++void
++f2 (svbool_t pg, svint8_t s8) __arm_streaming
++{
++  svwrite_ver_za8_m (0, 0, pg, s8); /* { dg-error {ACLE function 'svwrite_ver_za8_s8_m' can only be called from a function that has 'za' state} } */
++}
++
++void
++f3 (svbool_t pg, svint8_t s8) __arm_inout("za")
++{
++  svwrite_ver_za8_m (0, 0, pg, s8); /* { dg-error {ACLE function 'svwrite_ver_za8_s8_m' can only be called when SME streaming mode is enabled} } */
++}
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index e2a9ef5fa..292737dae 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -10622,7 +10622,8 @@ proc check_effective_target_aarch64_tiny { } {
+ # various architecture extensions via the .arch_extension pseudo-op.
+ 
+ foreach { aarch64_ext } { "fp" "simd" "crypto" "crc" "lse" "dotprod" "sve"
+-			  "i8mm" "f32mm" "f64mm" "bf16" "sb" "sve2" } {
++			  "i8mm" "f32mm" "f64mm" "bf16" "sb" "sve2"
++			  "sme" "sme-i16i64" } {
+     eval [string map [list FUNC $aarch64_ext] {
+ 	proc check_effective_target_aarch64_asm_FUNC_ok { } {
+ 	  if { [istarget aarch64*-*-*] } {
+-- 
+2.33.0
+
diff --git a/0212-Backport-SME-aarch64-Add-support-for-__arm_locally_s.patch b/0212-Backport-SME-aarch64-Add-support-for-__arm_locally_s.patch
new file mode 100644
index 0000000..72576e3
--- /dev/null
+++ b/0212-Backport-SME-aarch64-Add-support-for-__arm_locally_s.patch
@@ -0,0 +1,1748 @@
+From 0ad41f11bea5c303ff39c54cae8e46afdfae6070 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:29 +0000
+Subject: [PATCH 113/157] [Backport][SME] aarch64: Add support for
+ __arm_locally_streaming
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=3f6e5991fab507aa79121dc44d1afcd622c78744
+
+This patch adds support for the __arm_locally_streaming attribute,
+which allows a function to use SME internally without changing
+the function's ABI.  The attribute is valid but redundant for
+__arm_streaming functions.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_arm_attribute_table): Add
+	arm::locally_streaming.
+	(aarch64_fndecl_is_locally_streaming): New function.
+	(aarch64_fndecl_sm_state): Handle locally-streaming functions.
+	(aarch64_cfun_enables_pstate_sm): New function.
+	(aarch64_add_offset): Add an argument that specifies whether
+	the streaming vector length should be used instead of the
+	prevailing one.
+	(aarch64_split_add_offset, aarch64_add_sp, aarch64_sub_sp): Likewise.
+	(aarch64_allocate_and_probe_stack_space): Likewise.
+	(aarch64_expand_mov_immediate): Update calls accordingly.
+	(aarch64_need_old_pstate_sm): Return true for locally-streaming
+	streaming-compatible functions.
+	(aarch64_layout_frame): Force all call-preserved Z and P registers
+	to be saved and restored if the function switches PSTATE.SM in the
+	prologue.
+	(aarch64_get_separate_components): Disable shrink-wrapping of
+	such Z and P saves and restores.
+	(aarch64_use_late_prologue_epilogue): New function.
+	(aarch64_expand_prologue): Measure SVE lengths in the streaming
+	vector length for locally-streaming functions, then emit code
+	to enable streaming mode.
+	(aarch64_expand_epilogue): Likewise in reverse.
+	(TARGET_USE_LATE_PROLOGUE_EPILOGUE): Define.
+	* config/aarch64/aarch64-c.cc (aarch64_define_unconditional_macros):
+	Define __arm_locally_streaming.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/locally_streaming_1.c: New test.
+	* gcc.target/aarch64/sme/locally_streaming_2.c: Likewise.
+	* gcc.target/aarch64/sme/locally_streaming_3.c: Likewise.
+	* gcc.target/aarch64/sme/locally_streaming_4.c: Likewise.
+	* gcc.target/aarch64/sme/keyword_macros_1.c: Add
+	__arm_locally_streaming.
+	* g++.target/aarch64/sme/keyword_macros_1.C: Likewise.
+---
+ gcc/config/aarch64/aarch64-c.cc               |   1 +
+ gcc/config/aarch64/aarch64.cc                 | 233 +++++++--
+ .../g++.target/aarch64/sme/keyword_macros_1.C |   1 +
+ .../gcc.target/aarch64/sme/keyword_macros_1.c |   1 +
+ .../aarch64/sme/locally_streaming_1.c         | 466 ++++++++++++++++++
+ .../aarch64/sme/locally_streaming_2.c         | 177 +++++++
+ .../aarch64/sme/locally_streaming_3.c         | 273 ++++++++++
+ .../aarch64/sme/locally_streaming_4.c         | 145 ++++++
+ 8 files changed, 1259 insertions(+), 38 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_4.c
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index cb8a6c2fc..745719d8b 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -86,6 +86,7 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
+ 
+   DEFINE_ARM_KEYWORD_MACRO ("streaming");
+   DEFINE_ARM_KEYWORD_MACRO ("streaming_compatible");
++  DEFINE_ARM_KEYWORD_MACRO ("locally_streaming");
+ 
+ #undef DEFINE_ARM_KEYWORD_MACRO
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 113784e31..4cb43c2e2 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -3283,6 +3283,7 @@ static const attribute_spec aarch64_arm_attributes[] =
+ 			  NULL, attr_streaming_exclusions },
+   { "streaming_compatible", 0, 0, false, true,  true,  true,
+ 			  NULL, attr_streaming_exclusions },
++  { "locally_streaming",  0, 0, true, false, false, false, NULL, NULL },
+   { "new",		  1, -1, true, false, false, false,
+ 			  handle_arm_new, NULL },
+   { "preserves",	  1, -1, false, true,  true,  true,
+@@ -4657,6 +4658,16 @@ aarch64_fntype_isa_mode (const_tree fntype)
+ 	  | aarch64_fntype_pstate_za (fntype));
+ }
+ 
++/* Return true if FNDECL uses streaming mode internally, as an
++   implementation choice.  */
++
++static bool
++aarch64_fndecl_is_locally_streaming (const_tree fndecl)
++{
++  return lookup_attribute ("arm", "locally_streaming",
++			   DECL_ATTRIBUTES (fndecl));
++}
++
+ /* Return the state of PSTATE.SM when compiling the body of
+    function FNDECL.  This might be different from the state of
+    PSTATE.SM on entry.  */
+@@ -4664,6 +4675,9 @@ aarch64_fntype_isa_mode (const_tree fntype)
+ static aarch64_feature_flags
+ aarch64_fndecl_pstate_sm (const_tree fndecl)
+ {
++  if (aarch64_fndecl_is_locally_streaming (fndecl))
++    return AARCH64_FL_SM_ON;
++
+   return aarch64_fntype_pstate_sm (TREE_TYPE (fndecl));
+ }
+ 
+@@ -4739,6 +4753,16 @@ aarch64_cfun_has_new_state (const char *state_name)
+   return aarch64_fndecl_has_new_state (cfun->decl, state_name);
+ }
+ 
++/* Return true if PSTATE.SM is 1 in the body of the current function,
++   but is not guaranteed to be 1 on entry.  */
++
++static bool
++aarch64_cfun_enables_pstate_sm ()
++{
++  return (aarch64_fndecl_is_locally_streaming (cfun->decl)
++	  && aarch64_cfun_incoming_pstate_sm () != AARCH64_FL_SM_ON);
++}
++
+ /* Return true if the current function has state STATE_NAME, either by
+    creating new state itself or by sharing state with callers.  */
+ 
+@@ -6931,6 +6955,10 @@ aarch64_add_offset_temporaries (rtx x)
+    TEMP2, if nonnull, is a second temporary register that doesn't
+    overlap either DEST or REG.
+ 
++   FORCE_ISA_MODE is AARCH64_FL_SM_ON if any variable component of OFFSET
++   is measured relative to the SME vector length instead of the current
++   prevailing vector length.  It is 0 otherwise.
++
+    Since this function may be used to adjust the stack pointer, we must
+    ensure that it cannot cause transient stack deallocation (for example
+    by first incrementing SP and then decrementing when adjusting by a
+@@ -6939,6 +6967,7 @@ aarch64_add_offset_temporaries (rtx x)
+ static void
+ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+ 		    poly_int64 offset, rtx temp1, rtx temp2,
++		    aarch64_feature_flags force_isa_mode,
+ 		    bool frame_related_p, bool emit_move_imm = true)
+ {
+   gcc_assert (emit_move_imm || temp1 != NULL_RTX);
+@@ -6951,9 +6980,18 @@ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+   /* Try using ADDVL or ADDPL to add the whole value.  */
+   if (src != const0_rtx && aarch64_sve_addvl_addpl_immediate_p (offset))
+     {
+-      rtx offset_rtx = gen_int_mode (offset, mode);
++      gcc_assert (offset.coeffs[0] == offset.coeffs[1]);
++      rtx offset_rtx;
++      if (force_isa_mode == 0)
++	offset_rtx = gen_int_mode (offset, mode);
++      else
++	offset_rtx = aarch64_sme_vq_immediate (mode, offset.coeffs[0], 0);
+       rtx_insn *insn = emit_insn (gen_add3_insn (dest, src, offset_rtx));
+       RTX_FRAME_RELATED_P (insn) = frame_related_p;
++      if (frame_related_p && (force_isa_mode & AARCH64_FL_SM_ON))
++	add_reg_note (insn, REG_CFA_ADJUST_CFA,
++		      gen_rtx_SET (dest, plus_constant (Pmode, src,
++							offset)));
+       return;
+     }
+ 
+@@ -6969,11 +7007,19 @@ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+   if (src != const0_rtx
+       && aarch64_sve_addvl_addpl_immediate_p (poly_offset))
+     {
+-      rtx offset_rtx = gen_int_mode (poly_offset, mode);
++      rtx offset_rtx;
++      if (force_isa_mode == 0)
++	offset_rtx = gen_int_mode (poly_offset, mode);
++      else
++	offset_rtx = aarch64_sme_vq_immediate (mode, factor, 0);
+       if (frame_related_p)
+ 	{
+ 	  rtx_insn *insn = emit_insn (gen_add3_insn (dest, src, offset_rtx));
+ 	  RTX_FRAME_RELATED_P (insn) = true;
++	  if (force_isa_mode & AARCH64_FL_SM_ON)
++	    add_reg_note (insn, REG_CFA_ADJUST_CFA,
++			  gen_rtx_SET (dest, plus_constant (Pmode, src,
++							    poly_offset)));
+ 	  src = dest;
+ 	}
+       else
+@@ -7004,9 +7050,19 @@ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+       rtx val;
+       if (IN_RANGE (rel_factor, -32, 31))
+ 	{
++	  if (force_isa_mode & AARCH64_FL_SM_ON)
++	    {
++	      /* Try to use an unshifted RDSVL, otherwise fall back on
++		 a shifted RDSVL #1.  */
++	      if (aarch64_sve_rdvl_addvl_factor_p (factor))
++		shift = 0;
++	      else
++		factor = rel_factor * 16;
++	      val = aarch64_sme_vq_immediate (mode, factor, 0);
++	    }
+ 	  /* Try to use an unshifted CNT[BHWD] or RDVL.  */
+-	  if (aarch64_sve_cnt_factor_p (factor)
+-	      || aarch64_sve_rdvl_addvl_factor_p (factor))
++	  else if (aarch64_sve_cnt_factor_p (factor)
++		   || aarch64_sve_rdvl_addvl_factor_p (factor))
+ 	    {
+ 	      val = gen_int_mode (poly_int64 (factor, factor), mode);
+ 	      shift = 0;
+@@ -7036,11 +7092,18 @@ aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+ 	     a shift and add sequence for the multiplication.
+ 	     If CNTB << SHIFT is out of range, stick with the current
+ 	     shift factor.  */
+-	  if (IN_RANGE (low_bit, 2, 16 * 16))
++	  if (force_isa_mode == 0
++	      && IN_RANGE (low_bit, 2, 16 * 16))
+ 	    {
+ 	      val = gen_int_mode (poly_int64 (low_bit, low_bit), mode);
+ 	      shift = 0;
+ 	    }
++	  else if ((force_isa_mode & AARCH64_FL_SM_ON)
++		   && aarch64_sve_rdvl_addvl_factor_p (low_bit))
++	    {
++	      val = aarch64_sme_vq_immediate (mode, low_bit, 0);
++	      shift = 0;
++	    }
+ 	  else
+ 	    val = gen_int_mode (BYTES_PER_SVE_VECTOR, mode);
+ 
+@@ -7128,30 +7191,34 @@ aarch64_split_add_offset (scalar_int_mode mode, rtx dest, rtx src,
+ 			  rtx offset_rtx, rtx temp1, rtx temp2)
+ {
+   aarch64_add_offset (mode, dest, src, rtx_to_poly_int64 (offset_rtx),
+-		      temp1, temp2, false);
++		      temp1, temp2, 0, false);
+ }
+ 
+ /* Add DELTA to the stack pointer, marking the instructions frame-related.
+-   TEMP1 is available as a temporary if nonnull.  EMIT_MOVE_IMM is false
+-   if TEMP1 already contains abs (DELTA).  */
++   TEMP1 is available as a temporary if nonnull.  FORCE_ISA_MODE is as
++   for aarch64_add_offset.  EMIT_MOVE_IMM is false if TEMP1 already
++   contains abs (DELTA).  */
+ 
+ static inline void
+-aarch64_add_sp (rtx temp1, rtx temp2, poly_int64 delta, bool emit_move_imm)
++aarch64_add_sp (rtx temp1, rtx temp2, poly_int64 delta,
++		aarch64_feature_flags force_isa_mode, bool emit_move_imm)
+ {
+   aarch64_add_offset (Pmode, stack_pointer_rtx, stack_pointer_rtx, delta,
+-		      temp1, temp2, true, emit_move_imm);
++		      temp1, temp2, force_isa_mode, true, emit_move_imm);
+ }
+ 
+ /* Subtract DELTA from the stack pointer, marking the instructions
+-   frame-related if FRAME_RELATED_P.  TEMP1 is available as a temporary
+-   if nonnull.  */
++   frame-related if FRAME_RELATED_P.  FORCE_ISA_MODE is as for
++   aarch64_add_offset.  TEMP1 is available as a temporary if nonnull.  */
+ 
+ static inline void
+-aarch64_sub_sp (rtx temp1, rtx temp2, poly_int64 delta, bool frame_related_p,
+-		bool emit_move_imm = true)
++aarch64_sub_sp (rtx temp1, rtx temp2, poly_int64 delta,
++		aarch64_feature_flags force_isa_mode,
++		bool frame_related_p, bool emit_move_imm = true)
+ {
+   aarch64_add_offset (Pmode, stack_pointer_rtx, stack_pointer_rtx, -delta,
+-		      temp1, temp2, frame_related_p, emit_move_imm);
++		      temp1, temp2, force_isa_mode, frame_related_p,
++		      emit_move_imm);
+ }
+ 
+ /* A streaming-compatible function needs to switch temporarily to the known
+@@ -8176,11 +8243,11 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 		{
+ 		  base = aarch64_force_temporary (int_mode, dest, base);
+ 		  aarch64_add_offset (int_mode, dest, base, offset,
+-				      NULL_RTX, NULL_RTX, false);
++				      NULL_RTX, NULL_RTX, 0, false);
+ 		}
+ 	      else
+ 		aarch64_add_offset (int_mode, dest, base, offset,
+-				    dest, NULL_RTX, false);
++				    dest, NULL_RTX, 0, false);
+ 	    }
+ 	  return;
+ 	}
+@@ -8207,7 +8274,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 	      gcc_assert (can_create_pseudo_p ());
+ 	      base = aarch64_force_temporary (int_mode, dest, base);
+ 	      aarch64_add_offset (int_mode, dest, base, const_offset,
+-				  NULL_RTX, NULL_RTX, false);
++				  NULL_RTX, NULL_RTX, 0, false);
+ 	      return;
+ 	    }
+ 
+@@ -8247,7 +8314,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
+ 	      gcc_assert(can_create_pseudo_p ());
+ 	      base = aarch64_force_temporary (int_mode, dest, base);
+ 	      aarch64_add_offset (int_mode, dest, base, const_offset,
+-				  NULL_RTX, NULL_RTX, false);
++				  NULL_RTX, NULL_RTX, 0, false);
+ 	      return;
+ 	    }
+ 	  /* FALLTHRU */
+@@ -9755,6 +9822,9 @@ aarch64_need_old_pstate_sm ()
+   if (aarch64_cfun_incoming_pstate_sm () != 0)
+     return false;
+ 
++  if (aarch64_cfun_enables_pstate_sm ())
++    return true;
++
+   if (cfun->machine->call_switches_pstate_sm)
+     for (auto insn = get_insns (); insn; insn = NEXT_INSN (insn))
+       if (auto *call = dyn_cast (insn))
+@@ -9781,6 +9851,7 @@ aarch64_layout_frame (void)
+   bool frame_related_fp_reg_p = false;
+   aarch64_frame &frame = cfun->machine->frame;
+   poly_int64 top_of_locals = -1;
++  bool enables_pstate_sm = aarch64_cfun_enables_pstate_sm ();
+ 
+   vec_safe_truncate (frame.saved_gprs, 0);
+   vec_safe_truncate (frame.saved_fprs, 0);
+@@ -9818,7 +9889,7 @@ aarch64_layout_frame (void)
+       frame.reg_offset[regno] = SLOT_REQUIRED;
+ 
+   for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++)
+-    if (df_regs_ever_live_p (regno)
++    if ((enables_pstate_sm || df_regs_ever_live_p (regno))
+ 	&& !fixed_regs[regno]
+ 	&& !crtl->abi->clobbers_full_reg_p (regno))
+       {
+@@ -9847,7 +9918,7 @@ aarch64_layout_frame (void)
+     }
+ 
+   for (regno = P0_REGNUM; regno <= P15_REGNUM; regno++)
+-    if (df_regs_ever_live_p (regno)
++    if ((enables_pstate_sm || df_regs_ever_live_p (regno))
+ 	&& !fixed_regs[regno]
+ 	&& !crtl->abi->clobbers_full_reg_p (regno))
+       frame.reg_offset[regno] = SLOT_REQUIRED;
+@@ -9964,7 +10035,8 @@ aarch64_layout_frame (void)
+   /* If the current function changes the SVE vector length, ensure that the
+      old value of the DWARF VG register is saved and available in the CFI,
+      so that outer frames with VL-sized offsets can be processed correctly.  */
+-  if (cfun->machine->call_switches_pstate_sm)
++  if (cfun->machine->call_switches_pstate_sm
++      || aarch64_cfun_enables_pstate_sm ())
+     {
+       frame.reg_offset[VG_REGNUM] = offset;
+       offset += UNITS_PER_WORD;
+@@ -10749,9 +10821,16 @@ aarch64_get_separate_components (void)
+   bitmap_clear (components);
+ 
+   /* The registers we need saved to the frame.  */
++  bool enables_pstate_sm = aarch64_cfun_enables_pstate_sm ();
+   for (unsigned regno = 0; regno <= LAST_SAVED_REGNUM; regno++)
+     if (aarch64_register_saved_on_entry (regno))
+       {
++	/* Disallow shrink wrapping for registers that will be clobbered
++	   by an SMSTART SM in the prologue.  */
++	if (enables_pstate_sm
++	    && (FP_REGNUM_P (regno) || PR_REGNUM_P (regno)))
++	  continue;
++
+ 	/* Punt on saves and restores that use ST1D and LD1D.  We could
+ 	   try to be smarter, but it would involve making sure that the
+ 	   spare predicate register itself is safe to use at the save
+@@ -11070,11 +11149,16 @@ aarch64_emit_stack_tie (rtx reg)
+    events, e.g. if we were to allow the stack to be dropped by more than a page
+    and then have multiple probes up and we take a signal somewhere in between
+    then the signal handler doesn't know the state of the stack and can make no
+-   assumptions about which pages have been probed.  */
++   assumptions about which pages have been probed.
++
++   FORCE_ISA_MODE is AARCH64_FL_SM_ON if any variable component of POLY_SIZE
++   is measured relative to the SME vector length instead of the current
++   prevailing vector length.  It is 0 otherwise.  */
+ 
+ static void
+ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+ 					poly_int64 poly_size,
++					aarch64_feature_flags force_isa_mode,
+ 					bool frame_related_p,
+ 					bool final_adjustment_p)
+ {
+@@ -11116,7 +11200,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+   if (known_lt (poly_size, min_probe_threshold)
+       || !flag_stack_clash_protection)
+     {
+-      aarch64_sub_sp (temp1, temp2, poly_size, frame_related_p);
++      aarch64_sub_sp (temp1, temp2, poly_size, force_isa_mode,
++		      frame_related_p);
+       return;
+     }
+ 
+@@ -11133,7 +11218,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+ 
+       /* First calculate the amount of bytes we're actually spilling.  */
+       aarch64_add_offset (Pmode, temp1, CONST0_RTX (Pmode),
+-			  poly_size, temp1, temp2, false, true);
++			  poly_size, temp1, temp2, force_isa_mode,
++			  false, true);
+ 
+       rtx_insn *insn = get_last_insn ();
+ 
+@@ -11191,7 +11277,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+     {
+       for (HOST_WIDE_INT i = 0; i < rounded_size; i += guard_size)
+ 	{
+-	  aarch64_sub_sp (NULL, temp2, guard_size, true);
++	  aarch64_sub_sp (NULL, temp2, guard_size, force_isa_mode, true);
+ 	  emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+ 					   guard_used_by_caller));
+ 	  emit_insn (gen_blockage ());
+@@ -11202,7 +11288,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+     {
+       /* Compute the ending address.  */
+       aarch64_add_offset (Pmode, temp1, stack_pointer_rtx, -rounded_size,
+-			  temp1, NULL, false, true);
++			  temp1, NULL, force_isa_mode, false, true);
+       rtx_insn *insn = get_last_insn ();
+ 
+       /* For the initial allocation, we don't have a frame pointer
+@@ -11268,7 +11354,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
+       if (final_adjustment_p && rounded_size != 0)
+ 	min_probe_threshold = 0;
+ 
+-      aarch64_sub_sp (temp1, temp2, residual, frame_related_p);
++      aarch64_sub_sp (temp1, temp2, residual, force_isa_mode, frame_related_p);
+       if (residual >= min_probe_threshold)
+ 	{
+ 	  if (dump_file)
+@@ -11333,6 +11419,14 @@ aarch64_epilogue_uses (int regno)
+   return 0;
+ }
+ 
++/* Implement TARGET_USE_LATE_PROLOGUE_EPILOGUE.  */
++
++static bool
++aarch64_use_late_prologue_epilogue ()
++{
++  return aarch64_cfun_enables_pstate_sm ();
++}
++
+ /* The current function's frame has a save slot for the incoming state
+    of SVCR.  Return a legitimate memory for the slot, based on the hard
+    frame pointer.  */
+@@ -11469,6 +11563,9 @@ aarch64_expand_prologue (void)
+   unsigned reg2 = frame.wb_push_candidate2;
+   bool emit_frame_chain = frame.emit_frame_chain;
+   rtx_insn *insn;
++  aarch64_feature_flags force_isa_mode = 0;
++  if (aarch64_cfun_enables_pstate_sm ())
++    force_isa_mode = AARCH64_FL_SM_ON;
+ 
+   if (flag_stack_clash_protection && known_eq (callee_adjust, 0))
+     {
+@@ -11530,7 +11627,7 @@ aarch64_expand_prologue (void)
+      less the amount of the guard reserved for use by the caller's
+      outgoing args.  */
+   aarch64_allocate_and_probe_stack_space (tmp0_rtx, tmp1_rtx, initial_adjust,
+-					  true, false);
++					  force_isa_mode, true, false);
+ 
+   if (callee_adjust != 0)
+     aarch64_push_regs (reg1, reg2, callee_adjust);
+@@ -11553,7 +11650,8 @@ aarch64_expand_prologue (void)
+ 	gcc_assert (known_eq (chain_offset, 0));
+       aarch64_add_offset (Pmode, hard_frame_pointer_rtx,
+ 			  stack_pointer_rtx, chain_offset,
+-			  tmp1_rtx, tmp0_rtx, frame_pointer_needed);
++			  tmp1_rtx, tmp0_rtx, force_isa_mode,
++			  frame_pointer_needed);
+       if (frame_pointer_needed && !frame_size.is_constant ())
+ 	{
+ 	  /* Variable-sized frames need to describe the save slot
+@@ -11600,6 +11698,7 @@ aarch64_expand_prologue (void)
+ 		  || known_eq (initial_adjust, 0));
+       aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx,
+ 					      sve_callee_adjust,
++					      force_isa_mode,
+ 					      !frame_pointer_needed, false);
+       bytes_below_sp -= sve_callee_adjust;
+     }
+@@ -11612,12 +11711,15 @@ aarch64_expand_prologue (void)
+      that is assumed by the called.  */
+   gcc_assert (known_eq (bytes_below_sp, final_adjust));
+   aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx, final_adjust,
++					  force_isa_mode,
+ 					  !frame_pointer_needed, true);
+   if (emit_frame_chain && maybe_ne (final_adjust, 0))
+     aarch64_emit_stack_tie (hard_frame_pointer_rtx);
+ 
+-  /* Save the incoming value of PSTATE.SM, if required.  */
+-  if (known_ge (frame.old_svcr_offset, 0))
++  /* Save the incoming value of PSTATE.SM, if required.  Code further
++     down does this for locally-streaming functions.  */
++  if (known_ge (frame.old_svcr_offset, 0)
++      && !aarch64_cfun_enables_pstate_sm ())
+     {
+       rtx mem = aarch64_old_svcr_mem ();
+       MEM_VOLATILE_P (mem) = 1;
+@@ -11649,6 +11751,34 @@ aarch64_expand_prologue (void)
+ 	    emit_move_insn (gen_rtx_REG (DImode, R1_REGNUM), old_r1);
+ 	}
+     }
++
++  /* Enable PSTATE.SM, if required.  */
++  if (aarch64_cfun_enables_pstate_sm ())
++    {
++      rtx_insn *guard_label = nullptr;
++      if (known_ge (cfun->machine->frame.old_svcr_offset, 0))
++	{
++	  /* The current function is streaming-compatible.  Save the
++	     original state of PSTATE.SM.  */
++	  rtx svcr = gen_rtx_REG (DImode, IP0_REGNUM);
++	  emit_insn (gen_aarch64_read_svcr (svcr));
++	  emit_move_insn (aarch64_old_svcr_mem (), svcr);
++	  guard_label = aarch64_guard_switch_pstate_sm (svcr,
++							aarch64_isa_flags);
++	}
++      aarch64_sme_mode_switch_regs args_switch;
++      auto &args = crtl->args.info;
++      for (unsigned int i = 0; i < args.num_sme_mode_switch_args; ++i)
++	{
++	  rtx x = args.sme_mode_switch_args[i];
++	  args_switch.add_reg (GET_MODE (x), REGNO (x));
++	}
++      args_switch.emit_prologue ();
++      emit_insn (gen_aarch64_smstart_sm ());
++      args_switch.emit_epilogue ();
++      if (guard_label)
++	emit_label (guard_label);
++    }
+ }
+ 
+ /* Return TRUE if we can use a simple_return insn.
+@@ -11695,6 +11825,9 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+   HOST_WIDE_INT guard_size
+     = 1 << param_stack_clash_protection_guard_size;
+   HOST_WIDE_INT guard_used_by_caller = STACK_CLASH_CALLER_GUARD;
++  aarch64_feature_flags force_isa_mode = 0;
++  if (aarch64_cfun_enables_pstate_sm ())
++    force_isa_mode = AARCH64_FL_SM_ON;
+ 
+   /* We can re-use the registers when:
+ 
+@@ -11719,6 +11852,24 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+     = maybe_ne (get_frame_size ()
+ 		+ frame.saved_varargs_size, 0);
+ 
++  /* Reset PSTATE.SM, if required.  */
++  if (aarch64_cfun_enables_pstate_sm ())
++    {
++      rtx_insn *guard_label = nullptr;
++      if (known_ge (cfun->machine->frame.old_svcr_offset, 0))
++	guard_label = aarch64_guard_switch_pstate_sm (IP0_REGNUM,
++						      aarch64_isa_flags);
++      aarch64_sme_mode_switch_regs return_switch;
++      if (crtl->return_rtx && REG_P (crtl->return_rtx))
++	return_switch.add_reg (GET_MODE (crtl->return_rtx),
++			       REGNO (crtl->return_rtx));
++      return_switch.emit_prologue ();
++      emit_insn (gen_aarch64_smstop_sm ());
++      return_switch.emit_epilogue ();
++      if (guard_label)
++	emit_label (guard_label);
++    }
++
+   /* Emit a barrier to prevent loads from a deallocated stack.  */
+   if (maybe_gt (final_adjust, crtl->outgoing_args_size)
+       || cfun->calls_alloca
+@@ -11739,19 +11890,21 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+     aarch64_add_offset (Pmode, stack_pointer_rtx,
+ 			hard_frame_pointer_rtx,
+ 			-bytes_below_hard_fp + final_adjust,
+-			tmp1_rtx, tmp0_rtx, callee_adjust == 0);
++			tmp1_rtx, tmp0_rtx, force_isa_mode,
++			callee_adjust == 0);
+   else
+      /* The case where we need to re-use the register here is very rare, so
+ 	avoid the complicated condition and just always emit a move if the
+ 	immediate doesn't fit.  */
+-     aarch64_add_sp (tmp1_rtx, tmp0_rtx, final_adjust, true);
++     aarch64_add_sp (tmp1_rtx, tmp0_rtx, final_adjust, force_isa_mode, true);
+ 
+   /* Restore the vector registers before the predicate registers,
+      so that we can use P4 as a temporary for big-endian SVE frames.  */
+   aarch64_restore_callee_saves (final_adjust, frame.saved_fprs, &cfi_ops);
+   aarch64_restore_callee_saves (final_adjust, frame.saved_prs, &cfi_ops);
+   if (maybe_ne (sve_callee_adjust, 0))
+-    aarch64_add_sp (NULL_RTX, NULL_RTX, sve_callee_adjust, true);
++    aarch64_add_sp (NULL_RTX, NULL_RTX, sve_callee_adjust,
++		    force_isa_mode, true);
+ 
+   /* When shadow call stack is enabled, the scs_pop in the epilogue will
+      restore x30, we don't need to restore x30 again in the traditional
+@@ -11781,7 +11934,7 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ 
+   /* Liveness of EP0_REGNUM can not be trusted across function calls either, so
+      add restriction on emit_move optimization to leaf functions.  */
+-  aarch64_add_sp (tmp0_rtx, tmp1_rtx, initial_adjust,
++  aarch64_add_sp (tmp0_rtx, tmp1_rtx, initial_adjust, force_isa_mode,
+ 		  (!can_inherit_p || !crtl->is_leaf
+ 		   || df_regs_ever_live_p (EP0_REGNUM)));
+ 
+@@ -11914,7 +12067,8 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+   temp1 = gen_rtx_REG (Pmode, EP1_REGNUM);
+ 
+   if (vcall_offset == 0)
+-    aarch64_add_offset (Pmode, this_rtx, this_rtx, delta, temp1, temp0, false);
++    aarch64_add_offset (Pmode, this_rtx, this_rtx, delta, temp1, temp0,
++			0, false);
+   else
+     {
+       gcc_assert ((vcall_offset & (POINTER_BYTES - 1)) == 0);
+@@ -11927,7 +12081,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+ 				       plus_constant (Pmode, this_rtx, delta));
+ 	  else
+ 	    aarch64_add_offset (Pmode, this_rtx, this_rtx, delta,
+-				temp1, temp0, false);
++				temp1, temp0, 0, false);
+ 	}
+ 
+       if (Pmode == ptr_mode)
+@@ -30962,6 +31116,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_EXTRA_LIVE_ON_ENTRY
+ #define TARGET_EXTRA_LIVE_ON_ENTRY aarch64_extra_live_on_entry
+ 
++#undef TARGET_USE_LATE_PROLOGUE_EPILOGUE
++#define TARGET_USE_LATE_PROLOGUE_EPILOGUE aarch64_use_late_prologue_epilogue
++
+ #undef TARGET_EMIT_EPILOGUE_FOR_SIBCALL
+ #define TARGET_EMIT_EPILOGUE_FOR_SIBCALL aarch64_expand_epilogue
+ 
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+index 8b0755014..dc5c097bd 100644
+--- a/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
++++ b/gcc/testsuite/g++.target/aarch64/sme/keyword_macros_1.C
+@@ -7,3 +7,4 @@ void f4 () __arm_out("za");
+ void f5 () __arm_inout("za");
+ void f6 () __arm_preserves("za");
+ __arm_new("za") void f7 () {}
++__arm_locally_streaming void f8 () {}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+index fcabe3edc..22f5facfd 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/keyword_macros_1.c
+@@ -7,3 +7,4 @@ void f4 () __arm_out("za");
+ void f5 () __arm_inout("za");
+ void f6 () __arm_preserves("za");
+ __arm_new("za") void f7 () {}
++__arm_locally_streaming void f8 () {}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c
+new file mode 100644
+index 000000000..20ff4b87d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c
+@@ -0,0 +1,466 @@
++// { dg-options "-O -fomit-frame-pointer" }
++// { dg-final { check-function-bodies "**" "" } }
++
++void consume_za () [[arm::streaming, arm::inout("za")]];
++
++/*
++** n_ls:
++**	sub	sp, sp, #?80
++**	cntd	x16
++**	str	x16, \[sp\]
++**	stp	d8, d9, \[sp, #?16\]
++**	stp	d10, d11, \[sp, #?32\]
++**	stp	d12, d13, \[sp, #?48\]
++**	stp	d14, d15, \[sp, #?64\]
++**	smstart	sm
++**	smstop	sm
++**	ldp	d8, d9, \[sp, #?16\]
++**	ldp	d10, d11, \[sp, #?32\]
++**	ldp	d12, d13, \[sp, #?48\]
++**	ldp	d14, d15, \[sp, #?64\]
++**	add	sp, sp, #?80
++**	ret
++*/
++[[arm::locally_streaming]] void
++n_ls ()
++{
++  asm ("");
++}
++
++/*
++** s_ls:
++**	ret
++*/
++[[arm::locally_streaming]] void
++s_ls () [[arm::streaming]]
++{
++  asm ("");
++}
++
++/*
++** sc_ls:
++**	stp	x29, x30, \[sp, #?-96\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	mrs	x16, svcr
++**	str	x16, \[x29, #?16\]
++**	tbnz	x16, 0, [^\n]+
++**	smstart	sm
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, [^\n]+
++**	smstop	sm
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x29, x30, \[sp\], #?96
++**	ret
++*/
++[[arm::locally_streaming]] void
++sc_ls () [[arm::streaming_compatible]]
++{
++  asm ("");
++}
++
++/*
++** n_ls_new_za:
++**	str	x30, \[sp, #?-80\]!
++**	cntd	x16
++**	str	x16, \[sp, #?8\]
++**	stp	d8, d9, \[sp, #?16\]
++**	stp	d10, d11, \[sp, #?32\]
++**	stp	d12, d13, \[sp, #?48\]
++**	stp	d14, d15, \[sp, #?64\]
++**	smstart	sm
++**	mrs	(x[0-9]+), tpidr2_el0
++**	cbz	\1, [^\n]+
++**	bl	__arm_tpidr2_save
++**	msr	tpidr2_el0, xzr
++**	zero	{ za }
++**	smstart	za
++**	bl	consume_za
++**	smstop	za
++**	smstop	sm
++**	ldp	d8, d9, \[sp, #?16\]
++**	ldp	d10, d11, \[sp, #?32\]
++**	ldp	d12, d13, \[sp, #?48\]
++**	ldp	d14, d15, \[sp, #?64\]
++**	ldr	x30, \[sp\], #?80
++**	ret
++*/
++[[arm::locally_streaming, arm::new("za")]] void
++n_ls_new_za ()
++{
++  consume_za ();
++  asm ("");
++}
++
++/*
++** s_ls_new_za:
++**	str	x30, \[sp, #?-16\]!
++**	mrs	(x[0-9]+), tpidr2_el0
++**	cbz	\1, [^\n]+
++**	bl	__arm_tpidr2_save
++**	msr	tpidr2_el0, xzr
++**	zero	{ za }
++**	smstart	za
++**	bl	consume_za
++**	smstop	za
++**	ldr	x30, \[sp\], #?16
++**	ret
++*/
++[[arm::locally_streaming, arm::new("za")]] void
++s_ls_new_za () [[arm::streaming]]
++{
++  consume_za ();
++  asm ("");
++}
++
++/*
++** sc_ls_new_za:
++**	stp	x29, x30, \[sp, #?-96\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	mrs	x16, svcr
++**	str	x16, \[x29, #?16\]
++**	tbnz	x16, 0, [^\n]+
++**	smstart	sm
++**	mrs	(x[0-9]+), tpidr2_el0
++**	cbz	\1, [^\n]+
++**	bl	__arm_tpidr2_save
++**	msr	tpidr2_el0, xzr
++**	zero	{ za }
++**	smstart	za
++**	bl	consume_za
++**	smstop	za
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, [^\n]+
++**	smstop	sm
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x29, x30, \[sp\], #?96
++**	ret
++*/
++[[arm::locally_streaming, arm::new("za")]] void
++sc_ls_new_za () [[arm::streaming_compatible]]
++{
++  consume_za ();
++  asm ("");
++}
++
++/*
++** n_ls_shared_za:
++**	str	x30, \[sp, #?-80\]!
++**	cntd	x16
++**	str	x16, \[sp, #?8\]
++**	stp	d8, d9, \[sp, #?16\]
++**	stp	d10, d11, \[sp, #?32\]
++**	stp	d12, d13, \[sp, #?48\]
++**	stp	d14, d15, \[sp, #?64\]
++**	smstart	sm
++**	bl	consume_za
++**	smstop	sm
++**	ldp	d8, d9, \[sp, #?16\]
++**	ldp	d10, d11, \[sp, #?32\]
++**	ldp	d12, d13, \[sp, #?48\]
++**	ldp	d14, d15, \[sp, #?64\]
++**	ldr	x30, \[sp\], #?80
++**	ret
++*/
++[[arm::locally_streaming]] void
++n_ls_shared_za () [[arm::inout("za")]]
++{
++  consume_za ();
++  asm ("");
++}
++
++/*
++** s_ls_shared_za:
++**	str	x30, \[sp, #?-16\]!
++**	bl	consume_za
++**	ldr	x30, \[sp\], #?16
++**	ret
++*/
++[[arm::locally_streaming]] void
++s_ls_shared_za () [[arm::streaming, arm::inout("za")]]
++{
++  consume_za ();
++  asm ("");
++}
++
++/*
++** sc_ls_shared_za:
++**	stp	x29, x30, \[sp, #?-96\]!
++**	mov	x29, sp
++**	cntd	x16
++**	str	x16, \[sp, #?24\]
++**	stp	d8, d9, \[sp, #?32\]
++**	stp	d10, d11, \[sp, #?48\]
++**	stp	d12, d13, \[sp, #?64\]
++**	stp	d14, d15, \[sp, #?80\]
++**	mrs	x16, svcr
++**	str	x16, \[x29, #?16\]
++**	tbnz	x16, 0, [^\n]+
++**	smstart	sm
++**	bl	consume_za
++**	ldr	x16, \[x29, #?16\]
++**	tbnz	x16, 0, [^\n]+
++**	smstop	sm
++**	ldp	d8, d9, \[sp, #?32\]
++**	ldp	d10, d11, \[sp, #?48\]
++**	ldp	d12, d13, \[sp, #?64\]
++**	ldp	d14, d15, \[sp, #?80\]
++**	ldp	x29, x30, \[sp\], #?96
++**	ret
++*/
++[[arm::locally_streaming]] void
++sc_ls_shared_za () [[arm::streaming_compatible, arm::inout("za")]]
++{
++  consume_za ();
++  asm ("");
++}
++
++/*
++** n_ls_vector_pcs:
++**	sub	sp, sp, #?272
++**	cntd	x16
++**	str	x16, \[sp\]
++**	stp	q8, q9, \[sp, #?16\]
++**	stp	q10, q11, \[sp, #?48\]
++**	stp	q12, q13, \[sp, #?80\]
++**	stp	q14, q15, \[sp, #?112\]
++**	stp	q16, q17, \[sp, #?144\]
++**	stp	q18, q19, \[sp, #?176\]
++**	stp	q20, q21, \[sp, #?208\]
++**	stp	q22, q23, \[sp, #?240\]
++**	smstart	sm
++**	smstop	sm
++**	ldp	q8, q9, \[sp, #?16\]
++**	ldp	q10, q11, \[sp, #?48\]
++**	ldp	q12, q13, \[sp, #?80\]
++**	ldp	q14, q15, \[sp, #?112\]
++**	ldp	q16, q17, \[sp, #?144\]
++**	ldp	q18, q19, \[sp, #?176\]
++**	ldp	q20, q21, \[sp, #?208\]
++**	ldp	q22, q23, \[sp, #?240\]
++**	add	sp, sp, #?272
++**	ret
++*/
++[[arm::locally_streaming]] void __attribute__((aarch64_vector_pcs))
++n_ls_vector_pcs ()
++{
++  asm ("");
++}
++
++/*
++** n_ls_sve_pcs:
++**	sub	sp, sp, #?16
++**	cntd	x16
++**	str	x16, \[sp\]
++**	addsvl	sp, sp, #-18
++**	str	p4, \[sp\]
++**	str	p5, \[sp, #1, mul vl\]
++**	str	p6, \[sp, #2, mul vl\]
++**	str	p7, \[sp, #3, mul vl\]
++**	str	p8, \[sp, #4, mul vl\]
++**	str	p9, \[sp, #5, mul vl\]
++**	str	p10, \[sp, #6, mul vl\]
++**	str	p11, \[sp, #7, mul vl\]
++**	str	p12, \[sp, #8, mul vl\]
++**	str	p13, \[sp, #9, mul vl\]
++**	str	p14, \[sp, #10, mul vl\]
++**	str	p15, \[sp, #11, mul vl\]
++**	str	z8, \[sp, #2, mul vl\]
++**	str	z9, \[sp, #3, mul vl\]
++**	str	z10, \[sp, #4, mul vl\]
++**	str	z11, \[sp, #5, mul vl\]
++**	str	z12, \[sp, #6, mul vl\]
++**	str	z13, \[sp, #7, mul vl\]
++**	str	z14, \[sp, #8, mul vl\]
++**	str	z15, \[sp, #9, mul vl\]
++**	str	z16, \[sp, #10, mul vl\]
++**	str	z17, \[sp, #11, mul vl\]
++**	str	z18, \[sp, #12, mul vl\]
++**	str	z19, \[sp, #13, mul vl\]
++**	str	z20, \[sp, #14, mul vl\]
++**	str	z21, \[sp, #15, mul vl\]
++**	str	z22, \[sp, #16, mul vl\]
++**	str	z23, \[sp, #17, mul vl\]
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	smstop	sm
++**	ldr	z8, \[sp, #2, mul vl\]
++**	ldr	z9, \[sp, #3, mul vl\]
++**	ldr	z10, \[sp, #4, mul vl\]
++**	ldr	z11, \[sp, #5, mul vl\]
++**	ldr	z12, \[sp, #6, mul vl\]
++**	ldr	z13, \[sp, #7, mul vl\]
++**	ldr	z14, \[sp, #8, mul vl\]
++**	ldr	z15, \[sp, #9, mul vl\]
++**	ldr	z16, \[sp, #10, mul vl\]
++**	ldr	z17, \[sp, #11, mul vl\]
++**	ldr	z18, \[sp, #12, mul vl\]
++**	ldr	z19, \[sp, #13, mul vl\]
++**	ldr	z20, \[sp, #14, mul vl\]
++**	ldr	z21, \[sp, #15, mul vl\]
++**	ldr	z22, \[sp, #16, mul vl\]
++**	ldr	z23, \[sp, #17, mul vl\]
++**	ldr	p4, \[sp\]
++**	ldr	p5, \[sp, #1, mul vl\]
++**	ldr	p6, \[sp, #2, mul vl\]
++**	ldr	p7, \[sp, #3, mul vl\]
++**	ldr	p8, \[sp, #4, mul vl\]
++**	ldr	p9, \[sp, #5, mul vl\]
++**	ldr	p10, \[sp, #6, mul vl\]
++**	ldr	p11, \[sp, #7, mul vl\]
++**	ldr	p12, \[sp, #8, mul vl\]
++**	ldr	p13, \[sp, #9, mul vl\]
++**	ldr	p14, \[sp, #10, mul vl\]
++**	ldr	p15, \[sp, #11, mul vl\]
++**	addsvl	sp, sp, #18
++**	add	sp, sp, #?16
++**	ret
++*/
++[[arm::locally_streaming]] void
++n_ls_sve_pcs (__SVBool_t x)
++{
++  asm ("");
++}
++
++/*
++** n_ls_v0:
++**	addsvl	sp, sp, #-1
++**	...
++**	smstart	sm
++**	add	x[0-9]+, [^\n]+
++**	smstop	sm
++**	...
++**	addsvl	sp, sp, #1
++**	...
++*/
++#define TEST(VN) __SVInt32_t VN; asm ("" :: "r" (&VN));
++[[arm::locally_streaming]] void
++n_ls_v0 ()
++{
++  TEST (v0);
++}
++
++/*
++** n_ls_v32:
++**	addsvl	sp, sp, #-32
++**	...
++**	smstart	sm
++**	...
++**	smstop	sm
++**	...
++**	rdsvl	(x[0-9]+), #1
++**	lsl	(x[0-9]+), \1, #?5
++**	add	sp, sp, \2
++**	...
++*/
++[[arm::locally_streaming]] void
++n_ls_v32 ()
++{
++  TEST (v0);
++  TEST (v1);
++  TEST (v2);
++  TEST (v3);
++  TEST (v4);
++  TEST (v5);
++  TEST (v6);
++  TEST (v7);
++  TEST (v8);
++  TEST (v9);
++  TEST (v10);
++  TEST (v11);
++  TEST (v12);
++  TEST (v13);
++  TEST (v14);
++  TEST (v15);
++  TEST (v16);
++  TEST (v17);
++  TEST (v18);
++  TEST (v19);
++  TEST (v20);
++  TEST (v21);
++  TEST (v22);
++  TEST (v23);
++  TEST (v24);
++  TEST (v25);
++  TEST (v26);
++  TEST (v27);
++  TEST (v28);
++  TEST (v29);
++  TEST (v30);
++  TEST (v31);
++}
++
++/*
++** n_ls_v33:
++**	rdsvl	(x[0-9]+), #1
++**	mov	(x[0-9]+), #?33
++**	mul	(x[0-9]+), (?:\1, \2|\2, \1)
++**	sub	sp, sp, \3
++**	...
++**	smstart	sm
++**	...
++**	smstop	sm
++**	...
++**	rdsvl	(x[0-9]+), #1
++**	mov	(x[0-9]+), #?33
++**	mul	(x[0-9]+), (?:\4, \5|\5, \4)
++**	add	sp, sp, \6
++**	...
++*/
++[[arm::locally_streaming]] void
++n_ls_v33 ()
++{
++  TEST (v0);
++  TEST (v1);
++  TEST (v2);
++  TEST (v3);
++  TEST (v4);
++  TEST (v5);
++  TEST (v6);
++  TEST (v7);
++  TEST (v8);
++  TEST (v9);
++  TEST (v10);
++  TEST (v11);
++  TEST (v12);
++  TEST (v13);
++  TEST (v14);
++  TEST (v15);
++  TEST (v16);
++  TEST (v17);
++  TEST (v18);
++  TEST (v19);
++  TEST (v20);
++  TEST (v21);
++  TEST (v22);
++  TEST (v23);
++  TEST (v24);
++  TEST (v25);
++  TEST (v26);
++  TEST (v27);
++  TEST (v28);
++  TEST (v29);
++  TEST (v30);
++  TEST (v31);
++  TEST (v32);
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_2.c b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_2.c
+new file mode 100644
+index 000000000..0eba99385
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_2.c
+@@ -0,0 +1,177 @@
++// { dg-options "-O -fomit-frame-pointer" }
++// { dg-final { check-function-bodies "**" "" } }
++
++#include 
++#include 
++
++/*
++** test_d0:
++**	...
++**	smstart	sm
++**	...
++**	fmov	x10, d0
++**	smstop	sm
++**	fmov	d0, x10
++**	...
++*/
++[[arm::locally_streaming]] double
++test_d0 ()
++{
++  asm ("");
++  return 1.0f;
++}
++
++/*
++** test_d0_vec:
++**	...
++**	smstart	sm
++**	...
++** (
++**	fmov	x10, d0
++** |
++**	umov	x10, v0.d\[0\]
++** )
++**	smstop	sm
++**	fmov	d0, x10
++**	...
++*/
++[[arm::locally_streaming]] int8x8_t
++test_d0_vec ()
++{
++  asm ("");
++  return (int8x8_t) {};
++}
++
++/*
++** test_q0:
++**	...
++**	smstart	sm
++**	...
++**	str	q0, \[sp, #?-16\]!
++**	smstop	sm
++**	ldr	q0, \[sp\], #?16
++**	...
++*/
++[[arm::locally_streaming]] int8x16_t
++test_q0 ()
++{
++  asm ("");
++  return (int8x16_t) {};
++}
++
++/*
++** test_q1:
++**	...
++**	smstart	sm
++**	...
++**	stp	q0, q1, \[sp, #?-32\]!
++**	smstop	sm
++**	ldp	q0, q1, \[sp\], #?32
++**	...
++*/
++[[arm::locally_streaming]] int8x16x2_t
++test_q1 ()
++{
++  asm ("");
++  return (int8x16x2_t) {};
++}
++
++/*
++** test_q2:
++**	...
++**	smstart	sm
++**	...
++**	stp	q0, q1, \[sp, #?-48\]!
++**	str	q2, \[sp, #?32\]
++**	smstop	sm
++**	ldr	q2, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?48
++**	...
++*/
++[[arm::locally_streaming]] int8x16x3_t
++test_q2 ()
++{
++  asm ("");
++  return (int8x16x3_t) {};
++}
++
++/*
++** test_q3:
++**	...
++**	smstart	sm
++**	...
++**	stp	q0, q1, \[sp, #?-64\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	smstop	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q0, q1, \[sp\], #?64
++**	...
++*/
++[[arm::locally_streaming]] int8x16x4_t
++test_q3 ()
++{
++  asm ("");
++  return (int8x16x4_t) {};
++}
++
++/*
++** test_z0:
++**	...
++**	smstart	sm
++**	mov	z0\.b, #0
++**	addvl	sp, sp, #-1
++**	str	z0, \[sp\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	addvl	sp, sp, #1
++**	...
++*/
++[[arm::locally_streaming]] svint8_t
++test_z0 ()
++{
++  asm ("");
++  return (svint8_t) {};
++}
++
++/*
++** test_z3:
++**	...
++**	smstart	sm
++**	...
++**	addvl	sp, sp, #-4
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	...
++*/
++[[arm::locally_streaming]] svint8x4_t
++test_z3 ()
++{
++  asm ("");
++  return (svint8x4_t) {};
++}
++
++/*
++** test_p0:
++**	...
++**	smstart	sm
++**	pfalse	p0\.b
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	...
++*/
++[[arm::locally_streaming]] svbool_t
++test_p0 ()
++{
++  asm ("");
++  return (svbool_t) {};
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_3.c b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_3.c
+new file mode 100644
+index 000000000..2bdea6ac6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_3.c
+@@ -0,0 +1,273 @@
++// { dg-options "-O -fomit-frame-pointer" }
++// { dg-final { check-function-bodies "**" "" } }
++
++#include 
++#include 
++
++/*
++** test_d0:
++**	...
++**	fmov	x10, d0
++**	smstart	sm
++**	fmov	d0, x10
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_d0 (double d0)
++{
++  asm ("");
++}
++
++/*
++** test_d7:
++**	...
++**	fmov	x10, d0
++**	fmov	x11, d1
++**	fmov	x12, d2
++**	fmov	x13, d3
++**	fmov	x14, d4
++**	fmov	x15, d5
++**	fmov	x16, d6
++**	fmov	x17, d7
++**	smstart	sm
++**	fmov	d0, x10
++**	fmov	d1, x11
++**	fmov	d2, x12
++**	fmov	d3, x13
++**	fmov	d4, x14
++**	fmov	d5, x15
++**	fmov	d6, x16
++**	fmov	d7, x17
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_d7 (double d0, double d1, double d2, double d3,
++	 double d4, double d5, double d6, double d7)
++{
++  asm ("");
++}
++
++/*
++** test_d0_vec:
++**	...
++** (
++**	fmov	x10, d0
++** |
++**	umov	x10, v0.d\[0\]
++** )
++**	smstart	sm
++**	fmov	d0, x10
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_d0_vec (int8x8_t d0)
++{
++  asm ("");
++}
++
++/*
++** test_d7_vec:
++**	...
++** (
++**	fmov	x10, d0
++**	fmov	x11, d1
++**	fmov	x12, d2
++**	fmov	x13, d3
++**	fmov	x14, d4
++**	fmov	x15, d5
++**	fmov	x16, d6
++**	fmov	x17, d7
++** |
++**	umov	x10, v0.d\[0\]
++**	umov	x11, v1.d\[0\]
++**	umov	x12, v2.d\[0\]
++**	umov	x13, v3.d\[0\]
++**	umov	x14, v4.d\[0\]
++**	umov	x15, v5.d\[0\]
++**	umov	x16, v6.d\[0\]
++**	umov	x17, v7.d\[0\]
++** )
++**	smstart	sm
++**	fmov	d0, x10
++**	fmov	d1, x11
++**	fmov	d2, x12
++**	fmov	d3, x13
++**	fmov	d4, x14
++**	fmov	d5, x15
++**	fmov	d6, x16
++**	fmov	d7, x17
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_d7_vec (int8x8_t d0, int8x8_t d1, int8x8_t d2, int8x8_t d3,
++	     int8x8_t d4, int8x8_t d5, int8x8_t d6, int8x8_t d7)
++{
++  asm ("");
++}
++
++/*
++** test_q0:
++**	...
++**	str	q0, \[sp, #?-16\]!
++**	smstart	sm
++**	ldr	q0, \[sp\], #?16
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_q0 (int8x16_t q0)
++{
++  asm ("");
++}
++
++/*
++** test_q7:
++**	...
++**	stp	q0, q1, \[sp, #?-128\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	stp	q4, q5, \[sp, #?64\]
++**	stp	q6, q7, \[sp, #?96\]
++**	smstart	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q4, q5, \[sp, #?64\]
++**	ldp	q6, q7, \[sp, #?96\]
++**	ldp	q0, q1, \[sp\], #?128
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_q7 (int8x16x4_t q0, int8x16x4_t q4)
++{
++  asm ("");
++}
++
++/*
++** test_z0:
++**	...
++**	addvl	sp, sp, #-1
++**	str	z0, \[sp\]
++**	smstart	sm
++**	ldr	z0, \[sp\]
++**	addvl	sp, sp, #1
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_z0 (svint8_t z0)
++{
++  asm ("");
++}
++
++/*
++** test_z7:
++**	...
++**	addvl	sp, sp, #-8
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	str	z4, \[sp, #4, mul vl\]
++**	str	z5, \[sp, #5, mul vl\]
++**	str	z6, \[sp, #6, mul vl\]
++**	str	z7, \[sp, #7, mul vl\]
++**	smstart	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	ldr	z4, \[sp, #4, mul vl\]
++**	ldr	z5, \[sp, #5, mul vl\]
++**	ldr	z6, \[sp, #6, mul vl\]
++**	ldr	z7, \[sp, #7, mul vl\]
++**	addvl	sp, sp, #8
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_z7 (svint8x4_t z0, svint8x4_t z4)
++{
++  asm ("");
++}
++
++/*
++** test_p0:
++**	...
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	addvl	sp, sp, #1
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_p0 (svbool_t p0)
++{
++  asm ("");
++}
++
++/*
++** test_p3:
++**	...
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	str	p1, \[sp, #1, mul vl\]
++**	str	p2, \[sp, #2, mul vl\]
++**	str	p3, \[sp, #3, mul vl\]
++**	smstart	sm
++**	ldr	p0, \[sp\]
++**	ldr	p1, \[sp, #1, mul vl\]
++**	ldr	p2, \[sp, #2, mul vl\]
++**	ldr	p3, \[sp, #3, mul vl\]
++**	addvl	sp, sp, #1
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_p3 (svbool_t p0, svbool_t p1, svbool_t p2, svbool_t p3)
++{
++  asm ("");
++}
++
++/*
++** test_mixed:
++**	...
++**	addvl	sp, sp, #-3
++**	str	p0, \[sp\]
++**	str	p1, \[sp, #1, mul vl\]
++**	str	p2, \[sp, #2, mul vl\]
++**	str	p3, \[sp, #3, mul vl\]
++**	str	z3, \[sp, #1, mul vl\]
++**	str	z7, \[sp, #2, mul vl\]
++**	stp	q2, q6, \[sp, #?-32\]!
++**	fmov	w10, s0
++**	fmov	x11, d1
++**	fmov	w12, s4
++**	fmov	x13, d5
++**	smstart	sm
++**	fmov	s0, w10
++**	fmov	d1, x11
++**	fmov	s4, w12
++**	fmov	d5, x13
++**	ldp	q2, q6, \[sp\], #?32
++**	ldr	p0, \[sp\]
++**	ldr	p1, \[sp, #1, mul vl\]
++**	ldr	p2, \[sp, #2, mul vl\]
++**	ldr	p3, \[sp, #3, mul vl\]
++**	ldr	z3, \[sp, #1, mul vl\]
++**	ldr	z7, \[sp, #2, mul vl\]
++**	addvl	sp, sp, #3
++**	smstop	sm
++**	...
++*/
++[[arm::locally_streaming]] void
++test_mixed (float s0, double d1, float32x4_t q2, svfloat32_t z3,
++	    float s4, double d5, float64x2_t q6, svfloat64_t z7,
++	    svbool_t p0, svbool_t p1, svbool_t p2, svbool_t p3)
++{
++  asm ("");
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_4.c b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_4.c
+new file mode 100644
+index 000000000..42adeb152
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_4.c
+@@ -0,0 +1,145 @@
++// { dg-options "-O -fomit-frame-pointer" }
++/* { dg-final { check-function-bodies "**" "" } } */
++
++#include 
++#include 
++
++/*
++** test_d0:
++**	...
++**	smstart	sm
++**	...
++**	fmov	x10, d0
++**	smstop	sm
++**	fmov	d0, x10
++**	...
++**	smstart	sm
++**	...
++**	smstop	sm
++**	...
++*/
++void consume_d0 (double d0);
++
++__arm_locally_streaming void
++test_d0 ()
++{
++  asm ("");
++  consume_d0 (1.0);
++  asm ("");
++}
++
++/*
++** test_d7:
++**	...
++**	fmov	x10, d0
++**	fmov	x11, d1
++**	fmov	x12, d2
++**	fmov	x13, d3
++**	fmov	x14, d4
++**	fmov	x15, d5
++**	fmov	x16, d6
++**	fmov	x17, d7
++**	smstop	sm
++**	fmov	d0, x10
++**	fmov	d1, x11
++**	fmov	d2, x12
++**	fmov	d3, x13
++**	fmov	d4, x14
++**	fmov	d5, x15
++**	fmov	d6, x16
++**	fmov	d7, x17
++**	...
++*/
++void consume_d7 (double d0, double d1, double d2, double d3,
++		 double d4, double d5, double d6, double d7);
++__arm_locally_streaming void
++test_d7 ()
++{
++  asm ("");
++  consume_d7 (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
++  asm ("");
++}
++
++/*
++** test_q7:
++**	...
++**	stp	q0, q1, \[sp, #?-128\]!
++**	stp	q2, q3, \[sp, #?32\]
++**	stp	q4, q5, \[sp, #?64\]
++**	stp	q6, q7, \[sp, #?96\]
++**	smstop	sm
++**	ldp	q2, q3, \[sp, #?32\]
++**	ldp	q4, q5, \[sp, #?64\]
++**	ldp	q6, q7, \[sp, #?96\]
++**	ldp	q0, q1, \[sp\], #?128
++**	...
++*/
++void consume_q7 (int8x16x4_t q0, int8x16x4_t q4);
++
++__arm_locally_streaming void
++test_q7 (int8x16x4_t *ptr)
++{
++  asm ("");
++  consume_q7 (ptr[0], ptr[1]);
++  asm ("");
++}
++
++/*
++** test_z7:
++**	...
++**	addvl	sp, sp, #-8
++**	str	z0, \[sp\]
++**	str	z1, \[sp, #1, mul vl\]
++**	str	z2, \[sp, #2, mul vl\]
++**	str	z3, \[sp, #3, mul vl\]
++**	str	z4, \[sp, #4, mul vl\]
++**	str	z5, \[sp, #5, mul vl\]
++**	str	z6, \[sp, #6, mul vl\]
++**	str	z7, \[sp, #7, mul vl\]
++**	smstop	sm
++**	ldr	z0, \[sp\]
++**	ldr	z1, \[sp, #1, mul vl\]
++**	ldr	z2, \[sp, #2, mul vl\]
++**	ldr	z3, \[sp, #3, mul vl\]
++**	ldr	z4, \[sp, #4, mul vl\]
++**	ldr	z5, \[sp, #5, mul vl\]
++**	ldr	z6, \[sp, #6, mul vl\]
++**	ldr	z7, \[sp, #7, mul vl\]
++**	addvl	sp, sp, #8
++**	...
++*/
++void consume_z7 (svint8x4_t z0, svint8x4_t z4);
++
++__arm_locally_streaming void
++test_z7 (svint8x4_t *ptr1, svint8x4_t *ptr2)
++{
++  asm ("");
++  consume_z7 (*ptr1, *ptr2);
++  asm ("");
++}
++
++/*
++** test_p3:
++**	...
++**	addvl	sp, sp, #-1
++**	str	p0, \[sp\]
++**	str	p1, \[sp, #1, mul vl\]
++**	str	p2, \[sp, #2, mul vl\]
++**	str	p3, \[sp, #3, mul vl\]
++**	smstop	sm
++**	ldr	p0, \[sp\]
++**	ldr	p1, \[sp, #1, mul vl\]
++**	ldr	p2, \[sp, #2, mul vl\]
++**	ldr	p3, \[sp, #3, mul vl\]
++**	addvl	sp, sp, #1
++**	...
++*/
++void consume_p3 (svbool_t p0, svbool_t p1, svbool_t p2, svbool_t p3);
++
++__arm_locally_streaming void
++test_p3 (svbool_t *ptr1, svbool_t *ptr2, svbool_t *ptr3, svbool_t *ptr4)
++{
++  asm ("");
++  consume_p3 (*ptr1, *ptr2, *ptr3, *ptr4);
++  asm ("");
++}
+-- 
+2.33.0
+
diff --git a/0213-Backport-SME-aarch64-Handle-PSTATE.SM-across-abnorma.patch b/0213-Backport-SME-aarch64-Handle-PSTATE.SM-across-abnorma.patch
new file mode 100644
index 0000000..f120a98
--- /dev/null
+++ b/0213-Backport-SME-aarch64-Handle-PSTATE.SM-across-abnorma.patch
@@ -0,0 +1,708 @@
+From ef9c800309fa326ca56dd9d9affd7d5498624bb8 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:29 +0000
+Subject: [PATCH 114/157] [Backport][SME] aarch64: Handle PSTATE.SM across
+ abnormal edges
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=275706fc59b5fdcc26d46d9f19951fc86b40c515
+
+PSTATE.SM is always off on entry to an exception handler, and on entry
+to a nonlocal goto receiver.  Those entry points need to switch
+PSTATE.SM back to the appropriate state for the current function.
+In the case of streaming-compatible functions, they need to restore
+the mode that the caller was originally using.
+
+The requirement on nonlocal goto receivers means that nonlocal
+jumps need to ensure that PSTATE.SM is zero.
+
+gcc/
+	* config/aarch64/aarch64.cc: Include except.h
+	(aarch64_sme_mode_switch_regs::add_call_preserved_reg): New function.
+	(aarch64_sme_mode_switch_regs::add_call_preserved_regs): Likewise.
+	(aarch64_need_old_pstate_sm): Return true if the function has
+	a nonlocal-goto or exception receiver.
+	(aarch64_switch_pstate_sm_for_landing_pad): New function.
+	(aarch64_switch_pstate_sm_for_jump): Likewise.
+	(pass_switch_pstate_sm::gate): Enable the pass for all
+	streaming and streaming-compatible functions.
+	(pass_switch_pstate_sm::execute): Handle non-local gotos and their
+	receivers.  Handle exception handler entry points.
+
+gcc/testsuite/
+	* g++.target/aarch64/sme/exceptions_2.C: New test.
+	* gcc.target/aarch64/sme/nonlocal_goto_1.c: Likewise.
+	* gcc.target/aarch64/sme/nonlocal_goto_2.c: Likewise.
+	* gcc.target/aarch64/sme/nonlocal_goto_3.c: Likewise.
+	* gcc.target/aarch64/sme/nonlocal_goto_4.c: Likewise.
+	* gcc.target/aarch64/sme/nonlocal_goto_5.c: Likewise.
+	* gcc.target/aarch64/sme/nonlocal_goto_6.c: Likewise.
+	* gcc.target/aarch64/sme/nonlocal_goto_7.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                 | 141 ++++++++++++++++-
+ .../g++.target/aarch64/sme/exceptions_2.C     | 148 ++++++++++++++++++
+ .../gcc.target/aarch64/sme/nonlocal_goto_1.c  |  58 +++++++
+ .../gcc.target/aarch64/sme/nonlocal_goto_2.c  |  44 ++++++
+ .../gcc.target/aarch64/sme/nonlocal_goto_3.c  |  46 ++++++
+ .../gcc.target/aarch64/sme/nonlocal_goto_4.c  |  25 +++
+ .../gcc.target/aarch64/sme/nonlocal_goto_5.c  |  26 +++
+ .../gcc.target/aarch64/sme/nonlocal_goto_6.c  |  31 ++++
+ .../gcc.target/aarch64/sme/nonlocal_goto_7.c  |  25 +++
+ 9 files changed, 537 insertions(+), 7 deletions(-)
+ create mode 100644 gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_6.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_7.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 4cb43c2e2..effb567c2 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -82,6 +82,7 @@
+ #include "tree-dfa.h"
+ #include "asan.h"
+ #include "aarch64-feature-deps.h"
++#include "except.h"
+ #include "tree-pass.h"
+ #include "cfgbuild.h"
+ 
+@@ -7295,6 +7296,8 @@ public:
+   void add_reg (machine_mode, unsigned int);
+   void add_call_args (rtx_call_insn *);
+   void add_call_result (rtx_call_insn *);
++  void add_call_preserved_reg (unsigned int);
++  void add_call_preserved_regs (bitmap);
+ 
+   void emit_prologue ();
+   void emit_epilogue ();
+@@ -7427,6 +7430,46 @@ aarch64_sme_mode_switch_regs::add_call_result (rtx_call_insn *call_insn)
+     add_reg (GET_MODE (dest), REGNO (dest));
+ }
+ 
++/* REGNO is a register that is call-preserved under the current function's ABI.
++   Record that it must be preserved around the mode switch.  */
++
++void
++aarch64_sme_mode_switch_regs::add_call_preserved_reg (unsigned int regno)
++{
++  if (FP_REGNUM_P (regno))
++    switch (crtl->abi->id ())
++      {
++      case ARM_PCS_SVE:
++	add_reg (VNx16QImode, regno);
++	break;
++      case ARM_PCS_SIMD:
++	add_reg (V16QImode, regno);
++	break;
++      case ARM_PCS_AAPCS64:
++	add_reg (DImode, regno);
++	break;
++      default:
++	gcc_unreachable ();
++      }
++  else if (PR_REGNUM_P (regno))
++    add_reg (VNx16BImode, regno);
++}
++
++/* The hard registers in REGS are call-preserved under the current function's
++   ABI.  Record that they must be preserved around the mode switch.  */
++
++void
++aarch64_sme_mode_switch_regs::add_call_preserved_regs (bitmap regs)
++{
++  bitmap_iterator bi;
++  unsigned int regno;
++  EXECUTE_IF_SET_IN_BITMAP (regs, 0, regno, bi)
++    if (HARD_REGISTER_NUM_P (regno))
++      add_call_preserved_reg (regno);
++    else
++      break;
++}
++
+ /* Emit code to save registers before the mode switch.  */
+ 
+ void
+@@ -9825,6 +9868,23 @@ aarch64_need_old_pstate_sm ()
+   if (aarch64_cfun_enables_pstate_sm ())
+     return true;
+ 
++  /* Non-local goto receivers are entered with PSTATE.SM equal to 0,
++     but the function needs to return with PSTATE.SM unchanged.  */
++  if (nonlocal_goto_handler_labels)
++    return true;
++
++  /* Likewise for exception handlers.  */
++  eh_landing_pad lp;
++  for (unsigned int i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i)
++    if (lp && lp->post_landing_pad)
++      return true;
++
++  /* Non-local gotos need to set PSTATE.SM to zero.  It's possible to call
++     streaming-compatible functions without SME being available, so PSTATE.SM
++     should only be changed if it is currently set to one.  */
++  if (crtl->has_nonlocal_goto)
++    return true;
++
+   if (cfun->machine->call_switches_pstate_sm)
+     for (auto insn = get_insns (); insn; insn = NEXT_INSN (insn))
+       if (auto *call = dyn_cast (insn))
+@@ -30209,6 +30269,59 @@ aarch64_md_asm_adjust (vec &outputs, vec &inputs,
+   return seq;
+ }
+ 
++/* BB is the target of an exception or nonlocal goto edge, which means
++   that PSTATE.SM is known to be 0 on entry.  Put it into the state that
++   the current function requires.  */
++
++static bool
++aarch64_switch_pstate_sm_for_landing_pad (basic_block bb)
++{
++  if (TARGET_NON_STREAMING)
++    return false;
++
++  start_sequence ();
++  rtx_insn *guard_label = nullptr;
++  if (TARGET_STREAMING_COMPATIBLE)
++    guard_label = aarch64_guard_switch_pstate_sm (IP0_REGNUM,
++						  AARCH64_FL_SM_OFF);
++  aarch64_sme_mode_switch_regs args_switch;
++  args_switch.add_call_preserved_regs (df_get_live_in (bb));
++  args_switch.emit_prologue ();
++  aarch64_switch_pstate_sm (AARCH64_FL_SM_OFF, AARCH64_FL_SM_ON);
++  args_switch.emit_epilogue ();
++  if (guard_label)
++    emit_label (guard_label);
++  auto seq = get_insns ();
++  end_sequence ();
++
++  emit_insn_after (seq, bb_note (bb));
++  return true;
++}
++
++/* JUMP is a nonlocal goto.  Its target requires PSTATE.SM to be 0 on entry,
++   so arrange to make it so.  */
++
++static bool
++aarch64_switch_pstate_sm_for_jump (rtx_insn *jump)
++{
++  if (TARGET_NON_STREAMING)
++    return false;
++
++  start_sequence ();
++  rtx_insn *guard_label = nullptr;
++  if (TARGET_STREAMING_COMPATIBLE)
++    guard_label = aarch64_guard_switch_pstate_sm (IP0_REGNUM,
++						  AARCH64_FL_SM_OFF);
++  aarch64_switch_pstate_sm (AARCH64_FL_SM_ON, AARCH64_FL_SM_OFF);
++  if (guard_label)
++    emit_label (guard_label);
++  auto seq = get_insns ();
++  end_sequence ();
++
++  emit_insn_before (seq, jump);
++  return true;
++}
++
+ /* If CALL involves a change in PSTATE.SM, emit the instructions needed
+    to switch to the new mode and the instructions needed to restore the
+    original mode.  Return true if something changed.  */
+@@ -30292,9 +30405,10 @@ public:
+ };
+ 
+ bool
+-pass_switch_pstate_sm::gate (function *)
++pass_switch_pstate_sm::gate (function *fn)
+ {
+-  return cfun->machine->call_switches_pstate_sm;
++  return (aarch64_fndecl_pstate_sm (fn->decl) != AARCH64_FL_SM_OFF
++	  || cfun->machine->call_switches_pstate_sm);
+ }
+ 
+ /* Emit any instructions needed to switch PSTATE.SM.  */
+@@ -30307,11 +30421,24 @@ pass_switch_pstate_sm::execute (function *fn)
+   bitmap_clear (blocks);
+   FOR_EACH_BB_FN (bb, fn)
+     {
+-      rtx_insn *insn;
+-      FOR_BB_INSNS (bb, insn)
+-	if (auto *call = dyn_cast (insn))
+-	  if (aarch64_switch_pstate_sm_for_call (call))
+-	    bitmap_set_bit (blocks, bb->index);
++      if (has_abnormal_call_or_eh_pred_edge_p (bb)
++	  && aarch64_switch_pstate_sm_for_landing_pad (bb))
++	bitmap_set_bit (blocks, bb->index);
++
++      if (cfun->machine->call_switches_pstate_sm)
++	{
++	  rtx_insn *insn;
++	  FOR_BB_INSNS (bb, insn)
++	    if (auto *call = dyn_cast (insn))
++	      if (aarch64_switch_pstate_sm_for_call (call))
++		bitmap_set_bit (blocks, bb->index);
++	}
++
++      auto end = BB_END (bb);
++      if (JUMP_P (end)
++	  && find_reg_note (end, REG_NON_LOCAL_GOTO, NULL_RTX)
++	  && aarch64_switch_pstate_sm_for_jump (end))
++	bitmap_set_bit (blocks, bb->index);
+     }
+   find_many_sub_basic_blocks (blocks);
+   clear_aux_for_blocks ();
+diff --git a/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C b/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C
+new file mode 100644
+index 000000000..f791b6ecc
+--- /dev/null
++++ b/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C
+@@ -0,0 +1,148 @@
++// { dg-options "-O -fno-optimize-sibling-calls" }
++// { dg-final { check-function-bodies "**" "" } }
++
++void n_callee();
++void s_callee() __arm_streaming;
++void sc_callee() __arm_streaming_compatible;
++
++void n_callee_ne() noexcept;
++void s_callee_ne() noexcept __arm_streaming;
++void sc_callee_ne() noexcept __arm_streaming_compatible;
++
++void n_caller1()
++{
++  try
++    {
++      n_callee();
++      sc_callee();
++    }
++  catch (...)
++    {
++      n_callee_ne();
++      sc_callee_ne();
++    }
++}
++// { dg-final { scan-assembler {_Z9n_caller1v:(?:(?!smstart|smstop).)*\tret} } }
++
++/*
++** _Z9n_caller2v:
++**	...
++**	cntd	(x[0-9]+)
++**	str	\1, [^\n]+
++**	...
++**	bl	__cxa_begin_catch
++**	smstart	sm
++**	bl	_Z11s_callee_nev
++**	smstop	sm
++**	bl	__cxa_end_catch
++**	...
++*/
++void n_caller2()
++{
++  try
++    {
++      n_callee();
++      sc_callee();
++    }
++  catch (...)
++    {
++      s_callee_ne();
++    }
++}
++
++/*
++** _Z9s_caller1v:
++**	...
++**	bl	__cxa_end_catch
++**	smstart	sm
++**	...
++*/
++int s_caller1() __arm_streaming
++{
++  try
++    {
++      s_callee();
++      return 1;
++    }
++  catch (...)
++    {
++      return 2;
++    }
++}
++
++/*
++** _Z9s_caller2v:
++**	...
++**	bl	__cxa_begin_catch
++**	smstart	sm
++**	bl	_Z11s_callee_nev
++**	smstop	sm
++**	bl	__cxa_end_catch
++**	smstart	sm
++**	...
++*/
++int s_caller2() __arm_streaming
++{
++  try
++    {
++      n_callee();
++      return 1;
++    }
++  catch (...)
++    {
++      s_callee_ne();
++      return 2;
++    }
++}
++
++/*
++** _Z10sc_caller1v:
++**	...
++**	cntd	(x[0-9]+)
++**	str	\1, [^\n]+
++**	mrs	(x[0-9]+), svcr
++**	str	\2, ([^\n]+)
++**	...
++**	bl	__cxa_end_catch
++**	ldr	(x[0-9]+), \3
++**	tbz	\4, 0, [^\n]+
++**	smstart	sm
++**	...
++*/
++int sc_caller1() __arm_streaming_compatible
++{
++  try
++    {
++      sc_callee();
++      return 1;
++    }
++  catch (...)
++    {
++      return 2;
++    }
++}
++
++/*
++** _Z10ls_caller1v:
++**	...
++**	cntd	(x[0-9]+)
++**	str	\1, [^\n]+
++**	...
++**	bl	__cxa_begin_catch
++**	smstart	sm
++**	bl	_Z12sc_callee_nev
++**	smstop	sm
++**	bl	__cxa_end_catch
++**	...
++*/
++__arm_locally_streaming void ls_caller1()
++{
++  try
++    {
++      sc_callee();
++    }
++  catch (...)
++    {
++      sc_callee_ne();
++    }
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_1.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_1.c
+new file mode 100644
+index 000000000..4e3869fcc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_1.c
+@@ -0,0 +1,58 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void run(void (*)());
++
++/*
++** foo:
++**	...
++**	mrs	x16, svcr
++**	...
++**	str	x16, (.*)
++**	...
++**	ldr	x16, \1
++**	tbz	x16, 0, .*
++**	smstop	sm
++**	bl	__clear_cache
++**	ldr	x16, \1
++**	tbz	x16, 0, .*
++**	smstart	sm
++**	add	x0, .*
++**	ldr	x16, \1
++**	tbz	x16, 0, .*
++**	smstop	sm
++**	bl	run
++**	ldr	x16, \1
++**	tbz	x16, 0, .*
++**	smstart	sm
++**	mov	w0, 1
++**	...
++**	ret
++**	ldr	x16, \1
++**	tbz	x16, 0, .*
++**	smstart	sm
++**	mov	w0, 0
++**	...
++*/
++int
++foo (int *ptr) __arm_streaming_compatible
++{
++  __label__ failure;
++
++  void bar () { *ptr += 1; goto failure; }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
++
++// { dg-final { scan-assembler {\tstp\tx19, x20,} } }
++// { dg-final { scan-assembler {\tstp\tx21, x22,} } }
++// { dg-final { scan-assembler {\tstp\tx23, x24,} } }
++// { dg-final { scan-assembler {\tstp\tx25, x26,} } }
++// { dg-final { scan-assembler {\tstp\tx27, x28,} } }
++// { dg-final { scan-assembler {\tstp\td8, d9,} } }
++// { dg-final { scan-assembler {\tstp\td10, d11,} } }
++// { dg-final { scan-assembler {\tstp\td12, d13,} } }
++// { dg-final { scan-assembler {\tstp\td14, d15,} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_2.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_2.c
+new file mode 100644
+index 000000000..2a2db72c3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_2.c
+@@ -0,0 +1,44 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void run(void (*)());
++
++/*
++** foo:
++**	...
++**	smstop	sm
++**	bl	__clear_cache
++**	smstart	sm
++**	add	x0, .*
++**	smstop	sm
++**	bl	run
++**	smstart	sm
++**	mov	w0, 1
++**	...
++**	ret
++**	smstart	sm
++**	mov	w0, 0
++**	...
++*/
++int
++foo (int *ptr) __arm_streaming
++{
++  __label__ failure;
++
++  void bar () { *ptr += 1; goto failure; }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
++
++// { dg-final { scan-assembler {\tstp\tx19, x20,} } }
++// { dg-final { scan-assembler {\tstp\tx21, x22,} } }
++// { dg-final { scan-assembler {\tstp\tx23, x24,} } }
++// { dg-final { scan-assembler {\tstp\tx25, x26,} } }
++// { dg-final { scan-assembler {\tstp\tx27, x28,} } }
++// { dg-final { scan-assembler {\tstp\td8, d9,} } }
++// { dg-final { scan-assembler {\tstp\td10, d11,} } }
++// { dg-final { scan-assembler {\tstp\td12, d13,} } }
++// { dg-final { scan-assembler {\tstp\td14, d15,} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_3.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_3.c
+new file mode 100644
+index 000000000..022b04052
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_3.c
+@@ -0,0 +1,46 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void run(void (*)());
++
++/*
++** foo:
++**	...
++**	smstart	sm
++**	...
++**	smstop	sm
++**	bl	__clear_cache
++**	smstart	sm
++**	add	x0, .*
++**	smstop	sm
++**	bl	run
++**	smstart	sm
++**	mov	w0, 1
++**	...
++**	smstart	sm
++**	mov	w0, 0
++**	smstop	sm
++**	...
++*/
++__arm_locally_streaming int
++foo (int *ptr)
++{
++  __label__ failure;
++
++  void bar () { *ptr += 1; goto failure; }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
++
++// { dg-final { scan-assembler {\tstp\tx19, x20,} } }
++// { dg-final { scan-assembler {\tstp\tx21, x22,} } }
++// { dg-final { scan-assembler {\tstp\tx23, x24,} } }
++// { dg-final { scan-assembler {\tstp\tx25, x26,} } }
++// { dg-final { scan-assembler {\tstp\tx27, x28,} } }
++// { dg-final { scan-assembler {\tstp\td8, d9,} } }
++// { dg-final { scan-assembler {\tstp\td10, d11,} } }
++// { dg-final { scan-assembler {\tstp\td12, d13,} } }
++// { dg-final { scan-assembler {\tstp\td14, d15,} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_4.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_4.c
+new file mode 100644
+index 000000000..044607628
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_4.c
+@@ -0,0 +1,25 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void run(void (*)());
++
++/*
++** bar.0:
++**	...
++**	smstart	sm
++**	...
++**	smstop	sm
++**	br	x[0-9]+
++*/
++int
++foo (int *ptr)
++{
++  __label__ failure;
++
++  __arm_locally_streaming void bar () { *ptr += 1; goto failure; }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_5.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_5.c
+new file mode 100644
+index 000000000..4246aec8b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_5.c
+@@ -0,0 +1,26 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void run(void (*)() __arm_streaming);
++
++/*
++** bar.0:
++**	...
++**	smstop	sm
++**	br	x[0-9]+
++*/
++int
++foo (int *ptr)
++{
++  __label__ failure;
++
++  void bar () __arm_streaming { *ptr += 1; goto failure; }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
++
++// { dg-final { scan-assembler-not {smstart\t} } }
++// { dg-final { scan-assembler-not {mrs\t} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_6.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_6.c
+new file mode 100644
+index 000000000..151e2f22d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_6.c
+@@ -0,0 +1,31 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++/* { dg-final { check-function-bodies "**" "" } } */
++
++void run(void (*)() __arm_streaming_compatible);
++
++/*
++** bar.0:
++**	...
++**	mrs	x16, svcr
++**	...
++**	str	x16, (.*)
++**	...
++**	ldr	x16, \1
++**	tbz	x16, 0, .*
++**	smstop	sm
++**	br	x[0-9]+
++*/
++int
++foo (int *ptr)
++{
++  __label__ failure;
++
++  void bar () __arm_streaming_compatible { *ptr += 1; goto failure; }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
++
++// { dg-final { scan-assembler-not {smstart\t} } }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_7.c b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_7.c
+new file mode 100644
+index 000000000..9cc3ad5d2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/nonlocal_goto_7.c
+@@ -0,0 +1,25 @@
++/* { dg-options "-O2 -fno-schedule-insns -fno-schedule-insns2" } */
++
++void run(void (*)() __arm_inout("za"));
++void callee () __arm_inout("za");
++
++int
++foo (int *ptr)
++{
++  __label__ failure;
++
++  void bar () __arm_inout("za")
++  {
++    callee ();
++    *ptr += 1;
++    goto failure;
++  }
++  run (bar);
++  return 1;
++
++failure:
++  return 0;
++}
++
++// { dg-final { scan-assembler-not {\tsmstart\t} } }
++// { dg-final { scan-assembler-not {\tsmstop\t} } }
+-- 
+2.33.0
+
diff --git a/0214-Backport-SME-aarch64-Enforce-inlining-restrictions-f.patch b/0214-Backport-SME-aarch64-Enforce-inlining-restrictions-f.patch
new file mode 100644
index 0000000..db7c5b3
--- /dev/null
+++ b/0214-Backport-SME-aarch64-Enforce-inlining-restrictions-f.patch
@@ -0,0 +1,913 @@
+From c4578108ab766178fe7ebd51421c1ac9f317b675 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:30 +0000
+Subject: [PATCH 115/157] [Backport][SME] aarch64: Enforce inlining
+ restrictions for SME
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0e9aa05df6c643610a3821af52eda642a525a886
+
+A function that has local ZA state cannot be inlined into its caller,
+since we only support managing ZA switches at function scope.
+
+A function whose body directly clobbers ZA state cannot be inlined into
+a function with ZA state.
+
+A function whose body requires a particular PSTATE.SM setting can only
+be inlined into a function body that guarantees that PSTATE.SM setting.
+The callee's function type doesn't matter here: one locally-streaming
+function can be inlined into another.
+
+gcc/
+	* config/aarch64/aarch64.cc: Include symbol-summary.h, ipa-prop.h,
+	and ipa-fnsummary.h
+	(aarch64_function_attribute_inlinable_p): New function.
+	(AARCH64_IPA_SM_FIXED, AARCH64_IPA_CLOBBERS_ZA): New constants.
+	(aarch64_need_ipa_fn_target_info): New function.
+	(aarch64_update_ipa_fn_target_info): Likewise.
+	(aarch64_can_inline_p): Restrict the previous ISA flag checks
+	to non-modal features.  Prevent callees that require a particular
+	PSTATE.SM state from being inlined into callers that can't guarantee
+	that state.  Also prevent callees that have ZA state from being
+	inlined into callers that don't.  Finally, prevent callees that
+	clobber ZA from being inlined into callers that have ZA state.
+	(TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P): Define.
+	(TARGET_NEED_IPA_FN_TARGET_INFO): Likewise.
+	(TARGET_UPDATE_IPA_FN_TARGET_INFO): Likewise.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/inlining_1.c: New test.
+	* gcc.target/aarch64/sme/inlining_2.c: Likewise.
+	* gcc.target/aarch64/sme/inlining_3.c: Likewise.
+	* gcc.target/aarch64/sme/inlining_4.c: Likewise.
+	* gcc.target/aarch64/sme/inlining_5.c: Likewise.
+	* gcc.target/aarch64/sme/inlining_6.c: Likewise.
+	* gcc.target/aarch64/sme/inlining_7.c: Likewise.
+	* gcc.target/aarch64/sme/inlining_8.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                 | 132 +++++++++++++++++-
+ .../gcc.target/aarch64/sme/inlining_1.c       |  47 +++++++
+ .../gcc.target/aarch64/sme/inlining_10.c      |  57 ++++++++
+ .../gcc.target/aarch64/sme/inlining_11.c      |  57 ++++++++
+ .../gcc.target/aarch64/sme/inlining_12.c      |  15 ++
+ .../gcc.target/aarch64/sme/inlining_13.c      |  15 ++
+ .../gcc.target/aarch64/sme/inlining_14.c      |  15 ++
+ .../gcc.target/aarch64/sme/inlining_15.c      |  27 ++++
+ .../gcc.target/aarch64/sme/inlining_2.c       |  47 +++++++
+ .../gcc.target/aarch64/sme/inlining_3.c       |  47 +++++++
+ .../gcc.target/aarch64/sme/inlining_4.c       |  47 +++++++
+ .../gcc.target/aarch64/sme/inlining_5.c       |  47 +++++++
+ .../gcc.target/aarch64/sme/inlining_6.c       |  31 ++++
+ .../gcc.target/aarch64/sme/inlining_7.c       |  31 ++++
+ .../gcc.target/aarch64/sme/inlining_8.c       |  31 ++++
+ .../gcc.target/aarch64/sme/inlining_9.c       |  55 ++++++++
+ 16 files changed, 696 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_10.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_11.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_12.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_13.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_14.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_15.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_6.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_7.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_8.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/inlining_9.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index effb567c2..eab94d5c2 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -85,6 +85,9 @@
+ #include "except.h"
+ #include "tree-pass.h"
+ #include "cfgbuild.h"
++#include "symbol-summary.h"
++#include "ipa-prop.h"
++#include "ipa-fnsummary.h"
+ 
+ /* This file should be included last.  */
+ #include "target-def.h"
+@@ -21351,6 +21354,17 @@ aarch64_option_valid_attribute_p (tree fndecl, tree, tree args, int)
+   return ret;
+ }
+ 
++/* Implement TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P.  Use an opt-out
++   rather than an opt-in list.  */
++
++static bool
++aarch64_function_attribute_inlinable_p (const_tree fndecl)
++{
++  /* A function that has local ZA state cannot be inlined into its caller,
++     since we only support managing ZA switches at function scope.  */
++  return !aarch64_fndecl_has_new_state (fndecl, "za");
++}
++
+ /* Helper for aarch64_can_inline_p.  In the case where CALLER and CALLEE are
+    tri-bool options (yes, no, don't care) and the default value is
+    DEF, determine whether to reject inlining.  */
+@@ -21372,6 +21386,60 @@ aarch64_tribools_ok_for_inlining_p (int caller, int callee,
+   return (callee == caller || callee == def);
+ }
+ 
++/* Bit allocations for ipa_fn_summary::target_info.  */
++
++/* Set if the function contains a stmt that relies on the function's
++   choice of PSTATE.SM setting (0 for non-streaming, 1 for streaming).
++   Not meaningful for streaming-compatible functions.  */
++constexpr auto AARCH64_IPA_SM_FIXED = 1U << 0;
++
++/* Set if the function clobbers ZA.  Not meaningful for functions that
++   have ZA state.  */
++constexpr auto AARCH64_IPA_CLOBBERS_ZA = 1U << 1;
++
++/* Implement TARGET_NEED_IPA_FN_TARGET_INFO.  */
++
++static bool
++aarch64_need_ipa_fn_target_info (const_tree, unsigned int &)
++{
++  /* We could in principle skip this for streaming-compatible functions
++     that have ZA state, but that's a rare combination.  */
++  return true;
++}
++
++/* Implement TARGET_UPDATE_IPA_FN_TARGET_INFO.  */
++
++static bool
++aarch64_update_ipa_fn_target_info (unsigned int &info, const gimple *stmt)
++{
++  if (auto *ga = dyn_cast (stmt))
++    {
++      /* We don't know what the asm does, so conservatively assume that
++	 it requires the function's current SM mode.  */
++      info |= AARCH64_IPA_SM_FIXED;
++      for (unsigned int i = 0; i < gimple_asm_nclobbers (ga); ++i)
++	{
++	  tree op = gimple_asm_clobber_op (ga, i);
++	  const char *clobber = TREE_STRING_POINTER (TREE_VALUE (op));
++	  if (strcmp (clobber, "za") == 0)
++	    info |= AARCH64_IPA_CLOBBERS_ZA;
++	}
++    }
++  if (auto *call = dyn_cast (stmt))
++    {
++      if (gimple_call_builtin_p (call, BUILT_IN_MD))
++	{
++	  /* The attributes on AArch64 builtins are supposed to be accurate.
++	     If the function isn't marked streaming-compatible then it
++	     needs whichever SM mode it selects.  */
++	  tree decl = gimple_call_fndecl (call);
++	  if (aarch64_fndecl_pstate_sm (decl) != 0)
++	    info |= AARCH64_IPA_SM_FIXED;
++	}
++    }
++  return true;
++}
++
+ /* Implement TARGET_CAN_INLINE_P.  Decide whether it is valid
+    to inline CALLEE into CALLER based on target-specific info.
+    Make sure that the caller and callee have compatible architectural
+@@ -21394,12 +21462,56 @@ aarch64_can_inline_p (tree caller, tree callee)
+ 					   : target_option_default_node);
+ 
+   /* Callee's ISA flags should be a subset of the caller's.  */
+-  if ((caller_opts->x_aarch64_asm_isa_flags
+-       & callee_opts->x_aarch64_asm_isa_flags)
+-      != callee_opts->x_aarch64_asm_isa_flags)
++  auto caller_asm_isa = (caller_opts->x_aarch64_asm_isa_flags
++			 & ~AARCH64_FL_ISA_MODES);
++  auto callee_asm_isa = (callee_opts->x_aarch64_asm_isa_flags
++			 & ~AARCH64_FL_ISA_MODES);
++  if (callee_asm_isa & ~caller_asm_isa)
+     return false;
+-  if ((caller_opts->x_aarch64_isa_flags & callee_opts->x_aarch64_isa_flags)
+-      != callee_opts->x_aarch64_isa_flags)
++
++  auto caller_isa = (caller_opts->x_aarch64_isa_flags
++		     & ~AARCH64_FL_ISA_MODES);
++  auto callee_isa = (callee_opts->x_aarch64_isa_flags
++		     & ~AARCH64_FL_ISA_MODES);
++  if (callee_isa & ~caller_isa)
++    return false;
++
++  /* Return true if the callee might have target_info property PROPERTY.
++     The answer must be true unless we have positive proof to the contrary.  */
++  auto callee_has_property = [&](unsigned int property)
++    {
++      if (ipa_fn_summaries)
++	if (auto *summary = ipa_fn_summaries->get (cgraph_node::get (callee)))
++	  if (!(summary->target_info & property))
++	    return false;
++      return true;
++    };
++
++  /* Streaming-compatible code can be inlined into functions with any
++     PSTATE.SM mode.  Otherwise the caller and callee must agree on
++     PSTATE.SM mode, unless we can prove that the callee is naturally
++     streaming-compatible.  */
++  auto caller_sm = (caller_opts->x_aarch64_isa_flags & AARCH64_FL_SM_STATE);
++  auto callee_sm = (callee_opts->x_aarch64_isa_flags & AARCH64_FL_SM_STATE);
++  if (callee_sm
++      && caller_sm != callee_sm
++      && callee_has_property (AARCH64_IPA_SM_FIXED))
++    return false;
++
++  /* aarch64_function_attribute_inlinable_p prevents new-ZA functions
++     from being inlined into others.  We also need to prevent inlining
++     of shared-ZA functions into functions without ZA state, since this
++     is an error condition.
++
++     The only other problematic case for ZA is inlining a function that
++     directly clobbers ZA into a function that has ZA state.  */
++  auto caller_za = (caller_opts->x_aarch64_isa_flags & AARCH64_FL_ZA_ON);
++  auto callee_za = (callee_opts->x_aarch64_isa_flags & AARCH64_FL_ZA_ON);
++  if (!caller_za && callee_za)
++    return false;
++  if (caller_za
++      && !callee_za
++      && callee_has_property (AARCH64_IPA_CLOBBERS_ZA))
+     return false;
+ 
+   /* Allow non-strict aligned functions inlining into strict
+@@ -30732,6 +30844,16 @@ aarch64_get_v16qi_mode ()
+ #undef TARGET_CAN_ELIMINATE
+ #define TARGET_CAN_ELIMINATE aarch64_can_eliminate
+ 
++#undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P
++#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P \
++  aarch64_function_attribute_inlinable_p
++
++#undef TARGET_NEED_IPA_FN_TARGET_INFO
++#define TARGET_NEED_IPA_FN_TARGET_INFO aarch64_need_ipa_fn_target_info
++
++#undef TARGET_UPDATE_IPA_FN_TARGET_INFO
++#define TARGET_UPDATE_IPA_FN_TARGET_INFO aarch64_update_ipa_fn_target_info
++
+ #undef TARGET_CAN_INLINE_P
+ #define TARGET_CAN_INLINE_P aarch64_can_inline_p
+ 
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_1.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_1.c
+new file mode 100644
+index 000000000..24dc2b341
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_1.c
+@@ -0,0 +1,47 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++sc_callee () [[arm::streaming_compatible]] {}
++
++inline void __attribute__((always_inline))
++s_callee () [[arm::streaming]] {}
++
++inline void __attribute__((always_inline))
++n_callee () {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_callee () [[arm::streaming_compatible]] {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_callee () {}
++
++inline void __attribute__((always_inline))
++sc_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++inline void __attribute__((always_inline))
++s_asm_callee () [[arm::streaming]] { asm (""); } // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++n_asm_callee () { asm (""); } // { dg-error "inlining failed" }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_asm_callee () [[arm::streaming_compatible]] { asm (""); } // { dg-error "inlining failed" }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_asm_callee () { asm (""); } // { dg-error "inlining failed" }
++
++void
++sc_caller () [[arm::streaming_compatible]]
++{
++  sc_callee ();
++  s_callee ();
++  n_callee ();
++  sc_ls_callee ();
++  n_ls_callee ();
++
++  sc_asm_callee ();
++  s_asm_callee ();
++  n_asm_callee ();
++  sc_ls_asm_callee ();
++  n_ls_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_10.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_10.c
+new file mode 100644
+index 000000000..adfd45a87
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_10.c
+@@ -0,0 +1,57 @@
++/* { dg-options "" } */
++
++#include 
++#include 
++
++uint8x16_t *neon;
++svint64_t *sve;
++int64_t *ptr;
++
++// Gets expanded to addition early, so no error.  An error would be
++// more correct though.
++inline void __attribute__((always_inline))
++call_vadd ()
++{
++  neon[4] = vaddq_u8 (neon[5], neon[6]);
++}
++
++inline void __attribute__((always_inline))
++call_vbsl () // { dg-error "inlining failed" }
++{
++  neon[0] = vbslq_u8 (neon[1], neon[2], neon[3]);
++}
++
++inline void __attribute__((always_inline))
++call_svadd ()
++{
++  *sve = svadd_x (svptrue_b8 (), *sve, 1);
++}
++
++inline void __attribute__((always_inline))
++call_svld1_gather () // { dg-error "inlining failed" }
++{
++  *sve = svld1_gather_offset (svptrue_b8 (), ptr, *sve);
++}
++
++inline void __attribute__((always_inline))
++call_svzero () [[arm::inout("za")]]
++{
++  svzero_za ();
++}
++
++inline void __attribute__((always_inline))
++call_svst1_za () [[arm::streaming, arm::inout("za")]] // { dg-error "inlining failed" }
++{
++  svst1_ver_za64 (0, 0, svptrue_b8 (), ptr);
++}
++
++void
++sc_caller () [[arm::inout("za"), arm::streaming_compatible]]
++{
++  call_vadd ();
++  call_vbsl ();
++  call_svadd ();
++  call_svld1_gather ();
++  call_svzero ();
++  call_svst1_za ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_11.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_11.c
+new file mode 100644
+index 000000000..d05a92c1c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_11.c
+@@ -0,0 +1,57 @@
++/* { dg-options "" } */
++
++#include 
++#include 
++
++uint8x16_t *neon;
++svint64_t *sve;
++int64_t *ptr;
++
++// Gets expanded to addition early, so no error.  An error would be
++// more correct though.
++inline void __attribute__((always_inline))
++call_vadd ()
++{
++  neon[4] = vaddq_u8 (neon[5], neon[6]);
++}
++
++inline void __attribute__((always_inline))
++call_vbsl () // { dg-error "inlining failed" }
++{
++  neon[0] = vbslq_u8 (neon[1], neon[2], neon[3]);
++}
++
++inline void __attribute__((always_inline))
++call_svadd ()
++{
++  *sve = svadd_x (svptrue_b8 (), *sve, 1);
++}
++
++inline void __attribute__((always_inline))
++call_svld1_gather () // { dg-error "inlining failed" }
++{
++  *sve = svld1_gather_offset (svptrue_b8 (), ptr, *sve);
++}
++
++inline void __attribute__((always_inline))
++call_svzero () [[arm::inout("za")]]
++{
++  svzero_za ();
++}
++
++inline void __attribute__((always_inline))
++call_svst1_za () [[arm::streaming, arm::inout("za")]]
++{
++  svst1_ver_za64 (0, 0, svptrue_b8 (), ptr);
++}
++
++void
++sc_caller () [[arm::inout("za"), arm::streaming]]
++{
++  call_vadd ();
++  call_vbsl ();
++  call_svadd ();
++  call_svld1_gather ();
++  call_svzero ();
++  call_svst1_za ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_12.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_12.c
+new file mode 100644
+index 000000000..366f8b24a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_12.c
+@@ -0,0 +1,15 @@
++/* { dg-options "" } */
++
++#include 
++
++inline void __attribute__((always_inline))
++call_svzero () [[arm::inout("za"), arm::streaming_compatible]] // { dg-error "inlining failed" }
++{
++  svzero_za ();
++}
++
++void
++n_caller ()
++{
++  call_svzero ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_13.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_13.c
+new file mode 100644
+index 000000000..bdbd7408c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_13.c
+@@ -0,0 +1,15 @@
++/* { dg-options "" } */
++
++#include 
++
++inline void __attribute__((always_inline))
++call_svzero () [[arm::inout("za"), arm::streaming_compatible]] // { dg-error "inlining failed" }
++{
++  svzero_za ();
++}
++
++void
++s_caller ()
++{
++  call_svzero ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_14.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_14.c
+new file mode 100644
+index 000000000..0ce4384f6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_14.c
+@@ -0,0 +1,15 @@
++/* { dg-options "" } */
++
++#include 
++
++inline void __attribute__((always_inline))
++call_svzero () [[arm::inout("za"), arm::streaming_compatible]] // { dg-error "inlining failed" }
++{
++  svzero_za ();
++}
++
++void
++sc_caller ()
++{
++  call_svzero ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_15.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_15.c
+new file mode 100644
+index 000000000..06fc5d7f5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_15.c
+@@ -0,0 +1,27 @@
++/* { dg-options "" } */
++
++#include 
++
++inline void
++call_svzero () [[arm::inout("za"), arm::streaming_compatible]]
++{
++  svzero_za ();
++}
++
++void
++n_caller ()
++{
++  call_svzero (); // { dg-error "call to a function that shares 'za' state from a function that has no 'za' state" }
++}
++
++void
++s_caller ()
++{
++  call_svzero (); // { dg-error "call to a function that shares 'za' state from a function that has no 'za' state" }
++}
++
++void
++sc_caller ()
++{
++  call_svzero (); // { dg-error "call to a function that shares 'za' state from a function that has no 'za' state" }
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_2.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_2.c
+new file mode 100644
+index 000000000..ea2a57049
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_2.c
+@@ -0,0 +1,47 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++sc_callee () [[arm::streaming_compatible]] {}
++
++inline void __attribute__((always_inline))
++s_callee () [[arm::streaming]] {}
++
++inline void __attribute__((always_inline))
++n_callee () {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_callee () [[arm::streaming_compatible]] {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_callee () {}
++
++inline void __attribute__((always_inline))
++sc_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++inline void __attribute__((always_inline))
++s_asm_callee () [[arm::streaming]] { asm (""); }
++
++inline void __attribute__((always_inline))
++n_asm_callee () { asm (""); } // { dg-error "inlining failed" }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_asm_callee () { asm (""); }
++
++void
++s_caller () [[arm::streaming]]
++{
++  sc_callee ();
++  s_callee ();
++  n_callee ();
++  sc_ls_callee ();
++  n_ls_callee ();
++
++  sc_asm_callee ();
++  s_asm_callee ();
++  n_asm_callee ();
++  sc_ls_asm_callee ();
++  n_ls_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_3.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_3.c
+new file mode 100644
+index 000000000..d7ffb3819
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_3.c
+@@ -0,0 +1,47 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++sc_callee () [[arm::streaming_compatible]] {}
++
++inline void __attribute__((always_inline))
++s_callee () [[arm::streaming]] {}
++
++inline void __attribute__((always_inline))
++n_callee () {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_callee () [[arm::streaming_compatible]] {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_callee () {}
++
++inline void __attribute__((always_inline))
++sc_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++inline void __attribute__((always_inline))
++s_asm_callee () [[arm::streaming]] { asm (""); } // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++n_asm_callee () { asm (""); }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_asm_callee () [[arm::streaming_compatible]] { asm (""); } // { dg-error "inlining failed" }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_asm_callee () { asm (""); } // { dg-error "inlining failed" }
++
++void
++n_caller ()
++{
++  sc_callee ();
++  s_callee ();
++  n_callee ();
++  sc_ls_callee ();
++  n_ls_callee ();
++
++  sc_asm_callee ();
++  s_asm_callee ();
++  n_asm_callee ();
++  sc_ls_asm_callee ();
++  n_ls_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_4.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_4.c
+new file mode 100644
+index 000000000..789203725
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_4.c
+@@ -0,0 +1,47 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++sc_callee () [[arm::streaming_compatible]] {}
++
++inline void __attribute__((always_inline))
++s_callee () [[arm::streaming]] {}
++
++inline void __attribute__((always_inline))
++n_callee () {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_callee () [[arm::streaming_compatible]] {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_callee () {}
++
++inline void __attribute__((always_inline))
++sc_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++inline void __attribute__((always_inline))
++s_asm_callee () [[arm::streaming]] { asm (""); }
++
++inline void __attribute__((always_inline))
++n_asm_callee () { asm (""); } // { dg-error "inlining failed" }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_asm_callee () { asm (""); }
++
++[[arm::locally_streaming]] void
++sc_ls_caller () [[arm::streaming_compatible]]
++{
++  sc_callee ();
++  s_callee ();
++  n_callee ();
++  sc_ls_callee ();
++  n_ls_callee ();
++
++  sc_asm_callee ();
++  s_asm_callee ();
++  n_asm_callee ();
++  sc_ls_asm_callee ();
++  n_ls_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_5.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_5.c
+new file mode 100644
+index 000000000..d19cdc450
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_5.c
+@@ -0,0 +1,47 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++sc_callee () [[arm::streaming_compatible]] {}
++
++inline void __attribute__((always_inline))
++s_callee () [[arm::streaming]] {}
++
++inline void __attribute__((always_inline))
++n_callee () {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_callee () [[arm::streaming_compatible]] {}
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_callee () {}
++
++inline void __attribute__((always_inline))
++sc_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++inline void __attribute__((always_inline))
++s_asm_callee () [[arm::streaming]] { asm (""); }
++
++inline void __attribute__((always_inline))
++n_asm_callee () { asm (""); } // { dg-error "inlining failed" }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++sc_ls_asm_callee () [[arm::streaming_compatible]] { asm (""); }
++
++[[arm::locally_streaming]] inline void __attribute__((always_inline))
++n_ls_asm_callee () { asm (""); }
++
++[[arm::locally_streaming]] void
++n_ls_caller ()
++{
++  sc_callee ();
++  s_callee ();
++  n_callee ();
++  sc_ls_callee ();
++  n_ls_callee ();
++
++  sc_asm_callee ();
++  s_asm_callee ();
++  n_asm_callee ();
++  sc_ls_asm_callee ();
++  n_ls_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_6.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_6.c
+new file mode 100644
+index 000000000..a5eb399f1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_6.c
+@@ -0,0 +1,31 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++shared_callee () [[arm::inout("za")]] {}
++
++[[arm::new("za")]] inline void __attribute__((always_inline))
++new_callee () {} // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++normal_callee () {}
++
++inline void __attribute__((always_inline))
++shared_asm_callee () [[arm::inout("za")]] { asm volatile ("" ::: "za"); }
++
++[[arm::new("za")]] inline void __attribute__((always_inline))
++new_asm_callee () { asm volatile ("" ::: "za"); } // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++normal_asm_callee () { asm volatile ("" ::: "za"); } // { dg-error "inlining failed" }
++
++void
++shared_caller () [[arm::inout("za")]]
++{
++  shared_callee ();
++  new_callee ();
++  normal_callee ();
++
++  shared_asm_callee ();
++  new_asm_callee ();
++  normal_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_7.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_7.c
+new file mode 100644
+index 000000000..0f046283f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_7.c
+@@ -0,0 +1,31 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++shared_callee () [[arm::inout("za")]] {}
++
++[[arm::new("za")]] inline void __attribute__((always_inline))
++new_callee () {} // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++normal_callee () {}
++
++inline void __attribute__((always_inline))
++shared_asm_callee () [[arm::inout("za")]] { asm volatile ("" ::: "za"); }
++
++[[arm::new("za")]] inline void __attribute__((always_inline))
++new_asm_callee () { asm volatile ("" ::: "za"); } // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++normal_asm_callee () { asm volatile ("" ::: "za"); } // { dg-error "inlining failed" }
++
++[[arm::new("za")]] void
++new_caller ()
++{
++  shared_callee ();
++  new_callee ();
++  normal_callee ();
++
++  shared_asm_callee ();
++  new_asm_callee ();
++  normal_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_8.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_8.c
+new file mode 100644
+index 000000000..fd8a3a61e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_8.c
+@@ -0,0 +1,31 @@
++/* { dg-options "" } */
++
++inline void __attribute__((always_inline))
++shared_callee () [[arm::inout("za")]] {} // { dg-error "inlining failed" }
++
++[[arm::new("za")]] inline void __attribute__((always_inline))
++new_callee () {} // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++normal_callee () {}
++
++inline void __attribute__((always_inline))
++shared_asm_callee () [[arm::inout("za")]] { asm volatile ("" ::: "za"); } // { dg-error "inlining failed" }
++
++[[arm::new("za")]] inline void __attribute__((always_inline))
++new_asm_callee () { asm volatile ("" ::: "za"); } // { dg-error "inlining failed" }
++
++inline void __attribute__((always_inline))
++normal_asm_callee () { asm volatile ("" ::: "za"); }
++
++void
++normal_caller ()
++{
++  shared_callee ();
++  new_callee ();
++  normal_callee ();
++
++  shared_asm_callee ();
++  new_asm_callee ();
++  normal_asm_callee ();
++}
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/inlining_9.c b/gcc/testsuite/gcc.target/aarch64/sme/inlining_9.c
+new file mode 100644
+index 000000000..91520e378
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/inlining_9.c
+@@ -0,0 +1,55 @@
++/* { dg-options "" } */
++
++#include 
++#include 
++
++uint8x16_t *neon;
++svint64_t *sve;
++int64_t *ptr;
++
++inline void __attribute__((always_inline))
++call_vadd ()
++{
++  neon[4] = vaddq_u8 (neon[5], neon[6]);
++}
++
++inline void __attribute__((always_inline))
++call_vbsl ()
++{
++  neon[0] = vbslq_u8 (neon[1], neon[2], neon[3]);
++}
++
++inline void __attribute__((always_inline))
++call_svadd ()
++{
++  *sve = svadd_x (svptrue_b8 (), *sve, 1);
++}
++
++inline void __attribute__((always_inline))
++call_svld1_gather ()
++{
++  *sve = svld1_gather_offset (svptrue_b8 (), ptr, *sve);
++}
++
++inline void __attribute__((always_inline))
++call_svzero () [[arm::inout("za")]]
++{
++  svzero_za ();
++}
++
++inline void __attribute__((always_inline))
++call_svst1_za () [[arm::streaming, arm::inout("za")]] // { dg-error "inlining failed" }
++{
++  svst1_ver_za64 (0, 0, svptrue_b8 (), ptr);
++}
++
++void
++n_caller () [[arm::inout("za")]]
++{
++  call_vadd ();
++  call_vbsl ();
++  call_svadd ();
++  call_svld1_gather ();
++  call_svzero ();
++  call_svst1_za ();
++}
+-- 
+2.33.0
+
diff --git a/0215-Backport-SME-aarch64-Update-sibcall-handling-for-SME.patch b/0215-Backport-SME-aarch64-Update-sibcall-handling-for-SME.patch
new file mode 100644
index 0000000..aa57f9c
--- /dev/null
+++ b/0215-Backport-SME-aarch64-Update-sibcall-handling-for-SME.patch
@@ -0,0 +1,424 @@
+From 08b6cbe756ede25b16b8e9ff9ee32f76c4f8430f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 10:11:30 +0000
+Subject: [PATCH 116/157] [Backport][SME] aarch64: Update sibcall handling for
+ SME
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0e7fee57c00ae17611651e0b057dc03b6e276b82
+
+We only support tail calls between functions with the same PSTATE.ZA
+setting ("private-ZA" to "private-ZA" and "shared-ZA" to "shared-ZA").
+
+Only a normal non-streaming function can tail-call another non-streaming
+function, and only a streaming function can tail-call another streaming
+function.  Any function can tail-call a streaming-compatible function.
+
+gcc/
+	* config/aarch64/aarch64.cc (aarch64_function_ok_for_sibcall):
+	Enforce PSTATE.SM and PSTATE.ZA restrictions.
+	(aarch64_expand_epilogue): Save and restore the arguments
+	to a sibcall around any change to PSTATE.SM.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/sibcall_1.c: New test.
+	* gcc.target/aarch64/sme/sibcall_2.c: Likewise.
+	* gcc.target/aarch64/sme/sibcall_3.c: Likewise.
+	* gcc.target/aarch64/sme/sibcall_4.c: Likewise.
+	* gcc.target/aarch64/sme/sibcall_5.c: Likewise.
+	* gcc.target/aarch64/sme/sibcall_6.c: Likewise.
+	* gcc.target/aarch64/sme/sibcall_7.c: Likewise.
+	* gcc.target/aarch64/sme/sibcall_8.c: Likewise.
+---
+ gcc/config/aarch64/aarch64.cc                 |  9 +++-
+ .../gcc.target/aarch64/sme/sibcall_1.c        | 45 +++++++++++++++++++
+ .../gcc.target/aarch64/sme/sibcall_2.c        | 45 +++++++++++++++++++
+ .../gcc.target/aarch64/sme/sibcall_3.c        | 45 +++++++++++++++++++
+ .../gcc.target/aarch64/sme/sibcall_4.c        | 45 +++++++++++++++++++
+ .../gcc.target/aarch64/sme/sibcall_5.c        | 45 +++++++++++++++++++
+ .../gcc.target/aarch64/sme/sibcall_6.c        | 26 +++++++++++
+ .../gcc.target/aarch64/sme/sibcall_7.c        | 26 +++++++++++
+ .../gcc.target/aarch64/sme/sibcall_8.c        | 19 ++++++++
+ 9 files changed, 304 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_1.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_2.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_3.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_4.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_5.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_6.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_7.c
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sme/sibcall_8.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index eab94d5c2..b8e540b6e 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -8660,6 +8660,11 @@ aarch64_function_ok_for_sibcall (tree, tree exp)
+   if (crtl->abi->id () != expr_callee_abi (exp).id ())
+     return false;
+ 
++  tree fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
++  if (aarch64_fntype_pstate_sm (fntype) & ~aarch64_cfun_incoming_pstate_sm ())
++    return false;
++  if (aarch64_fntype_pstate_za (fntype) != aarch64_cfun_incoming_pstate_za ())
++    return false;
+   return true;
+ }
+ 
+@@ -11923,7 +11928,9 @@ aarch64_expand_epilogue (rtx_call_insn *sibcall)
+ 	guard_label = aarch64_guard_switch_pstate_sm (IP0_REGNUM,
+ 						      aarch64_isa_flags);
+       aarch64_sme_mode_switch_regs return_switch;
+-      if (crtl->return_rtx && REG_P (crtl->return_rtx))
++      if (sibcall)
++	return_switch.add_call_args (sibcall);
++      else if (crtl->return_rtx && REG_P (crtl->return_rtx))
+ 	return_switch.add_reg (GET_MODE (crtl->return_rtx),
+ 			       REGNO (crtl->return_rtx));
+       return_switch.emit_prologue ();
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_1.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_1.c
+new file mode 100644
+index 000000000..c7530de5c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_1.c
+@@ -0,0 +1,45 @@
++/* { dg-options "-O2" } */
++
++void sc_callee () [[arm::streaming_compatible]];
++void s_callee () [[arm::streaming]];
++void n_callee ();
++
++[[arm::locally_streaming]] __attribute__((noipa)) void
++sc_ls_callee () [[arm::streaming_compatible]] {}
++[[arm::locally_streaming]] __attribute__((noipa)) void
++n_ls_callee () {}
++
++void
++sc_to_sc () [[arm::streaming_compatible]]
++{
++  sc_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_callee} } } */
++
++void
++sc_to_s () [[arm::streaming_compatible]]
++{
++  s_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\ts_callee} } } */
++
++void
++sc_to_n () [[arm::streaming_compatible]]
++{
++  n_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tn_callee} } } */
++
++void
++sc_to_sc_ls () [[arm::streaming_compatible]]
++{
++  sc_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_ls_callee} } } */
++
++void
++sc_to_n_ls () [[arm::streaming_compatible]]
++{
++  n_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tn_ls_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_2.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_2.c
+new file mode 100644
+index 000000000..8d1c8a9f9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_2.c
+@@ -0,0 +1,45 @@
++/* { dg-options "-O2" } */
++
++void sc_callee () [[arm::streaming_compatible]];
++void s_callee () [[arm::streaming]];
++void n_callee ();
++
++[[arm::locally_streaming]] __attribute__((noipa)) void
++sc_ls_callee () [[arm::streaming_compatible]] {}
++[[arm::locally_streaming]] __attribute__((noipa)) void
++n_ls_callee () {}
++
++void
++s_to_sc () [[arm::streaming]]
++{
++  sc_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_callee} } } */
++
++void
++s_to_s () [[arm::streaming]]
++{
++  s_callee ();
++}
++/* { dg-final { scan-assembler {\tb\ts_callee} } } */
++
++void
++s_to_n () [[arm::streaming]]
++{
++  n_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tn_callee} } } */
++
++void
++s_to_sc_ls () [[arm::streaming]]
++{
++  sc_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_ls_callee} } } */
++
++void
++s_to_n_ls () [[arm::streaming]]
++{
++  n_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tn_ls_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_3.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_3.c
+new file mode 100644
+index 000000000..2ae937fc5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_3.c
+@@ -0,0 +1,45 @@
++/* { dg-options "-O2" } */
++
++void sc_callee () [[arm::streaming_compatible]];
++void s_callee () [[arm::streaming]];
++void n_callee ();
++
++[[arm::locally_streaming]] __attribute__((noipa)) void
++sc_ls_callee () [[arm::streaming_compatible]] {}
++[[arm::locally_streaming]] __attribute__((noipa)) void
++n_ls_callee () {}
++
++void
++n_to_sc ()
++{
++  sc_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_callee} } } */
++
++void
++n_to_s ()
++{
++  s_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\ts_callee} } } */
++
++void
++n_to_n ()
++{
++  n_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tn_callee} } } */
++
++void
++n_to_sc_ls ()
++{
++  sc_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_ls_callee} } } */
++
++void
++n_to_n_ls ()
++{
++  n_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tn_ls_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_4.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_4.c
+new file mode 100644
+index 000000000..6935a1bd7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_4.c
+@@ -0,0 +1,45 @@
++/* { dg-options "-O2" } */
++
++void sc_callee () [[arm::streaming_compatible]];
++void s_callee () [[arm::streaming]];
++void n_callee ();
++
++[[arm::locally_streaming]] __attribute__((noipa)) void
++sc_ls_callee () [[arm::streaming_compatible]] {}
++[[arm::locally_streaming]] __attribute__((noipa)) void
++n_ls_callee () {}
++
++[[arm::locally_streaming]] void
++sc_to_sc () [[arm::streaming_compatible]]
++{
++  sc_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_callee} } } */
++
++[[arm::locally_streaming]] void
++sc_to_s () [[arm::streaming_compatible]]
++{
++  s_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\ts_callee} } } */
++
++[[arm::locally_streaming]] void
++sc_to_n () [[arm::streaming_compatible]]
++{
++  n_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tn_callee} } } */
++
++[[arm::locally_streaming]] void
++sc_to_sc_ls () [[arm::streaming_compatible]]
++{
++  sc_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_ls_callee} } } */
++
++[[arm::locally_streaming]] void
++sc_to_n_ls () [[arm::streaming_compatible]]
++{
++  n_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tn_ls_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_5.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_5.c
+new file mode 100644
+index 000000000..7aaf58dfa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_5.c
+@@ -0,0 +1,45 @@
++/* { dg-options "-O2" } */
++
++void sc_callee () [[arm::streaming_compatible]];
++void s_callee () [[arm::streaming]];
++void n_callee ();
++
++[[arm::locally_streaming]] __attribute__((noipa)) void
++sc_ls_callee () [[arm::streaming_compatible]] {}
++[[arm::locally_streaming]] __attribute__((noipa)) void
++n_ls_callee () {}
++
++[[arm::locally_streaming]] void
++n_to_sc ()
++{
++  sc_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_callee} } } */
++
++[[arm::locally_streaming]] void
++n_to_s ()
++{
++  s_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\ts_callee} } } */
++
++[[arm::locally_streaming]] void
++n_to_n ()
++{
++  n_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tn_callee} } } */
++
++[[arm::locally_streaming]] void
++n_to_sc_ls ()
++{
++  sc_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tsc_ls_callee} } } */
++
++[[arm::locally_streaming]] void
++n_to_n_ls ()
++{
++  n_ls_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tn_ls_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_6.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_6.c
+new file mode 100644
+index 000000000..e568edb17
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_6.c
+@@ -0,0 +1,26 @@
++/* { dg-options "-O2" } */
++
++void shared_callee () [[arm::inout("za")]];
++[[arm::new("za")]] __attribute__((noipa)) void new_callee () {}
++void normal_callee ();
++
++void
++shared_to_shared () [[arm::inout("za")]]
++{
++  shared_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tshared_callee} } } */
++
++void
++shared_to_new () [[arm::inout("za")]]
++{
++  new_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tnew_callee} } } */
++
++void
++shared_to_normal () [[arm::inout("za")]]
++{
++  normal_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tnormal_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_7.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_7.c
+new file mode 100644
+index 000000000..a5f576d20
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_7.c
+@@ -0,0 +1,26 @@
++/* { dg-options "-O2" } */
++
++void shared_callee () [[arm::inout("za")]];
++[[arm::new("za")]] __attribute__((noipa)) void new_callee () {}
++void normal_callee ();
++
++[[arm::new("za")]] void
++new_to_shared ()
++{
++  shared_callee ();
++}
++/* { dg-final { scan-assembler {\tbl\tshared_callee} } } */
++
++[[arm::new("za")]] void
++new_to_new ()
++{
++  new_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tnew_callee} } } */
++
++[[arm::new("za")]] void
++new_to_normal ()
++{
++  normal_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tnormal_callee} } } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/sibcall_8.c b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_8.c
+new file mode 100644
+index 000000000..33370f7a8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sme/sibcall_8.c
+@@ -0,0 +1,19 @@
++/* { dg-options "-O2" } */
++
++void shared_callee () [[arm::inout("za")]];
++[[arm::new("za")]] __attribute__((noipa)) void new_callee () {}
++void normal_callee ();
++
++void
++normal_to_new ()
++{
++  new_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tnew_callee} } } */
++
++void
++normal_to_normal ()
++{
++  normal_callee ();
++}
++/* { dg-final { scan-assembler {\tb\tnormal_callee} } } */
+-- 
+2.33.0
+
diff --git a/0216-Backport-SME-libgcc-aarch64-Configure-check-for-.var.patch b/0216-Backport-SME-libgcc-aarch64-Configure-check-for-.var.patch
new file mode 100644
index 0000000..6e8467e
--- /dev/null
+++ b/0216-Backport-SME-libgcc-aarch64-Configure-check-for-.var.patch
@@ -0,0 +1,117 @@
+From e0da78a258a34c26488b7ae623f9ae8727c2b264 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy 
+Date: Mon, 14 Nov 2022 17:14:18 +0000
+Subject: [PATCH 117/157] [Backport][SME] libgcc: aarch64: Configure check for
+ .variant_pcs support
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=3ebb591c65b4fbe0cddd23ebc0ca2d9f7aef2cec
+
+Ideally SME support routines in libgcc are marked as variant PCS symbols
+so check if as supports the directive.
+
+libgcc/ChangeLog:
+
+	* config.in: Undef HAVE_AS_VARIANT_PCS.
+	* configure: Regenerate.
+	* configure.ac: Check for .variant_pcs.
+---
+ libgcc/config.in    |  3 +++
+ libgcc/configure    | 39 +++++++++++++++++++++++++++++++++++++++
+ libgcc/configure.ac | 17 +++++++++++++++++
+ 3 files changed, 59 insertions(+)
+
+diff --git a/libgcc/config.in b/libgcc/config.in
+index f93c64a00..5dd96cdf6 100644
+--- a/libgcc/config.in
++++ b/libgcc/config.in
+@@ -13,6 +13,9 @@
+ /* Define to 1 if the assembler supports LSE. */
+ #undef HAVE_AS_LSE
+ 
++/* Define to 1 if the assembler supports .variant_pcs. */
++#undef HAVE_AS_VARIANT_PCS
++
+ /* Define to 1 if the target assembler supports thread-local storage. */
+ #undef HAVE_CC_TLS
+ 
+diff --git a/libgcc/configure b/libgcc/configure
+index 1f9b2ac57..afe02b303 100755
+--- a/libgcc/configure
++++ b/libgcc/configure
+@@ -5619,6 +5619,45 @@ $as_echo "#define HAVE_AS_LSE 1" >>confdefs.h
+   ;;
+ esac
+ 
++
++
++case "${target}" in
++aarch64*-*-*)
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if as supports .variant_pcs" >&5
++$as_echo_n "checking if as supports .variant_pcs... " >&6; }
++if ${libgcc_cv_as_variant_pcs+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++
++    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++int
++main ()
++{
++asm (".variant_pcs foobar");
++  ;
++  return 0;
++}
++_ACEOF
++if ac_fn_c_try_compile "$LINENO"; then :
++  libgcc_cv_as_variant_pcs=yes
++else
++  libgcc_cv_as_variant_pcs=no
++fi
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_as_variant_pcs" >&5
++$as_echo "$libgcc_cv_as_variant_pcs" >&6; }
++  if test x$libgcc_cv_as_variant_pcs = xyes; then
++
++$as_echo "#define HAVE_AS_VARIANT_PCS 1" >>confdefs.h
++
++  fi
++  ;;
++esac
++
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" >&5
+ $as_echo_n "checking for init priority support... " >&6; }
+ if ${libgcc_cv_init_priority+:} false; then :
+diff --git a/libgcc/configure.ac b/libgcc/configure.ac
+index 2fc9d5d7c..abc398c91 100644
+--- a/libgcc/configure.ac
++++ b/libgcc/configure.ac
+@@ -648,6 +648,23 @@ changequote([,])dnl
+ esac])
+ LIBGCC_CHECK_AS_LSE
+ 
++dnl Check if as supports .variant_pcs.
++AC_DEFUN([LIBGCC_CHECK_AS_VARIANT_PCS], [
++case "${target}" in
++aarch64*-*-*)
++  AC_CACHE_CHECK([if as supports .variant_pcs], libgcc_cv_as_variant_pcs, [
++    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
++      [[asm (".variant_pcs foobar");]])],
++      [libgcc_cv_as_variant_pcs=yes], [libgcc_cv_as_variant_pcs=no])
++  ])
++  if test x$libgcc_cv_as_variant_pcs = xyes; then
++    AC_DEFINE(HAVE_AS_VARIANT_PCS, 1,
++	      [Define to 1 if the assembler supports .variant_pcs.])
++  fi
++  ;;
++esac])
++LIBGCC_CHECK_AS_VARIANT_PCS
++
+ dnl Check if as supports RTM instructions.
+ AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
+-- 
+2.33.0
+
diff --git a/0217-Backport-SME-libgcc-aarch64-Configure-check-for-__ge.patch b/0217-Backport-SME-libgcc-aarch64-Configure-check-for-__ge.patch
new file mode 100644
index 0000000..07c1417
--- /dev/null
+++ b/0217-Backport-SME-libgcc-aarch64-Configure-check-for-__ge.patch
@@ -0,0 +1,117 @@
+From 66d4035958e1dee2d16f9290004921674eb492b3 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy 
+Date: Mon, 4 Dec 2023 10:52:52 +0000
+Subject: [PATCH 118/157] [Backport][SME] libgcc: aarch64: Configure check for
+ __getauxval
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=dbbfb52b0e9c66ee9d05b8fd17c4f44655e48463
+
+Add configure check for the __getauxval ABI symbol, which is always
+available on aarch64 glibc, and may be available on other linux C
+runtimes. For now only enabled on glibc, others have to override it
+
+  target_configargs=libgcc_cv_have___getauxval=yes
+
+This is deliberately obscure as it should be auto detected, ideally
+via a feature test macro in unistd.h (link time detection is not
+possible since the libc may not be installed at libgcc build time),
+but currently there is no such feature test mechanism.
+
+Without __getauxval, libgcc cannot do runtime CPU feature detection
+and has to assume only the build time known features are available.
+
+libgcc/ChangeLog:
+
+	* config.in: Undef HAVE___GETAUXVAL.
+	* configure: Regenerate.
+	* configure.ac: Check for __getauxval.
+---
+ libgcc/config.in    |  3 +++
+ libgcc/configure    | 26 ++++++++++++++++++++++++++
+ libgcc/configure.ac | 19 +++++++++++++++++++
+ 3 files changed, 48 insertions(+)
+
+diff --git a/libgcc/config.in b/libgcc/config.in
+index 5dd96cdf6..441d4d39b 100644
+--- a/libgcc/config.in
++++ b/libgcc/config.in
+@@ -16,6 +16,9 @@
+ /* Define to 1 if the assembler supports .variant_pcs. */
+ #undef HAVE_AS_VARIANT_PCS
+ 
++/* Define to 1 if __getauxval is available. */
++#undef HAVE___GETAUXVAL
++
+ /* Define to 1 if the target assembler supports thread-local storage. */
+ #undef HAVE_CC_TLS
+ 
+diff --git a/libgcc/configure b/libgcc/configure
+index afe02b303..a874ef57e 100755
+--- a/libgcc/configure
++++ b/libgcc/configure
+@@ -5658,6 +5658,32 @@ $as_echo "#define HAVE_AS_VARIANT_PCS 1" >>confdefs.h
+   ;;
+ esac
+ 
++# Check __getauxval ABI symbol for CPU feature detection.
++case ${target} in
++aarch64*-linux-*)
++  # No link check because the libc may not be present.
++  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __getauxval" >&5
++$as_echo_n "checking for __getauxval... " >&6; }
++if ${libgcc_cv_have___getauxval+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  case ${target} in
++		  *-linux-gnu*)
++		    libgcc_cv_have___getauxval=yes
++		    ;;
++		  *)
++		    libgcc_cv_have___getauxval=no
++		  esac
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_have___getauxval" >&5
++$as_echo "$libgcc_cv_have___getauxval" >&6; }
++  if test x$libgcc_cv_have___getauxval = xyes; then
++
++$as_echo "#define HAVE___GETAUXVAL 1" >>confdefs.h
++
++  fi
++esac
++
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" >&5
+ $as_echo_n "checking for init priority support... " >&6; }
+ if ${libgcc_cv_init_priority+:} false; then :
+diff --git a/libgcc/configure.ac b/libgcc/configure.ac
+index abc398c91..64b45ae14 100644
+--- a/libgcc/configure.ac
++++ b/libgcc/configure.ac
+@@ -665,6 +665,25 @@ aarch64*-*-*)
+ esac])
+ LIBGCC_CHECK_AS_VARIANT_PCS
+ 
++# Check __getauxval ABI symbol for CPU feature detection.
++case ${target} in
++aarch64*-linux-*)
++  # No link check because the libc may not be present.
++  AC_CACHE_CHECK([for __getauxval],
++		 [libgcc_cv_have___getauxval],
++		 [case ${target} in
++		  *-linux-gnu*)
++		    libgcc_cv_have___getauxval=yes
++		    ;;
++		  *)
++		    libgcc_cv_have___getauxval=no
++		  esac])
++  if test x$libgcc_cv_have___getauxval = xyes; then
++    AC_DEFINE(HAVE___GETAUXVAL, 1,
++	      [Define to 1 if __getauxval is available.])
++  fi
++esac
++
+ dnl Check if as supports RTM instructions.
+ AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
+-- 
+2.33.0
+
diff --git a/0218-Backport-SME-libgcc-aarch64-Add-SME-runtime-support.patch b/0218-Backport-SME-libgcc-aarch64-Add-SME-runtime-support.patch
new file mode 100644
index 0000000..30b85d9
--- /dev/null
+++ b/0218-Backport-SME-libgcc-aarch64-Add-SME-runtime-support.patch
@@ -0,0 +1,627 @@
+From 1e111ac2d71c5469dc526559de009542acaeb16f Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy 
+Date: Tue, 15 Nov 2022 14:08:55 +0000
+Subject: [PATCH 119/157] [Backport][SME] libgcc: aarch64: Add SME runtime
+ support
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=328c17af772207cb03740809c05ba2c3abfb86be
+
+The call ABI for SME (Scalable Matrix Extension) requires a number of
+helper routines which are added to libgcc so they are tied to the
+compiler version instead of the libc version. See
+https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#sme-support-routines
+
+The routines are in shared libgcc and static libgcc eh, even though
+they are not related to exception handling.  This is to avoid linking
+a copy of the routines into dynamic linked binaries, because TPIDR2_EL0
+block can be extended in the future which is better to handle in a
+single place per process.
+
+The support routines have to decide if SME is accessible or not. Linux
+tells userspace if SME is accessible via AT_HWCAP2, otherwise a new
+__aarch64_sme_accessible symbol was introduced that a libc can define.
+Due to libgcc and libc build order, the symbol availability cannot be
+checked so for __aarch64_sme_accessible an unistd.h feature test macro
+is used while such detection mechanism is not available for __getauxval
+so we rely on configure checks based on the target triplet.
+
+Asm helper code is added to make writing the routines easier.
+
+libgcc/ChangeLog:
+
+	* config/aarch64/t-aarch64: Add sources to the build.
+	* config/aarch64/__aarch64_have_sme.c: New file.
+	* config/aarch64/__arm_sme_state.S: New file.
+	* config/aarch64/__arm_tpidr2_restore.S: New file.
+	* config/aarch64/__arm_tpidr2_save.S: New file.
+	* config/aarch64/__arm_za_disable.S: New file.
+	* config/aarch64/aarch64-asm.h: New file.
+	* config/aarch64/libgcc-sme.ver: New file.
+---
+ libgcc/config/aarch64/__aarch64_have_sme.c   |  75 ++++++++++++++
+ libgcc/config/aarch64/__arm_sme_state.S      |  55 ++++++++++
+ libgcc/config/aarch64/__arm_tpidr2_restore.S |  89 ++++++++++++++++
+ libgcc/config/aarch64/__arm_tpidr2_save.S    | 101 +++++++++++++++++++
+ libgcc/config/aarch64/__arm_za_disable.S     |  65 ++++++++++++
+ libgcc/config/aarch64/aarch64-asm.h          |  98 ++++++++++++++++++
+ libgcc/config/aarch64/libgcc-sme.ver         |  24 +++++
+ libgcc/config/aarch64/t-aarch64              |  10 ++
+ 8 files changed, 517 insertions(+)
+ create mode 100644 libgcc/config/aarch64/__aarch64_have_sme.c
+ create mode 100644 libgcc/config/aarch64/__arm_sme_state.S
+ create mode 100644 libgcc/config/aarch64/__arm_tpidr2_restore.S
+ create mode 100644 libgcc/config/aarch64/__arm_tpidr2_save.S
+ create mode 100644 libgcc/config/aarch64/__arm_za_disable.S
+ create mode 100644 libgcc/config/aarch64/aarch64-asm.h
+ create mode 100644 libgcc/config/aarch64/libgcc-sme.ver
+
+diff --git a/libgcc/config/aarch64/__aarch64_have_sme.c b/libgcc/config/aarch64/__aarch64_have_sme.c
+new file mode 100644
+index 000000000..5e6492462
+--- /dev/null
++++ b/libgcc/config/aarch64/__aarch64_have_sme.c
+@@ -0,0 +1,75 @@
++/* Initializer for SME support.
++   Copyright (C) 2023 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
++   .  */
++
++#include "auto-target.h"
++
++#ifndef inhibit_libc
++/* For libc feature test macros.  */
++# include 
++#endif
++
++#if __ARM_FEATURE_SME
++/* Avoid runtime SME detection if libgcc is built with SME.  */
++# define HAVE_SME_CONST const
++# define HAVE_SME_VALUE 1
++#elif HAVE___GETAUXVAL
++/* SME access detection on Linux.  */
++# define HAVE_SME_CONST
++# define HAVE_SME_VALUE 0
++# define HAVE_SME_CTOR sme_accessible ()
++
++# define AT_HWCAP2	26
++# define HWCAP2_SME	(1 << 23)
++unsigned long int __getauxval (unsigned long int);
++
++static _Bool
++sme_accessible (void)
++{
++  unsigned long hwcap2 = __getauxval (AT_HWCAP2);
++  return (hwcap2 & HWCAP2_SME) != 0;
++}
++#elif __LIBC___AARCH64_SME_ACCESSIBLE
++/* Alternative SME access detection.  */
++# define HAVE_SME_CONST
++# define HAVE_SME_VALUE 0
++# define HAVE_SME_CTOR __aarch64_sme_accessible ()
++_Bool __aarch64_sme_accessible (void);
++#else
++# define HAVE_SME_CONST const
++# define HAVE_SME_VALUE 0
++#endif
++
++/* Define the symbol gating SME support in libgcc.  */
++HAVE_SME_CONST _Bool __aarch64_have_sme
++  __attribute__((visibility("hidden"), nocommon)) = HAVE_SME_VALUE;
++
++#ifdef HAVE_SME_CTOR
++/* Use a higher priority to ensure it runs before user constructors
++   with priority 100. */
++static void __attribute__((constructor (90)))
++init_have_sme (void)
++{
++  __aarch64_have_sme = HAVE_SME_CTOR;
++}
++#endif
+diff --git a/libgcc/config/aarch64/__arm_sme_state.S b/libgcc/config/aarch64/__arm_sme_state.S
+new file mode 100644
+index 000000000..c4e16cac0
+--- /dev/null
++++ b/libgcc/config/aarch64/__arm_sme_state.S
+@@ -0,0 +1,55 @@
++/* Support routine for SME.
++   Copyright (C) 2023 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
++   .  */
++
++#include "aarch64-asm.h"
++
++/* Query SME state.  Call ABI:
++   - Private ZA, streaming-compatible.
++   - x2-x15, x19-x29, sp and fp regs are call preserved.
++   - Takes no argument.
++   - Returns SME state in x0 and TPIDR2_EL0 in x1.  */
++
++.hidden __aarch64_have_sme
++
++variant_pcs (__arm_sme_state)
++
++ENTRY (__arm_sme_state)
++	/* Check if SME is available.  */
++	adrp	x1, __aarch64_have_sme
++	ldrb	w1, [x1, :lo12:__aarch64_have_sme]
++	cbz	w1, L(nosme)
++
++	/* Expose the bottom 2 bits of svcr (SM, ZA) in x0 and set the
++	   top 2 bits indicating that SME and TPIDR2_EL0 are available.  */
++	.inst	0xd53b4240  /* mrs	x0, svcr  */
++	.inst	0xd53bd0a1  /* mrs	x1, tpidr2_el0  */
++	and	x0, x0, 3
++	orr	x0, x0, 0xc000000000000000
++	ret
++
++L(nosme):
++	mov	x0, 0
++	mov	x1, 0
++	ret
++END (__arm_sme_state)
+diff --git a/libgcc/config/aarch64/__arm_tpidr2_restore.S b/libgcc/config/aarch64/__arm_tpidr2_restore.S
+new file mode 100644
+index 000000000..4569d04a2
+--- /dev/null
++++ b/libgcc/config/aarch64/__arm_tpidr2_restore.S
+@@ -0,0 +1,89 @@
++/* Support routine for SME.
++   Copyright (C) 2023 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
++   .  */
++
++#include "aarch64-asm.h"
++
++/* Used for lazy ZA restore.  Call ABI:
++   - Shared ZA, streaming-compatible.
++   - x0 is a pointer to a TPIDR2 block.
++   - x0-x13, x19-x29, sp and fp regs are call preserved.
++   - Does not return a value.
++   - Can abort on failure (then registers are not preserved).  */
++
++variant_pcs (__arm_tpidr2_restore)
++
++ENTRY (__arm_tpidr2_restore)
++	.inst	0xd53bd0ae  /* mrs	x14, tpidr2_el0  */
++	cbnz	x14, L(fail)
++
++	/* check reserved bytes.  */
++	ldrh	w15, [x0, 10]
++	ldr	w16, [x0, 12]
++	orr	w15, w15, w16
++	cbnz	w15, L(fail)
++
++	ldr	x16, [x0]
++	cbz	x16, L(end)
++	ldrh	w17, [x0, 8]
++	cbz	w17, L(end)
++
++	/* x0: blk, x14: 0, x15: 0,
++	   x16: za_save_buffer, x17: num_za_save_slices.  */
++
++L(restore_loop):
++	.inst	0xe1006200  /* ldr	za[w15, 0], [x16]  */
++	.inst	0xe1006201  /* ldr	za[w15, 1], [x16, 1, mul vl]  */
++	.inst	0xe1006202  /* ldr	za[w15, 2], [x16, 2, mul vl]  */
++	.inst	0xe1006203  /* ldr	za[w15, 3], [x16, 3, mul vl]  */
++	.inst	0xe1006204  /* ldr	za[w15, 4], [x16, 4, mul vl]  */
++	.inst	0xe1006205  /* ldr	za[w15, 5], [x16, 5, mul vl]  */
++	.inst	0xe1006206  /* ldr	za[w15, 6], [x16, 6, mul vl]  */
++	.inst	0xe1006207  /* ldr	za[w15, 7], [x16, 7, mul vl]  */
++	.inst	0xe1006208  /* ldr	za[w15, 8], [x16, 8, mul vl]  */
++	.inst	0xe1006209  /* ldr	za[w15, 9], [x16, 9, mul vl]  */
++	.inst	0xe100620a  /* ldr	za[w15, 10], [x16, 10, mul vl]  */
++	.inst	0xe100620b  /* ldr	za[w15, 11], [x16, 11, mul vl]  */
++	.inst	0xe100620c  /* ldr	za[w15, 12], [x16, 12, mul vl]  */
++	.inst	0xe100620d  /* ldr	za[w15, 13], [x16, 13, mul vl]  */
++	.inst	0xe100620e  /* ldr	za[w15, 14], [x16, 14, mul vl]  */
++	.inst	0xe100620f  /* ldr	za[w15, 15], [x16, 15, mul vl]  */
++	add	w15, w15, 16
++	.inst	0x04305a10  /* addsvl	x16, x16, 16  */
++	cmp	w17, w15
++	bhi	L(restore_loop)
++L(end):
++	ret
++L(fail):
++	PACIASP
++	stp	x29, x30, [sp, -32]!
++	.cfi_adjust_cfa_offset 32
++	.cfi_rel_offset x29, 0
++	.cfi_rel_offset x30, 8
++	mov	x29, sp
++	.inst	0x04e0e3f0  /* cntd	x16  */
++	str	x16, [sp, 16]
++	.cfi_rel_offset 46, 16
++	.inst	0xd503467f  /* smstop  */
++	bl	abort
++END (__arm_tpidr2_restore)
+diff --git a/libgcc/config/aarch64/__arm_tpidr2_save.S b/libgcc/config/aarch64/__arm_tpidr2_save.S
+new file mode 100644
+index 000000000..879cf7980
+--- /dev/null
++++ b/libgcc/config/aarch64/__arm_tpidr2_save.S
+@@ -0,0 +1,101 @@
++/* Support routine for SME.
++   Copyright (C) 2023 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
++   .  */
++
++#include "aarch64-asm.h"
++
++/* Used for lazy ZA save.  Call ABI:
++   - Private ZA, streaming-compatible.
++   - x0-x13, x19-x29, sp and fp regs are call preserved.
++   - Takes no argument.
++   - Does not return a value.
++   - Can abort on failure (then registers are not preserved).  */
++
++.hidden __aarch64_have_sme
++
++variant_pcs (__arm_tpidr2_save)
++
++ENTRY (__arm_tpidr2_save)
++	/* Check if SME is available.  */
++	adrp	x14, __aarch64_have_sme
++	ldrb	w14, [x14, :lo12:__aarch64_have_sme]
++	cbz	w14, L(end)
++
++	.inst	0xd53bd0ae  /* mrs	x14, tpidr2_el0  */
++	cbz	x14, L(end)
++
++	/* check reserved bytes.  */
++	ldrh	w15, [x14, 10]
++	ldr	w16, [x14, 12]
++	orr	w15, w15, w16
++	cbnz	w15, L(fail)
++
++	ldr	x16, [x14]
++	cbz	x16, L(end)
++	ldrh	w17, [x14, 8]
++	cbz	w17, L(end)
++
++	/* x14: tpidr2, x15: 0,
++	   x16: za_save_buffer, x17: num_za_save_slices.  */
++
++L(save_loop):
++	.inst	0xe1206200  /* str	za[w15, 0], [x16]  */
++	.inst	0xe1206201  /* str	za[w15, 1], [x16, 1, mul vl] */
++	.inst	0xe1206202  /* str	za[w15, 2], [x16, 2, mul vl] */
++	.inst	0xe1206203  /* str	za[w15, 3], [x16, 3, mul vl] */
++	.inst	0xe1206204  /* str	za[w15, 4], [x16, 4, mul vl] */
++	.inst	0xe1206205  /* str	za[w15, 5], [x16, 5, mul vl] */
++	.inst	0xe1206206  /* str	za[w15, 6], [x16, 6, mul vl] */
++	.inst	0xe1206207  /* str	za[w15, 7], [x16, 7, mul vl] */
++	.inst	0xe1206208  /* str	za[w15, 8], [x16, 8, mul vl] */
++	.inst	0xe1206209  /* str	za[w15, 9], [x16, 9, mul vl] */
++	.inst	0xe120620a  /* str	za[w15, 10], [x16, 10, mul vl] */
++	.inst	0xe120620b  /* str	za[w15, 11], [x16, 11, mul vl] */
++	.inst	0xe120620c  /* str	za[w15, 12], [x16, 12, mul vl] */
++	.inst	0xe120620d  /* str	za[w15, 13], [x16, 13, mul vl] */
++	.inst	0xe120620e  /* str	za[w15, 14], [x16, 14, mul vl] */
++	.inst	0xe120620f  /* str	za[w15, 15], [x16, 15, mul vl] */
++	add	w15, w15, 16
++	.inst	0x04305a10  /* addsvl	x16, x16, 16  */
++	cmp	w17, w15
++	bhi	L(save_loop)
++L(end):
++	ret
++L(fail):
++	PACIASP
++	stp	x29, x30, [sp, -32]!
++	.cfi_adjust_cfa_offset 32
++	.cfi_rel_offset x29, 0
++	.cfi_rel_offset x30, 8
++	mov	x29, sp
++	.inst	0x04e0e3f0  /* cntd	x16  */
++	str	x16, [sp, 16]
++	.cfi_rel_offset 46, 16
++	.inst	0xd503467f  /* smstop  */
++	bl	abort
++END (__arm_tpidr2_save)
++
++/* Hidden alias used by __arm_za_disable.  */
++.global __libgcc_arm_tpidr2_save
++.hidden __libgcc_arm_tpidr2_save
++.set __libgcc_arm_tpidr2_save, __arm_tpidr2_save
+diff --git a/libgcc/config/aarch64/__arm_za_disable.S b/libgcc/config/aarch64/__arm_za_disable.S
+new file mode 100644
+index 000000000..cff5b9cec
+--- /dev/null
++++ b/libgcc/config/aarch64/__arm_za_disable.S
+@@ -0,0 +1,65 @@
++/* Support routine for SME.
++   Copyright (C) 2023 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
++   .  */
++
++#include "aarch64-asm.h"
++
++/* Disable ZA.  Call ABI:
++   - Private ZA, streaming-compatible.
++   - x0-x13, x19-x29, sp and fp regs are call preserved.
++   - Takes no argument.
++   - Does not return a value.
++   - Can abort on failure (then registers are not preserved).  */
++
++.hidden __aarch64_have_sme
++
++.hidden __libgcc_arm_tpidr2_save
++
++variant_pcs (__arm_za_disable)
++
++ENTRY (__arm_za_disable)
++	/* Check if SME is available.  */
++	adrp	x14, __aarch64_have_sme
++	ldrb	w14, [x14, :lo12:__aarch64_have_sme]
++	cbz	w14, L(end)
++
++	.inst	0xd53bd0ae  /* mrs	x14, tpidr2_el0  */
++	cbz	x14, L(end)
++
++	PACIASP
++	stp	x29, x30, [sp, -16]!
++	.cfi_adjust_cfa_offset 16
++	.cfi_rel_offset x29, 0
++	.cfi_rel_offset x30, 8
++	mov	x29, sp
++	bl	__libgcc_arm_tpidr2_save
++	.inst	0xd51bd0bf  /* msr	tpidr2_el0, xzr  */
++	.inst	0xd503447f  /* smstop	za  */
++	ldp	x29, x30, [sp], 16
++	.cfi_adjust_cfa_offset -16
++	.cfi_restore x29
++	.cfi_restore x30
++	AUTIASP
++L(end):
++	ret
++END (__arm_za_disable)
+diff --git a/libgcc/config/aarch64/aarch64-asm.h b/libgcc/config/aarch64/aarch64-asm.h
+new file mode 100644
+index 000000000..8969b06b0
+--- /dev/null
++++ b/libgcc/config/aarch64/aarch64-asm.h
+@@ -0,0 +1,98 @@
++/* AArch64 asm definitions.
++   Copyright (C) 2023 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
++   .  */
++
++#include "auto-target.h"
++
++#define L(label) .L ## label
++
++/* Marking variant PCS symbol references is important for PLT calls
++   otherwise it is for documenting the PCS in the symbol table.  */
++#ifdef HAVE_AS_VARIANT_PCS
++# define variant_pcs(name) .variant_pcs name
++#else
++# define variant_pcs(name)
++#endif
++
++/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
++#define FEATURE_1_AND 0xc0000000
++#define FEATURE_1_BTI 1
++#define FEATURE_1_PAC 2
++
++/* Supported features based on the code generation options.  */
++#if defined(__ARM_FEATURE_BTI_DEFAULT)
++# define BTI_FLAG FEATURE_1_BTI
++# define BTI_C hint	34
++#else
++# define BTI_FLAG 0
++# define BTI_C
++#endif
++
++#if __ARM_FEATURE_PAC_DEFAULT & 3
++# define PAC_FLAG FEATURE_1_PAC
++# define PACIASP hint	25; .cfi_window_save
++# define AUTIASP hint	29; .cfi_window_save
++#else
++# define PAC_FLAG 0
++# define PACIASP
++# define AUTIASP
++#endif
++
++/* Add a NT_GNU_PROPERTY_TYPE_0 note.  */
++#define GNU_PROPERTY(type, value)	\
++  .section .note.gnu.property, "a";	\
++  .p2align 3;				\
++  .word 4;				\
++  .word 16;				\
++  .word 5;				\
++  .asciz "GNU";				\
++  .word type;				\
++  .word 4;				\
++  .word value;				\
++  .word 0;				\
++  .previous
++
++#if defined(__linux__) || defined(__FreeBSD__)
++/* Do not require executable stack.  */
++.section .note.GNU-stack, "", %progbits
++.previous
++
++/* Add GNU property note if built with branch protection.  */
++# if (BTI_FLAG|PAC_FLAG) != 0
++GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG)
++# endif
++#endif
++
++#define ENTRY_ALIGN(name, align) \
++  .global name;		\
++  .type name,%function;	\
++  .balign align;	\
++  name:			\
++  .cfi_startproc;	\
++  BTI_C
++
++#define ENTRY(name) ENTRY_ALIGN(name, 16)
++
++#define END(name) \
++  .cfi_endproc;		\
++  .size name, .-name
+diff --git a/libgcc/config/aarch64/libgcc-sme.ver b/libgcc/config/aarch64/libgcc-sme.ver
+new file mode 100644
+index 000000000..da889c6c0
+--- /dev/null
++++ b/libgcc/config/aarch64/libgcc-sme.ver
+@@ -0,0 +1,24 @@
++# Copyright (C) 2023 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
++# .
++
++GCC_14.0 {
++  __arm_sme_state
++  __arm_tpidr2_restore
++  __arm_tpidr2_save
++  __arm_za_disable
++}
+diff --git a/libgcc/config/aarch64/t-aarch64 b/libgcc/config/aarch64/t-aarch64
+index 8ca803bd3..5a8feb184 100644
+--- a/libgcc/config/aarch64/t-aarch64
++++ b/libgcc/config/aarch64/t-aarch64
+@@ -19,3 +19,13 @@
+ # .
+ 
+ LIB2ADD += $(srcdir)/config/aarch64/sync-cache.c
++
++# Add sme runtime to shared libgcc
++LIB2ADDEH += \
++	$(srcdir)/config/aarch64/__aarch64_have_sme.c \
++	$(srcdir)/config/aarch64/__arm_sme_state.S \
++	$(srcdir)/config/aarch64/__arm_tpidr2_restore.S \
++	$(srcdir)/config/aarch64/__arm_tpidr2_save.S \
++	$(srcdir)/config/aarch64/__arm_za_disable.S
++
++SHLIB_MAPFILES += $(srcdir)/config/aarch64/libgcc-sme.ver
+-- 
+2.33.0
+
diff --git a/0219-Backport-SME-libgcc-aarch64-Add-SME-unwinder-support.patch b/0219-Backport-SME-libgcc-aarch64-Add-SME-unwinder-support.patch
new file mode 100644
index 0000000..91c5d4b
--- /dev/null
+++ b/0219-Backport-SME-libgcc-aarch64-Add-SME-unwinder-support.patch
@@ -0,0 +1,70 @@
+From 310c8b5aaedad1430146fed9d8992201278164a6 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy 
+Date: Fri, 29 Sep 2023 13:55:51 +0100
+Subject: [PATCH 120/157] [Backport][SME] libgcc: aarch64: Add SME unwinder
+ support
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=91d68665b8b7a5dffd0bbf8cd1f74c3c41d4c2d8
+
+To support the ZA lazy save scheme, the PCS requires the unwinder to
+reset the SME state to PSTATE.SM=0, PSTATE.ZA=0, TPIDR2_EL0=0 on entry
+to an exception handler. We use the __arm_za_disable SME runtime call
+unconditionally to achieve this.
+https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#exceptions
+
+The hidden alias is used to avoid a PLT and avoid inconsistent VPCS
+marking (we don't rely on special PCS at the call site). In case of
+static linking the SME runtime init code is linked in code that raises
+exceptions.
+
+libgcc/ChangeLog:
+
+	* config/aarch64/__arm_za_disable.S: Add hidden alias.
+	* config/aarch64/aarch64-unwind.h: Reset the SME state before
+	EH return via the _Unwind_Frames_Extra hook.
+---
+ libgcc/config/aarch64/__arm_za_disable.S |  5 +++++
+ libgcc/config/aarch64/aarch64-unwind.h   | 16 ++++++++++++++++
+ 2 files changed, 21 insertions(+)
+
+diff --git a/libgcc/config/aarch64/__arm_za_disable.S b/libgcc/config/aarch64/__arm_za_disable.S
+index cff5b9cec..03fc28a39 100644
+--- a/libgcc/config/aarch64/__arm_za_disable.S
++++ b/libgcc/config/aarch64/__arm_za_disable.S
+@@ -63,3 +63,8 @@ ENTRY (__arm_za_disable)
+ L(end):
+ 	ret
+ END (__arm_za_disable)
++
++/* Hidden alias used by the unwinder.  */
++.global __libgcc_arm_za_disable
++.hidden __libgcc_arm_za_disable
++.set __libgcc_arm_za_disable, __arm_za_disable
+diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
+index 40b22d3c2..bfa695dcb 100644
+--- a/libgcc/config/aarch64/aarch64-unwind.h
++++ b/libgcc/config/aarch64/aarch64-unwind.h
+@@ -87,4 +87,20 @@ aarch64_frob_update_context (struct _Unwind_Context *context,
+   return;
+ }
+ 
++/* SME runtime function local to libgcc, streaming compatible
++   and preserves more registers than the base PCS requires, but
++   we don't rely on that here.  */
++__attribute__ ((visibility ("hidden")))
++void __libgcc_arm_za_disable (void);
++
++/* Disable the SME ZA state in case an unwound frame used the ZA
++   lazy saving scheme.  */
++#undef _Unwind_Frames_Extra
++#define _Unwind_Frames_Extra(x)				\
++  do							\
++    {							\
++      __libgcc_arm_za_disable ();			\
++    }							\
++  while (0)
++
+ #endif /* defined AARCH64_UNWIND_H && defined __ILP32__ */
+-- 
+2.33.0
+
diff --git a/0220-Backport-SME-libgcc-Fix-config.in.patch b/0220-Backport-SME-libgcc-Fix-config.in.patch
new file mode 100644
index 0000000..58b57e1
--- /dev/null
+++ b/0220-Backport-SME-libgcc-Fix-config.in.patch
@@ -0,0 +1,51 @@
+From b20b75158d1230a8b6cbabb36e3b128cbd9ec86f Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy 
+Date: Fri, 8 Dec 2023 12:22:54 +0000
+Subject: [PATCH 121/157] [Backport][SME] libgcc: Fix config.in
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=47575ec9edcd3078f066aa54ba428420be796bef
+
+It was updated incorrectly in
+
+  commit dbbfb52b0e9c66ee9d05b8fd17c4f44655e48463
+  Author:     Szabolcs Nagy 
+  CommitDate: 2023-12-08 11:29:06 +0000
+
+    libgcc: aarch64: Configure check for __getauxval
+
+so regenerate it.
+
+libgcc/ChangeLog:
+
+	* config.in: Regenerate.
+---
+ libgcc/config.in | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/libgcc/config.in b/libgcc/config.in
+index 441d4d39b..8f7dd437b 100644
+--- a/libgcc/config.in
++++ b/libgcc/config.in
+@@ -16,9 +16,6 @@
+ /* Define to 1 if the assembler supports .variant_pcs. */
+ #undef HAVE_AS_VARIANT_PCS
+ 
+-/* Define to 1 if __getauxval is available. */
+-#undef HAVE___GETAUXVAL
+-
+ /* Define to 1 if the target assembler supports thread-local storage. */
+ #undef HAVE_CC_TLS
+ 
+@@ -67,6 +64,9 @@
+ /* Define to 1 if you have the  header file. */
+ #undef HAVE_UNISTD_H
+ 
++/* Define to 1 if __getauxval is available. */
++#undef HAVE___GETAUXVAL
++
+ /* Define to the address where bug reports for this package should be sent. */
+ #undef PACKAGE_BUGREPORT
+ 
+-- 
+2.33.0
+
diff --git a/0221-Backport-SME-aarch64-Add-funwind-tables-to-some-test.patch b/0221-Backport-SME-aarch64-Add-funwind-tables-to-some-test.patch
new file mode 100644
index 0000000..2bd3268
--- /dev/null
+++ b/0221-Backport-SME-aarch64-Add-funwind-tables-to-some-test.patch
@@ -0,0 +1,54 @@
+From 0214ca06a182481851ed90aae21f460f87d26084 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sun, 10 Dec 2023 19:46:05 +0000
+Subject: [PATCH 122/157] [Backport][SME] aarch64: Add -funwind-tables to some
+ tests
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=02ecdaab7a50f4505fd905effb6d238d773dc813
+
+The .cfi scans in these tests failed for *-elf targets because
+those targets don't enable .eh_frame info by default.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/call_sm_switch_1.c: Add -funwind-tables.
+	* gcc.target/aarch64/sme/call_sm_switch_3.c: Likewise.
+	* gcc.target/aarch64/sme/call_sm_switch_5.c: Likewise.
+---
+ gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c | 2 +-
+ gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c | 2 +-
+ gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c
+index a2de55773..98922aaea 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_1.c
+@@ -1,4 +1,4 @@
+-// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls -funwind-tables" }
+ // { dg-final { check-function-bodies "**" "" } }
+ 
+ void ns_callee ();
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c
+index ed999d085..4250fe798 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_3.c
+@@ -1,4 +1,4 @@
+-// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls -funwind-tables" }
+ // { dg-final { check-function-bodies "**" "" } }
+ 
+ __attribute__((aarch64_vector_pcs)) void ns_callee ();
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+index be9b5cc04..e3d9bc274 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+@@ -1,4 +1,4 @@
+-// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls" }
++// { dg-options "-O -fomit-frame-pointer -fno-optimize-sibling-calls -funwind-tables" }
+ // { dg-final { check-function-bodies "**" "" } }
+ 
+ #include 
+-- 
+2.33.0
+
diff --git a/0222-Backport-SME-aarch64-Skip-some-SME-register-save-tes.patch b/0222-Backport-SME-aarch64-Skip-some-SME-register-save-tes.patch
new file mode 100644
index 0000000..0b0dbd9
--- /dev/null
+++ b/0222-Backport-SME-aarch64-Skip-some-SME-register-save-tes.patch
@@ -0,0 +1,106 @@
+From cc2e901eccd40992432f74270a9ebc1b708b6eb1 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sun, 10 Dec 2023 19:46:05 +0000
+Subject: [PATCH 123/157] [Backport][SME] aarch64: Skip some SME register save
+ tests on BE
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=23ea0bc2cf042d74c4adfe26a57cf96b1d837a91
+
+Big-endian targets need to save Z8-Z15 in the same order as
+the registers would appear for D8-D15, because the layout is
+mandated by the EH ABI.  BE targets therefore use ST1D instead
+of the normal STR for those registers (but not for others).
+
+That difference is already tested elsewhere and isn't important
+for the SME tests.  This patch therefore restricts the affected
+tests to LE.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sme/call_sm_switch_5.c: Restrict tests that
+	contain Z8-Z23 saves to little-endian.
+	* gcc.target/aarch64/sme/call_sm_switch_8.c: Likewise.
+	* gcc.target/aarch64/sme/locally_streaming_1.c: Likewise.
+---
+ gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c    | 6 +++---
+ gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c    | 6 +++---
+ gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c | 2 +-
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+index e3d9bc274..6238ab80d 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_5.c
+@@ -14,7 +14,7 @@ struct callbacks {
+ };
+ 
+ /*
+-** n_caller:	{ target lp64 }
++** n_caller:	{ target { lp64 && aarch64_little_endian } }
+ **	stp	x30, (x19|x2[0-8]), \[sp, #?-32\]!
+ **	cntd	x16
+ **	str	x16, \[sp, #?16\]
+@@ -114,7 +114,7 @@ n_caller (struct callbacks *c)
+ }
+ 
+ /*
+-** s_caller:	{ target lp64 }
++** s_caller:	{ target { lp64 && aarch64_little_endian } }
+ **	stp	x30, (x19|x2[0-8]), \[sp, #?-32\]!
+ **	cntd	x16
+ **	str	x16, \[sp, #?16\]
+@@ -214,7 +214,7 @@ s_caller (struct callbacks *c) [[arm::streaming]]
+ }
+ 
+ /*
+-** sc_caller:
++** sc_caller:	{ target aarch64_little_endian }
+ **	stp	x29, x30, \[sp, #?-32\]!
+ **	mov	x29, sp
+ **	cntd	x16
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c
+index f44724df3..c909b34ff 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/call_sm_switch_8.c
+@@ -7,7 +7,7 @@ svint8_t produce_z0 ();
+ void consume_z0 (svint8_t);
+ 
+ /*
+-** test_z0:
++** test_z0:	{ target aarch64_little_endian }
+ **	...
+ **	smstop	sm
+ **	bl	produce_z0
+@@ -32,7 +32,7 @@ svint8x4_t produce_z3 ();
+ void consume_z3 (svint8x4_t);
+ 
+ /*
+-** test_z3:
++** test_z3:	{ target aarch64_little_endian }
+ **	...
+ **	smstop	sm
+ **	bl	produce_z3
+@@ -61,7 +61,7 @@ svbool_t produce_p0 ();
+ void consume_p0 (svbool_t);
+ 
+ /*
+-** test_p0:
++** test_p0:	{ target aarch64_little_endian }
+ **	...
+ **	smstop	sm
+ **	bl	produce_p0
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c
+index 20ff4b87d..4bb637f47 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/locally_streaming_1.c
+@@ -265,7 +265,7 @@ n_ls_vector_pcs ()
+ }
+ 
+ /*
+-** n_ls_sve_pcs:
++** n_ls_sve_pcs:	{ target aarch64_little_endian }
+ **	sub	sp, sp, #?16
+ **	cntd	x16
+ **	str	x16, \[sp\]
+-- 
+2.33.0
+
diff --git a/0223-Backport-SME-Add-OPTIONS_H_EXTRA-to-GTFILES.patch b/0223-Backport-SME-Add-OPTIONS_H_EXTRA-to-GTFILES.patch
new file mode 100644
index 0000000..edbbd5a
--- /dev/null
+++ b/0223-Backport-SME-Add-OPTIONS_H_EXTRA-to-GTFILES.patch
@@ -0,0 +1,37 @@
+From ab7a2c3b74c65d62d661621c56ef984cfb72f985 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Sep 2022 11:32:50 +0100
+Subject: [PATCH 124/157] [Backport][SME] Add OPTIONS_H_EXTRA to GTFILES
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c1e1fa054970a30844eb94d726b4954dcb8b9063
+
+I have a patch that adds a typedef to aarch64's -opts.h.
+The typedef is used for a TargetVariable in the .opt file,
+which means that it is covered by PCH and so needs to be
+visible to gengtype.
+
+-opts.h is not included directly in tm.h, but indirectly
+by target headers (in this case aarch64.h).  There was therefore
+nothing that caused it to be added to GTFILES.
+
+gcc/
+	* Makefile.in (GTFILES): Add OPTIONS_H_EXTRA.
+---
+ gcc/Makefile.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 5cd838270..fcfa54697 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -2648,6 +2648,7 @@ s-match: build/genmatch$(build_exeext) $(srcdir)/match.pd cfn-operators.pd
+ 
+ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
+   $(host_xm_file_list) \
++  $(OPTIONS_H_EXTRA) \
+   $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
+   $(srcdir)/wide-int.h $(srcdir)/alias.h \
+   $(srcdir)/coverage.cc  $(srcdir)/rtl.h \
+-- 
+2.33.0
+
diff --git a/0224-Backport-SME-aarch64-Add-V1DI-mode.patch b/0224-Backport-SME-aarch64-Add-V1DI-mode.patch
new file mode 100644
index 0000000..401391c
--- /dev/null
+++ b/0224-Backport-SME-aarch64-Add-V1DI-mode.patch
@@ -0,0 +1,177 @@
+From 21f9190106f8324be42e3e8e0510467386dd68a0 Mon Sep 17 00:00:00 2001
+From: Andrew Carlotti 
+Date: Fri, 15 Jul 2022 15:25:53 +0100
+Subject: [PATCH 125/157] [Backport][SME] aarch64: Add V1DI mode
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5ba864c5d11a1c20891a1e054cb7814ec23de5c9
+
+We already have a V1DF mode, so this makes the vector modes more consistent.
+
+Additionally, this allows us to recognise uint64x1_t and int64x1_t types given
+only the mode and type qualifiers (e.g. in aarch64_lookup_simd_builtin_type).
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64-builtins.cc
+	(v1di_UP): Add V1DI mode to _UP macros.
+	* config/aarch64/aarch64-modes.def (VECTOR_MODE): Add V1DI mode.
+	* config/aarch64/aarch64-simd-builtin-types.def: Use V1DI mode.
+	* config/aarch64/aarch64-simd.md
+	(vec_extractv2dfv1df): Replace with...
+	(vec_extract): ...this.
+	* config/aarch64/aarch64.cc
+	(aarch64_classify_vector_mode): Add V1DI mode.
+	* config/aarch64/iterators.md
+	(VQ_2E, V1HALF, V1half): New.
+	(nunits): Add V1DI mode.
+---
+ gcc/config/aarch64/aarch64-builtins.cc            |  1 +
+ gcc/config/aarch64/aarch64-modes.def              |  1 +
+ gcc/config/aarch64/aarch64-simd-builtin-types.def |  6 +++---
+ gcc/config/aarch64/aarch64-simd.md                | 14 +++++++-------
+ gcc/config/aarch64/aarch64.cc                     |  2 +-
+ gcc/config/aarch64/iterators.md                   | 14 ++++++++++++--
+ 6 files changed, 25 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
+index 015e9d975..37bb3af48 100644
+--- a/gcc/config/aarch64/aarch64-builtins.cc
++++ b/gcc/config/aarch64/aarch64-builtins.cc
+@@ -55,6 +55,7 @@
+ #define v2si_UP  E_V2SImode
+ #define v2sf_UP  E_V2SFmode
+ #define v1df_UP  E_V1DFmode
++#define v1di_UP  E_V1DImode
+ #define di_UP    E_DImode
+ #define df_UP    E_DFmode
+ #define v16qi_UP E_V16QImode
+diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def
+index 8fa66fdb3..dd74da4b3 100644
+--- a/gcc/config/aarch64/aarch64-modes.def
++++ b/gcc/config/aarch64/aarch64-modes.def
+@@ -70,6 +70,7 @@ VECTOR_MODES (INT, 8);        /*       V8QI V4HI V2SI.  */
+ VECTOR_MODES (INT, 16);       /* V16QI V8HI V4SI V2DI.  */
+ VECTOR_MODES (FLOAT, 8);      /*                 V2SF.  */
+ VECTOR_MODES (FLOAT, 16);     /*            V4SF V2DF.  */
++VECTOR_MODE (INT, DI, 1);     /*                 V1DI.  */
+ VECTOR_MODE (FLOAT, DF, 1);   /*                 V1DF.  */
+ VECTOR_MODE (FLOAT, HF, 2);   /*                 V2HF.  */
+ 
+diff --git a/gcc/config/aarch64/aarch64-simd-builtin-types.def b/gcc/config/aarch64/aarch64-simd-builtin-types.def
+index 248e51e96..405455814 100644
+--- a/gcc/config/aarch64/aarch64-simd-builtin-types.def
++++ b/gcc/config/aarch64/aarch64-simd-builtin-types.def
+@@ -24,7 +24,7 @@
+   ENTRY (Int16x8_t, V8HI, none, 11)
+   ENTRY (Int32x2_t, V2SI, none, 11)
+   ENTRY (Int32x4_t, V4SI, none, 11)
+-  ENTRY (Int64x1_t, DI, none, 11)
++  ENTRY (Int64x1_t, V1DI, none, 11)
+   ENTRY (Int64x2_t, V2DI, none, 11)
+   ENTRY (Uint8x8_t, V8QI, unsigned, 11)
+   ENTRY (Uint8x16_t, V16QI, unsigned, 12)
+@@ -32,7 +32,7 @@
+   ENTRY (Uint16x8_t, V8HI, unsigned, 12)
+   ENTRY (Uint32x2_t, V2SI, unsigned, 12)
+   ENTRY (Uint32x4_t, V4SI, unsigned, 12)
+-  ENTRY (Uint64x1_t, DI, unsigned, 12)
++  ENTRY (Uint64x1_t, V1DI, unsigned, 12)
+   ENTRY (Uint64x2_t, V2DI, unsigned, 12)
+   ENTRY (Poly8_t, QI, poly, 9)
+   ENTRY (Poly16_t, HI, poly, 10)
+@@ -42,7 +42,7 @@
+   ENTRY (Poly8x16_t, V16QI, poly, 12)
+   ENTRY (Poly16x4_t, V4HI, poly, 12)
+   ENTRY (Poly16x8_t, V8HI, poly, 12)
+-  ENTRY (Poly64x1_t, DI, poly, 12)
++  ENTRY (Poly64x1_t, V1DI, poly, 12)
+   ENTRY (Poly64x2_t, V2DI, poly, 12)
+   ENTRY (Float16x4_t, V4HF, none, 13)
+   ENTRY (Float16x8_t, V8HF, none, 13)
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index 62493cdfa..04592fc90 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -8326,16 +8326,16 @@
+ })
+ 
+ ;; Extract a single-element 64-bit vector from one half of a 128-bit vector.
+-(define_expand "vec_extractv2dfv1df"
+-  [(match_operand:V1DF 0 "register_operand")
+-   (match_operand:V2DF 1 "register_operand")
++(define_expand "vec_extract"
++  [(match_operand: 0 "register_operand")
++   (match_operand:VQ_2E 1 "register_operand")
+    (match_operand 2 "immediate_operand")]
+   "TARGET_SIMD"
+ {
+-  /* V1DF is rarely used by other patterns, so it should be better to hide
+-     it in a subreg destination of a normal DF op.  */
+-  rtx scalar0 = gen_lowpart (DFmode, operands[0]);
+-  emit_insn (gen_vec_extractv2dfdf (scalar0, operands[1], operands[2]));
++  /* V1DI and V1DF are rarely used by other patterns, so it should be better
++     to hide it in a subreg destination of a normal DI or DF op.  */
++  rtx scalar0 = gen_lowpart (mode, operands[0]);
++  emit_insn (gen_vec_extract (scalar0, operands[1], operands[2]));
+   DONE;
+ })
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index b8e540b6e..f7285555b 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -4117,7 +4117,7 @@ aarch64_classify_vector_mode (machine_mode mode)
+     case E_V8QImode:
+     case E_V4HImode:
+     case E_V2SImode:
+-    /* ...E_V1DImode doesn't exist.  */
++    case E_V1DImode:
+     case E_V4HFmode:
+     case E_V4BFmode:
+     case E_V2SFmode:
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index 152d28f6b..94db8c53f 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -138,6 +138,9 @@
+ ;; VQ without 2 element modes.
+ (define_mode_iterator VQ_NO2E [V16QI V8HI V4SI V8HF V4SF V8BF])
+ 
++;; 2 element quad vector modes.
++(define_mode_iterator VQ_2E [V2DI V2DF])
++
+ ;; BFmode vector modes.
+ (define_mode_iterator VBF [V4BF V8BF])
+ 
+@@ -1116,12 +1119,13 @@
+ (define_mode_attr nunits [(V8QI "8") (V16QI "16")
+ 			  (V4HI "4") (V8HI "8")
+ 			  (V2SI "2") (V4SI "4")
+-			  (V2DI "2") (V8DI "8")
++			  (V1DI "1") (V2DI "2")
+ 			  (V4HF "4") (V8HF "8")
+ 			  (V4BF "4") (V8BF "8")
+ 			  (V2SF "2") (V4SF "4")
+ 			  (V1DF "1") (V2DF "2")
+-			  (DI "1") (DF "1")])
++			  (DI "1") (DF "1")
++			  (V8DI "8")])
+ 
+ ;; Map a mode to the number of bits in it, if the size of the mode
+ ;; is constant.
+@@ -1501,6 +1505,12 @@
+ 			 (V2DI "di")    (V2SF  "sf")
+ 			 (V4SF "v2sf")  (V2DF  "df")])
+ 
++;; Single-element half modes of quad vector modes.
++(define_mode_attr V1HALF [(V2DI "V1DI")  (V2DF  "V1DF")])
++
++;; Single-element half modes of quad vector modes, in lower-case
++(define_mode_attr V1half [(V2DI "v1di")  (V2DF  "v1df")])
++
+ ;; Double modes of vector modes.
+ (define_mode_attr VDBL [(V8QI "V16QI") (V4HI "V8HI")
+ 			(V4HF "V8HF")  (V4BF "V8BF")
+-- 
+2.33.0
+
diff --git a/0225-Backport-SME-Allow-md-iterators-to-include-other-ite.patch b/0225-Backport-SME-Allow-md-iterators-to-include-other-ite.patch
new file mode 100644
index 0000000..fa5b887
--- /dev/null
+++ b/0225-Backport-SME-Allow-md-iterators-to-include-other-ite.patch
@@ -0,0 +1,217 @@
+From eaea26e2218ee61a9be0e2933548c752167dcdb5 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Fri, 10 Nov 2023 15:46:21 +0000
+Subject: [PATCH 126/157] [Backport][SME] Allow md iterators to include other
+ iterators
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5dbaf4851bbf56b6176dca1f1e7d38a16b5b84ee
+
+This patch allows an .md iterator to include the contents of
+previous iterators, possibly with an extra condition attached.
+
+Too much indirection might become hard to follow, so for the
+AArch64 changes I tried to stick to things that seemed likely
+to be uncontroversial:
+
+(a) structure iterators that combine modes for different sizes
+    and vector counts
+
+(b) iterators that explicitly duplicate another iterator
+    (for iterating over the cross product)
+
+gcc/
+	* read-rtl.cc (md_reader::read_mapping): Allow iterators to
+	include other iterators.
+	* doc/md.texi: Document the change.
+	* config/aarch64/iterators.md (DREG2, VQ2, TX2, DX2, SX2): Include
+	the iterator that is being duplicated, rather than reproducing it.
+	(VSTRUCT_D): Redefine using VSTRUCT_[234]D.
+	(VSTRUCT_Q): Likewise VSTRUCT_[234]Q.
+	(VSTRUCT_2QD, VSTRUCT_3QD, VSTRUCT_4QD, VSTRUCT_QD): Redefine using
+	the individual D and Q iterators.
+---
+ gcc/config/aarch64/iterators.md | 58 ++++++++-------------------------
+ gcc/doc/md.texi                 | 13 ++++++++
+ gcc/read-rtl.cc                 | 21 ++++++++++--
+ 3 files changed, 46 insertions(+), 46 deletions(-)
+
+diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
+index 94db8c53f..a1659dfba 100644
+--- a/gcc/config/aarch64/iterators.md
++++ b/gcc/config/aarch64/iterators.md
+@@ -106,7 +106,7 @@
+ (define_mode_iterator DREG [V8QI V4HI V4HF V2SI V2SF DF])
+ 
+ ;; Copy of the above.
+-(define_mode_iterator DREG2 [V8QI V4HI V4HF V2SI V2SF DF])
++(define_mode_iterator DREG2 [DREG])
+ 
+ ;; All modes suitable to store/load pair (2 elements) using STP/LDP.
+ (define_mode_iterator VP_2E [V2SI V2SF V2DI V2DF])
+@@ -121,7 +121,7 @@
+ (define_mode_iterator VQ [V16QI V8HI V4SI V2DI V8HF V4SF V2DF V8BF])
+ 
+ ;; Copy of the above.
+-(define_mode_iterator VQ2 [V16QI V8HI V4SI V2DI V8HF V8BF V4SF V2DF])
++(define_mode_iterator VQ2 [VQ])
+ 
+ ;; Quad vector modes suitable for moving.  Includes BFmode.
+ (define_mode_iterator VQMOV [V16QI V8HI V4SI V2DI V8HF V8BF V4SF V2DF])
+@@ -321,14 +321,6 @@
+ ;; Advanced SIMD opaque structure modes.
+ (define_mode_iterator VSTRUCT [OI CI XI])
+ 
+-;; Advanced SIMD 64-bit vector structure modes.
+-(define_mode_iterator VSTRUCT_D [V2x8QI V2x4HI V2x2SI V2x1DI
+-				 V2x4HF V2x2SF V2x1DF V2x4BF
+-				 V3x8QI V3x4HI V3x2SI V3x1DI
+-				 V3x4HF V3x2SF V3x1DF V3x4BF
+-				 V4x8QI V4x4HI V4x2SI V4x1DI
+-				 V4x4HF V4x2SF V4x1DF V4x4BF])
+-
+ ;; Advanced SIMD 64-bit 2-vector structure modes.
+ (define_mode_iterator VSTRUCT_2D [V2x8QI V2x4HI V2x2SI V2x1DI
+ 				  V2x4HF V2x2SF V2x1DF V2x4BF])
+@@ -341,6 +333,9 @@
+ (define_mode_iterator VSTRUCT_4D [V4x8QI V4x4HI V4x2SI V4x1DI
+ 				  V4x4HF V4x2SF V4x1DF V4x4BF])
+ 
++;; Advanced SIMD 64-bit vector structure modes.
++(define_mode_iterator VSTRUCT_D [VSTRUCT_2D VSTRUCT_3D VSTRUCT_4D])
++
+ ;; Advanced SIMD 64-bit 2-vector structure modes minus V2x1DI and V2x1DF.
+ (define_mode_iterator VSTRUCT_2DNX [V2x8QI V2x4HI V2x2SI V2x4HF
+ 				    V2x2SF V2x4BF])
+@@ -365,14 +360,6 @@
+ ;; Advanced SIMD 64-bit 4-vector structure modes with 64-bit elements.
+ (define_mode_iterator VSTRUCT_4DX [V4x1DI V4x1DF])
+ 
+-;; Advanced SIMD 128-bit vector structure modes.
+-(define_mode_iterator VSTRUCT_Q [V2x16QI V2x8HI V2x4SI V2x2DI
+-				 V2x8HF V2x4SF V2x2DF V2x8BF
+-				 V3x16QI V3x8HI V3x4SI V3x2DI
+-				 V3x8HF V3x4SF V3x2DF V3x8BF
+-				 V4x16QI V4x8HI V4x4SI V4x2DI
+-				 V4x8HF V4x4SF V4x2DF V4x8BF])
+-
+ ;; Advanced SIMD 128-bit 2-vector structure modes.
+ (define_mode_iterator VSTRUCT_2Q [V2x16QI V2x8HI V2x4SI V2x2DI
+ 				  V2x8HF V2x4SF V2x2DF V2x8BF])
+@@ -385,49 +372,32 @@
+ (define_mode_iterator VSTRUCT_4Q [V4x16QI V4x8HI V4x4SI V4x2DI
+ 				  V4x8HF V4x4SF V4x2DF V4x8BF])
+ 
++;; Advanced SIMD 128-bit vector structure modes.
++(define_mode_iterator VSTRUCT_Q [VSTRUCT_2Q VSTRUCT_3Q VSTRUCT_4Q])
++
+ ;; Advanced SIMD 2-vector structure modes.
+-(define_mode_iterator VSTRUCT_2QD [V2x8QI V2x4HI V2x2SI V2x1DI
+-				   V2x4HF V2x2SF V2x1DF V2x4BF
+-				   V2x16QI V2x8HI V2x4SI V2x2DI
+-				   V2x8HF V2x4SF V2x2DF V2x8BF])
++(define_mode_iterator VSTRUCT_2QD [VSTRUCT_2D VSTRUCT_2Q])
+ 
+ ;; Advanced SIMD 3-vector structure modes.
+-(define_mode_iterator VSTRUCT_3QD [V3x8QI V3x4HI V3x2SI V3x1DI
+-				   V3x4HF V3x2SF V3x1DF V3x4BF
+-				   V3x16QI V3x8HI V3x4SI V3x2DI
+-				   V3x8HF V3x4SF V3x2DF V3x8BF])
++(define_mode_iterator VSTRUCT_3QD [VSTRUCT_3D VSTRUCT_3Q])
+ 
+ ;; Advanced SIMD 4-vector structure modes.
+-(define_mode_iterator VSTRUCT_4QD [V4x8QI V4x4HI V4x2SI V4x1DI
+-				   V4x4HF V4x2SF V4x1DF V4x4BF
+-				   V4x16QI V4x8HI V4x4SI V4x2DI
+-				   V4x8HF V4x4SF V4x2DF V4x8BF])
++(define_mode_iterator VSTRUCT_4QD [VSTRUCT_4D VSTRUCT_4Q])
+ 
+ ;; Advanced SIMD vector structure modes.
+-(define_mode_iterator VSTRUCT_QD [V2x8QI V2x4HI V2x2SI V2x1DI
+-				  V2x4HF V2x2SF V2x1DF V2x4BF
+-				  V3x8QI V3x4HI V3x2SI V3x1DI
+-				  V3x4HF V3x2SF V3x1DF V3x4BF
+-				  V4x8QI V4x4HI V4x2SI V4x1DI
+-				  V4x4HF V4x2SF V4x1DF V4x4BF
+-				  V2x16QI V2x8HI V2x4SI V2x2DI
+-				  V2x8HF V2x4SF V2x2DF V2x8BF
+-				  V3x16QI V3x8HI V3x4SI V3x2DI
+-				  V3x8HF V3x4SF V3x2DF V3x8BF
+-				  V4x16QI V4x8HI V4x4SI V4x2DI
+-				  V4x8HF V4x4SF V4x2DF V4x8BF])
++(define_mode_iterator VSTRUCT_QD [VSTRUCT_D VSTRUCT_Q])
+ 
+ ;; Double scalar modes
+ (define_mode_iterator DX [DI DF DD])
+ 
+ ;; Duplicate of the above
+-(define_mode_iterator DX2 [DI DF DD])
++(define_mode_iterator DX2 [DX])
+ 
+ ;; Single scalar modes
+ (define_mode_iterator SX [SI SF])
+ 
+ ;; Duplicate of the above
+-(define_mode_iterator SX2 [SI SF])
++(define_mode_iterator SX2 [SX])
+ 
+ ;; Single and double integer and float modes
+ (define_mode_iterator DSX [DF DI SF SI])
+diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
+index 04ace8f7f..c0cf0ec64 100644
+--- a/gcc/doc/md.texi
++++ b/gcc/doc/md.texi
+@@ -11561,6 +11561,19 @@ to @code{@var{mode}}.  For example:
+ means that the @code{:DI} expansion only applies if @code{TARGET_64BIT}
+ but that the @code{:SI} expansion has no such constraint.
+ 
++It is also possible to include iterators in other iterators.  For example:
++
++@smallexample
++(define_mode_iterator VI [V16QI V8HI V4SI V2DI])
++(define_mode_iterator VF [V8HF V4SF (V2DF "TARGET_DOUBLE")])
++(define_mode_iterator V [VI (VF "TARGET_FLOAT")])
++@end smallexample
++
++makes @samp{:V} iterate over the modes in @code{VI} and the modes
++in @code{VF}.  When a construct uses @samp{:V}, the @code{V8HF} and
++@code{V4SF} expansions require @samp{TARGET_FLOAT} while the @code{V2DF}
++expansion requires @samp{TARGET_DOUBLE && TARGET_FLOAT}.
++
+ Iterators are applied in the order they are defined.  This can be
+ significant if two iterators are used in a construct that requires
+ substitutions.  @xref{Substitutions}.
+diff --git a/gcc/read-rtl.cc b/gcc/read-rtl.cc
+index 798d24859..cdfa9e7b8 100644
+--- a/gcc/read-rtl.cc
++++ b/gcc/read-rtl.cc
+@@ -1261,8 +1261,25 @@ md_reader::read_mapping (struct iterator_group *group, htab_t table)
+ 	  string = read_string (false);
+ 	  require_char_ws (')');
+ 	}
+-      number = group->find_builtin (name.string);
+-      end_ptr = add_map_value (end_ptr, number, string);
++      auto *subm = (struct mapping *) htab_find (group->iterators,
++						 &name.string);
++      if (subm)
++	{
++	  if (m == subm)
++	    fatal_with_file_and_line ("recursive definition of `%s'",
++				      name.string);
++	  for (map_value *v = subm->values; v; v = v->next)
++	    {
++	      auto *joined = rtx_reader_ptr->join_c_conditions (v->string,
++								string);
++	      end_ptr = add_map_value (end_ptr, v->number, joined);
++	    }
++	}
++      else
++	{
++	  number = group->find_builtin (name.string);
++	  end_ptr = add_map_value (end_ptr, number, string);
++	}
+       c = read_skip_spaces ();
+     }
+   while (c != ']');
+-- 
+2.33.0
+
diff --git a/0226-Backport-SME-riscv-Add-support-for-strlen-inline-exp.patch b/0226-Backport-SME-riscv-Add-support-for-strlen-inline-exp.patch
new file mode 100644
index 0000000..94d1277
--- /dev/null
+++ b/0226-Backport-SME-riscv-Add-support-for-strlen-inline-exp.patch
@@ -0,0 +1,142 @@
+From 637e6469f2225b6f6f6b0c84b4e7abcd8dfd7ca4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christoph=20M=C3=BCllner?= 
+Date: Wed, 28 Sep 2022 11:19:06 +0200
+Subject: [PATCH 127/157] [Backport][SME] riscv: Add support for strlen inline
+ expansion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=df48285b2484eb4f8e0570c566677114eb0e553a
+
+Note: Only introduce the definitions of function
+emit_likely_jump_insn and emit_unlikely_jump_insn,
+and drop others.
+
+This patch implements the expansion of the strlen builtin for RV32/RV64
+for xlen-aligned aligned strings if Zbb or XTheadBb instructions are available.
+The inserted sequences are:
+
+rv32gc_zbb (RV64 is similar):
+      add     a3,a0,4
+      li      a4,-1
+.L1:  lw      a5,0(a0)
+      add     a0,a0,4
+      orc.b   a5,a5
+      beq     a5,a4,.L1
+      not     a5,a5
+      ctz     a5,a5
+      srl     a5,a5,0x3
+      add     a0,a0,a5
+      sub     a0,a0,a3
+
+rv64gc_xtheadbb (RV32 is similar):
+      add       a4,a0,8
+.L2:  ld        a5,0(a0)
+      add       a0,a0,8
+      th.tstnbz a5,a5
+      beqz      a5,.L2
+      th.rev    a5,a5
+      th.ff1    a5,a5
+      srl       a5,a5,0x3
+      add       a0,a0,a5
+      sub       a0,a0,a4
+
+This allows to inline calls to strlen(), with optimized code for
+xlen-aligned strings, resulting in the following benefits over
+a call to libc:
+* no call/ret instructions
+* no stack frame allocation
+* no register saving/restoring
+* no alignment test
+
+The inlining mechanism is gated by a new switch ('-minline-strlen')
+and by the variable 'optimize_size'.
+
+Tested using the glibc string tests.
+
+Signed-off-by: Christoph Müllner 
+
+gcc/ChangeLog:
+
+	* config.gcc: Add new object riscv-string.o.
+	riscv-string.cc.
+	* config/riscv/riscv-protos.h (riscv_expand_strlen):
+	New function.
+	* config/riscv/riscv.md (strlen): New expand INSN.
+	* config/riscv/riscv.opt: New flag 'minline-strlen'.
+	* config/riscv/t-riscv: Add new object riscv-string.o.
+	* config/riscv/thead.md (th_rev2): Export INSN name.
+	(th_rev2): Likewise.
+	(th_tstnbz2): New INSN.
+	* doc/invoke.texi: Document '-minline-strlen'.
+	* emit-rtl.cc (emit_likely_jump_insn): New helper function.
+	(emit_unlikely_jump_insn): Likewise.
+	* rtl.h (emit_likely_jump_insn): New prototype.
+	(emit_unlikely_jump_insn): Likewise.
+	* config/riscv/riscv-string.cc: New file.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/riscv/xtheadbb-strlen-unaligned.c: New test.
+	* gcc.target/riscv/xtheadbb-strlen.c: New test.
+	* gcc.target/riscv/zbb-strlen-disabled-2.c: New test.
+	* gcc.target/riscv/zbb-strlen-disabled.c: New test.
+	* gcc.target/riscv/zbb-strlen-unaligned.c: New test.
+	* gcc.target/riscv/zbb-strlen.c: New test.
+---
+ gcc/emit-rtl.cc | 24 ++++++++++++++++++++++++
+ gcc/rtl.h       |  2 ++
+ 2 files changed, 26 insertions(+)
+
+diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
+index 1e02ae254..2df5ff414 100644
+--- a/gcc/emit-rtl.cc
++++ b/gcc/emit-rtl.cc
+@@ -5163,6 +5163,30 @@ emit_jump_insn (rtx x)
+   return last;
+ }
+ 
++/* Make an insn of code JUMP_INSN with pattern X,
++   add a REG_BR_PROB note that indicates very likely probability,
++   and add it to the end of the doubly-linked list.  */
++
++rtx_insn *
++emit_likely_jump_insn (rtx x)
++{
++  rtx_insn *jump = emit_jump_insn (x);
++  add_reg_br_prob_note (jump, profile_probability::very_likely ());
++  return jump;
++}
++
++/* Make an insn of code JUMP_INSN with pattern X,
++   add a REG_BR_PROB note that indicates very unlikely probability,
++   and add it to the end of the doubly-linked list.  */
++
++rtx_insn *
++emit_unlikely_jump_insn (rtx x)
++{
++  rtx_insn *jump = emit_jump_insn (x);
++  add_reg_br_prob_note (jump, profile_probability::very_unlikely ());
++  return jump;
++}
++
+ /* Make an insn of code CALL_INSN with pattern X
+    and add it to the end of the doubly-linked list.  */
+ 
+diff --git a/gcc/rtl.h b/gcc/rtl.h
+index 488016bb4..a0db225cb 100644
+--- a/gcc/rtl.h
++++ b/gcc/rtl.h
+@@ -3333,6 +3333,8 @@ extern rtx_note *emit_note_after (enum insn_note, rtx_insn *);
+ extern rtx_insn *emit_insn (rtx);
+ extern rtx_insn *emit_debug_insn (rtx);
+ extern rtx_insn *emit_jump_insn (rtx);
++extern rtx_insn *emit_likely_jump_insn (rtx);
++extern rtx_insn *emit_unlikely_jump_insn (rtx);
+ extern rtx_insn *emit_call_insn (rtx);
+ extern rtx_code_label *emit_label (rtx);
+ extern rtx_jump_table_data *emit_jump_table_data (rtx);
+-- 
+2.33.0
+
diff --git a/0227-Backport-SME-attribs-Add-overloads-with-namespace-na.patch b/0227-Backport-SME-attribs-Add-overloads-with-namespace-na.patch
new file mode 100644
index 0000000..bdb5966
--- /dev/null
+++ b/0227-Backport-SME-attribs-Add-overloads-with-namespace-na.patch
@@ -0,0 +1,189 @@
+From 8c6ffb4c6f86231eee318ceeb8546a53037edfe9 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Tue, 4 Oct 2022 23:13:15 +0200
+Subject: [PATCH 128/157] [Backport][SME] attribs: Add overloads with namespace
+ name
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0764dc8537a4f87089ecd32391cb5f8803b43c96
+
+I've discovered a problem with the way we handle scoped attributes.  For
+declaration or type attributes for attributes we don't know anything about
+we just don't add them to the declarations or types, so later in the FEs and
+middle-end it is fine to use lookup_attribute etc.  which just check the
+attribute name and not namespace because non-standard non-GNU attributes
+just won't show there.  But in the case of attributes on statements, nothing
+has filtered out the unknown attributes, so with my earlier assume
+attribute patch e.g.  c-c++-common/Wno-attributes-6.c test failed because
+it uses:
+[[vendor::assume(1 + 1 == 2)]];
+with -Wno-attributes=vendor::assume and lookup_attribute ("assume", )
+finds such attribute and handled it that way.
+So, for those cases, this patch introduces lookup_attribute and
+remove_attribute overloads which specify also the namespace.
+I think the fallthrough, hot, cold, likely, unlikely attribute handling
+will need to use the new APIs too, so that we don't handle
+msft::fallthrough attribute as something we'd know.
+
+2022-10-04  Jakub Jelinek  
+
+	* attribs.h (remove_attribute): Declare overload with additional
+	attr_ns argument.
+	(private_lookup_attribute): Declare overload with additional
+	attr_ns and attr_ns_len arguments.
+	(lookup_attribute): New overload with additional attr_ns argument.
+	* attribs.cc (remove_attribute): New overload with additional
+	attr_ns argument.
+	(private_lookup_attribute): New overload with additional
+	attr_ns and attr_ns_len arguments.
+---
+ gcc/attribs.cc | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ gcc/attribs.h  | 38 ++++++++++++++++++++++++++++++
+ 2 files changed, 101 insertions(+)
+
+diff --git a/gcc/attribs.cc b/gcc/attribs.cc
+index 656ea739e..8e2696bc5 100644
+--- a/gcc/attribs.cc
++++ b/gcc/attribs.cc
+@@ -1598,6 +1598,36 @@ remove_attribute (const char *attr_name, tree list)
+   return list;
+ }
+ 
++/* Similarly but also match namespace on the removed attributes.  */
++
++tree
++remove_attribute (const char *attr_ns, const char *attr_name, tree list)
++{
++  tree *p;
++  gcc_checking_assert (attr_name[0] != '_');
++  gcc_checking_assert (attr_ns == NULL || attr_ns[0] != '_');
++
++  for (p = &list; *p;)
++    {
++      tree l = *p;
++
++      tree attr = get_attribute_name (l);
++      if (is_attribute_p (attr_name, attr))
++	{
++	  tree ns = get_attribute_namespace (l);
++	  if ((ns == NULL_TREE && attr_ns == NULL)
++	      || (ns && attr_ns && is_attribute_p (attr_ns, ns)))
++	    {
++	      *p = TREE_CHAIN (l);
++	      continue;
++	    }
++	}
++      p = &TREE_CHAIN (l);
++    }
++
++  return list;
++}
++
+ /* Return an attribute list that is the union of a1 and a2.  */
+ 
+ tree
+@@ -1995,6 +2025,39 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
+   return list;
+ }
+ 
++/* Similarly but with also attribute namespace.  */
++
++tree
++private_lookup_attribute (const char *attr_ns, const char *attr_name,
++			  size_t attr_ns_len, size_t attr_len, tree list)
++{
++  while (list)
++    {
++      tree attr = get_attribute_name (list);
++      size_t ident_len = IDENTIFIER_LENGTH (attr);
++      if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr),
++		       ident_len))
++	{
++	  tree ns = get_attribute_namespace (list);
++	  if (ns == NULL_TREE)
++	    {
++	      if (attr_ns == NULL)
++		break;
++	    }
++	  else if (attr_ns)
++	    {
++	      ident_len = IDENTIFIER_LENGTH (ns);
++	      if (cmp_attribs (attr_ns, attr_ns_len, IDENTIFIER_POINTER (ns),
++			       ident_len))
++		break;
++	    }
++	}
++      list = TREE_CHAIN (list);
++    }
++
++  return list;
++}
++
+ /* Return true if the function decl or type NODE has been declared
+    with attribute ANAME among attributes ATTRS.  */
+ 
+diff --git a/gcc/attribs.h b/gcc/attribs.h
+index 0856f98fb..9ad530fcb 100644
+--- a/gcc/attribs.h
++++ b/gcc/attribs.h
+@@ -88,6 +88,10 @@ extern tree merge_type_attributes (tree, tree);
+ 
+ extern tree remove_attribute (const char *, tree);
+ 
++/* Similarly but also with specific attribute namespace.  */
++
++extern tree remove_attribute (const char *, const char *, tree);
++
+ /* Given two attributes lists, return a list of their union.  */
+ 
+ extern tree merge_attributes (tree, tree);
+@@ -119,6 +123,10 @@ extern int attribute_list_contained (const_tree, const_tree);
+    for size.  */
+ extern tree private_lookup_attribute (const char *attr_name, size_t attr_len,
+ 				      tree list);
++extern tree private_lookup_attribute (const char *attr_ns,
++				      const char *attr_name,
++				      size_t attr_ns_len, size_t attr_len,
++				      tree list);
+ 
+ extern unsigned decls_mismatched_attributes (tree, tree, tree,
+ 					     const char* const[],
+@@ -215,6 +223,36 @@ lookup_attribute (const char *attr_name, tree list)
+     }
+ }
+ 
++/* Similar to lookup_attribute, but also match the attribute namespace.  */
++
++static inline tree
++lookup_attribute (const char *attr_ns, const char *attr_name, tree list)
++{
++  if (CHECKING_P && attr_name[0] != '_')
++    {
++      size_t attr_len = strlen (attr_name);
++      gcc_checking_assert (!canonicalize_attr_name (attr_name, attr_len));
++    }
++  if (CHECKING_P && attr_ns && attr_ns[0] != '_')
++    {
++      size_t attr_ns_len = strlen (attr_ns);
++      gcc_checking_assert (!canonicalize_attr_name (attr_ns, attr_ns_len));
++    }
++  /* In most cases, list is NULL_TREE.  */
++  if (list == NULL_TREE)
++    return NULL_TREE;
++  else
++    {
++      size_t attr_ns_len = attr_ns ? strlen (attr_ns) : 0;
++      size_t attr_len = strlen (attr_name);
++      /* Do the strlen() before calling the out-of-line implementation.
++	 In most cases attr_name is a string constant, and the compiler
++	 will optimize the strlen() away.  */
++      return private_lookup_attribute (attr_ns, attr_name,
++				       attr_ns_len, attr_len, list);
++    }
++}
++
+ /* Given an attribute name ATTR_NAME and a list of attributes LIST,
+    return a pointer to the attribute's list first element if the attribute
+    starts with ATTR_NAME.  ATTR_NAME must be in the form 'text' (not
+-- 
+2.33.0
+
diff --git a/0228-Backport-SME-vec-Add-array_slice-constructors-from-n.patch b/0228-Backport-SME-vec-Add-array_slice-constructors-from-n.patch
new file mode 100644
index 0000000..625c065
--- /dev/null
+++ b/0228-Backport-SME-vec-Add-array_slice-constructors-from-n.patch
@@ -0,0 +1,47 @@
+From 044dc671f7eb723df5b6ce2364d6ae579c0cc984 Mon Sep 17 00:00:00 2001
+From: Martin Jambor 
+Date: Tue, 30 Aug 2022 18:50:35 +0200
+Subject: [PATCH 129/157] [Backport][SME] vec: Add array_slice constructors
+ from non-const and gc vectors
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=15433c214df295f2281a90fcf283355b21beca0e
+
+This patch adds constructors of array_slice that are required to
+create them from non-const (heap or auto) vectors or from GC vectors.
+
+gcc/ChangeLog:
+
+2022-08-08  Martin Jambor  
+
+	* vec.h (array_slice): Add constructors for non-const reference to
+	heap vector and pointers to heap vectors.
+---
+ gcc/vec.h | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/gcc/vec.h b/gcc/vec.h
+index 3ba7ea7ed..fc3b10c85 100644
+--- a/gcc/vec.h
++++ b/gcc/vec.h
+@@ -2264,6 +2264,18 @@ public:
+   array_slice (const vec &v)
+     : m_base (v.address ()), m_size (v.length ()) {}
+ 
++  template
++  array_slice (vec &v)
++    : m_base (v.address ()), m_size (v.length ()) {}
++
++  template
++  array_slice (const vec *v)
++    : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
++
++  template
++  array_slice (vec *v)
++    : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
++
+   iterator begin () { return m_base; }
+   iterator end () { return m_base + m_size; }
+ 
+-- 
+2.33.0
+
diff --git a/0229-Backport-SME-A-couple-of-va_gc_atomic-tweaks.patch b/0229-Backport-SME-A-couple-of-va_gc_atomic-tweaks.patch
new file mode 100644
index 0000000..0fd733c
--- /dev/null
+++ b/0229-Backport-SME-A-couple-of-va_gc_atomic-tweaks.patch
@@ -0,0 +1,140 @@
+From 12dd36f06e13ee9cd684c00732caa684f49b3610 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 29 Jun 2023 08:48:17 +0100
+Subject: [PATCH 130/157] [Backport][SME] A couple of va_gc_atomic tweaks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=4e9f6c14280699997a633cefd3fb315b2bd4762c
+
+The only current user of va_gc_atomic is Ada's:
+
+    vec
+
+It uses the generic gt_pch_nx routines (with gt_pch_nx being the
+“note pointers” hooks), such as:
+
+    template
+    void
+    gt_pch_nx (vec *v)
+    {
+      extern void gt_pch_nx (T &);
+      for (unsigned i = 0; i < v->length (); i++)
+	gt_pch_nx ((*v)[i]);
+    }
+
+It then defines gt_pch_nx routines for Entity_Id &.
+
+The problem is that if we wanted to take the same approach for
+an array of unsigned ints, we'd need to define:
+
+    inline void gt_pch_nx (unsigned int &) { }
+
+which would then be ambiguous with:
+
+    inline void gt_pch_nx (unsigned int) { }
+
+The point of va_gc_atomic is that the elements don't need to be GCed,
+and so we have:
+
+    template
+    void
+    gt_ggc_mx (vec *v ATTRIBUTE_UNUSED)
+    {
+      /* Nothing to do.  Vectors of atomic types wrt GC do not need to
+	 be traversed.  */
+    }
+
+I think it's therefore reasonable to assume that no pointers will
+need to be processed for PCH either.
+
+The patch also relaxes the array_slice constructor for vec *
+so that it handles all embedded vectors.
+
+gcc/
+	* vec.h (gt_pch_nx): Add overloads for va_gc_atomic.
+	(array_slice): Relax va_gc constructor to handle all vectors
+	with a vl_embed layout.
+
+gcc/ada/
+	* gcc-interface/decl.cc (gt_pch_nx): Remove overloads for Entity_Id.
+---
+ gcc/ada/gcc-interface/decl.cc | 11 -----------
+ gcc/vec.h                     | 22 ++++++++++++++++++----
+ 2 files changed, 18 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc
+index 1c7a71684..7193b55c7 100644
+--- a/gcc/ada/gcc-interface/decl.cc
++++ b/gcc/ada/gcc-interface/decl.cc
+@@ -163,17 +163,6 @@ struct GTY((for_user)) tree_entity_vec_map
+   vec *to;
+ };
+ 
+-void
+-gt_pch_nx (Entity_Id &)
+-{
+-}
+-
+-void
+-gt_pch_nx (Entity_Id *x, gt_pointer_operator op, void *cookie)
+-{
+-  op (x, NULL, cookie);
+-}
+-
+ struct dummy_type_hasher : ggc_cache_ptr_hash
+ {
+   static inline hashval_t
+diff --git a/gcc/vec.h b/gcc/vec.h
+index fc3b10c85..592d3f7e0 100644
+--- a/gcc/vec.h
++++ b/gcc/vec.h
+@@ -1383,6 +1383,13 @@ gt_pch_nx (vec *v)
+     gt_pch_nx ((*v)[i]);
+ }
+ 
++template
++void
++gt_pch_nx (vec *)
++{
++  /* No pointers to note.  */
++}
++
+ template
+ void
+ gt_pch_nx (vec *v, gt_pointer_operator op, void *cookie)
+@@ -1400,6 +1407,13 @@ gt_pch_nx (vec *v, gt_pointer_operator op, void *cookie)
+     gt_pch_nx (&((*v)[i]), op, cookie);
+ }
+ 
++template
++void
++gt_pch_nx (vec *, gt_pointer_operator, void *)
++{
++  /* No pointers to note.  */
++}
++
+ 
+ /* Space efficient vector.  These vectors can grow dynamically and are
+    allocated together with their control data.  They are suited to be
+@@ -2268,12 +2282,12 @@ public:
+   array_slice (vec &v)
+     : m_base (v.address ()), m_size (v.length ()) {}
+ 
+-  template
+-  array_slice (const vec *v)
++  template
++  array_slice (const vec *v)
+     : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
+ 
+-  template
+-  array_slice (vec *v)
++  template
++  array_slice (vec *v)
+     : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
+ 
+   iterator begin () { return m_base; }
+-- 
+2.33.0
+
diff --git a/0230-Backport-SME-middle-end-Fix-issue-of-poly_uint16-1-1.patch b/0230-Backport-SME-middle-end-Fix-issue-of-poly_uint16-1-1.patch
new file mode 100644
index 0000000..588ea40
--- /dev/null
+++ b/0230-Backport-SME-middle-end-Fix-issue-of-poly_uint16-1-1.patch
@@ -0,0 +1,34 @@
+From bb15d4c4476e3ba303c5afe0adae0d86ab5f0a9b Mon Sep 17 00:00:00 2001
+From: zhongjuzhe 
+Date: Mon, 22 Aug 2022 10:15:31 +0100
+Subject: [PATCH 131/157] [Backport][SME] middle-end: Fix issue of poly_uint16
+ (1, 1) in self test
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=21e7d87a901d45f0cb5e5510d22bfbdb0d0ac6a1
+
+This patch fix issue of poly_uint16 (1, 1) in machine mode self test.
+
+gcc/ChangeLog:
+
+	* simplify-rtx.cc (test_vector_subregs_fore_back): Make first value
+	and repeat value different.
+---
+ gcc/simplify-rtx.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
+index e152918b0..fc79a2e2e 100644
+--- a/gcc/simplify-rtx.cc
++++ b/gcc/simplify-rtx.cc
+@@ -8380,7 +8380,7 @@ test_vector_subregs_fore_back (machine_mode inner_mode)
+   for (unsigned int i = 0; i < count; ++i)
+     builder.quick_push (gen_int_mode (i, int_mode));
+   for (unsigned int i = 0; i < count; ++i)
+-    builder.quick_push (gen_int_mode (-(int) i, int_mode));
++    builder.quick_push (gen_int_mode (-1 - (int) i, int_mode));
+   rtx x = builder.build ();
+ 
+   test_vector_subregs_modes (x);
+-- 
+2.33.0
+
diff --git a/0231-SME-Add-missing-header-file-in-aarch64.cc.patch b/0231-SME-Add-missing-header-file-in-aarch64.cc.patch
new file mode 100644
index 0000000..6aa3d84
--- /dev/null
+++ b/0231-SME-Add-missing-header-file-in-aarch64.cc.patch
@@ -0,0 +1,24 @@
+From cce05b3365c3986ca74c04f442662a21b4f03a61 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Mon, 4 Mar 2024 14:39:36 +0800
+Subject: [PATCH 132/157] [SME] Add missing header file in `aarch64.cc`
+
+---
+ gcc/config/aarch64/aarch64.cc | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index f7285555b..0117a3e12 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -86,6 +86,7 @@
+ #include "tree-pass.h"
+ #include "cfgbuild.h"
+ #include "symbol-summary.h"
++#include "value-range.h"
+ #include "ipa-prop.h"
+ #include "ipa-fnsummary.h"
+ 
+-- 
+2.33.0
+
diff --git a/0232-Backport-SME-c-Add-support-for-__extension__.patch b/0232-Backport-SME-c-Add-support-for-__extension__.patch
new file mode 100644
index 0000000..5ba9828
--- /dev/null
+++ b/0232-Backport-SME-c-Add-support-for-__extension__.patch
@@ -0,0 +1,327 @@
+From 3714cfb47fafef884aa2ff330935fb44b7966909 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 24 Aug 2023 11:49:58 +0100
+Subject: [PATCH 133/157] [Backport][SME] c: Add support for [[__extension__
+ ...]]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=207a5daa9dcf31e367152163ad2a2ab4a0858967
+
+[[]] attributes are a recent addition to C, but as a GNU extension,
+GCC allows them to be used in C11 and earlier.  Normally this use
+would trigger a pedwarn (for -pedantic, -Wc11-c2x-compat, etc.).
+
+This patch allows the pedwarn to be suppressed by starting the
+attribute-list with __extension__.
+
+Also, :: is not a single lexing token prior to C2X, so it wasn't
+possible to use scoped attributes in C11, even as a GNU extension.
+The patch allows two colons to be used in place of :: when
+__extension__ is used.  No attempt is made to check whether the
+two colons are immediately adjacent.
+
+gcc/
+	* doc/extend.texi: Document the C [[__extension__ ...]] construct.
+
+gcc/c/
+	* c-parser.cc (c_parser_std_attribute): Conditionally allow
+	two colons to be used in place of ::.
+	(c_parser_std_attribute_list): New function, split out from...
+	(c_parser_std_attribute_specifier): ...here.  Allow the attribute-list
+	to start with __extension__.  When it does, also allow two colons
+	to be used in place of ::.
+
+gcc/testsuite/
+	* gcc.dg/c2x-attr-syntax-6.c: New test.
+	* gcc.dg/c2x-attr-syntax-7.c: Likewise.
+---
+ gcc/c/c-parser.cc                        | 64 ++++++++++++++++++------
+ gcc/doc/extend.texi                      | 27 ++++++++--
+ gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c | 62 +++++++++++++++++++++++
+ gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c | 60 ++++++++++++++++++++++
+ 4 files changed, 193 insertions(+), 20 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c
+ create mode 100644 gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c
+
+diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
+index 78a313fe3..486f46e1c 100644
+--- a/gcc/c/c-parser.cc
++++ b/gcc/c/c-parser.cc
+@@ -4894,10 +4894,18 @@ c_parser_balanced_token_sequence (c_parser *parser)
+      ( balanced-token-sequence[opt] )
+ 
+    Keywords are accepted as identifiers for this purpose.
+-*/
++
++   As an extension, we permit an attribute-specifier to be:
++
++     [ [ __extension__ attribute-list ] ]
++
++   Two colons are then accepted as a synonym for ::.  No attempt is made
++   to check whether the colons are immediately adjacent.  LOOSE_SCOPE_P
++   indicates whether this relaxation is in effect.  */
+ 
+ static tree
+-c_parser_std_attribute (c_parser *parser, bool for_tm)
++c_parser_std_attribute (c_parser *parser, bool for_tm,
++			bool loose_scope_p = false)
+ {
+   c_token *token = c_parser_peek_token (parser);
+   tree ns, name, attribute;
+@@ -4910,9 +4918,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
+     }
+   name = canonicalize_attr_name (token->value);
+   c_parser_consume_token (parser);
+-  if (c_parser_next_token_is (parser, CPP_SCOPE))
++  if (c_parser_next_token_is (parser, CPP_SCOPE)
++      || (loose_scope_p
++	  && c_parser_next_token_is (parser, CPP_COLON)
++	  && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
+     {
+       ns = name;
++      if (c_parser_next_token_is (parser, CPP_COLON))
++	c_parser_consume_token (parser);
+       c_parser_consume_token (parser);
+       token = c_parser_peek_token (parser);
+       if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
+@@ -4981,19 +4994,9 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
+ }
+ 
+ static tree
+-c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
++c_parser_std_attribute_list (c_parser *parser, bool for_tm,
++			     bool loose_scope_p = false)
+ {
+-  location_t loc = c_parser_peek_token (parser)->location;
+-  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
+-    return NULL_TREE;
+-  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
+-    {
+-      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+-      return NULL_TREE;
+-    }
+-  if (!for_tm)
+-    pedwarn_c11 (loc, OPT_Wpedantic,
+-		 "ISO C does not support %<[[]]%> attributes before C2X");
+   tree attributes = NULL_TREE;
+   while (true)
+     {
+@@ -5005,7 +5008,7 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
+ 	  c_parser_consume_token (parser);
+ 	  continue;
+ 	}
+-      tree attribute = c_parser_std_attribute (parser, for_tm);
++      tree attribute = c_parser_std_attribute (parser, for_tm, loose_scope_p);
+       if (attribute != error_mark_node)
+ 	{
+ 	  TREE_CHAIN (attribute) = attributes;
+@@ -5014,6 +5017,35 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
+       if (c_parser_next_token_is_not (parser, CPP_COMMA))
+ 	break;
+     }
++  return attributes;
++}
++
++static tree
++c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
++{
++  location_t loc = c_parser_peek_token (parser)->location;
++  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
++    return NULL_TREE;
++  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
++    {
++      c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
++      return NULL_TREE;
++    }
++  tree attributes;
++  if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
++    {
++      auto ext = disable_extension_diagnostics ();
++      c_parser_consume_token (parser);
++      attributes = c_parser_std_attribute_list (parser, for_tm, true);
++      restore_extension_diagnostics (ext);
++    }
++  else
++    {
++      if (!for_tm)
++	pedwarn_c11 (loc, OPT_Wpedantic,
++		     "ISO C does not support %<[[]]%> attributes before C2X");
++      attributes = c_parser_std_attribute_list (parser, for_tm);
++    }
+   c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+   c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+   return nreverse (attributes);
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 674db2f1a..3cfecee53 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -11726,10 +11726,29 @@ macros to replace them with the customary keywords.  It looks like this:
+ @findex __extension__
+ @opindex pedantic
+ @option{-pedantic} and other options cause warnings for many GNU C extensions.
+-You can
+-prevent such warnings within one expression by writing
+-@code{__extension__} before the expression.  @code{__extension__} has no
+-effect aside from this.
++You can suppress such warnings using the keyword @code{__extension__}.
++Specifically:
++
++@itemize @bullet
++@item
++Writing @code{__extension__} before an expression prevents warnings
++about extensions within that expression.
++
++@item
++In C, writing:
++
++@smallexample
++[[__extension__ @dots{}]]
++@end smallexample
++
++suppresses warnings about using @samp{[[]]} attributes in C versions
++that predate C2X@.  Since the scope token @samp{::} is not a single
++lexing token in earlier versions of C, this construct also allows two colons
++to be used in place of @code{::}.  GCC does not check whether the two
++colons are immediately adjacent.
++@end itemize
++
++@code{__extension__} has no effect aside from this.
+ 
+ @node Incomplete Enums
+ @section Incomplete @code{enum} Types
+diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c
+new file mode 100644
+index 000000000..9e5f65ce4
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c
+@@ -0,0 +1,62 @@
++/* Test C2x attribute syntax: use of __extension__ in C11 mode.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c11 -pedantic-errors" } */
++
++#define FOO ::
++#define BAR :
++#define JOIN(A, B) A/**/B
++#define JOIN2(A, B) A##B
++
++typedef int [[__extension__ gnu::vector_size (4)]] g1;
++typedef int [[__extension__ gnu :: vector_size (4)]] g2;
++typedef int [[__extension__ gnu : : vector_size (4)]] g3;
++typedef int [[__extension__ gnu: :vector_size (4)]] g4;
++typedef int [[__extension__ gnu FOO vector_size (4)]] g5;
++typedef int [[__extension__ gnu BAR BAR vector_size (4)]] g6;
++typedef int [[__extension__ gnu :/**/: vector_size (4)]] g7;
++typedef int [[__extension__ gnu JOIN(:,:) vector_size (4)]] g8;
++typedef int [[__extension__ gnu :: vector_size (sizeof (void (*)(...)))]] g10;
++typedef int [[__extension__]] g11;
++typedef int [[__extension__,]] g12;
++typedef int [[__extension__, ,,,, ,, ,]] g13;
++[[__extension__ deprecated]] int g14 ();
++[[__extension__ nodiscard]] int g15 ();
++[[__extension__ noreturn]] void g16 ();
++
++int
++cases (int x)
++{
++  switch (x)
++    {
++    case 1:
++    case 2:
++    case 4:
++      x += 1;
++      [[__extension__ fallthrough]];
++    case 19:
++    case 33:
++      x *= 2;
++      [[fallthrough]];  /* { dg-error {attributes before C2X} } */
++    case 99:
++      return x;
++
++    default:
++      return 0;
++    }
++}
++
++typedef int [[__extension__ vector_size (4)]] b1; /* { dg-error {'vector_size' attribute ignored} } */
++typedef int [[__extension__ __extension__]] b2; /* { dg-error {'extension' attribute ignored} } */
++typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error {'unknown_attribute' attribute ignored} } */
++typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error {pasting ":" and ":" does not give a valid preprocessing token} } */
++typedef int [[gnu::vector_size(4)]] b6; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++/* { dg-error {attributes before C2X} "" { target *-*-* } .-2 } */
++typedef int [[gnu : : vector_size(4)]] b7; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++/* { dg-error {attributes before C2X} "" { target *-*-* } .-2 } */
++typedef int [[gnu : vector_size(4)]] b8; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++/* { dg-error {attributes before C2X} "" { target *-*-* } .-2 } */
+diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c
+new file mode 100644
+index 000000000..702f733b1
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c
+@@ -0,0 +1,60 @@
++/* Test C2x attribute syntax: use of __extension__ in C11 mode.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */
++
++#define FOO ::
++#define BAR :
++#define JOIN(A, B) A/**/B
++#define JOIN2(A, B) A##B
++
++typedef int [[__extension__ gnu::vector_size (4)]] g1;
++typedef int [[__extension__ gnu :: vector_size (4)]] g2;
++typedef int [[__extension__ gnu : : vector_size (4)]] g3;
++typedef int [[__extension__ gnu: :vector_size (4)]] g4;
++typedef int [[__extension__ gnu FOO vector_size (4)]] g5;
++typedef int [[__extension__ gnu BAR BAR vector_size (4)]] g6;
++typedef int [[__extension__ gnu :/**/: vector_size (4)]] g7;
++typedef int [[__extension__ gnu JOIN(:,:) vector_size (4)]] g8;
++typedef int [[__extension__ gnu :: vector_size (sizeof (void (*)(...)))]] g10;
++typedef int [[__extension__]] g11;
++typedef int [[__extension__,]] g12;
++typedef int [[__extension__, ,,,, ,, ,]] g13;
++[[__extension__ deprecated]] int g14 ();
++[[__extension__ nodiscard]] int g15 ();
++[[__extension__ noreturn]] void g16 ();
++
++int
++cases (int x)
++{
++  switch (x)
++    {
++    case 1:
++    case 2:
++    case 4:
++      x += 1;
++      [[__extension__ fallthrough]];
++    case 19:
++    case 33:
++      x *= 2;
++      [[fallthrough]];  /* { dg-warning {attributes before C2X} } */
++    case 99:
++      return x;
++
++    default:
++      return 0;
++    }
++}
++
++typedef int [[__extension__ vector_size (4)]] b1; /* { dg-error {'vector_size' attribute ignored} } */
++typedef int [[__extension__ __extension__]] b2; /* { dg-error {'extension' attribute ignored} } */
++typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error {'unknown_attribute' attribute ignored} } */
++typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5;
++typedef int [[gnu::vector_size(4)]] b6; /* { dg-warning {attributes before C2X} } */
++typedef int [[gnu : : vector_size(4)]] b7; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++/* { dg-warning {attributes before C2X} "" { target *-*-* } .-2 } */
++typedef int [[gnu : vector_size(4)]] b8; /* { dg-error {expected '\]' before ':'} } */
++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
++/* { dg-warning {attributes before C2X} "" { target *-*-* } .-2 } */
+-- 
+2.33.0
+
diff --git a/0233-Backport-SME-lra-Updates-of-biggest-mode-for-hard-re.patch b/0233-Backport-SME-lra-Updates-of-biggest-mode-for-hard-re.patch
new file mode 100644
index 0000000..95b50de
--- /dev/null
+++ b/0233-Backport-SME-lra-Updates-of-biggest-mode-for-hard-re.patch
@@ -0,0 +1,140 @@
+From 29a71fc5cbfc3b5e4649abf51740daed5ea243bd Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 5 Dec 2023 09:20:55 +0000
+Subject: [PATCH 134/157] [Backport][SME] lra: Updates of biggest mode for hard
+ regs [PR112278]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=6e2e0ce6795c863e295eb33559f8dc0500297da3
+
+LRA keeps track of the biggest mode for both hard registers and
+pseudos.  The updates assume that the modes are ordered, i.e. that
+we can tell whether one is no bigger than the other at compile time.
+
+That is (or at least seemed to be) a reasonable restriction for pseudos.
+But it isn't necessarily so for hard registers, since the uses of hard
+registers can be logically distinct.  The testcase is an example of this.
+
+The biggest mode of hard registers is also special for other reasons.
+As the existing comment says:
+
+  /* A reg can have a biggest_mode of VOIDmode if it was only ever seen as
+     part of a multi-word register.  In that case, just use the reg_rtx
+     mode.  Do the same also if the biggest mode was larger than a register
+     or we can not compare the modes.  Otherwise, limit the size to that of
+     the biggest access in the function or to the natural mode at least.  */
+
+This patch applies the same approach to the updates.
+
+gcc/
+	PR rtl-optimization/112278
+	* lra-int.h (lra_update_biggest_mode): New function.
+	* lra-coalesce.cc (merge_pseudos): Use it.
+	* lra-lives.cc (process_bb_lives): Likewise.
+	* lra.cc (new_insn_reg): Likewise.
+
+gcc/testsuite/
+	PR rtl-optimization/112278
+	* gcc.target/aarch64/sve/pr112278.c: New test.
+---
+ gcc/lra-coalesce.cc                             |  4 +---
+ gcc/lra-int.h                                   | 15 +++++++++++++++
+ gcc/lra-lives.cc                                |  4 +---
+ gcc/lra.cc                                      |  5 ++---
+ gcc/testsuite/gcc.target/aarch64/sve/pr112278.c | 15 +++++++++++++++
+ 5 files changed, 34 insertions(+), 9 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr112278.c
+
+diff --git a/gcc/lra-coalesce.cc b/gcc/lra-coalesce.cc
+index c82934569..901a44663 100644
+--- a/gcc/lra-coalesce.cc
++++ b/gcc/lra-coalesce.cc
+@@ -112,9 +112,7 @@ merge_pseudos (int regno1, int regno2)
+     = (lra_merge_live_ranges
+        (lra_reg_info[first].live_ranges,
+ 	lra_copy_live_range_list (lra_reg_info[first2].live_ranges)));
+-  if (partial_subreg_p (lra_reg_info[first].biggest_mode,
+-			lra_reg_info[first2].biggest_mode))
+-    lra_reg_info[first].biggest_mode = lra_reg_info[first2].biggest_mode;
++  lra_update_biggest_mode (first, lra_reg_info[first2].biggest_mode);
+ }
+ 
+ /* Change pseudos in *LOC on their coalescing group
+diff --git a/gcc/lra-int.h b/gcc/lra-int.h
+index 04baefef3..040e87d11 100644
+--- a/gcc/lra-int.h
++++ b/gcc/lra-int.h
+@@ -525,4 +525,19 @@ lra_assign_reg_val (int from, int to)
+   lra_reg_info[to].offset = lra_reg_info[from].offset;
+ }
+ 
++/* Update REGNO's biggest recorded mode so that it includes a reference
++   in mode MODE.  */
++inline void
++lra_update_biggest_mode (int regno, machine_mode mode)
++{
++  if (!ordered_p (GET_MODE_SIZE (lra_reg_info[regno].biggest_mode),
++		  GET_MODE_SIZE (mode)))
++    {
++      gcc_checking_assert (HARD_REGISTER_NUM_P (regno));
++      lra_reg_info[regno].biggest_mode = reg_raw_mode[regno];
++    }
++  else if (partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
++    lra_reg_info[regno].biggest_mode = mode;
++}
++
+ #endif /* GCC_LRA_INT_H */
+diff --git a/gcc/lra-lives.cc b/gcc/lra-lives.cc
+index a755464ee..fb4a12304 100644
+--- a/gcc/lra-lives.cc
++++ b/gcc/lra-lives.cc
+@@ -770,9 +770,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
+ 	{
+ 	  int regno = reg->regno;
+ 
+-	  if (partial_subreg_p (lra_reg_info[regno].biggest_mode,
+-				reg->biggest_mode))
+-	    lra_reg_info[regno].biggest_mode = reg->biggest_mode;
++	  lra_update_biggest_mode (regno, reg->biggest_mode);
+ 	  if (HARD_REGISTER_NUM_P (regno))
+ 	    lra_hard_reg_usage[regno] += freq;
+ 	}
+diff --git a/gcc/lra.cc b/gcc/lra.cc
+index 1444cb759..8fda432f1 100644
+--- a/gcc/lra.cc
++++ b/gcc/lra.cc
+@@ -559,9 +559,8 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
+   lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
+   ir->type = type;
+   ir->biggest_mode = mode;
+-  if (NONDEBUG_INSN_P (insn)
+-      && partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
+-    lra_reg_info[regno].biggest_mode = mode;
++  if (NONDEBUG_INSN_P (insn))
++    lra_update_biggest_mode (regno, mode);
+   ir->subreg_p = subreg_p;
+   ir->early_clobber_alts = early_clobber_alts;
+   ir->regno = regno;
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr112278.c b/gcc/testsuite/gcc.target/aarch64/sve/pr112278.c
+new file mode 100644
+index 000000000..4f56add2b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/sve/pr112278.c
+@@ -0,0 +1,15 @@
++#include 
++#include 
++
++void
++f (void)
++{
++  {
++    register svint8_t v0 asm ("z0");
++    asm volatile ("" : "=w" (v0));
++  }
++  {
++    register int8x8x4_t v0 asm ("v0");
++    asm volatile ("" : "=w" (v0));
++  }
++}
+-- 
+2.33.0
+
diff --git a/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch b/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch
new file mode 100644
index 0000000..f4b1efd
--- /dev/null
+++ b/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch
@@ -0,0 +1,672 @@
+From 0a34bb6b18cdf34cb9d4f34b1697e1bcfcff139b Mon Sep 17 00:00:00 2001
+From: Joseph Myers 
+Date: Thu, 25 Aug 2022 21:02:57 +0000
+Subject: [PATCH 135/157] [Backport][SME] c: Support C2x empty initializer
+ braces
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=14cfa01755a66afbae2539f8b5796c960ddcecc6
+
+ISO C2x standardizes empty initializer braces {}.  Implement this
+feature accordingly.  The basic case was already supported and so just
+needed diagnostic adjustments.  However, the standard feature also
+includes two cases that were not previously supported: empty
+initializer braces for scalars, and empty initializer braces for
+VLAs.  Thus, add support for those features as well, updating existing
+tests that expected them to be diagnosed.
+
+There was already some gimplifier support for converting
+variable-sized initializations with empty CONSTRUCTORs to memset.
+However, it didn't apply here; code earlier in gimplify_modify_expr
+ended up calling gimplify_init_constructor via
+gimplify_modify_expr_rhs, which ended up handling the CONSTRUCTOR in a
+way that generated an ICE later.  Add a check for this case earlier in
+gimplify_modify_expr to avoid that issue.
+
+Bootstrapped with no regressions for x86_64-pc-linux-gnu.
+
+gcc/
+	* gimplify.cc (gimplify_modify_expr): Convert initialization from
+	a variable-size CONSTRUCTOR to memset before call to
+	gimplify_modify_expr_rhs.
+
+gcc/c/
+	* c-decl.cc (start_decl): Do not diagnose initialization of
+	variable-sized objects here.
+	* c-parser.cc (c_parser_braced_init): Add argument DECL.  All
+	callers changed.
+	(c_parser_initializer): Diagnose initialization of variable-sized
+	objects other than with braced initializer.
+	(c_parser_braced_init): Use pedwarn_c11 for empty initializer
+	braces and update diagnostic text.  Diagnose initialization of
+	variable-sized objects with nonempty braces.
+	* c-typeck.cc (digest_init): Update diagnostic for initialization
+	of variable-sized objects.
+	(really_start_incremental_init, set_designator)
+	(process_init_element): Update comments.
+	(pop_init_level): Allow scalar empty initializers.
+
+gcc/testsuite/
+	* gcc.dg/c11-empty-init-1.c, gcc.dg/c11-empty-init-2.c,
+	gcc.dg/c11-empty-init-3.c, gcc.dg/c2x-empty-init-1.c,
+	gcc.dg/c2x-empty-init-2.c, gcc.dg/c2x-empty-init-3.c,
+	gcc.dg/gnu2x-empty-init-1.c, gcc.dg/gnu2x-empty-init-2.c: New
+	tests.
+	* gcc.dg/torture/dfp-default-init-1.c: Also test empty
+	initializers.
+	* gcc.dg/init-bad-1.c, gcc.dg/noncompile/pr71583.c,
+	gcc.dg/pr61096-1.c, gcc.dg/vla-init-2.c, gcc.dg/vla-init-3.c,
+	gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Update expected
+	diagnostics.
+	* gcc.dg/ubsan/c-shift-1.c: Use nonempty initializers for VLA
+	initializations expected to be diagnosed.
+---
+ gcc/c/c-decl.cc                           | 20 +-----
+ gcc/c/c-parser.cc                         | 24 +++++--
+ gcc/c/c-typeck.cc                         | 23 ++++---
+ gcc/gimplify.cc                           | 15 +++++
+ gcc/testsuite/gcc.dg/c11-empty-init-1.c   | 25 +++++++
+ gcc/testsuite/gcc.dg/c11-empty-init-2.c   | 25 +++++++
+ gcc/testsuite/gcc.dg/c11-empty-init-3.c   | 25 +++++++
+ gcc/testsuite/gcc.dg/c2x-empty-init-1.c   | 80 +++++++++++++++++++++++
+ gcc/testsuite/gcc.dg/c2x-empty-init-2.c   | 18 +++++
+ gcc/testsuite/gcc.dg/c2x-empty-init-3.c   | 25 +++++++
+ gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c | 29 ++++++++
+ gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c | 16 +++++
+ gcc/testsuite/gcc.dg/init-bad-1.c         |  3 +-
+ gcc/testsuite/gcc.dg/noncompile/pr71583.c |  2 +-
+ gcc/testsuite/gcc.dg/pr61096-1.c          |  2 +-
+ gcc/testsuite/gcc.dg/ubsan/c-shift-1.c    | 12 ++--
+ gcc/testsuite/gcc.dg/vla-init-2.c         |  1 -
+ gcc/testsuite/gcc.dg/vla-init-3.c         |  1 -
+ 18 files changed, 301 insertions(+), 45 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c
+
+diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
+index 9d87a8cdb..685bb1757 100644
+--- a/gcc/c/c-decl.cc
++++ b/gcc/c/c-decl.cc
+@@ -5166,29 +5166,15 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
+ 	  initialized = false;
+ 	else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
+ 	  {
+-	    /* A complete type is ok if size is fixed.  */
+-
+-	    if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl)))
+-		|| C_DECL_VARIABLE_SIZE (decl))
+-	      {
+-		error ("variable-sized object may not be initialized");
+-		initialized = false;
+-	      }
++	    /* A complete type is ok if size is fixed.  If the size is
++	       variable, an empty initializer is OK and nonempty
++	       initializers will be diagnosed in the parser.  */
+ 	  }
+ 	else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
+ 	  {
+ 	    error ("variable %qD has initializer but incomplete type", decl);
+ 	    initialized = false;
+ 	  }
+-	else if (C_DECL_VARIABLE_SIZE (decl))
+-	  {
+-	    /* Although C99 is unclear about whether incomplete arrays
+-	       of VLAs themselves count as VLAs, it does not make
+-	       sense to permit them to be initialized given that
+-	       ordinary VLAs may not be initialized.  */
+-	    error ("variable-sized object may not be initialized");
+-	    initialized = false;
+-	  }
+       }
+ 
+   if (initialized)
+diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
+index 486f46e1c..6db535d11 100644
+--- a/gcc/c/c-parser.cc
++++ b/gcc/c/c-parser.cc
+@@ -1515,7 +1515,7 @@ static tree c_parser_simple_asm_expr (c_parser *);
+ static tree c_parser_gnu_attributes (c_parser *);
+ static struct c_expr c_parser_initializer (c_parser *, tree);
+ static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
+-					   struct obstack *);
++					   struct obstack *, tree);
+ static void c_parser_initelt (c_parser *, struct obstack *);
+ static void c_parser_initval (c_parser *, struct c_expr *,
+ 			      struct obstack *);
+@@ -5247,11 +5247,15 @@ static struct c_expr
+ c_parser_initializer (c_parser *parser, tree decl)
+ {
+   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+-    return c_parser_braced_init (parser, NULL_TREE, false, NULL);
++    return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
+   else
+     {
+       struct c_expr ret;
+       location_t loc = c_parser_peek_token (parser)->location;
++      if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
++	error_at (loc,
++		  "variable-sized object may not be initialized except "
++		  "with an empty initializer");
+       ret = c_parser_expr_no_commas (parser, NULL);
+       /* This is handled mostly by gimplify.cc, but we have to deal with
+ 	 not warning about int x = x; as it is a GCC extension to turn off
+@@ -5278,11 +5282,12 @@ location_t last_init_list_comma;
+    compound literal, and NULL_TREE for other initializers and for
+    nested braced lists.  NESTED_P is true for nested braced lists,
+    false for the list of a compound literal or the list that is the
+-   top-level initializer in a declaration.  */
++   top-level initializer in a declaration.  DECL is the declaration for
++   the top-level initializer for a declaration, otherwise NULL_TREE.  */
+ 
+ static struct c_expr
+ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
+-		      struct obstack *outer_obstack)
++		      struct obstack *outer_obstack, tree decl)
+ {
+   struct c_expr ret;
+   struct obstack braced_init_obstack;
+@@ -5300,10 +5305,15 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
+     really_start_incremental_init (type);
+   if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+     {
+-      pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces");
++      pedwarn_c11 (brace_loc, OPT_Wpedantic,
++		   "ISO C forbids empty initializer braces before C2X");
+     }
+   else
+     {
++      if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
++	error_at (brace_loc,
++		  "variable-sized object may not be initialized except "
++		  "with an empty initializer");
+       /* Parse a non-empty initializer list, possibly with a trailing
+ 	 comma.  */
+       while (true)
+@@ -5559,7 +5569,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
+ 
+   if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
+     init = c_parser_braced_init (parser, NULL_TREE, true,
+-				 braced_init_obstack);
++				 braced_init_obstack, NULL_TREE);
+   else
+     {
+       init = c_parser_expr_no_commas (parser, after);
+@@ -10312,7 +10322,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
+       error_at (type_loc, "compound literal has variable size");
+       type = error_mark_node;
+     }
+-  init = c_parser_braced_init (parser, type, false, NULL);
++  init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE);
+   finish_init ();
+   maybe_warn_string_init (type_loc, type, init);
+ 
+diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
+index 603b03fe1..0889dd4cb 100644
+--- a/gcc/c/c-typeck.cc
++++ b/gcc/c/c-typeck.cc
+@@ -8267,7 +8267,9 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
+ 
+   if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+     {
+-      error_init (init_loc, "variable-sized object may not be initialized");
++      error_init (init_loc,
++		  "variable-sized object may not be initialized except "
++		  "with an empty initializer");
+       return error_mark_node;
+     }
+ 
+@@ -8617,8 +8619,9 @@ really_start_incremental_init (tree type)
+ 	    constructor_max_index = integer_minus_one_node;
+ 
+ 	  /* constructor_max_index needs to be an INTEGER_CST.  Attempts
+-	     to initialize VLAs will cause a proper error; avoid tree
+-	     checking errors as well by setting a safe value.  */
++	     to initialize VLAs with a nonempty initializer will cause a
++	     proper error; avoid tree checking errors as well by setting a
++	     safe value.  */
+ 	  if (constructor_max_index
+ 	      && TREE_CODE (constructor_max_index) != INTEGER_CST)
+ 	    constructor_max_index = integer_minus_one_node;
+@@ -9000,12 +9003,14 @@ pop_init_level (location_t loc, int implicit,
+ 	   && !gnu_vector_type_p (constructor_type))
+     {
+       /* A nonincremental scalar initializer--just return
+-	 the element, after verifying there is just one.  */
++	 the element, after verifying there is just one.
++         Empty scalar initializers are supported in C2X.  */
+       if (vec_safe_is_empty (constructor_elements))
+ 	{
+-	  if (!constructor_erroneous && constructor_type != error_mark_node)
+-	    error_init (loc, "empty scalar initializer");
+-	  ret.value = error_mark_node;
++	  if (constructor_erroneous || constructor_type == error_mark_node)
++	    ret.value = error_mark_node;
++	  else
++	    ret.value = build_zero_cst (constructor_type);
+ 	}
+       else if (vec_safe_length (constructor_elements) != 1)
+ 	{
+@@ -9090,7 +9095,7 @@ set_designator (location_t loc, bool array,
+     return true;
+ 
+   /* Likewise for an initializer for a variable-size type.  Those are
+-     diagnosed in digest_init.  */
++     diagnosed in the parser, except for empty initializer braces.  */
+   if (COMPLETE_TYPE_P (constructor_type)
+       && TREE_CODE (TYPE_SIZE (constructor_type)) != INTEGER_CST)
+     return true;
+@@ -10251,7 +10256,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
+     return;
+ 
+   /* Ignore elements of an initializer for a variable-size type.
+-     Those are diagnosed in digest_init.  */
++     Those are diagnosed in the parser (empty initializer braces are OK).  */
+   if (COMPLETE_TYPE_P (constructor_type)
+       && !poly_int_tree_p (TYPE_SIZE (constructor_type)))
+     return;
+diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
+index a551c574a..91500e2fb 100644
+--- a/gcc/gimplify.cc
++++ b/gcc/gimplify.cc
+@@ -6026,6 +6026,21 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
+       return GS_ALL_DONE;
+     }
+ 
++  /* Convert initialization from an empty variable-size CONSTRUCTOR to
++     memset.  */
++  if (TREE_TYPE (*from_p) != error_mark_node
++      && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
++      && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
++      && TREE_CODE (*from_p) == CONSTRUCTOR
++      && CONSTRUCTOR_NELTS (*from_p) == 0)
++    {
++      maybe_with_size_expr (from_p);
++      gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
++      return gimplify_modify_expr_to_memset (expr_p,
++					     TREE_OPERAND (*from_p, 1),
++					     want_value, pre_p);
++    }
++
+   /* Insert pointer conversions required by the middle-end that are not
+      required by the frontend.  This fixes middle-end type checking for
+      for example gcc.dg/redecl-6.c.  */
+diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-1.c b/gcc/testsuite/gcc.dg/c11-empty-init-1.c
+new file mode 100644
+index 000000000..120c28225
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c11-empty-init-1.c
+@@ -0,0 +1,25 @@
++/* Test C11 does not support empty initializers.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c11 -pedantic-errors" } */
++
++struct s { int a; };
++struct s s = {}; /* { dg-error "empty initializer" } */
++int x = {}; /* { dg-error "empty initializer" } */
++float y = {}; /* { dg-error "empty initializer" } */
++void *p = {}; /* { dg-error "empty initializer" } */
++union u { int a; long b; };
++union u z = {}; /* { dg-error "empty initializer" } */
++int aa[2] = {}; /* { dg-error "empty initializer" } */
++
++void
++f (int a)
++{
++  int vla[a] = {}; /* { dg-error "empty initializer" } */
++  struct s as = {}; /* { dg-error "empty initializer" } */
++  int ax = {}; /* { dg-error "empty initializer" } */
++  float ay = {}; /* { dg-error "empty initializer" } */
++  void *ap = {}; /* { dg-error "empty initializer" } */
++  union u az = {}; /* { dg-error "empty initializer" } */
++  int aaa[2] = {}; /* { dg-error "empty initializer" } */
++  int t = (int) {}; /* { dg-error "empty initializer" } */
++}
+diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-2.c b/gcc/testsuite/gcc.dg/c11-empty-init-2.c
+new file mode 100644
+index 000000000..3ec7c512a
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c11-empty-init-2.c
+@@ -0,0 +1,25 @@
++/* Test C11 does not support empty initializers.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c11 -pedantic" } */
++
++struct s { int a; };
++struct s s = {}; /* { dg-warning "empty initializer" } */
++int x = {}; /* { dg-warning "empty initializer" } */
++float y = {}; /* { dg-warning "empty initializer" } */
++void *p = {}; /* { dg-warning "empty initializer" } */
++union u { int a; long b; };
++union u z = {}; /* { dg-warning "empty initializer" } */
++int aa[2] = {}; /* { dg-warning "empty initializer" } */
++
++void
++f (int a)
++{
++  int vla[a] = {}; /* { dg-warning "empty initializer" } */
++  struct s as = {}; /* { dg-warning "empty initializer" } */
++  int ax = {}; /* { dg-warning "empty initializer" } */
++  float ay = {}; /* { dg-warning "empty initializer" } */
++  void *ap = {}; /* { dg-warning "empty initializer" } */
++  union u az = {}; /* { dg-warning "empty initializer" } */
++  int aaa[2] = {}; /* { dg-warning "empty initializer" } */
++  int t = (int) {}; /* { dg-warning "empty initializer" } */
++}
+diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-3.c b/gcc/testsuite/gcc.dg/c11-empty-init-3.c
+new file mode 100644
+index 000000000..fd43fa789
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c11-empty-init-3.c
+@@ -0,0 +1,25 @@
++/* Test C11 does not support empty initializers.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c11 -Wc11-c2x-compat" } */
++
++struct s { int a; };
++struct s s = {}; /* { dg-warning "empty initializer" } */
++int x = {}; /* { dg-warning "empty initializer" } */
++float y = {}; /* { dg-warning "empty initializer" } */
++void *p = {}; /* { dg-warning "empty initializer" } */
++union u { int a; long b; };
++union u z = {}; /* { dg-warning "empty initializer" } */
++int aa[2] = {}; /* { dg-warning "empty initializer" } */
++
++void
++f (int a)
++{
++  int vla[a] = {}; /* { dg-warning "empty initializer" } */
++  struct s as = {}; /* { dg-warning "empty initializer" } */
++  int ax = {}; /* { dg-warning "empty initializer" } */
++  float ay = {}; /* { dg-warning "empty initializer" } */
++  void *ap = {}; /* { dg-warning "empty initializer" } */
++  union u az = {}; /* { dg-warning "empty initializer" } */
++  int aaa[2] = {}; /* { dg-warning "empty initializer" } */
++  int t = (int) {}; /* { dg-warning "empty initializer" } */
++}
+diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-1.c b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c
+new file mode 100644
+index 000000000..1487a2b23
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c
+@@ -0,0 +1,80 @@
++/* Test C2X support for empty initializers: valid use cases.  */
++/* { dg-do run } */
++/* { dg-options "-std=c2x -pedantic-errors" } */
++
++extern void exit (int);
++extern void abort (void);
++
++struct s { int a; };
++struct s s = {};
++int x = {};
++float y = {};
++void *p = {};
++union u { int a; long b; };
++union u z = {};
++int aa[2] = {};
++
++void
++f (int a)
++{
++  volatile int vla[a] = {};
++  struct s as = {};
++  int ax = {};
++  float ay = {};
++  void *ap = {};
++  union u az = {};
++  int aaa[2] = {};
++  for (int i = 0; i < a; i++)
++    if (vla[i] != 0)
++      abort ();
++  if (as.a != 0)
++    abort ();
++  if (ax != 0)
++    abort ();
++  if (ay != 0)
++    abort ();
++  if (ap != 0)
++    abort ();
++  if (az.a != 0)
++    abort ();
++  if (aaa[0] != 0)
++    abort ();
++  if (aaa[1] != 0)
++    abort ();
++  if ((int) {} != 0)
++    abort ();
++  if ((float) {} != 0)
++    abort ();
++  if ((struct s) {}.a != 0)
++    abort ();
++  if ((union u) {}.a != 0)
++    abort ();
++  if ((int [5]) {}[2] != 0)
++    abort ();
++  /* Overwrite contents of vla before second call to make it more likely stack
++     contents are nonzero if proper initialization did not occur.  */
++  for (int i = 0; i < a; i++)
++    vla[i] = -1;
++}
++
++int
++main (void)
++{
++  f (100);
++  f (100);
++  if (s.a != 0)
++    abort ();
++  if (x != 0)
++    abort ();
++  if (y != 0)
++    abort ();
++  if (p != 0)
++    abort ();
++  if (z.a != 0)
++    abort ();
++  if (aa[0] != 0)
++    abort ();
++  if (aa[1] != 0)
++    abort ();
++  exit (0);
++}
+diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-2.c b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c
+new file mode 100644
+index 000000000..0dc81ce5b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c
+@@ -0,0 +1,18 @@
++/* Test C2X support for empty initializers: invalid use cases.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c2x -pedantic-errors" } */
++
++/* Empty initialization is invalid for arrays of unknown size.  This is
++   diagnosed via the diagnostic for zero-size arrays.  */
++int x[] = {}; /* { dg-error "zero or negative size array" } */
++
++void
++f (int a)
++{
++  int x1[] = {}; /* { dg-error "zero or negative size array" } */
++  int x2[][a] = {}; /* { dg-error "zero or negative size array" } */
++  /* Nonempty VLA initializers are still invalid.  */
++  int x3[a] = { 0 }; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */
++  /* Variable-size compound literals are still invalid.  */
++  (void) (int [a]) {}; /* { dg-error "compound literal has variable size" } */
++}
+diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-3.c b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c
+new file mode 100644
+index 000000000..472f8169c
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c
+@@ -0,0 +1,25 @@
++/* Test empty initializers diagnosed in C2X mode with -Wc11-c2x-compat.  */
++/* { dg-do compile } */
++/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
++
++struct s { int a; };
++struct s s = {}; /* { dg-warning "empty initializer" } */
++int x = {}; /* { dg-warning "empty initializer" } */
++float y = {}; /* { dg-warning "empty initializer" } */
++void *p = {}; /* { dg-warning "empty initializer" } */
++union u { int a; long b; };
++union u z = {}; /* { dg-warning "empty initializer" } */
++int aa[2] = {}; /* { dg-warning "empty initializer" } */
++
++void
++f (int a)
++{
++  int vla[a] = {}; /* { dg-warning "empty initializer" } */
++  struct s as = {}; /* { dg-warning "empty initializer" } */
++  int ax = {}; /* { dg-warning "empty initializer" } */
++  float ay = {}; /* { dg-warning "empty initializer" } */
++  void *ap = {}; /* { dg-warning "empty initializer" } */
++  union u az = {}; /* { dg-warning "empty initializer" } */
++  int aaa[2] = {}; /* { dg-warning "empty initializer" } */
++  int t = (int) {}; /* { dg-warning "empty initializer" } */
++}
+diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c
+new file mode 100644
+index 000000000..e7dc9dfde
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c
+@@ -0,0 +1,29 @@
++/* Test C2X support for empty initializers: valid use cases with GNU
++   extensions.  */
++/* { dg-do run } */
++/* { dg-options "-std=gnu2x" } */
++
++extern void exit (int);
++extern void abort (void);
++
++void
++f (int a)
++{
++  struct s { volatile int x[a]; };
++  struct s b = {};
++  for (int i = 0; i < a; i++)
++    if (b.x[i] != 0)
++      abort ();
++  /* Overwrite contents of b.x before second call to make it more likely stack
++     contents are nonzero if proper initialization did not occur.  */
++  for (int i = 0; i < a; i++)
++    b.x[i] = -1;
++}
++
++int
++main (void)
++{
++  f (100);
++  f (100);
++  exit (0);
++}
+diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c
+new file mode 100644
+index 000000000..69ee4e36b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c
+@@ -0,0 +1,16 @@
++/* Test C2X support for empty initializers: invalid use cases with GNU
++   extensions.  */
++/* { dg-do compile } */
++/* { dg-options "-std=gnu2x" } */
++
++void
++f (int a)
++{
++  /* Make sure a non-braced initializer for a VLA-in-struct is still not
++     allowed.  */
++  struct s { int x[a]; };
++  struct s b;
++  for (int i = 0; i < a; i++)
++    b.x[i] = 0;
++  struct s c = b; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */
++}
+diff --git a/gcc/testsuite/gcc.dg/init-bad-1.c b/gcc/testsuite/gcc.dg/init-bad-1.c
+index 61734045f..0da10c315 100644
+--- a/gcc/testsuite/gcc.dg/init-bad-1.c
++++ b/gcc/testsuite/gcc.dg/init-bad-1.c
+@@ -21,8 +21,7 @@ char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of 'char' i
+ char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */
+ /* { dg-message "near init" "near" { target *-*-* } .-1 } */
+ 
+-int i = { }; /* { dg-error "empty scalar initializer" } */
+-/* { dg-message "near init" "near" { target *-*-* } .-1 } */
++int i = { };
+ 
+ int j = { 1 };
+ 
+diff --git a/gcc/testsuite/gcc.dg/noncompile/pr71583.c b/gcc/testsuite/gcc.dg/noncompile/pr71583.c
+index 5045b88b6..fe6e556ad 100644
+--- a/gcc/testsuite/gcc.dg/noncompile/pr71583.c
++++ b/gcc/testsuite/gcc.dg/noncompile/pr71583.c
+@@ -5,7 +5,7 @@ void
+ f (int i)
+ {
+   (int (*)[++i]) { int }; /* { dg-error "expected" } */
+-  (int (*)[++i]) { }; /* { dg-error "empty" } */
++  (int (*)[++i]) { };
+   (int (*)[++i]) { , }; /* { dg-error "expected" } */
+   (int (*)[++i]) { f () }; /* { dg-error "too few" } */
+ }
+diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c
+index e707904c0..f41789c5f 100644
+--- a/gcc/testsuite/gcc.dg/pr61096-1.c
++++ b/gcc/testsuite/gcc.dg/pr61096-1.c
+@@ -36,7 +36,7 @@ struct S s = { { 1 }, { 3 } }; /* { dg-error "23:extra brace group at end of ini
+ struct g g1 = { {0, { 1 } } }; /* { dg-error "21:initialization of flexible array member in a nested context" } */
+ struct g g2 = { .f[0] = 1 }; /* { dg-error "20:array index in non-array initializer" } */
+ 
+-__extension__ int a8 = { }; /* { dg-error "24:empty scalar initializer" } */
++__extension__ int a8 = { };
+ int a9[10] = {[1.2] = 2 }; /* { dg-error "16:array index in initializer not of integer type" } */
+ int a10[10] = {[e] = 2 }; /* { dg-error "17:nonconstant array index in initializer" } */
+ __extension__ int a11[10] = {[1 ... e] = 1 }; /* { dg-error "31:nonconstant array index in initializer" } */
+diff --git a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
+index 9d561016f..f88ee2de3 100644
+--- a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
++++ b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
+@@ -7,12 +7,12 @@ int
+ main (void)
+ {
+   /* None of the following should pass.  */
+-  int A[1 >> -1] = {};    /* { dg-error "variable-sized object may not be initialized" } */
+-  int B[-1 >> -1] = {};   /* { dg-error "variable-sized object may not be initialized" } */
+-  int D[1 << -1] = {};    /* { dg-error "variable-sized object may not be initialized" } */
+-  int E[-1 << -1] = {};   /* { dg-error "variable-sized object may not be initialized" } */
+-  int F[-1 >> 200] = {};  /* { dg-error "variable-sized object may not be initialized" } */
+-  int G[1 << 200] = {};   /* { dg-error "variable-sized object may not be initialized" } */
++  int A[1 >> -1] = { 0 };    /* { dg-error "variable-sized object may not be initialized" } */
++  int B[-1 >> -1] = { 0 };   /* { dg-error "variable-sized object may not be initialized" } */
++  int D[1 << -1] = { 0 };    /* { dg-error "variable-sized object may not be initialized" } */
++  int E[-1 << -1] = { 0 };   /* { dg-error "variable-sized object may not be initialized" } */
++  int F[-1 >> 200] = { 0 };  /* { dg-error "variable-sized object may not be initialized" } */
++  int G[1 << 200] = { 0 };   /* { dg-error "variable-sized object may not be initialized" } */
+ 
+   return 0;
+ }
+diff --git a/gcc/testsuite/gcc.dg/vla-init-2.c b/gcc/testsuite/gcc.dg/vla-init-2.c
+index 19fbffc26..f23630a36 100644
+--- a/gcc/testsuite/gcc.dg/vla-init-2.c
++++ b/gcc/testsuite/gcc.dg/vla-init-2.c
+@@ -7,4 +7,3 @@
+ 
+ const int i = 1;
+ void foo() { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */
+-/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */
+diff --git a/gcc/testsuite/gcc.dg/vla-init-3.c b/gcc/testsuite/gcc.dg/vla-init-3.c
+index 55e1de69c..a854f1268 100644
+--- a/gcc/testsuite/gcc.dg/vla-init-3.c
++++ b/gcc/testsuite/gcc.dg/vla-init-3.c
+@@ -6,4 +6,3 @@
+ /* { dg-options "" } */
+ 
+ void foo(int i) { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */
+-/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */
+-- 
+2.33.0
+
diff --git a/0235-Backport-SME-aarch64-Update-sizeless-tests-for-recen.patch b/0235-Backport-SME-aarch64-Update-sizeless-tests-for-recen.patch
new file mode 100644
index 0000000..04a80d1
--- /dev/null
+++ b/0235-Backport-SME-aarch64-Update-sizeless-tests-for-recen.patch
@@ -0,0 +1,115 @@
+From 67001778883e10110c505dd8876a447a19d1ac5e Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Wed, 31 Aug 2022 15:39:27 +0100
+Subject: [PATCH 136/157] [Backport][SME] aarch64: Update sizeless tests for
+ recent GNU C changes
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=de9805c08121a84ce368dccfe043a3f44c3ff13b
+
+The tests for sizeless SVE types include checks that the types
+are handled for initialisation purposes in the same way as scalars.
+GNU C and C2x now allow scalars to be initialised using empty braces,
+so this patch updates the SVE tests to match.
+
+gcc/testsuite/
+	* gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c: Update
+	tests for empty initializers.
+	* gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/sizeless-1.c: Likewise.
+	* gcc.target/aarch64/sve/acle/general-c/sizeless-2.c: Likewise.
+---
+ .../gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c     | 4 ++--
+ .../gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c     | 4 ++--
+ .../gcc.target/aarch64/sve/acle/general-c/sizeless-1.c        | 4 ++--
+ .../gcc.target/aarch64/sve/acle/general-c/sizeless-2.c        | 4 ++--
+ 4 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c
+index 285751eeb..9db953583 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c
+@@ -12,7 +12,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1,
+   /* Initialization.  */
+ 
+   svuint8_t init_sve_u1 = 0; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */
+-  svuint8_t init_sve_u2 = {}; /* { dg-error {empty scalar initializer} } */
++  svuint8_t init_sve_u2 = {};
+   svuint8_t init_sve_u3 = { sve_u1 };
+   svuint8_t init_sve_u4 = { gnu_u1 };
+   svuint8_t init_sve_u5 = { sve_s1 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'svint8_t'} } */
+@@ -31,7 +31,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1,
+ 
+   /* Compound literals.  */
+ 
+-  (svuint8_t) {}; /* { dg-error {empty scalar initializer} } */
++  (svuint8_t) {};
+   (svuint8_t) { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */
+   (svuint8_t) { sve_u1 };
+   (svuint8_t) { gnu_u1 };
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c
+index 306fd4780..c05b16406 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c
+@@ -12,7 +12,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1,
+   /* Initialization.  */
+ 
+   svuint8_t init_sve_u1 = 0; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */
+-  svuint8_t init_sve_u2 = {}; /* { dg-error {empty scalar initializer} } */
++  svuint8_t init_sve_u2 = {};
+   svuint8_t init_sve_u3 = { sve_u1 };
+   svuint8_t init_sve_u4 = { gnu_u1 };
+   svuint8_t init_sve_u5 = { sve_s1 };
+@@ -31,7 +31,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1,
+ 
+   /* Compound literals.  */
+ 
+-  (svuint8_t) {}; /* { dg-error {empty scalar initializer} } */
++  (svuint8_t) {};
+   (svuint8_t) { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */
+   (svuint8_t) { sve_u1 };
+   (svuint8_t) { gnu_u1 };
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
+index 7fc51e7ad..4b34a71c1 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
+@@ -66,14 +66,14 @@ statements (int n)
+ 
+   svint8_t init_sve_sc1 = sve_sc1;
+   svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */
+-  svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */
++  svint8_t init_sve_sc3 = {};
+ 
+   int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+   int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+ 
+   /* Compound literals.  */
+ 
+-  (svint8_t) {}; /* { dg-error {empty scalar initializer} } */
++  (svint8_t) {};
+   (svint8_t) { sve_sc1 };
+ 
+   (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
+index c575492c1..34dfd598e 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
+@@ -66,14 +66,14 @@ statements (int n)
+ 
+   svint8_t init_sve_sc1 = sve_sc1;
+   svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */
+-  svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */
++  svint8_t init_sve_sc3 = {};
+ 
+   int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+   int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+ 
+   /* Compound literals.  */
+ 
+-  (svint8_t) {}; /* { dg-error {empty scalar initializer} } */
++  (svint8_t) {};
+   (svint8_t) { sve_sc1 };
+ 
+   (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+-- 
+2.33.0
+
diff --git a/0236-Backport-SME-attribs-Namespace-aware-lookup_attribut.patch b/0236-Backport-SME-attribs-Namespace-aware-lookup_attribut.patch
new file mode 100644
index 0000000..f7a909f
--- /dev/null
+++ b/0236-Backport-SME-attribs-Namespace-aware-lookup_attribut.patch
@@ -0,0 +1,58 @@
+From dbe5a29054d4eb1e0f5173c8f2291569eac71c96 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Sat, 2 Dec 2023 13:49:55 +0000
+Subject: [PATCH 137/157] [Backport][SME] attribs: Namespace-aware
+ lookup_attribute_spec
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=df4643f90c45db2501c731d4fded60dc1426b484
+
+attribute_ignored_p already used a namespace-aware query
+to find the attribute_spec for an existing attribute:
+
+      const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attr));
+
+This patch does the same for other callers in the file.
+
+gcc/
+	* attribs.cc (comp_type_attributes): Pass the full TREE_PURPOSE
+	to lookup_attribute_spec, rather than just the name.
+	(remove_attributes_matching): Likewise.
+---
+ gcc/attribs.cc | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/attribs.cc b/gcc/attribs.cc
+index 8e2696bc5..1dbc30a95 100644
+--- a/gcc/attribs.cc
++++ b/gcc/attribs.cc
+@@ -1417,7 +1417,7 @@ comp_type_attributes (const_tree type1, const_tree type2)
+       const struct attribute_spec *as;
+       const_tree attr;
+ 
+-      as = lookup_attribute_spec (get_attribute_name (a));
++      as = lookup_attribute_spec (TREE_PURPOSE (a));
+       if (!as || as->affects_type_identity == false)
+ 	continue;
+ 
+@@ -1431,7 +1431,7 @@ comp_type_attributes (const_tree type1, const_tree type2)
+ 	{
+ 	  const struct attribute_spec *as;
+ 
+-	  as = lookup_attribute_spec (get_attribute_name (a));
++	  as = lookup_attribute_spec (TREE_PURPOSE (a));
+ 	  if (!as || as->affects_type_identity == false)
+ 	    continue;
+ 
+@@ -1473,8 +1473,7 @@ remove_attributes_matching (tree attrs, Predicate predicate)
+   const_tree start = attrs;
+   for (const_tree attr = attrs; attr; attr = TREE_CHAIN (attr))
+     {
+-      tree name = get_attribute_name (attr);
+-      const attribute_spec *as = lookup_attribute_spec (name);
++      const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attr));
+       const_tree end;
+       if (!predicate (attr, as))
+ 	end = attr;
+-- 
+2.33.0
+
diff --git a/0237-Backport-SME-c-family-ICE-with-gnu-nocf_check-PR1069.patch b/0237-Backport-SME-c-family-ICE-with-gnu-nocf_check-PR1069.patch
new file mode 100644
index 0000000..3d8cde6
--- /dev/null
+++ b/0237-Backport-SME-c-family-ICE-with-gnu-nocf_check-PR1069.patch
@@ -0,0 +1,281 @@
+From 6f42edc5035b7f7e96730dca19757b148e1be70c Mon Sep 17 00:00:00 2001
+From: Marek Polacek 
+Date: Thu, 29 Sep 2022 17:49:32 -0400
+Subject: [PATCH 138/157] [Backport][SME] c-family: ICE with
+ [[gnu::nocf_check]] [PR106937]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=67efffec943656a509e036cd3c785a5c3d6885e1
+
+When getting the name of an attribute, we ought to use
+get_attribute_name, which handles both [[]] and __attribute__(())
+forms.  Failure to do so may result in an ICE, like here.
+
+pp_c_attributes_display wasn't able to print the [[]] form of
+attributes, so this patch teaches it to.
+
+When printing a pointer to function with a standard attribute, the attribute
+should be printed after the parameter-list.  With this patch we print:
+
+  aka 'void (*)(int) [[gnu::nocf_check]]'
+
+or, in C++ with noexcept:
+
+  aka 'void (*)(int) noexcept [[gnu::nocf_check]]'
+
+pp_c_attributes has been unused since its introduction in r56273 so
+this patch removes it.
+
+	PR c++/106937
+
+gcc/c-family/ChangeLog:
+
+	* c-pretty-print.cc (pp_c_specifier_qualifier_list): Print only GNU
+	attributes here.
+	(c_pretty_printer::direct_abstract_declarator): Print the standard [[]]
+	attributes here.
+	(pp_c_attributes): Remove.
+	(pp_c_attributes_display): Print the [[]] form if appropriate.  Use
+	get_attribute_name.  Don't print a trailing space when printing the
+	[[]] form.
+	* c-pretty-print.h (pp_c_attributes): Remove.
+
+gcc/cp/ChangeLog:
+
+	* error.cc: Include "attribs.h".
+	(dump_type_prefix): Print only GNU attributes here.
+	(dump_type_suffix): Print standard attributes here.
+
+gcc/testsuite/ChangeLog:
+
+	* c-c++-common/pointer-to-fn1.c: New test.
+---
+ gcc/c-family/c-pretty-print.cc              | 96 ++++++++++++---------
+ gcc/c-family/c-pretty-print.h               |  1 -
+ gcc/cp/error.cc                             | 16 +++-
+ gcc/testsuite/c-c++-common/pointer-to-fn1.c | 18 ++++
+ 4 files changed, 86 insertions(+), 45 deletions(-)
+ create mode 100644 gcc/testsuite/c-c++-common/pointer-to-fn1.c
+
+diff --git a/gcc/c-family/c-pretty-print.cc b/gcc/c-family/c-pretty-print.cc
+index 71a0cb510..4d60627b3 100644
+--- a/gcc/c-family/c-pretty-print.cc
++++ b/gcc/c-family/c-pretty-print.cc
+@@ -462,7 +462,12 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t)
+ 	  {
+ 	    pp_c_whitespace (pp);
+ 	    pp_c_left_paren (pp);
+-	    pp_c_attributes_display (pp, TYPE_ATTRIBUTES (pointee));
++	    /* If we're dealing with the GNU form of attributes, print this:
++		 void (__attribute__((noreturn)) *f) ();
++	       If it is the standard [[]] attribute, we'll print the attribute
++	       in c_pretty_printer::direct_abstract_declarator/FUNCTION_TYPE.  */
++	    if (!cxx11_attribute_p (TYPE_ATTRIBUTES (pointee)))
++	      pp_c_attributes_display (pp, TYPE_ATTRIBUTES (pointee));
+ 	  }
+ 	else if (!c_dialect_cxx ())
+ 	  pp_c_whitespace (pp);
+@@ -591,6 +596,13 @@ c_pretty_printer::direct_abstract_declarator (tree t)
+     case FUNCTION_TYPE:
+       pp_c_parameter_type_list (this, t);
+       direct_abstract_declarator (TREE_TYPE (t));
++      /* If this is the standard [[]] attribute, print
++	 void (*)() [[noreturn]];  */
++      if (cxx11_attribute_p (TYPE_ATTRIBUTES (t)))
++	{
++	  pp_space (this);
++	  pp_c_attributes_display (this, TYPE_ATTRIBUTES (t));
++	}
+       break;
+ 
+     case ARRAY_TYPE:
+@@ -845,32 +857,7 @@ c_pretty_printer::declaration (tree t)
+   pp_c_init_declarator (this, t);
+ }
+ 
+-/* Pretty-print ATTRIBUTES using GNU C extension syntax.  */
+-
+-void
+-pp_c_attributes (c_pretty_printer *pp, tree attributes)
+-{
+-  if (attributes == NULL_TREE)
+-    return;
+-
+-  pp_c_ws_string (pp, "__attribute__");
+-  pp_c_left_paren (pp);
+-  pp_c_left_paren (pp);
+-  for (; attributes != NULL_TREE; attributes = TREE_CHAIN (attributes))
+-    {
+-      pp_tree_identifier (pp, TREE_PURPOSE (attributes));
+-      if (TREE_VALUE (attributes))
+-	pp_c_call_argument_list (pp, TREE_VALUE (attributes));
+-
+-      if (TREE_CHAIN (attributes))
+-	pp_separate_with (pp, ',');
+-    }
+-  pp_c_right_paren (pp);
+-  pp_c_right_paren (pp);
+-}
+-
+-/* Pretty-print ATTRIBUTES using GNU C extension syntax for attributes
+-   marked to be displayed on disgnostic.  */
++/* Pretty-print ATTRIBUTES marked to be displayed on diagnostic.  */
+ 
+ void
+ pp_c_attributes_display (c_pretty_printer *pp, tree a)
+@@ -880,10 +867,12 @@ pp_c_attributes_display (c_pretty_printer *pp, tree a)
+   if (a == NULL_TREE)
+     return;
+ 
++  const bool std_p = cxx11_attribute_p (a);
++
+   for (; a != NULL_TREE; a = TREE_CHAIN (a))
+     {
+-      const struct attribute_spec *as;
+-      as = lookup_attribute_spec (TREE_PURPOSE (a));
++      const struct attribute_spec *as
++	= lookup_attribute_spec (get_attribute_name (a));
+       if (!as || as->affects_type_identity == false)
+         continue;
+       if (c_dialect_cxx ()
+@@ -891,26 +880,47 @@ pp_c_attributes_display (c_pretty_printer *pp, tree a)
+ 	/* In C++ transaction_safe is printed at the end of the declarator.  */
+ 	continue;
+       if (is_first)
+-       {
+-         pp_c_ws_string (pp, "__attribute__");
+-         pp_c_left_paren (pp);
+-         pp_c_left_paren (pp);
+-         is_first = false;
+-       }
++	{
++	  if (std_p)
++	    {
++	      pp_c_left_bracket (pp);
++	      pp_c_left_bracket (pp);
++	    }
++	  else
++	    {
++	      pp_c_ws_string (pp, "__attribute__");
++	      pp_c_left_paren (pp);
++	      pp_c_left_paren (pp);
++	    }
++	  is_first = false;
++	}
+       else
+-       {
+-         pp_separate_with (pp, ',');
+-       }
+-      pp_tree_identifier (pp, TREE_PURPOSE (a));
++	pp_separate_with (pp, ',');
++      tree ns;
++      if (std_p && (ns = get_attribute_namespace (a)))
++	{
++	  pp_tree_identifier (pp, ns);
++	  pp_colon (pp);
++	  pp_colon (pp);
++	}
++      pp_tree_identifier (pp, get_attribute_name (a));
+       if (TREE_VALUE (a))
+-       pp_c_call_argument_list (pp, TREE_VALUE (a));
++	pp_c_call_argument_list (pp, TREE_VALUE (a));
+     }
+ 
+   if (!is_first)
+     {
+-      pp_c_right_paren (pp);
+-      pp_c_right_paren (pp);
+-      pp_c_whitespace (pp);
++      if (std_p)
++	{
++	  pp_c_right_bracket (pp);
++	  pp_c_right_bracket (pp);
++	}
++      else
++	{
++	  pp_c_right_paren (pp);
++	  pp_c_right_paren (pp);
++	  pp_c_whitespace (pp);
++	}
+     }
+ }
+ 
+diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h
+index ba7624dab..6a9090919 100644
+--- a/gcc/c-family/c-pretty-print.h
++++ b/gcc/c-family/c-pretty-print.h
+@@ -119,7 +119,6 @@ void pp_c_space_for_pointer_operator (c_pretty_printer *, tree);
+ /* Declarations.  */
+ void pp_c_tree_decl_identifier (c_pretty_printer *, tree);
+ void pp_c_function_definition (c_pretty_printer *, tree);
+-void pp_c_attributes (c_pretty_printer *, tree);
+ void pp_c_attributes_display (c_pretty_printer *, tree);
+ void pp_c_cv_qualifiers (c_pretty_printer *pp, int qualifiers, bool func_type);
+ void pp_c_type_qualifier_list (c_pretty_printer *, tree);
+diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
+index 1e944ca3f..eeb12a7b4 100644
+--- a/gcc/cp/error.cc
++++ b/gcc/cp/error.cc
+@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "internal-fn.h"
+ #include "gcc-rich-location.h"
+ #include "cp-name-hint.h"
++#include "attribs.h"
+ 
+ #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
+ #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
+@@ -896,7 +897,12 @@ dump_type_prefix (cxx_pretty_printer *pp, tree t, int flags)
+ 	  {
+ 	    pp_cxx_whitespace (pp);
+ 	    pp_cxx_left_paren (pp);
+-	    pp_c_attributes_display (pp, TYPE_ATTRIBUTES (sub));
++	    /* If we're dealing with the GNU form of attributes, print this:
++		 void (__attribute__((noreturn)) *f) ();
++	       If it is the standard [[]] attribute, we'll print the attribute
++	       in dump_type_suffix.  */
++	    if (!cxx11_attribute_p (TYPE_ATTRIBUTES (sub)))
++	      pp_c_attributes_display (pp, TYPE_ATTRIBUTES (sub));
+ 	  }
+ 	if (TYPE_PTR_P (t))
+ 	  pp_star (pp);
+@@ -1029,6 +1035,14 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)
+ 	if (tx_safe_fn_type_p (t))
+ 	  pp_cxx_ws_string (pp, "transaction_safe");
+ 	dump_exception_spec (pp, TYPE_RAISES_EXCEPTIONS (t), flags);
++	/* If this is the standard [[]] attribute, print
++	     void (*)() [[noreturn]];  */
++	if (cxx11_attribute_p (TYPE_ATTRIBUTES (t)))
++	  {
++	    pp_space (pp);
++	    pp_c_attributes_display (pp, TYPE_ATTRIBUTES (t));
++	    pp->padding = pp_before;
++	  }
+ 	dump_type_suffix (pp, TREE_TYPE (t), flags);
+ 	break;
+       }
+diff --git a/gcc/testsuite/c-c++-common/pointer-to-fn1.c b/gcc/testsuite/c-c++-common/pointer-to-fn1.c
+new file mode 100644
+index 000000000..975885462
+--- /dev/null
++++ b/gcc/testsuite/c-c++-common/pointer-to-fn1.c
+@@ -0,0 +1,18 @@
++/* PR c++/106937 */
++/* { dg-options "-fcf-protection" } */
++/* { dg-additional-options "-std=c++11 -fpermissive" { target c++ } } */
++/* Test printing a pointer to function with attribute.  */
++
++__attribute__((nocf_check)) typedef void (*FPA1)();
++[[gnu::nocf_check]] typedef void (*FPA2)(int);
++typedef void (*FP1)();
++typedef void (*FP2)(int);
++
++void
++g (FP1 f1, FP2 f2)
++{
++  FPA1 p1 = f1; // { dg-warning {aka 'void \(__attribute__\(\(nocf_check\)\) \*\)\(\)'} }
++  FPA2 p2 = f2; // { dg-warning {aka 'void \(\*\)\(int\) \[\[gnu::nocf_check\]\]'} }
++  FP1 p3 = p1; // { dg-warning {aka 'void \(__attribute__\(\(nocf_check\)\) \*\)\(\)'} }
++  FP2 p4 = p2; // { dg-warning {aka 'void \(\*\)\(int\) \[\[gnu::nocf_check\]\]'} }
++}
+-- 
+2.33.0
+
diff --git a/0238-Backport-SME-AArch64-Fix-assert-in-aarch64_move_imm-.patch b/0238-Backport-SME-AArch64-Fix-assert-in-aarch64_move_imm-.patch
new file mode 100644
index 0000000..58c1071
--- /dev/null
+++ b/0238-Backport-SME-AArch64-Fix-assert-in-aarch64_move_imm-.patch
@@ -0,0 +1,35 @@
+From d13efe98cafa04aeb24f8e0f695e648887986228 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra 
+Date: Wed, 7 Dec 2022 14:16:24 +0000
+Subject: [PATCH 139/157] [Backport][SME] AArch64: Fix assert in
+ aarch64_move_imm [PR108006]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=952c8a1dc6235dc49ab207a7f18f63d2bc97fbc9
+
+Ensure we only pass SI/DImode which fixes the assert.
+
+gcc/
+	PR target/108006
+	* config/aarch64/aarch64.cc (aarch64_expand_sve_const_vector):
+	Fix call to aarch64_move_imm to use SI/DI.
+---
+ gcc/config/aarch64/aarch64.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 0117a3e12..309ecc3d9 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -7925,7 +7925,8 @@ aarch64_expand_sve_const_vector (rtx target, rtx src)
+ 	  /* If the integer can be moved into a general register by a
+ 	     single instruction, do that and duplicate the result.  */
+ 	  if (CONST_INT_P (elt_value)
+-	      && aarch64_move_imm (INTVAL (elt_value), elt_mode))
++	      && aarch64_move_imm (INTVAL (elt_value),
++				   encoded_bits <= 32 ? SImode : DImode))
+ 	    {
+ 	      elt_value = force_reg (elt_mode, elt_value);
+ 	      return expand_vector_broadcast (mode, elt_value);
+-- 
+2.33.0
+
diff --git a/0239-Backport-SME-testsuite-Only-run-fcf-protection-test-.patch b/0239-Backport-SME-testsuite-Only-run-fcf-protection-test-.patch
new file mode 100644
index 0000000..df5e047
--- /dev/null
+++ b/0239-Backport-SME-testsuite-Only-run-fcf-protection-test-.patch
@@ -0,0 +1,37 @@
+From 071f26ce18db5a09cbae0607b065028a09a856ac Mon Sep 17 00:00:00 2001
+From: Marek Polacek 
+Date: Tue, 11 Oct 2022 12:51:40 -0400
+Subject: [PATCH 140/157] [Backport][SME] testsuite: Only run -fcf-protection
+ test on i?86/x86_64 [PR107213]
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=cc694f45087c892e69ebbb177203c708f00b1bc7
+
+This test fails on non-i?86/x86_64 targets because on those targets
+we get
+
+  error: '-fcf-protection=full' is not supported for this target
+
+so this patch limits where the test is run.
+
+	PR testsuite/107213
+
+gcc/testsuite/ChangeLog:
+
+	* c-c++-common/pointer-to-fn1.c: Only run on i?86/x86_64.
+---
+ gcc/testsuite/c-c++-common/pointer-to-fn1.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/testsuite/c-c++-common/pointer-to-fn1.c b/gcc/testsuite/c-c++-common/pointer-to-fn1.c
+index 975885462..e2f948d82 100644
+--- a/gcc/testsuite/c-c++-common/pointer-to-fn1.c
++++ b/gcc/testsuite/c-c++-common/pointer-to-fn1.c
+@@ -1,4 +1,5 @@
+ /* PR c++/106937 */
++/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+ /* { dg-options "-fcf-protection" } */
+ /* { dg-additional-options "-std=c++11 -fpermissive" { target c++ } } */
+ /* Test printing a pointer to function with attribute.  */
+-- 
+2.33.0
+
diff --git a/0240-Backport-SME-Fix-PRs-106764-106765-and-107307-all-IC.patch b/0240-Backport-SME-Fix-PRs-106764-106765-and-107307-all-IC.patch
new file mode 100644
index 0000000..d048c48
--- /dev/null
+++ b/0240-Backport-SME-Fix-PRs-106764-106765-and-107307-all-IC.patch
@@ -0,0 +1,113 @@
+From 202ebc25e509ae0a2ac7d05c822cf6a8a817e49a Mon Sep 17 00:00:00 2001
+From: Andrew Pinski 
+Date: Thu, 17 Nov 2022 22:08:07 +0000
+Subject: [PATCH 141/157] [Backport][SME] Fix PRs 106764, 106765, and 107307,
+ all ICE after invalid re-declaration
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=bd0c9d9e706adaeea0d96152daade0a6819a8715
+
+The problem here is the gimplifier returns GS_ERROR but
+in some cases we don't check that soon enough and try
+to do other work which could crash.
+So the fix in these two cases is to return GS_ERROR
+early if the gimplify_* functions had return GS_ERROR.
+
+OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
+
+Thanks,
+Andrew Pinski
+
+gcc/ChangeLog:
+
+	PR c/106764
+	PR c/106765
+	PR c/107307
+	* gimplify.cc (gimplify_compound_lval): Return GS_ERROR
+	if gimplify_expr had return GS_ERROR.
+	(gimplify_call_expr): Likewise.
+
+gcc/testsuite/ChangeLog:
+
+	PR c/106764
+	PR c/106765
+	PR c/107307
+	* gcc.dg/redecl-19.c: New test.
+	* gcc.dg/redecl-20.c: New test.
+	* gcc.dg/redecl-21.c: New test.
+---
+ gcc/gimplify.cc                  | 5 +++++
+ gcc/testsuite/gcc.dg/redecl-19.c | 5 +++++
+ gcc/testsuite/gcc.dg/redecl-20.c | 9 +++++++++
+ gcc/testsuite/gcc.dg/redecl-21.c | 9 +++++++++
+ 4 files changed, 28 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/redecl-19.c
+ create mode 100644 gcc/testsuite/gcc.dg/redecl-20.c
+ create mode 100644 gcc/testsuite/gcc.dg/redecl-21.c
+
+diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
+index 91500e2fb..e9f527850 100644
+--- a/gcc/gimplify.cc
++++ b/gcc/gimplify.cc
+@@ -3272,6 +3272,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
+   tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
+ 			fallback | fb_lvalue);
+   ret = MIN (ret, tret);
++  if (ret == GS_ERROR)
++    return GS_ERROR;
+ 
+   /* Step 2a: if we have component references we do not support on
+      registers then make sure the base isn't a register.  Of course
+@@ -3664,6 +3666,9 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
+   ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
+ 		       is_gimple_call_addr, fb_rvalue);
+ 
++  if (ret == GS_ERROR)
++    return GS_ERROR;
++
+   nargs = call_expr_nargs (*expr_p);
+ 
+   /* Get argument types for verification.  */
+diff --git a/gcc/testsuite/gcc.dg/redecl-19.c b/gcc/testsuite/gcc.dg/redecl-19.c
+new file mode 100644
+index 000000000..cc1068544
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/redecl-19.c
+@@ -0,0 +1,5 @@
++/* We used to ICE in the gimplifier, PR 106764 */
++/* { dg-do compile } */
++/* { dg-options "-w" } */
++(*a)(); // { dg-note "" }
++b(){a()} a; // { dg-error "" }
+diff --git a/gcc/testsuite/gcc.dg/redecl-20.c b/gcc/testsuite/gcc.dg/redecl-20.c
+new file mode 100644
+index 000000000..07f52115e
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/redecl-20.c
+@@ -0,0 +1,9 @@
++/* We used to ICE in the gimplifier, PR 107307 */
++// { dg-do compile }
++// { dg-options "-w" }
++void f ()
++{
++  const struct { int a[1]; } b; // { dg-note "" }
++  int *c = b.a;
++  int *b; // { dg-error "" }
++}
+diff --git a/gcc/testsuite/gcc.dg/redecl-21.c b/gcc/testsuite/gcc.dg/redecl-21.c
+new file mode 100644
+index 000000000..2f2a6548a
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/redecl-21.c
+@@ -0,0 +1,9 @@
++/* We used to ICE in the gimplifier, PR 106765 */
++/* { dg-do compile } */
++/* { dg-options "-w" } */
++struct a {
++  int b
++} c() {
++  struct a a; // { dg-note "" }
++  a.b;
++  d a; // { dg-error "" }
+-- 
+2.33.0
+
diff --git a/0241-Backport-SME-aarch64-Remove-expected-error-for-compo.patch b/0241-Backport-SME-aarch64-Remove-expected-error-for-compo.patch
new file mode 100644
index 0000000..5b03a5d
--- /dev/null
+++ b/0241-Backport-SME-aarch64-Remove-expected-error-for-compo.patch
@@ -0,0 +1,43 @@
+From bc42a8bdab7b2ffeb81441c7c8a9a1215d8502ee Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Thu, 26 Jan 2023 15:51:00 +0000
+Subject: [PATCH 142/157] [Backport][SME] aarch64: Remove expected error for
+ compound literals
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=96fbe541481fcc7d1a8884fb8dbefd7979eb9543
+
+GCC no longer treats empty compound literals as an error
+(see 14cfa01755a66afbae2539f8b5796c960ddcecc6).
+
+gcc/testsuite/
+	* gcc.target/aarch64/bfloat16_scalar_typecheck.c: Accept empty
+	compound literals.
+---
+ gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
+index 7c9188cf2..f4ae68028 100644
+--- a/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
++++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_scalar_typecheck.c
+@@ -40,7 +40,7 @@ bfloat16_t footest (bfloat16_t scalar0)
+   short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+   double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type 'bfloat16_t'} } */
+ 
+-  bfloat16_t scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */
++  bfloat16_t scalar2_1 = {};
+   bfloat16_t scalar2_2 = { glob_bfloat };
+   bfloat16_t scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+   bfloat16_t scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+@@ -92,7 +92,7 @@ bfloat16_t footest (bfloat16_t scalar0)
+ 
+   /* Compound literals.  */
+ 
+-  (bfloat16_t) {}; /* { dg-error {empty scalar initializer} } */
++  (bfloat16_t) {};
+   (bfloat16_t) { glob_bfloat };
+   (bfloat16_t) { 0 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+   (bfloat16_t) { 0.1 }; /* { dg-error {invalid conversion to type 'bfloat16_t'} } */
+-- 
+2.33.0
+
diff --git a/0242-Backport-SME-aarch64-Remove-redundant-builtins-code.patch b/0242-Backport-SME-aarch64-Remove-redundant-builtins-code.patch
new file mode 100644
index 0000000..85f8c59
--- /dev/null
+++ b/0242-Backport-SME-aarch64-Remove-redundant-builtins-code.patch
@@ -0,0 +1,264 @@
+From 42bfa9a26205da222cebbe830168b6f0b5e668b4 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Tue, 12 Jul 2022 12:59:25 +0100
+Subject: [PATCH 143/157] [Backport][SME] aarch64: Remove redundant builtins
+ code
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=e80daf04c8888f527d2fc7f6cbcd1b4c853dcd04
+
+aarch64_builtin_vectorized_function handles some built-in functions
+that already have equivalent internal functions.  This seems to be
+redundant now, since the target builtins that it chooses are mapped
+to the same optab patterns as the internal functions.
+
+gcc/
+	* config/aarch64/aarch64-builtins.cc
+	(aarch64_builtin_vectorized_function): Remove handling of
+	floor, ceil, trunc, round, nearbyint, sqrt, clz and ctz.
+
+gcc/testsuite/
+	* gcc.target/aarch64/vect_unary_1.c: New test.
+---
+ gcc/config/aarch64/aarch64-builtins.cc        |  32 ---
+ .../gcc.target/aarch64/vect_unary_1.c         | 186 ++++++++++++++++++
+ 2 files changed, 186 insertions(+), 32 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/vect_unary_1.c
+
+diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
+index 37bb3af48..23a84cd53 100644
+--- a/gcc/config/aarch64/aarch64-builtins.cc
++++ b/gcc/config/aarch64/aarch64-builtins.cc
+@@ -2653,38 +2653,6 @@ aarch64_builtin_vectorized_function (unsigned int fn, tree type_out,
+   switch (fn)
+     {
+ #undef AARCH64_CHECK_BUILTIN_MODE
+-#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
+-  (out_mode == V##C##N##Fmode && in_mode == V##C##N##Fmode)
+-    CASE_CFN_FLOOR:
+-      return AARCH64_FIND_FRINT_VARIANT (floor);
+-    CASE_CFN_CEIL:
+-      return AARCH64_FIND_FRINT_VARIANT (ceil);
+-    CASE_CFN_TRUNC:
+-      return AARCH64_FIND_FRINT_VARIANT (btrunc);
+-    CASE_CFN_ROUND:
+-      return AARCH64_FIND_FRINT_VARIANT (round);
+-    CASE_CFN_NEARBYINT:
+-      return AARCH64_FIND_FRINT_VARIANT (nearbyint);
+-    CASE_CFN_SQRT:
+-      return AARCH64_FIND_FRINT_VARIANT (sqrt);
+-#undef AARCH64_CHECK_BUILTIN_MODE
+-#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
+-  (out_mode == V##C##SImode && in_mode == V##C##N##Imode)
+-    CASE_CFN_CLZ:
+-      {
+-	if (AARCH64_CHECK_BUILTIN_MODE (4, S))
+-	  return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
+-	return NULL_TREE;
+-      }
+-    CASE_CFN_CTZ:
+-      {
+-	if (AARCH64_CHECK_BUILTIN_MODE (2, S))
+-	  return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si];
+-	else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
+-	  return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si];
+-	return NULL_TREE;
+-      }
+-#undef AARCH64_CHECK_BUILTIN_MODE
+ #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
+   (out_mode == V##C##N##Imode && in_mode == V##C##N##Fmode)
+     CASE_CFN_IFLOOR:
+diff --git a/gcc/testsuite/gcc.target/aarch64/vect_unary_1.c b/gcc/testsuite/gcc.target/aarch64/vect_unary_1.c
+new file mode 100644
+index 000000000..8516808be
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/vect_unary_1.c
+@@ -0,0 +1,186 @@
++/* { dg-options "-O3 --save-temps" } */
++/* { dg-final { check-function-bodies "**" "" "" } } */
++
++#include 
++
++#define TEST2(OUT, NAME, IN)						\
++OUT __attribute__((vector_size(sizeof(OUT) * 2)))			\
++test2_##OUT##_##NAME##_##IN (float dummy,				\
++			     IN __attribute__((vector_size(sizeof(IN) * 2))) y) \
++{									\
++  OUT __attribute__((vector_size(sizeof(OUT) * 2))) x;			\
++  x[0] = __builtin_##NAME (y[0]);					\
++  x[1] = __builtin_##NAME (y[1]);					\
++  return x;								\
++}									\
++
++#define TEST4(OUT, NAME, IN)						\
++OUT __attribute__((vector_size(16)))					\
++test4_##OUT##_##NAME##_##IN (float dummy,				\
++			     IN __attribute__((vector_size(16))) y)	\
++{									\
++  OUT __attribute__((vector_size(16))) x;				\
++  x[0] = __builtin_##NAME (y[0]);					\
++  x[1] = __builtin_##NAME (y[1]);					\
++  x[2] = __builtin_##NAME (y[2]);					\
++  x[3] = __builtin_##NAME (y[3]);					\
++  return x;								\
++}									\
++
++/*
++** test2_float_truncf_float:
++**	frintz	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (float, truncf, float)
++
++/*
++** test2_double_trunc_double:
++**	frintz	v0.2d, v1.2d
++**	ret
++*/
++TEST2 (double, trunc, double)
++
++/*
++** test4_float_truncf_float:
++**	frintz	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (float, truncf, float)
++
++/*
++** test2_float_roundf_float:
++**	frinta	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (float, roundf, float)
++
++/*
++** test2_double_round_double:
++**	frinta	v0.2d, v1.2d
++**	ret
++*/
++TEST2 (double, round, double)
++
++/*
++** test4_float_roundf_float:
++**	frinta	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (float, roundf, float)
++
++/*
++** test2_float_nearbyintf_float:
++**	frinti	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (float, nearbyintf, float)
++
++/*
++** test2_double_nearbyint_double:
++**	frinti	v0.2d, v1.2d
++**	ret
++*/
++TEST2 (double, nearbyint, double)
++
++/*
++** test4_float_nearbyintf_float:
++**	frinti	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (float, nearbyintf, float)
++
++/*
++** test2_float_floorf_float:
++**	frintm	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (float, floorf, float)
++
++/*
++** test2_double_floor_double:
++**	frintm	v0.2d, v1.2d
++**	ret
++*/
++TEST2 (double, floor, double)
++
++/*
++** test4_float_floorf_float:
++**	frintm	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (float, floorf, float)
++
++/*
++** test2_float_ceilf_float:
++**	frintp	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (float, ceilf, float)
++
++/*
++** test2_double_ceil_double:
++**	frintp	v0.2d, v1.2d
++**	ret
++*/
++TEST2 (double, ceil, double)
++
++/*
++** test4_float_ceilf_float:
++**	frintp	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (float, ceilf, float)
++
++/*
++** test2_float_rintf_float:
++**	frintx	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (float, rintf, float)
++
++/*
++** test2_double_rint_double:
++**	frintx	v0.2d, v1.2d
++**	ret
++*/
++TEST2 (double, rint, double)
++
++/*
++** test4_float_rintf_float:
++**	frintx	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (float, rintf, float)
++
++/*
++** test2_int_clz_int:
++**	clz	v0.2s, v1.2s
++**	ret
++*/
++TEST2 (int, clz, int)
++
++/*
++** test4_int_clz_int:
++**	clz	v0.4s, v1.4s
++**	ret
++*/
++TEST4 (int, clz, int)
++
++/*
++** test2_int_ctz_int:
++**	rev32	(v[0-9]+).8b, v1.8b
++**	rbit	(v[0-9]+).8b, \1.8b
++**	clz	v0.2s, \2.2s
++**	ret
++*/
++TEST2 (int, ctz, int)
++
++/*
++** test4_int_ctz_int:
++**	rev32	(v[0-9]+).16b, v1.16b
++**	rbit	(v[0-9]+).16b, \1.16b
++**	clz	v0.4s, \2.4s
++**	ret
++*/
++TEST4 (int, ctz, int)
+-- 
+2.33.0
+
diff --git a/0243-Backport-SME-AArch64-Fix-Armv9-a-warnings-that-get-e.patch b/0243-Backport-SME-AArch64-Fix-Armv9-a-warnings-that-get-e.patch
new file mode 100644
index 0000000..0e4b80b
--- /dev/null
+++ b/0243-Backport-SME-AArch64-Fix-Armv9-a-warnings-that-get-e.patch
@@ -0,0 +1,63 @@
+From a1ba437195286af3389ba9f2d43b8cb6c73ba3d8 Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Thu, 12 Oct 2023 15:55:58 +0100
+Subject: [PATCH 144/157] [Backport][SME] AArch64: Fix Armv9-a warnings that
+ get emitted whenever a ACLE header is used.
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=de593b3cffdc9c030c5e697ad9092b1b085dabc4
+
+At the moment, trying to use -march=armv9-a with any ACLE header such as
+arm_neon.h results in rows and rows of warnings saying:
+
+: warning: "__ARM_ARCH" redefined
+: note: this is the location of the previous definition
+
+This is obviously not useful and happens because the header was defined at
+__ARM_ARCH == 8 and the commandline changes it.
+
+The Arm port solves this by undef the macro during argument processing and we do
+the same on AArch64 for the majority of macros.  However we define this macro
+using a different helper which requires the manual undef.
+
+Thanks,
+Tamar
+
+gcc/ChangeLog:
+
+	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Add undef.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/aarch64/armv9_warning.c: New test.
+---
+ gcc/config/aarch64/aarch64-c.cc                  | 1 +
+ gcc/testsuite/gcc.target/aarch64/armv9_warning.c | 5 +++++
+ 2 files changed, 6 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/aarch64/armv9_warning.c
+
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 745719d8b..2d2ac42c4 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -129,6 +129,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
+ {
+   aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile);
+ 
++  cpp_undef (pfile, "__ARM_ARCH");
+   builtin_define_with_int_value ("__ARM_ARCH", AARCH64_ISA_V9A ? 9 : 8);
+ 
+   builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
+diff --git a/gcc/testsuite/gcc.target/aarch64/armv9_warning.c b/gcc/testsuite/gcc.target/aarch64/armv9_warning.c
+new file mode 100644
+index 000000000..35690d5bc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/aarch64/armv9_warning.c
+@@ -0,0 +1,5 @@
++/* { dg-do compile } */
++/* { dg-additional-options "-march=armv9-a -Wpedantic -Werror" } */
++
++#include 
++
+-- 
+2.33.0
+
diff --git a/0244-Backport-SME-Canonicalize-X-Y-as-X-Y-in-match.pd-whe.patch b/0244-Backport-SME-Canonicalize-X-Y-as-X-Y-in-match.pd-whe.patch
new file mode 100644
index 0000000..aab1bb6
--- /dev/null
+++ b/0244-Backport-SME-Canonicalize-X-Y-as-X-Y-in-match.pd-whe.patch
@@ -0,0 +1,184 @@
+From f6652dbebf81372884e9fd8b68627fc7a94d8d3b Mon Sep 17 00:00:00 2001
+From: Roger Sayle 
+Date: Fri, 27 May 2022 08:57:46 +0100
+Subject: [PATCH 145/157] [Backport][SME] Canonicalize X&-Y as X*Y in match.pd
+ when Y is [0,1].
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=8fb94fc6097c0a934aac0d89c9c5e2038da67655
+
+"For every pessimization, there's an equal and opposite optimization".
+
+In the review of my original patch for PR middle-end/98865, Richard
+Biener pointed out that match.pd shouldn't be transforming X*Y into
+X&-Y as the former is considered cheaper by tree-ssa's cost model
+(operator count).  A corollary of this is that we should instead be
+transforming X&-Y into the cheaper X*Y as a preferred canonical form
+(especially as RTL expansion now intelligently selects the appropriate
+implementation based on the target's costs).
+
+With this patch we now generate identical code for:
+int foo(int x, int y) { return -(x&1) & y; }
+int bar(int x, int y) { return (x&1) * y; }
+
+specifically on x86_64-pc-linux-gnu both use and/neg/and with -O2,
+but both use and/mul with -Os.
+
+One minor wrinkle/improvement is that this patch includes three
+additional optimizations (that account for the change in canonical
+form) to continue to optimize PR92834 and PR94786.
+
+2022-05-27  Roger Sayle  
+
+gcc/ChangeLog
+	* match.pd (match_zero_one_valued_p): New predicate.
+	(mult @0 @1): Use zero_one_valued_p for optimization to the
+	expression "bit_and @0 @1".
+	(bit_and (negate zero_one_valued_p@0) @1): Optimize to MULT_EXPR.
+	(plus @0 (mult (minus @1 @0) zero_one_valued_p@2)): New transform.
+	(minus @0 (mult (minus @0 @1) zero_one_valued_p@2)): Likewise.
+	(bit_xor @0 (mult (bit_xor @0 @1) zero_one_valued_p@2)): Likewise.
+	Remove three redundant transforms obsoleted by the three above.
+
+gcc/testsuite/ChangeLog
+	* gcc.dg/pr98865.c: New test case.
+---
+ gcc/match.pd                   | 86 ++++++++++++++++------------------
+ gcc/testsuite/gcc.dg/pr98865.c | 14 ++++++
+ 2 files changed, 55 insertions(+), 45 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/pr98865.c
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index aee58e47b..6d3165bcd 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -285,14 +285,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+            || !COMPLEX_FLOAT_TYPE_P (type)))
+    (negate @0)))
+ 
+-/* Transform { 0 or 1 } * { 0 or 1 } into { 0 or 1 } & { 0 or 1 } */
+-(simplify
+- (mult SSA_NAME@1 SSA_NAME@2)
+-  (if (INTEGRAL_TYPE_P (type)
+-       && get_nonzero_bits (@1) == 1
+-       && get_nonzero_bits (@2) == 1)
+-   (bit_and @1 @2)))
+-
+ /* Transform x * { 0 or 1, 0 or 1, ... } into x & { 0 or -1, 0 or -1, ...},
+    unless the target has native support for the former but not the latter.  */
+ (simplify
+@@ -1790,6 +1782,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+   (bit_not (bit_not @0))
+   @0)
+ 
++(match zero_one_valued_p
++ @0
++ (if (INTEGRAL_TYPE_P (type) && tree_nonzero_bits (@0) == 1)))
++(match zero_one_valued_p
++ truth_valued_p@0)
++
++/* Transform { 0 or 1 } * { 0 or 1 } into { 0 or 1 } & { 0 or 1 }.  */
++(simplify
++ (mult zero_one_valued_p@0 zero_one_valued_p@1)
++ (if (INTEGRAL_TYPE_P (type))
++  (bit_and @0 @1)))
++
++/* Transform X & -Y into X * Y when Y is { 0 or 1 }.  */
++(simplify
++ (bit_and:c (convert? (negate zero_one_valued_p@0)) @1)
++ (if (INTEGRAL_TYPE_P (type)
++      && INTEGRAL_TYPE_P (TREE_TYPE (@0))
++      && TREE_CODE (TREE_TYPE (@0)) != BOOLEAN_TYPE
++      && !TYPE_UNSIGNED (TREE_TYPE (@0)))
++  (mult (convert @0) @1)))
++
+ /* Convert ~ (-A) to A - 1.  */
+ (simplify
+  (bit_not (convert? (negate @0)))
+@@ -3281,44 +3294,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+   (cmp @0 (minmax:c @0 @1))
+   { constant_boolean_node (cmp == GE_EXPR || cmp == LE_EXPR, type); } ))
+ 
+-/* Undo fancy way of writing max/min or other ?: expressions,
+-   like a - ((a - b) & -(a < b)), in this case into (a < b) ? b : a.
++/* Undo fancy ways of writing max/min or other ?: expressions, like
++   a - ((a - b) & -(a < b))  and  a - (a - b) * (a < b) into (a < b) ? b : a.
+    People normally use ?: and that is what we actually try to optimize.  */
+-(for cmp (simple_comparison)
+- (simplify
+-  (minus @0 (bit_and:c (minus @0 @1)
+-		       (convert? (negate@4 (convert? (cmp@5 @2 @3))))))
+-  (if (INTEGRAL_TYPE_P (type)
+-       && INTEGRAL_TYPE_P (TREE_TYPE (@4))
+-       && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
+-       && INTEGRAL_TYPE_P (TREE_TYPE (@5))
+-       && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
+-	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+-       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+-   (cond (cmp @2 @3) @1 @0)))
+- (simplify
+-  (plus:c @0 (bit_and:c (minus @1 @0)
+-			(convert? (negate@4 (convert? (cmp@5 @2 @3))))))
+-  (if (INTEGRAL_TYPE_P (type)
+-       && INTEGRAL_TYPE_P (TREE_TYPE (@4))
+-       && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
+-       && INTEGRAL_TYPE_P (TREE_TYPE (@5))
+-       && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
+-	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+-       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+-   (cond (cmp @2 @3) @1 @0)))
+- /* Similarly with ^ instead of - though in that case with :c.  */
+- (simplify
+-  (bit_xor:c @0 (bit_and:c (bit_xor:c @0 @1)
+-			   (convert? (negate@4 (convert? (cmp@5 @2 @3))))))
+-  (if (INTEGRAL_TYPE_P (type)
+-       && INTEGRAL_TYPE_P (TREE_TYPE (@4))
+-       && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
+-       && INTEGRAL_TYPE_P (TREE_TYPE (@5))
+-       && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
+-	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+-       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+-   (cond (cmp @2 @3) @1 @0))))
++/* Transform A + (B-A)*cmp into cmp ? B : A.  */
++(simplify
++ (plus:c @0 (mult:c (minus @1 @0) zero_one_valued_p@2))
++ (if (INTEGRAL_TYPE_P (type)
++      && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
++  (cond (convert:boolean_type_node @2) @1 @0)))
++/* Transform A - (A-B)*cmp into cmp ? B : A.  */
++(simplify
++ (minus @0 (mult:c (minus @0 @1) zero_one_valued_p@2))
++ (if (INTEGRAL_TYPE_P (type)
++      && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
++  (cond (convert:boolean_type_node @2) @1 @0)))
++/* Transform A ^ (A^B)*cmp into cmp ? B : A.  */
++(simplify
++ (bit_xor:c @0 (mult:c (bit_xor:c @0 @1) zero_one_valued_p@2))
++ (if (INTEGRAL_TYPE_P (type)
++      && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
++  (cond (convert:boolean_type_node @2) @1 @0)))
+ 
+ /* Simplifications of shift and rotates.  */
+ 
+diff --git a/gcc/testsuite/gcc.dg/pr98865.c b/gcc/testsuite/gcc.dg/pr98865.c
+new file mode 100644
+index 000000000..95f727033
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr98865.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -fdump-tree-optimized" } */
++
++int foo(int x, int y)
++{
++  return -(x&1) & y;
++}
++
++int bar(int x, int y)
++{
++  return (x&1) * y;
++}
++
++/* { dg-final { scan-tree-dump-times " \\* " 2 "optimized" } } */
+-- 
+2.33.0
+
diff --git a/0245-Backport-SME-middle-end-Add-new-tbranch-optab-to-add.patch b/0245-Backport-SME-middle-end-Add-new-tbranch-optab-to-add.patch
new file mode 100644
index 0000000..229b797
--- /dev/null
+++ b/0245-Backport-SME-middle-end-Add-new-tbranch-optab-to-add.patch
@@ -0,0 +1,417 @@
+From a8f10b4b73c2624599765edf7ff19d53eca15135 Mon Sep 17 00:00:00 2001
+From: Tamar Christina 
+Date: Mon, 12 Dec 2022 15:16:50 +0000
+Subject: [PATCH 146/157] [Backport][SME] middle-end: Add new tbranch optab to
+ add support for bit-test-and-branch operations
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=dc582d2ef32e2d3723c68d111f4e49607631f34d
+
+This adds a new test-and-branch optab that can be used to do a conditional test
+of a bit and branch.   This is similar to the cbranch optab but instead can
+test any arbitrary bit inside the register.
+
+This patch recognizes boolean comparisons and single bit mask tests.
+
+gcc/ChangeLog:
+
+	* dojump.cc (do_jump): Pass along value.
+	(do_jump_by_parts_greater_rtx): Likewise.
+	(do_jump_by_parts_zero_rtx): Likewise.
+	(do_jump_by_parts_equality_rtx): Likewise.
+	(do_compare_rtx_and_jump): Likewise.
+	(do_compare_and_jump): Likewise.
+	* dojump.h (do_compare_rtx_and_jump): New.
+	* optabs.cc (emit_cmp_and_jump_insn_1): Refactor to take optab to check.
+	(validate_test_and_branch): New.
+	(emit_cmp_and_jump_insns): Optiobally take a value, and when value is
+	supplied then check if it's suitable for tbranch.
+	* optabs.def (tbranch_eq$a4, tbranch_ne$a4): New.
+	* doc/md.texi (tbranch_@var{op}@var{mode}4): Document it.
+	* optabs.h (emit_cmp_and_jump_insns): New.
+	* tree.h (tree_zero_one_valued_p): New.
+---
+ gcc/doc/md.texi |   7 +++
+ gcc/dojump.cc   |  52 +++++++++++++++-------
+ gcc/dojump.h    |   4 ++
+ gcc/optabs.cc   | 114 ++++++++++++++++++++++++++++++++++++++++++++----
+ gcc/optabs.def  |   2 +
+ gcc/optabs.h    |   4 ++
+ gcc/tree.h      |   1 +
+ 7 files changed, 159 insertions(+), 25 deletions(-)
+
+diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
+index c0cf0ec64..2193900e7 100644
+--- a/gcc/doc/md.texi
++++ b/gcc/doc/md.texi
+@@ -7299,6 +7299,13 @@ case, you can and should make operand 1's predicate reject some operators
+ in the @samp{cstore@var{mode}4} pattern, or remove the pattern altogether
+ from the machine description.
+ 
++@cindex @code{tbranch_@var{op}@var{mode}3} instruction pattern
++@item @samp{tbranch_@var{op}@var{mode}3}
++Conditional branch instruction combined with a bit test-and-compare
++instruction. Operand 0 is the operand of the comparison.  Operand 1 is the bit
++position of Operand 1 to test.  Operand 3 is the @code{code_label} to jump to.
++@var{op} is one of @var{eq} or @var{ne}.
++
+ @cindex @code{cbranch@var{mode}4} instruction pattern
+ @item @samp{cbranch@var{mode}4}
+ Conditional branch instruction combined with a compare instruction.
+diff --git a/gcc/dojump.cc b/gcc/dojump.cc
+index 0c880d653..604b28537 100644
+--- a/gcc/dojump.cc
++++ b/gcc/dojump.cc
+@@ -621,7 +621,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
+ 	}
+       do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
+ 			       NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
+-			       GET_MODE (temp), NULL_RTX,
++			       exp, GET_MODE (temp), NULL_RTX,
+ 			       if_false_label, if_true_label, prob);
+     }
+ 
+@@ -689,7 +689,7 @@ do_jump_by_parts_greater_rtx (scalar_int_mode mode, int unsignedp, rtx op0,
+ 
+       /* All but high-order word must be compared as unsigned.  */
+       do_compare_rtx_and_jump (op0_word, op1_word, code, (unsignedp || i > 0),
+-			       word_mode, NULL_RTX, NULL, if_true_label,
++			       NULL, word_mode, NULL_RTX, NULL, if_true_label,
+ 			       prob);
+ 
+       /* Emit only one comparison for 0.  Do not emit the last cond jump.  */
+@@ -697,8 +697,8 @@ do_jump_by_parts_greater_rtx (scalar_int_mode mode, int unsignedp, rtx op0,
+ 	break;
+ 
+       /* Consider lower words only if these are equal.  */
+-      do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
+-			       NULL_RTX, NULL, if_false_label,
++      do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, NULL,
++			       word_mode, NULL_RTX, NULL, if_false_label,
+ 			       prob.invert ());
+     }
+ 
+@@ -757,7 +757,7 @@ do_jump_by_parts_zero_rtx (scalar_int_mode mode, rtx op0,
+ 
+   if (part != 0)
+     {
+-      do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
++      do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, NULL, word_mode,
+ 			       NULL_RTX, if_false_label, if_true_label, prob);
+       return;
+     }
+@@ -768,7 +768,7 @@ do_jump_by_parts_zero_rtx (scalar_int_mode mode, rtx op0,
+ 
+   for (i = 0; i < nwords; i++)
+     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
+-                             const0_rtx, EQ, 1, word_mode, NULL_RTX,
++			     const0_rtx, EQ, 1, NULL, word_mode, NULL_RTX,
+ 			     if_false_label, NULL, prob);
+ 
+   if (if_true_label)
+@@ -811,8 +811,8 @@ do_jump_by_parts_equality_rtx (scalar_int_mode mode, rtx op0, rtx op1,
+ 
+   for (i = 0; i < nwords; i++)
+     do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
+-                             operand_subword_force (op1, i, mode),
+-                             EQ, 0, word_mode, NULL_RTX,
++			     operand_subword_force (op1, i, mode),
++			     EQ, 0, NULL, word_mode, NULL_RTX,
+ 			     if_false_label, NULL, prob);
+ 
+   if (if_true_label)
+@@ -964,6 +964,23 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
+ 			 rtx_code_label *if_false_label,
+ 			 rtx_code_label *if_true_label,
+ 			 profile_probability prob)
++{
++  do_compare_rtx_and_jump (op0, op1, code, unsignedp, NULL, mode, size,
++			  if_false_label, if_true_label, prob);
++}
++
++/* Like do_compare_and_jump but expects the values to compare as two rtx's.
++   The decision as to signed or unsigned comparison must be made by the caller.
++
++   If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
++   compared.  */
++
++void
++do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
++			 tree val, machine_mode mode, rtx size,
++			 rtx_code_label *if_false_label,
++			 rtx_code_label *if_true_label,
++			 profile_probability prob)
+ {
+   rtx tem;
+   rtx_code_label *dummy_label = NULL;
+@@ -1179,8 +1196,10 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
+ 		    }
+ 		  else
+ 		    dest_label = if_false_label;
+-                  do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
+-					   size, dest_label, NULL, first_prob);
++
++		  do_compare_rtx_and_jump (op0, op1, first_code, unsignedp,
++					   val, mode, size, dest_label, NULL,
++					   first_prob);
+ 		}
+ 	      /* For !and_them we want to split:
+ 		 if (x) goto t; // prob;
+@@ -1194,8 +1213,9 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
+               else
+ 		{
+ 		  profile_probability first_prob = prob.split (cprob);
+-		  do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode,
+-					   size, NULL, if_true_label, first_prob);
++		  do_compare_rtx_and_jump (op0, op1, first_code, unsignedp,
++					   val, mode, size, NULL,
++					   if_true_label, first_prob);
+ 		  if (orig_code == NE && can_compare_p (UNEQ, mode, ccp_jump))
+ 		    {
+ 		      /* x != y can be split into x unord y || x ltgt y
+@@ -1217,7 +1237,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
+ 	    }
+ 	}
+ 
+-      emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
++      emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, val,
+ 			       if_true_label, prob);
+     }
+ 
+@@ -1291,9 +1311,9 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
+       op1 = new_op1;
+     }
+ 
+-  do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
+-                           ((mode == BLKmode)
+-                            ? expr_size (treeop0) : NULL_RTX),
++  do_compare_rtx_and_jump (op0, op1, code, unsignedp, treeop0, mode,
++			   ((mode == BLKmode)
++			    ? expr_size (treeop0) : NULL_RTX),
+ 			   if_false_label, if_true_label, prob);
+ }
+ 
+diff --git a/gcc/dojump.h b/gcc/dojump.h
+index e379cceb3..d1d79c490 100644
+--- a/gcc/dojump.h
++++ b/gcc/dojump.h
+@@ -71,6 +71,10 @@ extern void jumpifnot (tree exp, rtx_code_label *label,
+ extern void jumpifnot_1 (enum tree_code, tree, tree, rtx_code_label *,
+ 			 profile_probability);
+ 
++extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int, tree,
++				     machine_mode, rtx, rtx_code_label *,
++				     rtx_code_label *, profile_probability);
++
+ extern void do_compare_rtx_and_jump (rtx, rtx, enum rtx_code, int,
+ 				     machine_mode, rtx, rtx_code_label *,
+ 				     rtx_code_label *, profile_probability);
+diff --git a/gcc/optabs.cc b/gcc/optabs.cc
+index 3d8fa3abd..b441137de 100644
+--- a/gcc/optabs.cc
++++ b/gcc/optabs.cc
+@@ -46,6 +46,8 @@ along with GCC; see the file COPYING3.  If not see
+ #include "libfuncs.h"
+ #include "internal-fn.h"
+ #include "langhooks.h"
++#include "gimple.h"
++#include "ssa.h"
+ 
+ static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
+ 				   machine_mode *);
+@@ -4621,7 +4623,8 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, machine_mode mode,
+ 
+ static void
+ emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
+-			  profile_probability prob)
++			  direct_optab cmp_optab, profile_probability prob,
++			  bool test_branch)
+ {
+   machine_mode optab_mode;
+   enum mode_class mclass;
+@@ -4630,12 +4633,17 @@ emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
+ 
+   mclass = GET_MODE_CLASS (mode);
+   optab_mode = (mclass == MODE_CC) ? CCmode : mode;
+-  icode = optab_handler (cbranch_optab, optab_mode);
++  icode = optab_handler (cmp_optab, optab_mode);
+ 
+   gcc_assert (icode != CODE_FOR_nothing);
+-  gcc_assert (insn_operand_matches (icode, 0, test));
+-  insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
+-                                          XEXP (test, 1), label));
++  gcc_assert (test_branch || insn_operand_matches (icode, 0, test));
++  if (test_branch)
++    insn = emit_jump_insn (GEN_FCN (icode) (XEXP (test, 0),
++					    XEXP (test, 1), label));
++  else
++    insn = emit_jump_insn (GEN_FCN (icode) (test, XEXP (test, 0),
++					    XEXP (test, 1), label));
++
+   if (prob.initialized_p ()
+       && profile_status_for_fn (cfun) != PROFILE_ABSENT
+       && insn
+@@ -4645,6 +4653,68 @@ emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
+     add_reg_br_prob_note (insn, prob);
+ }
+ 
++/* PTEST points to a comparison that compares its first operand with zero.
++   Check to see if it can be performed as a bit-test-and-branch instead.
++   On success, return the instruction that performs the bit-test-and-branch
++   and replace the second operand of *PTEST with the bit number to test.
++   On failure, return CODE_FOR_nothing and leave *PTEST unchanged.
++
++   Note that the comparison described by *PTEST should not be taken
++   literally after a successful return.  *PTEST is just a convenient
++   place to store the two operands of the bit-and-test.
++
++   VAL must contain the original tree expression for the first operand
++   of *PTEST.  */
++
++static enum insn_code
++validate_test_and_branch (tree val, rtx *ptest, machine_mode *pmode, optab *res)
++{
++  if (!val || TREE_CODE (val) != SSA_NAME)
++    return CODE_FOR_nothing;
++
++  machine_mode mode = TYPE_MODE (TREE_TYPE (val));
++  rtx test = *ptest;
++  direct_optab optab;
++
++  if (GET_CODE (test) == EQ)
++    optab = tbranch_eq_optab;
++  else if (GET_CODE (test) == NE)
++    optab = tbranch_ne_optab;
++  else
++    return CODE_FOR_nothing;
++
++  *res = optab;
++
++  /* If the target supports the testbit comparison directly, great.  */
++  auto icode = direct_optab_handler (optab, mode);
++  if (icode == CODE_FOR_nothing)
++    return icode;
++
++  if (tree_zero_one_valued_p (val))
++    {
++      auto pos = BITS_BIG_ENDIAN ? GET_MODE_BITSIZE (mode) - 1 : 0;
++      XEXP (test, 1) = gen_int_mode (pos, mode);
++      *ptest = test;
++      *pmode = mode;
++      return icode;
++    }
++
++  wide_int wcst = get_nonzero_bits (val);
++  if (wcst == -1)
++    return CODE_FOR_nothing;
++
++  int bitpos;
++
++  if ((bitpos = wi::exact_log2 (wcst)) == -1)
++    return CODE_FOR_nothing;
++
++  auto pos = BITS_BIG_ENDIAN ? GET_MODE_BITSIZE (mode) - 1 - bitpos : bitpos;
++  XEXP (test, 1) = gen_int_mode (pos, mode);
++  *ptest = test;
++  *pmode = mode;
++  return icode;
++}
++
+ /* Generate code to compare X with Y so that the condition codes are
+    set and to jump to LABEL if the condition is true.  If X is a
+    constant and Y is not a constant, then the comparison is swapped to
+@@ -4662,11 +4732,13 @@ emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label,
+    It will be potentially converted into an unsigned variant based on
+    UNSIGNEDP to select a proper jump instruction.
+    
+-   PROB is the probability of jumping to LABEL.  */
++   PROB is the probability of jumping to LABEL.  If the comparison is against
++   zero then VAL contains the expression from which the non-zero RTL is
++   derived.  */
+ 
+ void
+ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
+-			 machine_mode mode, int unsignedp, rtx label,
++			 machine_mode mode, int unsignedp, tree val, rtx label,
+                          profile_probability prob)
+ {
+   rtx op0 = x, op1 = y;
+@@ -4691,10 +4763,34 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
+ 
+   prepare_cmp_insn (op0, op1, comparison, size, unsignedp, OPTAB_LIB_WIDEN,
+ 		    &test, &mode);
+-  emit_cmp_and_jump_insn_1 (test, mode, label, prob);
++
++  /* Check if we're comparing a truth type with 0, and if so check if
++     the target supports tbranch.  */
++  machine_mode tmode = mode;
++  direct_optab optab;
++  if (op1 == CONST0_RTX (GET_MODE (op1))
++      && validate_test_and_branch (val, &test, &tmode,
++				   &optab) != CODE_FOR_nothing)
++    {
++      emit_cmp_and_jump_insn_1 (test, tmode, label, optab, prob, true);
++      return;
++    }
++
++  emit_cmp_and_jump_insn_1 (test, mode, label, cbranch_optab, prob, false);
+ }
+ 
+-
++/* Overloaded version of emit_cmp_and_jump_insns in which VAL is unknown.  */
++
++void
++emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
++			 machine_mode mode, int unsignedp, rtx label,
++			 profile_probability prob)
++{
++  emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, NULL,
++			   label, prob);
++}
++
++
+ /* Emit a library call comparison between floating point X and Y.
+    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
+ 
+diff --git a/gcc/optabs.def b/gcc/optabs.def
+index 801310eba..dbf529434 100644
+--- a/gcc/optabs.def
++++ b/gcc/optabs.def
+@@ -220,6 +220,8 @@ OPTAB_D (reload_in_optab, "reload_in$a")
+ OPTAB_D (reload_out_optab, "reload_out$a")
+ 
+ OPTAB_DC(cbranch_optab, "cbranch$a4", COMPARE)
++OPTAB_D (tbranch_eq_optab, "tbranch_eq$a3")
++OPTAB_D (tbranch_ne_optab, "tbranch_ne$a3")
+ OPTAB_D (addcc_optab, "add$acc")
+ OPTAB_D (negcc_optab, "neg$acc")
+ OPTAB_D (notcc_optab, "not$acc")
+diff --git a/gcc/optabs.h b/gcc/optabs.h
+index cfd7c742d..cd55604bc 100644
+--- a/gcc/optabs.h
++++ b/gcc/optabs.h
+@@ -268,6 +268,10 @@ extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
+ 				     machine_mode, int, rtx,
+ 				     profile_probability prob
+ 					= profile_probability::uninitialized ());
++extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
++				     machine_mode, int, tree, rtx,
++				     profile_probability prob
++					= profile_probability::uninitialized ());
+ 
+ /* Generate code to indirectly jump to a location given in the rtx LOC.  */
+ extern void emit_indirect_jump (rtx);
+diff --git a/gcc/tree.h b/gcc/tree.h
+index 3ff7732dc..07af584d6 100644
+--- a/gcc/tree.h
++++ b/gcc/tree.h
+@@ -4627,6 +4627,7 @@ 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 bool tree_zero_one_valued_p (tree);
+ extern tree truth_type_for (tree);
+ extern tree build_pointer_type_for_mode (tree, machine_mode, bool);
+ extern tree build_pointer_type (tree);
+-- 
+2.33.0
+
diff --git a/0246-Backport-SME-explow-Allow-dynamic-allocations-after-.patch b/0246-Backport-SME-explow-Allow-dynamic-allocations-after-.patch
new file mode 100644
index 0000000..fdefe48
--- /dev/null
+++ b/0246-Backport-SME-explow-Allow-dynamic-allocations-after-.patch
@@ -0,0 +1,110 @@
+From fe64cc72e6221cf05e40bc868287bd1fcf07479f Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Mon, 6 Nov 2023 10:49:58 +0000
+Subject: [PATCH 147/157] [Backport][SME] explow: Allow dynamic allocations
+ after vregs
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a7a45364dddef399bfb550235166df51108a3142
+
+This patch allows allocate_dynamic_stack_space to be called before
+or after virtual registers have been instantiated.  It uses the
+same approach as allocate_stack_local, which already supported this.
+
+gcc/
+	* function.h (get_stack_dynamic_offset): Declare.
+	* function.cc (get_stack_dynamic_offset): New function,
+	split out from...
+	(get_stack_dynamic_offset): ...here.
+	* explow.cc (allocate_dynamic_stack_space): Handle calls made
+	after virtual registers have been instantiated.
+---
+ gcc/explow.cc   | 10 +++++++---
+ gcc/function.cc | 12 +++++++++++-
+ gcc/function.h  |  1 +
+ 3 files changed, 19 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/explow.cc b/gcc/explow.cc
+index d8aa75ee9..124e8f49e 100644
+--- a/gcc/explow.cc
++++ b/gcc/explow.cc
+@@ -1375,12 +1375,16 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
+   HOST_WIDE_INT stack_usage_size = -1;
+   rtx_code_label *final_label;
+   rtx final_target, target;
++  rtx addr = (virtuals_instantiated
++	      ? plus_constant (Pmode, stack_pointer_rtx,
++			       get_stack_dynamic_offset ())
++	      : virtual_stack_dynamic_rtx);
+ 
+   /* If we're asking for zero bytes, it doesn't matter what we point
+      to since we can't dereference it.  But return a reasonable
+      address anyway.  */
+   if (size == const0_rtx)
+-    return virtual_stack_dynamic_rtx;
++    return addr;
+ 
+   /* Otherwise, show we're calling alloca or equivalent.  */
+   cfun->calls_alloca = 1;
+@@ -1532,7 +1536,7 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
+       poly_int64 saved_stack_pointer_delta;
+ 
+       if (!STACK_GROWS_DOWNWARD)
+-	emit_move_insn (target, virtual_stack_dynamic_rtx);
++	emit_move_insn (target, force_operand (addr, target));
+ 
+       /* Check stack bounds if necessary.  */
+       if (crtl->limit_stack)
+@@ -1575,7 +1579,7 @@ allocate_dynamic_stack_space (rtx size, unsigned size_align,
+       stack_pointer_delta = saved_stack_pointer_delta;
+ 
+       if (STACK_GROWS_DOWNWARD)
+-	emit_move_insn (target, virtual_stack_dynamic_rtx);
++	emit_move_insn (target, force_operand (addr, target));
+     }
+ 
+   suppress_reg_args_size = false;
+diff --git a/gcc/function.cc b/gcc/function.cc
+index f4fc211a0..e62b2a8d6 100644
+--- a/gcc/function.cc
++++ b/gcc/function.cc
+@@ -1945,6 +1945,16 @@ instantiate_decls (tree fndecl)
+   vec_free (cfun->local_decls);
+ }
+ 
++/* Return the value of STACK_DYNAMIC_OFFSET for the current function.
++   This is done through a function wrapper so that the macro sees a
++   predictable set of included files.  */
++
++poly_int64
++get_stack_dynamic_offset ()
++{
++  return STACK_DYNAMIC_OFFSET (current_function_decl);
++}
++
+ /* Pass through the INSNS of function FNDECL and convert virtual register
+    references to hard register references.  */
+ 
+@@ -1956,7 +1966,7 @@ instantiate_virtual_regs (void)
+   /* Compute the offsets to use for this function.  */
+   in_arg_offset = FIRST_PARM_OFFSET (current_function_decl);
+   var_offset = targetm.starting_frame_offset ();
+-  dynamic_offset = STACK_DYNAMIC_OFFSET (current_function_decl);
++  dynamic_offset = get_stack_dynamic_offset ();
+   out_arg_offset = STACK_POINTER_OFFSET;
+ #ifdef FRAME_POINTER_CFA_OFFSET
+   cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
+diff --git a/gcc/function.h b/gcc/function.h
+index 4e8131706..a5846465a 100644
+--- a/gcc/function.h
++++ b/gcc/function.h
+@@ -711,6 +711,7 @@ extern vec convert_jumps_to_returns (basic_block last_bb, bool simple_p,
+ extern basic_block emit_return_for_exit (edge exit_fallthru_edge,
+ 					 bool simple_p);
+ extern void reposition_prologue_and_epilogue_notes (void);
++extern poly_int64 get_stack_dynamic_offset ();
+ 
+ /* Returns the name of the current function.  */
+ extern const char *fndecl_name (tree);
+-- 
+2.33.0
+
diff --git a/0247-Backport-SME-PR105169-Fix-references-to-discarded-se.patch b/0247-Backport-SME-PR105169-Fix-references-to-discarded-se.patch
new file mode 100644
index 0000000..93a7e3a
--- /dev/null
+++ b/0247-Backport-SME-PR105169-Fix-references-to-discarded-se.patch
@@ -0,0 +1,225 @@
+From 6cc7bcadadbc2521a2db4c02adfe066d805e37ef Mon Sep 17 00:00:00 2001
+From: Giuliano Belinassi 
+Date: Fri, 6 May 2022 23:37:52 -0300
+Subject: [PATCH 148/157] [Backport][SME] PR105169 Fix references to discarded
+ sections
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7a3f38a966a52893fb5bae301a1a3d56961358fb
+
+When -fpatchable-function-entry= is enabled, certain C++ codes fails to
+link because of generated references to discarded sections in
+__patchable_function_entry section. This commit fixes this problem by
+puting those references in a COMDAT section.
+
+2022-05-06  Giuliano Belinassi  
+
+gcc/ChangeLog
+	PR c++/105169
+	* targhooks.cc (default_print_patchable_function_entry_1): Handle COMDAT case.
+	* varasm.cc (switch_to_comdat_section): New
+	(handle_vtv_comdat_section): Call switch_to_comdat_section.
+	* varasm.h: Declare switch_to_comdat_section.
+
+gcc/testsuite/ChangeLog
+2022-05-06  Giuliano Belinassi  
+
+	PR c++/105169
+	* g++.dg/modules/pr105169.h: New file.
+	* g++.dg/modules/pr105169_a.C: New test.
+	* g++.dg/modules/pr105169_b.C: New file.
+---
+ gcc/targhooks.cc                          |  8 ++++--
+ gcc/testsuite/g++.dg/modules/pr105169.h   | 22 +++++++++++++++
+ gcc/testsuite/g++.dg/modules/pr105169_a.C | 25 +++++++++++++++++
+ gcc/testsuite/g++.dg/modules/pr105169_b.C | 12 +++++++++
+ gcc/varasm.cc                             | 33 ++++++++++++++---------
+ gcc/varasm.h                              |  2 ++
+ 6 files changed, 87 insertions(+), 15 deletions(-)
+ create mode 100644 gcc/testsuite/g++.dg/modules/pr105169.h
+ create mode 100644 gcc/testsuite/g++.dg/modules/pr105169_a.C
+ create mode 100644 gcc/testsuite/g++.dg/modules/pr105169_b.C
+
+diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
+index c88afa5db..175a0e18a 100644
+--- a/gcc/targhooks.cc
++++ b/gcc/targhooks.cc
+@@ -2019,8 +2019,12 @@ default_print_patchable_function_entry_1 (FILE *file,
+       patch_area_number++;
+       ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number);
+ 
+-      switch_to_section (get_section ("__patchable_function_entries",
+-				      flags, current_function_decl));
++      section *sect = get_section ("__patchable_function_entries",
++				  flags, current_function_decl);
++      if (HAVE_COMDAT_GROUP && DECL_COMDAT_GROUP (current_function_decl))
++	switch_to_comdat_section (sect, current_function_decl);
++      else
++	switch_to_section (sect);
+       assemble_align (POINTER_SIZE);
+       fputs (asm_op, file);
+       assemble_name_raw (file, buf);
+diff --git a/gcc/testsuite/g++.dg/modules/pr105169.h b/gcc/testsuite/g++.dg/modules/pr105169.h
+new file mode 100644
+index 000000000..a7e762705
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/modules/pr105169.h
+@@ -0,0 +1,22 @@
++class IPXAddressClass
++{
++public:
++    IPXAddressClass(void);
++};
++
++class WinsockInterfaceClass
++{
++
++public:
++    WinsockInterfaceClass(void);
++
++    virtual void Set_Broadcast_Address(void*){};
++
++    virtual int Get_Protocol(void)
++    {
++        return 0;
++    };
++
++protected:
++};
++
+diff --git a/gcc/testsuite/g++.dg/modules/pr105169_a.C b/gcc/testsuite/g++.dg/modules/pr105169_a.C
+new file mode 100644
+index 000000000..66dc4b790
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/modules/pr105169_a.C
+@@ -0,0 +1,25 @@
++/* { dg-module-do link } */
++/* { dg-options "-std=c++11 -fpatchable-function-entry=1 -O2" } */
++/* { dg-additional-options "-std=c++11 -fpatchable-function-entry=1 -O2" } */
++
++/* This test is in the "modules" package because it supports multiple files
++   linkage.  */
++
++#include "pr105169.h"
++
++WinsockInterfaceClass* PacketTransport;
++
++IPXAddressClass::IPXAddressClass(void)
++{
++}
++
++int function()
++{
++  return PacketTransport->Get_Protocol();
++}
++
++int main()
++{
++  IPXAddressClass ipxaddr;
++  return 0;
++}
+diff --git a/gcc/testsuite/g++.dg/modules/pr105169_b.C b/gcc/testsuite/g++.dg/modules/pr105169_b.C
+new file mode 100644
+index 000000000..5f8b00dfe
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/modules/pr105169_b.C
+@@ -0,0 +1,12 @@
++/* { dg-module-do link } */
++/* { dg-options "-std=c++11 -fpatchable-function-entry=1 -O2" } */
++/* { dg-additional-options "-std=c++11 -fpatchable-function-entry=1 -O2" } */
++
++/* This test is in the "modules" package because it supports multiple files
++   linkage.  */
++
++#include "pr105169.h"
++
++WinsockInterfaceClass::WinsockInterfaceClass(void)
++{
++}
+diff --git a/gcc/varasm.cc b/gcc/varasm.cc
+index 3f69b47a7..bae935694 100644
+--- a/gcc/varasm.cc
++++ b/gcc/varasm.cc
+@@ -8459,25 +8459,21 @@ default_asm_output_ident_directive (const char *ident_str)
+     fprintf (asm_out_file, "%s\"%s\"\n", ident_asm_op, ident_str);
+ }
+ 
+-
+-/* This function ensures that vtable_map variables are not only
+-   in the comdat section, but that each variable has its own unique
+-   comdat name.  Without this the variables end up in the same section
+-   with a single comdat name.
+-
++/* Switch to a COMDAT section with COMDAT name of decl.
++   
+    FIXME:  resolve_unique_section needs to deal better with
+    decls with both DECL_SECTION_NAME and DECL_ONE_ONLY.  Once
+    that is fixed, this if-else statement can be replaced with
+    a single call to "switch_to_section (sect)".  */
+ 
+-static void
+-handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED)
++void
++switch_to_comdat_section (section *sect, tree decl)
+ {
+ #if defined (OBJECT_FORMAT_ELF)
+   targetm.asm_out.named_section (sect->named.name,
+ 				 sect->named.common.flags
+ 				 | SECTION_LINKONCE,
+-				 DECL_NAME (decl));
++				 decl);
+   in_section = sect;
+ #else
+   /* Neither OBJECT_FORMAT_PE, nor OBJECT_FORMAT_COFF is set here.
+@@ -8492,18 +8488,18 @@ handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED)
+     {
+       char *name;
+ 
+-      if (TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE)
++      if (TREE_CODE (decl) == IDENTIFIER_NODE)
+ 	name = ACONCAT ((sect->named.name, "$",
+-			 IDENTIFIER_POINTER (DECL_NAME (decl)), NULL));
++			 IDENTIFIER_POINTER (decl), NULL));
+       else
+ 	name = ACONCAT ((sect->named.name, "$",
+-			 IDENTIFIER_POINTER (DECL_COMDAT_GROUP (DECL_NAME (decl))),
++			 IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl)),
+ 			 NULL));
+ 
+       targetm.asm_out.named_section (name,
+ 				     sect->named.common.flags
+ 				     | SECTION_LINKONCE,
+-				     DECL_NAME (decl));
++				     decl);
+       in_section = sect;
+     }
+   else
+@@ -8511,4 +8507,15 @@ handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED)
+ #endif
+ }
+ 
++/* This function ensures that vtable_map variables are not only
++   in the comdat section, but that each variable has its own unique
++   comdat name.  Without this the variables end up in the same section
++   with a single comdat name.  */
++
++static void
++handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED)
++{
++  switch_to_comdat_section(sect, DECL_NAME (decl));
++}
++
+ #include "gt-varasm.h"
+diff --git a/gcc/varasm.h b/gcc/varasm.h
+index d5d8c4e55..8ba8374e7 100644
+--- a/gcc/varasm.h
++++ b/gcc/varasm.h
+@@ -79,4 +79,6 @@ extern rtx assemble_static_space (unsigned HOST_WIDE_INT);
+ 
+ extern rtx assemble_trampoline_template (void);
+ 
++extern void switch_to_comdat_section (section *, tree);
++
+ #endif  // GCC_VARASM_H
+-- 
+2.33.0
+
diff --git a/0248-Backport-SME-RISC-V-autovec-Verify-that-GET_MODE_NUN.patch b/0248-Backport-SME-RISC-V-autovec-Verify-that-GET_MODE_NUN.patch
new file mode 100644
index 0000000..df79d84
--- /dev/null
+++ b/0248-Backport-SME-RISC-V-autovec-Verify-that-GET_MODE_NUN.patch
@@ -0,0 +1,53 @@
+From a3b4a0ac472415a52ce836e8997f7a69a06fad33 Mon Sep 17 00:00:00 2001
+From: Michael Collison 
+Date: Sat, 6 May 2023 12:37:50 -0600
+Subject: [PATCH 149/157] [Backport][SME] RISC-V: autovec: Verify that
+ GET_MODE_NUNITS is a multiple of 2.
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=730909fa858bd691095bc23655077aa13b7941a9
+
+While working on autovectorizing for the RISCV port I encountered an issue
+where can_duplicate_and_interleave_p assumes that GET_MODE_NUNITS is a
+evenly divisible by two. The RISC-V target has vector modes (e.g. VNx1DImode),
+where GET_MODE_NUNITS is equal to one.
+
+Tested on RISCV and x86_64-linux-gnu. Okay?
+
+gcc/
+	* tree-vect-slp.cc (can_duplicate_and_interleave_p):
+	Check that GET_MODE_NUNITS is a multiple of 2.
+---
+ gcc/tree-vect-slp.cc | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index 6cbf8085f..d02f0ce37 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -401,10 +401,13 @@ can_duplicate_and_interleave_p (vec_info *vinfo, unsigned int count,
+ 	    (GET_MODE_BITSIZE (int_mode), 1);
+ 	  tree vector_type
+ 	    = get_vectype_for_scalar_type (vinfo, int_type, count);
++	  poly_int64 half_nelts;
+ 	  if (vector_type
+ 	      && VECTOR_MODE_P (TYPE_MODE (vector_type))
+ 	      && known_eq (GET_MODE_SIZE (TYPE_MODE (vector_type)),
+-			   GET_MODE_SIZE (base_vector_mode)))
++			   GET_MODE_SIZE (base_vector_mode))
++	      && multiple_p (GET_MODE_NUNITS (TYPE_MODE (vector_type)),
++			     2, &half_nelts))
+ 	    {
+ 	      /* Try fusing consecutive sequences of COUNT / NVECTORS elements
+ 		 together into elements of type INT_TYPE and using the result
+@@ -412,7 +415,7 @@ can_duplicate_and_interleave_p (vec_info *vinfo, unsigned int count,
+ 	      poly_uint64 nelts = GET_MODE_NUNITS (TYPE_MODE (vector_type));
+ 	      vec_perm_builder sel1 (nelts, 2, 3);
+ 	      vec_perm_builder sel2 (nelts, 2, 3);
+-	      poly_int64 half_nelts = exact_div (nelts, 2);
++
+ 	      for (unsigned int i = 0; i < 3; ++i)
+ 		{
+ 		  sel1.quick_push (i);
+-- 
+2.33.0
+
diff --git a/0249-Backport-SME-Add-operator-to-gimple_stmt_iterator-an.patch b/0249-Backport-SME-Add-operator-to-gimple_stmt_iterator-an.patch
new file mode 100644
index 0000000..293df25
--- /dev/null
+++ b/0249-Backport-SME-Add-operator-to-gimple_stmt_iterator-an.patch
@@ -0,0 +1,42 @@
+From b0ca9a6eb1406a60eec566cf302790bee89879af Mon Sep 17 00:00:00 2001
+From: Richard Biener 
+Date: Tue, 18 Apr 2023 16:58:26 +0200
+Subject: [PATCH 150/157] [Backport][SME] Add operator* to gimple_stmt_iterator
+ and gphi_iterator
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=c39cdd9e654540f74cd2478019c40f1611554a44
+
+This allows STL style iterator dereference.  It's the same
+as gsi_stmt () or .phi ().
+
+	* gimple-iterator.h (gimple_stmt_iterator::operator*): Add.
+	(gphi_iterator::operator*): Likewise.
+---
+ gcc/gimple-iterator.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
+index 216ebee24..5d281e4f7 100644
+--- a/gcc/gimple-iterator.h
++++ b/gcc/gimple-iterator.h
+@@ -24,6 +24,8 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ struct gimple_stmt_iterator
+ {
++  gimple *operator * () const { return ptr; }
++
+   /* Sequence node holding the current statement.  */
+   gimple_seq_node ptr;
+ 
+@@ -38,6 +40,8 @@ struct gimple_stmt_iterator
+ /* Iterator over GIMPLE_PHI statements.  */
+ struct gphi_iterator : public gimple_stmt_iterator
+ {
++  gphi *operator * () const { return as_a  (ptr); }
++
+   gphi *phi () const
+   {
+     return as_a  (ptr);
+-- 
+2.33.0
+
diff --git a/0250-Backport-SME-tree-optimization-110221-SLP-and-loop-m.patch b/0250-Backport-SME-tree-optimization-110221-SLP-and-loop-m.patch
new file mode 100644
index 0000000..16a75f8
--- /dev/null
+++ b/0250-Backport-SME-tree-optimization-110221-SLP-and-loop-m.patch
@@ -0,0 +1,75 @@
+From 90518c07dfb770b680fd8bdba76dd1b39103277d Mon Sep 17 00:00:00 2001
+From: Richard Biener 
+Date: Fri, 10 Nov 2023 12:39:11 +0100
+Subject: [PATCH 151/157] [Backport][SME] tree-optimization/110221 - SLP and
+ loop mask/len
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=e5f1956498251a4973d52c8aad3faf34d0443169
+
+The following fixes the issue that when SLP stmts are internal defs
+but appear invariant because they end up only using invariant defs
+then they get scheduled outside of the loop.  This nice optimization
+breaks down when loop masks or lens are applied since those are not
+explicitly tracked as dependences.  The following makes sure to never
+schedule internal defs outside of the vectorized loop when the
+loop uses masks/lens.
+
+	PR tree-optimization/110221
+	* tree-vect-slp.cc (vect_schedule_slp_node): When loop
+	masking / len is applied make sure to not schedule
+	intenal defs outside of the loop.
+
+	* gfortran.dg/pr110221.f: New testcase.
+---
+ gcc/testsuite/gfortran.dg/pr110221.f | 17 +++++++++++++++++
+ gcc/tree-vect-slp.cc                 | 10 ++++++++++
+ 2 files changed, 27 insertions(+)
+ create mode 100644 gcc/testsuite/gfortran.dg/pr110221.f
+
+diff --git a/gcc/testsuite/gfortran.dg/pr110221.f b/gcc/testsuite/gfortran.dg/pr110221.f
+new file mode 100644
+index 000000000..8b5738431
+--- /dev/null
++++ b/gcc/testsuite/gfortran.dg/pr110221.f
+@@ -0,0 +1,17 @@
++C PR middle-end/68146
++C { dg-do compile }
++C { dg-options "-O2 -w" }
++C { dg-additional-options "-mavx512f --param vect-partial-vector-usage=2" { target avx512f } }
++      SUBROUTINE CJYVB(V,Z,V0,CBJ,CDJ,CBY,CYY)
++      IMPLICIT DOUBLE PRECISION (A,B,G,O-Y)
++      IMPLICIT COMPLEX*16 (C,Z)
++      DIMENSION CBJ(0:*),CDJ(0:*),CBY(0:*)
++      N=INT(V)
++      CALL GAMMA2(VG,GA)
++      DO 65 K=1,N
++        CBY(K)=CYY
++65    CONTINUE
++      CDJ(0)=V0/Z*CBJ(0)-CBJ(1)
++      DO 70 K=1,N
++70      CDJ(K)=-(K+V0)/Z*CBJ(K)+CBJ(K-1)
++      END
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index d02f0ce37..e3e246977 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -8531,6 +8531,16 @@ vect_schedule_slp_node (vec_info *vinfo,
+       /* Emit other stmts after the children vectorized defs which is
+ 	 earliest possible.  */
+       gimple *last_stmt = NULL;
++      if (auto loop_vinfo = dyn_cast  (vinfo))
++	if (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
++	    || LOOP_VINFO_FULLY_WITH_LENGTH_P (loop_vinfo))
++	  {
++	    /* But avoid scheduling internal defs outside of the loop when
++	       we might have only implicitly tracked loop mask/len defs.  */
++	    gimple_stmt_iterator si
++	      = gsi_after_labels (LOOP_VINFO_LOOP (loop_vinfo)->header);
++	    last_stmt = *si;
++	  }
+       bool seen_vector_def = false;
+       FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child)
+ 	if (SLP_TREE_DEF_TYPE (child) == vect_internal_def)
+-- 
+2.33.0
+
diff --git a/0251-SME-Adapt-some-testsuites.patch b/0251-SME-Adapt-some-testsuites.patch
new file mode 100644
index 0000000..1653f53
--- /dev/null
+++ b/0251-SME-Adapt-some-testsuites.patch
@@ -0,0 +1,116 @@
+From b60c29e6658c8620f1116ce5a38a6eb823af64e6 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Thu, 7 Mar 2024 10:22:39 +0800
+Subject: [PATCH 152/157] [SME] Adapt some testsuites
+
+gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp:
+  GCC 12.3.0 do not support -std=c23 and -std=gnu23
+
+gcc.target/aarch64/sme/streaming_mode_2.c:
+  It's a warning in GCC 12.3.0
+
+gcc.dg/c2x-attr-syntax-6.c:
+gcc.dg/c2x-attr-syntax-7.c:
+  GCC 12.3.0 do not support C2x (...) function prototypes and
+  C2x noreturn attribute
+
+gcc.target/aarch64/sme/za_state_4.c:
+  Seems need a ldp/stp optimization, not a functionality issue
+---
+ gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c             |  2 --
+ gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c             |  2 --
+ .../gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp  |  2 --
+ .../gcc.target/aarch64/sme/streaming_mode_2.c        | 12 ++++++------
+ gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c    |  1 +
+ 5 files changed, 7 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c
+index 9e5f65ce4..2385b25fe 100644
+--- a/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c
++++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c
+@@ -15,13 +15,11 @@ typedef int [[__extension__ gnu FOO vector_size (4)]] g5;
+ typedef int [[__extension__ gnu BAR BAR vector_size (4)]] g6;
+ typedef int [[__extension__ gnu :/**/: vector_size (4)]] g7;
+ typedef int [[__extension__ gnu JOIN(:,:) vector_size (4)]] g8;
+-typedef int [[__extension__ gnu :: vector_size (sizeof (void (*)(...)))]] g10;
+ typedef int [[__extension__]] g11;
+ typedef int [[__extension__,]] g12;
+ typedef int [[__extension__, ,,,, ,, ,]] g13;
+ [[__extension__ deprecated]] int g14 ();
+ [[__extension__ nodiscard]] int g15 ();
+-[[__extension__ noreturn]] void g16 ();
+ 
+ int
+ cases (int x)
+diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c
+index 702f733b1..5bbdba665 100644
+--- a/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c
++++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c
+@@ -15,13 +15,11 @@ typedef int [[__extension__ gnu FOO vector_size (4)]] g5;
+ typedef int [[__extension__ gnu BAR BAR vector_size (4)]] g6;
+ typedef int [[__extension__ gnu :/**/: vector_size (4)]] g7;
+ typedef int [[__extension__ gnu JOIN(:,:) vector_size (4)]] g8;
+-typedef int [[__extension__ gnu :: vector_size (sizeof (void (*)(...)))]] g10;
+ typedef int [[__extension__]] g11;
+ typedef int [[__extension__,]] g12;
+ typedef int [[__extension__, ,,,, ,, ,]] g13;
+ [[__extension__ deprecated]] int g14 ();
+ [[__extension__ nodiscard]] int g15 ();
+-[[__extension__ noreturn]] void g16 ();
+ 
+ int
+ cases (int x)
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp
+index e2d002f26..a0a4fe4f7 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp
++++ b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme-acle-asm.exp
+@@ -52,9 +52,7 @@ set-torture-options {
+     "-std=c90 -O0 -g"
+     "-std=c99 -Og -g"
+     "-std=c11 -Os -g"
+-    "-std=c23 -O2 -fno-schedule-insns -fno-schedule-insns2 -DCHECK_ASM --save-temps"
+     "-std=gnu90 -O3 -g"
+-    "-std=gnu23 -Ofast -g"
+ } {
+     "-DTEST_FULL"
+     "-DTEST_OVERLOADS"
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c
+index e8be0f821..1e328c817 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/streaming_mode_2.c
+@@ -12,14 +12,14 @@ void
+ f ()
+ {
+   sc_fn_ptr = sc_fn;
+-  sc_fn_ptr = s_fn; // { dg-error "incompatible pointer type" }
+-  sc_fn_ptr = ns_fn; // { dg-error "incompatible pointer type" }
++  sc_fn_ptr = s_fn; // { dg-warning "incompatible pointer type" }
++  sc_fn_ptr = ns_fn; // { dg-warning "incompatible pointer type" }
+ 
+-  s_fn_ptr = sc_fn; // { dg-error "incompatible pointer type" }
++  s_fn_ptr = sc_fn; // { dg-warning "incompatible pointer type" }
+   s_fn_ptr = s_fn;
+-  s_fn_ptr = ns_fn; // { dg-error "incompatible pointer type" }
++  s_fn_ptr = ns_fn; // { dg-warning "incompatible pointer type" }
+ 
+-  ns_fn_ptr = sc_fn; // { dg-error "incompatible pointer type" }
+-  ns_fn_ptr = s_fn; // { dg-error "incompatible pointer type" }
++  ns_fn_ptr = sc_fn; // { dg-warning "incompatible pointer type" }
++  ns_fn_ptr = s_fn; // { dg-warning "incompatible pointer type" }
+   ns_fn_ptr = ns_fn;
+ }
+diff --git a/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c b/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c
+index cec0abf0e..a764a7c89 100644
+--- a/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c
++++ b/gcc/testsuite/gcc.target/aarch64/sme/za_state_4.c
+@@ -105,6 +105,7 @@ __arm_new("za") void test5()
+ **	mul	(x[0-9]+), \1, \1
+ **	sub	sp, sp, \2
+ **	mov	(x[0-9]+), sp
++**	add	[^\n]+
+ **	stp	\3, \1, \[x29, #?16\]
+ **	add	(x[0-9]+), x29, #?16
+ **	msr	tpidr2_el0, \4
+-- 
+2.33.0
+
diff --git a/0252-SME-Fix-error-by-backported-patches-and-IPA-prefetch.patch b/0252-SME-Fix-error-by-backported-patches-and-IPA-prefetch.patch
new file mode 100644
index 0000000..6018ee7
--- /dev/null
+++ b/0252-SME-Fix-error-by-backported-patches-and-IPA-prefetch.patch
@@ -0,0 +1,43 @@
+From ce53aec1f43f79c093db662a2e8e3062462757b4 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Thu, 22 Aug 2024 16:35:28 +0800
+Subject: [PATCH 153/157] [SME] Fix error by backported patches and IPA
+ prefetch
+
+Fix
+gtype-desc.cc: In function 'void gt_pch_p_30vec_cgraph_node__va_gc_atomic_(void*, void*, gt_pointer_operator, void*)':
+gtype-desc.cc:11032:35: error: call of overloaded 'gt_pch_nx(vec*, void (*&)(void*, void*, void*), void*&)' is ambiguous
+11032 |     gt_pch_nx (&((*x)), op, cookie);
+      |                                   ^
+In file included from ../../gcc/hash-table.h:248,
+                 from ../../gcc/coretypes.h:486,
+                 from gtype-desc.cc:23:
+../../gcc/vec.h:1395:1: note: candidate: 'void gt_pch_nx(vec*, gt_pointer_operator, void*) [with T = cgraph_node; A = va_gc_atomic; gt_pointer_operator = void (*)(void*, void*, void*)]'
+ 1395 | gt_pch_nx (vec *v, gt_pointer_operator op, void *cookie)
+      | ^~~~~~~~~
+../../gcc/vec.h:1403:1: note: candidate: 'void gt_pch_nx(vec*, gt_pointer_operator, void*) [with T = cgraph_node*; A = va_gc_atomic; gt_pointer_operator = void (*)(void*, void*, void*)]'
+ 1403 | gt_pch_nx (vec *v, gt_pointer_operator op, void *cookie)
+      | ^~~~~~~~~
+../../gcc/vec.h:1412:1: note: candidate: 'void gt_pch_nx(vec*, gt_pointer_operator, void*) [with T = cgraph_node*; gt_pointer_operator = void (*)(void*, void*, void*)]'
+ 1412 | gt_pch_nx (vec *, gt_pointer_operator, void *)
+      | ^~~~~~~~~
+---
+ gcc/cgraph.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/cgraph.h b/gcc/cgraph.h
+index b84ff2f98..2332539e5 100644
+--- a/gcc/cgraph.h
++++ b/gcc/cgraph.h
+@@ -1660,7 +1660,7 @@ public:
+   /* ECF flags determined from the caller.  */
+   int ecf_flags;
+   /* Vector of potential call targets determined by analysis.  */
+-  vec *targets;
++  vec *targets;
+ 
+   /* Number of speculative call targets, it's less than GCOV_TOPN_VALUES.  */
+   unsigned num_speculative_call_targets : 16;
+-- 
+2.33.0
+
diff --git a/0253-aarch64-Fix-return-register-handling-in-untyped_call.patch b/0253-aarch64-Fix-return-register-handling-in-untyped_call.patch
new file mode 100644
index 0000000..0bddd1a
--- /dev/null
+++ b/0253-aarch64-Fix-return-register-handling-in-untyped_call.patch
@@ -0,0 +1,66 @@
+From 38d0605ac8bc90324170041676fc05e7e595769e Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Wed, 20 Sep 2023 11:13:19 +0100
+Subject: [PATCH] aarch64: Fix return register handling in untyped_call
+
+While working on another patch, I hit a problem with the aarch64
+expansion of untyped_call.  The expander emits the usual:
+
+  (set (mem ...) (reg resN))
+
+instructions to store the result registers to memory, but it didn't
+say in RTL where those resN results came from.  This eventually led
+to a failure of gcc.dg/torture/stackalign/builtin-return-2.c,
+via regrename.
+
+This patch turns the untyped call from a plain call to a call_value,
+to represent that the call returns (or might return) a useful value.
+The patch also uses a PARALLEL return rtx to represent all the possible
+return registers.
+
+gcc/
+	* config/aarch64/aarch64.md (untyped_call): Emit a call_value
+	rather than a call.  List each possible destination register
+	in the call pattern.
+
+(cherry picked from commit 629efe27744d13c3b83bbe8338b84c37c83dbe4f)
+---
+ gcc/config/aarch64/aarch64.md | 20 +++++++++++++++++++-
+ 1 file changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
+index b9b3ba4f9164..cd568f3daa0f 100644
+--- a/gcc/config/aarch64/aarch64.md
++++ b/gcc/config/aarch64/aarch64.md
+@@ -1159,9 +1159,27 @@
+ {
+   int i;
+ 
++  /* Generate a PARALLEL that contains all of the register results.
++     The offsets are somewhat arbitrary, since we don't know the
++     actual return type.  The main thing we need to avoid is having
++     overlapping byte ranges, since those might give the impression
++     that two registers are known to have data in common.  */
++  rtvec rets = rtvec_alloc (XVECLEN (operands[2], 0));
++  poly_int64 offset = 0;
++  for (i = 0; i < XVECLEN (operands[2], 0); i++)
++    {
++      rtx reg = SET_SRC (XVECEXP (operands[2], 0, i));
++      gcc_assert (REG_P (reg));
++      rtx offset_rtx = gen_int_mode (offset, Pmode);
++      rtx piece = gen_rtx_EXPR_LIST (VOIDmode, reg, offset_rtx);
++      RTVEC_ELT (rets, i) = piece;
++      offset += GET_MODE_SIZE (GET_MODE (reg));
++    }
++  rtx ret = gen_rtx_PARALLEL (VOIDmode, rets);
++
+   /* Untyped calls always use the default ABI.  It's only possible to use
+      ABI variants if we know the type of the target function.  */
+-  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
++  emit_call_insn (gen_call_value (ret, operands[0], const0_rtx, const0_rtx));
+ 
+   for (i = 0; i < XVECLEN (operands[2], 0); i++)
+     {
+-- 
+2.43.5
+
diff --git a/0254-aarch64-Fix-loose-ldpstp-check.patch b/0254-aarch64-Fix-loose-ldpstp-check.patch
new file mode 100644
index 0000000..756a444
--- /dev/null
+++ b/0254-aarch64-Fix-loose-ldpstp-check.patch
@@ -0,0 +1,119 @@
+From 74f99f1adc696f446115f36974a3f94f66294a53 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford 
+Date: Wed, 20 Sep 2023 11:13:20 +0100
+Subject: [PATCH] aarch64: Fix loose ldpstp check [PR111411]
+
+aarch64_operands_ok_for_ldpstp contained the code:
+
+  /* One of the memory accesses must be a mempair operand.
+     If it is not the first one, they need to be swapped by the
+     peephole.  */
+  if (!aarch64_mem_pair_operand (mem_1, GET_MODE (mem_1))
+       && !aarch64_mem_pair_operand (mem_2, GET_MODE (mem_2)))
+    return false;
+
+But the requirement isn't just that one of the accesses must be a
+valid mempair operand.  It's that the lower access must be, since
+that's the access that will be used for the instruction operand.
+
+gcc/
+	PR target/111411
+	* config/aarch64/aarch64.cc (aarch64_operands_ok_for_ldpstp): Require
+	the lower memory access to a mem-pair operand.
+
+gcc/testsuite/
+	PR target/111411
+	* gcc.dg/rtl/aarch64/pr111411.c: New test.
+
+(cherry picked from commit 2d38f45bcca62ca0c7afef4b579f82c5c2a01610)
+---
+ gcc/config/aarch64/aarch64.cc               |  8 ++-
+ gcc/testsuite/gcc.dg/rtl/aarch64/pr111411.c | 57 +++++++++++++++++++++
+ 2 files changed, 60 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/pr111411.c
+
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 96c3f48fdc49..a979accd90a9 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -26031,11 +26031,9 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
+   gcc_assert (known_eq (GET_MODE_SIZE (GET_MODE (mem_1)),
+ 			GET_MODE_SIZE (GET_MODE (mem_2))));
+ 
+-  /* One of the memory accesses must be a mempair operand.
+-     If it is not the first one, they need to be swapped by the
+-     peephole.  */
+-  if (!aarch64_mem_pair_operand (mem_1, GET_MODE (mem_1))
+-       && !aarch64_mem_pair_operand (mem_2, GET_MODE (mem_2)))
++  /* The lower memory access must be a mem-pair operand.  */
++  rtx lower_mem = reversed ? mem_2 : mem_1;
++  if (!aarch64_mem_pair_operand (lower_mem, GET_MODE (lower_mem)))
+     return false;
+ 
+   if (REG_P (reg_1) && FP_REGNUM_P (REGNO (reg_1)))
+diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/pr111411.c b/gcc/testsuite/gcc.dg/rtl/aarch64/pr111411.c
+new file mode 100644
+index 000000000000..ad07e9c6c893
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/rtl/aarch64/pr111411.c
+@@ -0,0 +1,57 @@
++/* { dg-do compile { target aarch64*-*-* } } */
++/* { dg-require-effective-target lp64 } */
++/* { dg-options "-O -fdisable-rtl-postreload -fpeephole2 -fno-schedule-fusion" } */
++
++extern int data[];
++
++void __RTL (startwith ("ira")) foo (void *ptr)
++{
++  (function "foo"
++    (param "ptr"
++      (DECL_RTL (reg/v:DI <0> [ ptr ]))
++      (DECL_RTL_INCOMING (reg/v:DI x0 [ ptr ]))
++    ) ;; param "ptr"
++    (insn-chain
++      (block 2
++	(edge-from entry (flags "FALLTHRU"))
++	(cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++	(insn 4 (set (reg:DI <0>) (reg:DI x0)))
++	(insn 5 (set (reg:DI <1>)
++		     (plus:DI (reg:DI <0>) (const_int 768))))
++	(insn 6 (set (mem:SI (plus:DI (reg:DI <0>)
++				      (const_int 508)) [1 &data+508 S4 A4])
++		     (const_int 0)))
++	(insn 7 (set (mem:SI (plus:DI (reg:DI <1>)
++				      (const_int -256)) [1 &data+512 S4 A4])
++		     (const_int 0)))
++	(edge-to exit (flags "FALLTHRU"))
++      ) ;; block 2
++    ) ;; insn-chain
++  ) ;; function
++}
++
++void __RTL (startwith ("ira")) bar (void *ptr)
++{
++  (function "bar"
++    (param "ptr"
++      (DECL_RTL (reg/v:DI <0> [ ptr ]))
++      (DECL_RTL_INCOMING (reg/v:DI x0 [ ptr ]))
++    ) ;; param "ptr"
++    (insn-chain
++      (block 2
++	(edge-from entry (flags "FALLTHRU"))
++	(cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
++	(insn 4 (set (reg:DI <0>) (reg:DI x0)))
++	(insn 5 (set (reg:DI <1>)
++		     (plus:DI (reg:DI <0>) (const_int 768))))
++	(insn 6 (set (mem:SI (plus:DI (reg:DI <1>)
++				      (const_int -256)) [1 &data+512 S4 A4])
++		     (const_int 0)))
++	(insn 7 (set (mem:SI (plus:DI (reg:DI <0>)
++				      (const_int 508)) [1 &data+508 S4 A4])
++		     (const_int 0)))
++	(edge-to exit (flags "FALLTHRU"))
++      ) ;; block 2
++    ) ;; insn-chain
++  ) ;; function
++}
+-- 
+2.43.5
+
diff --git a/0255-x86-Add-a-new-option-mdaz-ftz-to-enable-FTZ-and-DAZ-.patch b/0255-x86-Add-a-new-option-mdaz-ftz-to-enable-FTZ-and-DAZ-.patch
new file mode 100644
index 0000000..d96f552
--- /dev/null
+++ b/0255-x86-Add-a-new-option-mdaz-ftz-to-enable-FTZ-and-DAZ-.patch
@@ -0,0 +1,135 @@
+From 1649f9fbbc5267de2a675336d3ac665528a03db8 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Wed, 10 May 2023 15:16:58 +0800
+Subject: [PATCH 01/28] x86: Add a new option -mdaz-ftz to enable FTZ and DAZ
+ flags in MXCSR.
+
+    if (mdaz-ftz)
+      link crtfastmath.o
+    else if ((Ofast || ffast-math || funsafe-math-optimizations)
+             && !mno-daz-ftz)
+      link crtfastmath.o
+    else
+      Don't link crtfastmath.o
+
+gcc/ChangeLog:
+
+	* config/i386/cygwin.h (ENDFILE_SPEC): Link crtfastmath.o
+	whenever -mdaz-ftz is specified. Don't link crtfastmath.o
+	when -mno-daz-ftz is specified.
+	* config/i386/darwin.h (ENDFILE_SPEC): Ditto.
+	* config/i386/gnu-user-common.h
+	(GNU_USER_TARGET_MATHFILE_SPEC): Ditto.
+	* config/i386/mingw32.h (ENDFILE_SPEC): Ditto.
+	* config/i386/i386.opt (mdaz-ftz): New option.
+	* doc/invoke.texi (x86 options): Document mftz-daz.
+---
+ gcc/config/i386/cygwin.h          |  2 +-
+ gcc/config/i386/darwin.h          |  4 ++--
+ gcc/config/i386/gnu-user-common.h |  2 +-
+ gcc/config/i386/i386.opt          |  4 ++++
+ gcc/config/i386/mingw32.h         |  2 +-
+ gcc/doc/invoke.texi               | 11 ++++++++++-
+ 6 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h
+index d06eda369..5412c5d44 100644
+--- a/gcc/config/i386/cygwin.h
++++ b/gcc/config/i386/cygwin.h
+@@ -57,7 +57,7 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ #undef ENDFILE_SPEC
+ #define ENDFILE_SPEC \
+-  "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}\
++  "%{mdaz-ftz:crtfastmath.o%s;Ofast|ffast-math|funsafe-math-optimizations:%{!mno-daz-ftz:crtfastmath.o%s}} \
+    %{!shared:%:if-exists(default-manifest.o%s)}\
+    %{fvtable-verify=none:%s; \
+     fvtable-verify=preinit:vtv_end.o%s; \
+diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
+index a55f6b2b8..2f773924d 100644
+--- a/gcc/config/i386/darwin.h
++++ b/gcc/config/i386/darwin.h
+@@ -109,8 +109,8 @@ along with GCC; see the file COPYING3.  If not see
+ "%{!force_cpusubtype_ALL:-force_cpusubtype_ALL} "
+ 
+ #undef ENDFILE_SPEC
+-#define ENDFILE_SPEC \
+-  "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
++#define ENDFILE_SPEC
++\  "%{mdaz-ftz:crtfastmath.o%s;Ofast|ffast-math|funsafe-math-optimizations:%{!mno-daz-ftz:crtfastmath.o%s}} \
+    %{mpc32:crtprec32.o%s} \
+    %{mpc64:crtprec64.o%s} \
+    %{mpc80:crtprec80.o%s}" TM_DESTRUCTOR
+diff --git a/gcc/config/i386/gnu-user-common.h b/gcc/config/i386/gnu-user-common.h
+index 23b54c5be..3d2a33f17 100644
+--- a/gcc/config/i386/gnu-user-common.h
++++ b/gcc/config/i386/gnu-user-common.h
+@@ -47,7 +47,7 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ /* Similar to standard GNU userspace, but adding -ffast-math support.  */
+ #define GNU_USER_TARGET_MATHFILE_SPEC \
+-  "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
++  "%{mdaz-ftz:crtfastmath.o%s;Ofast|ffast-math|funsafe-math-optimizations:%{!mno-daz-ftz:crtfastmath.o%s}} \
+    %{mpc32:crtprec32.o%s} \
+    %{mpc64:crtprec64.o%s} \
+    %{mpc80:crtprec80.o%s}"
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index fc1b944ac..498fb454d 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -420,6 +420,10 @@ mpc80
+ Target RejectNegative
+ Set 80387 floating-point precision to 80-bit.
+ 
++mdaz-ftz
++Target
++Set the FTZ and DAZ Flags.
++
+ mpreferred-stack-boundary=
+ Target RejectNegative Joined UInteger Var(ix86_preferred_stack_boundary_arg)
+ Attempt to keep stack aligned to this power of 2.
+diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
+index d3ca0cd02..ddbe6a405 100644
+--- a/gcc/config/i386/mingw32.h
++++ b/gcc/config/i386/mingw32.h
+@@ -197,7 +197,7 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ #undef ENDFILE_SPEC
+ #define ENDFILE_SPEC \
+-  "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
++  "%{mdaz-ftz:crtfastmath.o%s;Ofast|ffast-math|funsafe-math-optimizations:%{!mno-daz-ftz:crtfastmath.o%s}} \
+    %{!shared:%:if-exists(default-manifest.o%s)}\
+    %{fvtable-verify=none:%s; \
+     fvtable-verify=preinit:vtv_end.o%s; \
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 2b376e0e9..3a48655e5 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1437,7 +1437,7 @@ See RS/6000 and PowerPC Options.
+ -m96bit-long-double  -mlong-double-64  -mlong-double-80  -mlong-double-128 @gol
+ -mregparm=@var{num}  -msseregparm @gol
+ -mveclibabi=@var{type}  -mvect8-ret-in-mem @gol
+--mpc32  -mpc64  -mpc80  -mstackrealign @gol
++-mpc32  -mpc64  -mpc80 -mdaz-ftz -mstackrealign @gol
+ -momit-leaf-frame-pointer  -mno-red-zone  -mno-tls-direct-seg-refs @gol
+ -mcmodel=@var{code-model}  -mabi=@var{name}  -maddress-mode=@var{mode} @gol
+ -m32  -m64  -mx32  -m16  -miamcu  -mlarge-data-threshold=@var{num} @gol
+@@ -32122,6 +32122,15 @@ are enabled by default; routines in such libraries could suffer significant
+ loss of accuracy, typically through so-called ``catastrophic cancellation'',
+ when this option is used to set the precision to less than extended precision.
+ 
++@item -mdaz-ftz
++@opindex mdaz-ftz
++
++The flush-to-zero (FTZ) and denormals-are-zero (DAZ) flags in the MXCSR register
++are used to control floating-point calculations.SSE and AVX instructions
++including scalar and vector instructions could benefit from enabling the FTZ
++and DAZ flags when @option{-mdaz-ftz} is specified. Don't set FTZ/DAZ flags
++when @option{-mno-daz-ftz} is specified.
++
+ @item -mstackrealign
+ @opindex mstackrealign
+ Realign the stack at entry.  On the x86, the @option{-mstackrealign}
+-- 
+2.31.1
+
diff --git a/0256-Explicitly-view_convert_expr-mask-to-signed-type-whe.patch b/0256-Explicitly-view_convert_expr-mask-to-signed-type-whe.patch
new file mode 100644
index 0000000..39c8916
--- /dev/null
+++ b/0256-Explicitly-view_convert_expr-mask-to-signed-type-whe.patch
@@ -0,0 +1,65 @@
+From e70fa730dcfcb3a7b1d56a2e166752d4299f0504 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Mon, 5 Jun 2023 12:38:41 +0800
+Subject: [PATCH 02/28] Explicitly view_convert_expr mask to signed type when
+ folding pblendvb builtins.
+
+Since mask < 0 will be always false for vector char when
+-funsigned-char, but vpblendvb needs to check the most significant
+bit. The patch explicitly VCE to vector signed char.
+
+gcc/ChangeLog:
+
+	PR target/110108
+	* config/i386/i386.cc (ix86_gimple_fold_builtin): Explicitly
+	view_convert_expr mask to signed type when folding pblendvb
+	builtins.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/pr110108-2.c: New test.
+---
+ gcc/config/i386/i386.cc                    |  4 +++-
+ gcc/testsuite/gcc.target/i386/pr110108-2.c | 14 ++++++++++++++
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/pr110108-2.c
+
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index 462dce10e..479fc6010 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -18396,8 +18396,10 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+ 	      tree itype = GET_MODE_INNER (TYPE_MODE (type)) == E_SFmode
+ 		? intSI_type_node : intDI_type_node;
+ 	      type = get_same_sized_vectype (itype, type);
+-	      arg2 = gimple_build (&stmts, VIEW_CONVERT_EXPR, type, arg2);
+ 	    }
++	  else
++	    type = signed_type_for (type);
++	  arg2 = gimple_build (&stmts, VIEW_CONVERT_EXPR, type, arg2);
+ 	  tree zero_vec = build_zero_cst (type);
+ 	  tree cmp_type = truth_type_for (type);
+ 	  tree cmp = gimple_build (&stmts, LT_EXPR, cmp_type, arg2, zero_vec);
+diff --git a/gcc/testsuite/gcc.target/i386/pr110108-2.c b/gcc/testsuite/gcc.target/i386/pr110108-2.c
+new file mode 100644
+index 000000000..2d1d2fd49
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/pr110108-2.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile } */
++/* { dg-options "-mavx2 -O2 -funsigned-char" } */
++/* { dg-final { scan-assembler-times "vpblendvb" 2 } } */
++
++#include 
++__m128i do_stuff_128(__m128i X0, __m128i X1, __m128i X2) {
++  __m128i Result = _mm_blendv_epi8(X0, X1, X2);
++  return Result;
++}
++
++__m256i do_stuff_256(__m256i X0, __m256i X1, __m256i X2) {
++  __m256i Result = _mm256_blendv_epi8(X0, X1, X2);
++  return Result;
++}
+-- 
+2.31.1
+
diff --git a/0257-Make-option-mvzeroupper-independent-of-optimization-.patch b/0257-Make-option-mvzeroupper-independent-of-optimization-.patch
new file mode 100644
index 0000000..ffdffb1
--- /dev/null
+++ b/0257-Make-option-mvzeroupper-independent-of-optimization-.patch
@@ -0,0 +1,138 @@
+From 48715f03ad08f185153bfb0ff4c0802ab2d9579c Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Mon, 26 Jun 2023 09:50:25 +0800
+Subject: [PATCH 03/28] Make option mvzeroupper independent of optimization
+ level.
+
+pass_insert_vzeroupper is under condition
+
+TARGET_AVX && TARGET_VZEROUPPER
+&& flag_expensive_optimizations && !optimize_size
+
+But the document of mvzeroupper doesn't mention the insertion
+required -O2 and above, it may confuse users when they explicitly
+use -Os -mvzeroupper.
+
+------------
+mvzeroupper
+Target Mask(VZEROUPPER) Save
+Generate vzeroupper instruction before a transfer of control flow out of
+the function.
+------------
+
+The patch moves flag_expensive_optimizations && !optimize_size to
+ix86_option_override_internal. It makes -mvzeroupper independent of
+optimization level, but still keeps the behavior of architecture
+tuning(emit_vzeroupper) unchanged.
+
+gcc/ChangeLog:
+
+	* config/i386/i386-features.cc (pass_insert_vzeroupper:gate):
+	Move flag_expensive_optimizations && !optimize_size to ..
+	* config/i386/i386-options.cc (ix86_option_override_internal):
+	.. this, it makes -mvzeroupper independent of optimization
+	level, but still keeps the behavior of architecture
+	tuning(emit_vzeroupper) unchanged.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/avx-vzeroupper-29.c: New testcase.
+	* gcc.target/i386/avx-vzeroupper-12.c: Adjust testcase.
+	* gcc.target/i386/avx-vzeroupper-7.c: Ditto.
+	* gcc.target/i386/avx-vzeroupper-9.c: Ditto.
+---
+ gcc/config/i386/i386-features.cc                  |  3 +--
+ gcc/config/i386/i386-options.cc                   |  4 +++-
+ gcc/testsuite/gcc.target/i386/avx-vzeroupper-12.c |  3 ++-
+ gcc/testsuite/gcc.target/i386/avx-vzeroupper-29.c | 14 ++++++++++++++
+ gcc/testsuite/gcc.target/i386/avx-vzeroupper-7.c  |  3 ++-
+ gcc/testsuite/gcc.target/i386/avx-vzeroupper-9.c  |  3 ++-
+ 6 files changed, 24 insertions(+), 6 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/avx-vzeroupper-29.c
+
+diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
+index 6fe41c3c2..6a2444eb6 100644
+--- a/gcc/config/i386/i386-features.cc
++++ b/gcc/config/i386/i386-features.cc
+@@ -1875,8 +1875,7 @@ public:
+   /* opt_pass methods: */
+   virtual bool gate (function *)
+     {
+-      return TARGET_AVX && TARGET_VZEROUPPER
+-	&& flag_expensive_optimizations && !optimize_size;
++      return TARGET_AVX && TARGET_VZEROUPPER;
+     }
+ 
+   virtual unsigned int execute (function *)
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index ff44ad4e0..74e969b68 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -2702,7 +2702,9 @@ ix86_option_override_internal (bool main_args_p,
+     sorry ("%<-mcall-ms2sysv-xlogues%> isn%'t currently supported with SEH");
+ 
+   if (!(opts_set->x_target_flags & MASK_VZEROUPPER)
+-      && TARGET_EMIT_VZEROUPPER)
++      && TARGET_EMIT_VZEROUPPER
++      && flag_expensive_optimizations
++      && !optimize_size)
+     opts->x_target_flags |= MASK_VZEROUPPER;
+   if (!(opts_set->x_target_flags & MASK_STV))
+     opts->x_target_flags |= MASK_STV;
+diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-12.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-12.c
+index e694d4048..5a40e8783 100644
+--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-12.c
++++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-12.c
+@@ -16,5 +16,6 @@ foo ()
+   _mm256_zeroupper ();
+ }
+ 
+-/* { dg-final { scan-assembler-times "avx_vzeroupper" 4 } } */
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 4 { target ia32 } } } */
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 5 { target { ! ia32 } } } } */
+ /* { dg-final { scan-assembler-times "\\*avx_vzeroall" 1 } } */
+diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-29.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-29.c
+new file mode 100644
+index 000000000..4af637757
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-29.c
+@@ -0,0 +1,14 @@
++/* { dg-do compile } */
++/* { dg-options "-O0 -mavx -mtune=generic -mvzeroupper -dp" } */
++
++#include 
++
++extern __m256 x, y;
++
++void
++foo ()
++{
++  x = y;
++}
++
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 1 } } */
+diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-7.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-7.c
+index ab6d68779..75fe58897 100644
+--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-7.c
++++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-7.c
+@@ -12,4 +12,5 @@ foo ()
+   _mm256_zeroupper ();
+ }
+ 
+-/* { dg-final { scan-assembler-times "avx_vzeroupper" 1 } } */
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 1 { target ia32 } } } */
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 2 { target { ! ia32 } } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-9.c b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-9.c
+index 974e1626a..fa0a6dfca 100644
+--- a/gcc/testsuite/gcc.target/i386/avx-vzeroupper-9.c
++++ b/gcc/testsuite/gcc.target/i386/avx-vzeroupper-9.c
+@@ -15,4 +15,5 @@ foo ()
+   _mm256_zeroupper ();
+ }
+ 
+-/* { dg-final { scan-assembler-times "avx_vzeroupper" 4 } } */
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 4 { target ia32 } } } */
++/* { dg-final { scan-assembler-times "avx_vzeroupper" 5 { target { ! ia32 } } } } */
+-- 
+2.31.1
+
diff --git a/0258-i386-Sync-tune_string-with-arch_string-for-target-at.patch b/0258-i386-Sync-tune_string-with-arch_string-for-target-at.patch
new file mode 100644
index 0000000..d365246
--- /dev/null
+++ b/0258-i386-Sync-tune_string-with-arch_string-for-target-at.patch
@@ -0,0 +1,68 @@
+From 8039d773354360ed8ff2f25c63843fc637eacc67 Mon Sep 17 00:00:00 2001
+From: Hongyu Wang 
+Date: Sun, 25 Jun 2023 09:50:21 +0800
+Subject: [PATCH 04/28] i386: Sync tune_string with arch_string for target
+ attribute
+
+arch=*
+
+For function with target attribute arch=*, current logic will set its
+tune to -mtune from command line so all target_clones will get same
+tuning flags which would affect the performance for each clone. Override
+tune with arch if tune was not explicitly specified to get proper tuning
+flags for target_clones.
+
+gcc/ChangeLog:
+
+	* config/i386/i386-options.cc (ix86_valid_target_attribute_tree):
+	Override tune_string with arch_string if tune_string is not
+	explicitly specified.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/mvc17.c: New test.
+
+(cherry picked from commit 2916278d14e9ac28c361c396a67256acbebda6e8)
+---
+ gcc/config/i386/i386-options.cc       |  6 +++++-
+ gcc/testsuite/gcc.target/i386/mvc17.c | 11 +++++++++++
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/mvc17.c
+
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 74e969b68..fb2ed942f 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -1378,7 +1378,11 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args,
+       if (option_strings[IX86_FUNCTION_SPECIFIC_TUNE])
+ 	opts->x_ix86_tune_string
+ 	  = ggc_strdup (option_strings[IX86_FUNCTION_SPECIFIC_TUNE]);
+-      else if (orig_tune_defaulted)
++      /* If we have explicit arch string and no tune string specified, set
++	 tune_string to NULL and later it will be overriden by arch_string
++	 so target clones can get proper optimization.  */
++      else if (option_strings[IX86_FUNCTION_SPECIFIC_ARCH]
++	       || orig_tune_defaulted)
+ 	opts->x_ix86_tune_string = NULL;
+ 
+       /* If fpmath= is not set, and we now have sse2 on 32-bit, use it.  */
+diff --git a/gcc/testsuite/gcc.target/i386/mvc17.c b/gcc/testsuite/gcc.target/i386/mvc17.c
+new file mode 100644
+index 000000000..8b83c1aec
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/mvc17.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++/* { dg-require-ifunc "" } */
++/* { dg-options "-O2 -march=x86-64" } */
++/* { dg-final { scan-assembler-times "rep mov" 1 } } */
++
++__attribute__((target_clones("default","arch=icelake-server")))
++void
++foo (char *a, char *b, int size)
++{
++  __builtin_memcpy (a, b, size & 0x7F);
++}
+-- 
+2.31.1
+
diff --git a/0259-Refine-maskloadmn-pattern-with-UNSPEC_MASKLOAD.patch b/0259-Refine-maskloadmn-pattern-with-UNSPEC_MASKLOAD.patch
new file mode 100644
index 0000000..2918d3e
--- /dev/null
+++ b/0259-Refine-maskloadmn-pattern-with-UNSPEC_MASKLOAD.patch
@@ -0,0 +1,111 @@
+From fbcb1a5899b1bd3964aed78ed74041121e618d36 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Tue, 20 Jun 2023 15:41:00 +0800
+Subject: [PATCH 05/28] Refine maskloadmn pattern with UNSPEC_MASKLOAD.
+
+If mem_addr points to a memory region with less than whole vector size
+bytes of accessible memory and k is a mask that would prevent reading
+the inaccessible bytes from mem_addr, add UNSPEC_MASKLOAD to prevent
+it to be transformed to vpblendd.
+
+gcc/ChangeLog:
+
+	PR target/110309
+	* config/i386/sse.md (maskload):
+	Refine pattern with UNSPEC_MASKLOAD.
+	(maskload): Ditto.
+	(*_load_mask): Extend mode iterator to
+	VI12HF_AVX512VL.
+	(*_load): Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/pr110309.c: New test.
+---
+ gcc/config/i386/sse.md                   | 32 +++++++++++++-----------
+ gcc/testsuite/gcc.target/i386/pr110309.c | 10 ++++++++
+ 2 files changed, 28 insertions(+), 14 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/pr110309.c
+
+diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
+index eb767e56c..b30e96cb1 100644
+--- a/gcc/config/i386/sse.md
++++ b/gcc/config/i386/sse.md
+@@ -1411,12 +1411,12 @@
+ })
+ 
+ (define_insn "*_load_mask"
+-  [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
+-	(vec_merge:VI12_AVX512VL
+-	  (unspec:VI12_AVX512VL
+-	    [(match_operand:VI12_AVX512VL 1 "memory_operand" "m")]
++  [(set (match_operand:VI12HF_AVX512VL 0 "register_operand" "=v")
++	(vec_merge:VI12HF_AVX512VL
++	  (unspec:VI12HF_AVX512VL
++	    [(match_operand:VI12HF_AVX512VL 1 "memory_operand" "m")]
+ 	    UNSPEC_MASKLOAD)
+-	  (match_operand:VI12_AVX512VL 2 "nonimm_or_0_operand" "0C")
++	  (match_operand:VI12HF_AVX512VL 2 "nonimm_or_0_operand" "0C")
+ 	  (match_operand: 3 "register_operand" "Yk")))]
+   "TARGET_AVX512BW"
+   "vmovdqu\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"
+@@ -1425,9 +1425,9 @@
+    (set_attr "mode" "")])
+ 
+ (define_insn_and_split "*_load"
+-  [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
+-	(unspec:VI12_AVX512VL
+-	  [(match_operand:VI12_AVX512VL 1 "memory_operand" "m")]
++  [(set (match_operand:VI12HF_AVX512VL 0 "register_operand" "=v")
++	(unspec:VI12HF_AVX512VL
++	  [(match_operand:VI12HF_AVX512VL 1 "memory_operand" "m")]
+ 	  UNSPEC_MASKLOAD))]
+   "TARGET_AVX512BW"
+   "#"
+@@ -25973,17 +25973,21 @@
+   "TARGET_AVX")
+ 
+ (define_expand "maskload"
+-  [(set (match_operand:V48H_AVX512VL 0 "register_operand")
+-	(vec_merge:V48H_AVX512VL
+-	  (match_operand:V48H_AVX512VL 1 "memory_operand")
++  [(set (match_operand:V48_AVX512VL 0 "register_operand")
++	(vec_merge:V48_AVX512VL
++	  (unspec:V48_AVX512VL
++	    [(match_operand:V48_AVX512VL 1 "memory_operand")]
++	    UNSPEC_MASKLOAD)
+ 	  (match_dup 0)
+ 	  (match_operand: 2 "register_operand")))]
+   "TARGET_AVX512F")
+ 
+ (define_expand "maskload"
+-  [(set (match_operand:VI12_AVX512VL 0 "register_operand")
+-	(vec_merge:VI12_AVX512VL
+-	  (match_operand:VI12_AVX512VL 1 "memory_operand")
++  [(set (match_operand:VI12HF_AVX512VL 0 "register_operand")
++	(vec_merge:VI12HF_AVX512VL
++	  (unspec:VI12HF_AVX512VL
++	    [(match_operand:VI12HF_AVX512VL 1 "memory_operand")]
++	    UNSPEC_MASKLOAD)
+ 	  (match_dup 0)
+ 	  (match_operand: 2 "register_operand")))]
+   "TARGET_AVX512BW")
+diff --git a/gcc/testsuite/gcc.target/i386/pr110309.c b/gcc/testsuite/gcc.target/i386/pr110309.c
+new file mode 100644
+index 000000000..f6e9e9c3c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/pr110309.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 --param vect-partial-vector-usage=1 -march=znver4 -mprefer-vector-width=256" } */
++/* { dg-final { scan-assembler-not {(?n)vpblendd.*ymm} } } */
++
++
++void foo (int * __restrict a, int *b)
++{
++  for (int i = 0; i < 6; ++i)
++    a[i] = b[i] + 42;
++}
+-- 
+2.31.1
+
diff --git a/0260-Refine-maskstore-patterns-with-UNSPEC_MASKMOV.patch b/0260-Refine-maskstore-patterns-with-UNSPEC_MASKMOV.patch
new file mode 100644
index 0000000..e0546c3
--- /dev/null
+++ b/0260-Refine-maskstore-patterns-with-UNSPEC_MASKMOV.patch
@@ -0,0 +1,126 @@
+From 5ad28ef4010c1248b4d94396d03f863705f7b0db Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Mon, 26 Jun 2023 21:07:09 +0800
+Subject: [PATCH 06/28] Refine maskstore patterns with UNSPEC_MASKMOV.
+
+Similar like r14-2070-gc79476da46728e
+
+If mem_addr points to a memory region with less than whole vector size
+bytes of accessible memory and k is a mask that would prevent reading
+the inaccessible bytes from mem_addr, add UNSPEC_MASKMOV to prevent
+it to be transformed to any other whole memory access instructions.
+
+gcc/ChangeLog:
+
+	PR rtl-optimization/110237
+	* config/i386/sse.md (_store_mask): Refine with
+	UNSPEC_MASKMOV.
+	(maskstore_store_mask): New define_insn, it's renamed
+	from original _store_mask.
+---
+ gcc/config/i386/sse.md | 69 ++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 57 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
+index b30e96cb1..3af159896 100644
+--- a/gcc/config/i386/sse.md
++++ b/gcc/config/i386/sse.md
+@@ -1554,7 +1554,7 @@
+    (set_attr "prefix" "evex")
+    (set_attr "mode" "")])
+ 
+-(define_insn "_store_mask"
++(define_insn "*_store_mask"
+   [(set (match_operand:V48_AVX512VL 0 "memory_operand" "=m")
+ 	(vec_merge:V48_AVX512VL
+ 	  (match_operand:V48_AVX512VL 1 "register_operand" "v")
+@@ -1582,7 +1582,7 @@
+    (set_attr "memory" "store")
+    (set_attr "mode" "")])
+ 
+-(define_insn "_store_mask"
++(define_insn "*_store_mask"
+   [(set (match_operand:VI12HF_AVX512VL 0 "memory_operand" "=m")
+ 	(vec_merge:VI12HF_AVX512VL
+ 	  (match_operand:VI12HF_AVX512VL 1 "register_operand" "v")
+@@ -26002,21 +26002,66 @@
+   "TARGET_AVX")
+ 
+ (define_expand "maskstore"
+-  [(set (match_operand:V48H_AVX512VL 0 "memory_operand")
+-	(vec_merge:V48H_AVX512VL
+-	  (match_operand:V48H_AVX512VL 1 "register_operand")
+-	  (match_dup 0)
+-	  (match_operand: 2 "register_operand")))]
++  [(set (match_operand:V48_AVX512VL 0 "memory_operand")
++	(unspec:V48_AVX512VL
++	  [(match_operand:V48_AVX512VL 1 "register_operand")
++	   (match_dup 0)
++	   (match_operand: 2 "register_operand")]
++	  UNSPEC_MASKMOV))]
+   "TARGET_AVX512F")
+ 
+ (define_expand "maskstore"
+-  [(set (match_operand:VI12_AVX512VL 0 "memory_operand")
+-	(vec_merge:VI12_AVX512VL
+-	  (match_operand:VI12_AVX512VL 1 "register_operand")
+-	  (match_dup 0)
+-	  (match_operand: 2 "register_operand")))]
++  [(set (match_operand:VI12HF_AVX512VL 0 "memory_operand")
++	(unspec:VI12HF_AVX512VL
++	  [(match_operand:VI12HF_AVX512VL 1 "register_operand")
++	   (match_dup 0)
++	   (match_operand: 2 "register_operand")]
++	  UNSPEC_MASKMOV))]
+   "TARGET_AVX512BW")
+ 
++(define_insn "_store_mask"
++  [(set (match_operand:V48_AVX512VL 0 "memory_operand" "=m")
++	(unspec:V48_AVX512VL
++	  [(match_operand:V48_AVX512VL 1 "register_operand" "v")
++	   (match_dup 0)
++	   (match_operand: 2 "register_operand" "Yk")]
++	  UNSPEC_MASKMOV))]
++  "TARGET_AVX512F"
++{
++  if (FLOAT_MODE_P (GET_MODE_INNER (mode)))
++    {
++      if (misaligned_operand (operands[0], mode))
++	return "vmovu\t{%1, %0%{%2%}|%0%{%2%}, %1}";
++      else
++	return "vmova\t{%1, %0%{%2%}|%0%{%2%}, %1}";
++    }
++  else
++    {
++      if (misaligned_operand (operands[0], mode))
++	return "vmovdqu\t{%1, %0%{%2%}|%0%{%2%}, %1}";
++      else
++	return "vmovdqa\t{%1, %0%{%2%}|%0%{%2%}, %1}";
++    }
++}
++  [(set_attr "type" "ssemov")
++   (set_attr "prefix" "evex")
++   (set_attr "memory" "store")
++   (set_attr "mode" "")])
++
++(define_insn "_store_mask"
++  [(set (match_operand:VI12HF_AVX512VL 0 "memory_operand" "=m")
++	(unspec:VI12HF_AVX512VL
++	  [(match_operand:VI12HF_AVX512VL 1 "register_operand" "v")
++	   (match_dup 0)
++	   (match_operand: 2 "register_operand" "Yk")]
++	   UNSPEC_MASKMOV))]
++  "TARGET_AVX512BW"
++  "vmovdqu\t{%1, %0%{%2%}|%0%{%2%}, %1}"
++  [(set_attr "type" "ssemov")
++   (set_attr "prefix" "evex")
++   (set_attr "memory" "store")
++   (set_attr "mode" "")])
++
+ (define_expand "cbranch4"
+   [(set (reg:CC FLAGS_REG)
+ 	(compare:CC (match_operand:VI48_AVX 1 "register_operand")
+-- 
+2.31.1
+
diff --git a/0261-x86-Update-model-values-for-Alderlake-and-Rocketlake.patch b/0261-x86-Update-model-values-for-Alderlake-and-Rocketlake.patch
new file mode 100644
index 0000000..889bbdc
--- /dev/null
+++ b/0261-x86-Update-model-values-for-Alderlake-and-Rocketlake.patch
@@ -0,0 +1,38 @@
+From 50757adc93ef32a97a8a1083f5d53a9c00da6ac8 Mon Sep 17 00:00:00 2001
+From: "Cui, Lili" 
+Date: Thu, 29 Jun 2023 03:10:35 +0000
+Subject: [PATCH 07/28] x86: Update model values for Alderlake and Rocketlake.
+
+Update model values for Alderlake and Rocketlake according to SDM.
+
+gcc/ChangeLog
+
+	* common/config/i386/cpuinfo.h (get_intel_cpu): Remove model value 0xa8
+	from Rocketlake, remove model value 0xbf from Alderlake.
+---
+ gcc/common/config/i386/cpuinfo.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 0333da56b..28b2ff0b0 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -435,7 +435,6 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       cpu_model->__cpu_subtype = INTEL_COREI7_SKYLAKE;
+       break;
+     case 0xa7:
+-    case 0xa8:
+       /* Rocket Lake.  */
+       cpu = "rocketlake";
+       CHECK___builtin_cpu_is ("corei7");
+@@ -508,7 +507,6 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       break;
+     case 0x97:
+     case 0x9a:
+-    case 0xbf:
+       /* Alder Lake.  */
+       cpu = "alderlake";
+       CHECK___builtin_cpu_is ("corei7");
+-- 
+2.31.1
+
diff --git a/0262-Workaround-possible-CPUID-bug-in-Sandy-Bridge.patch b/0262-Workaround-possible-CPUID-bug-in-Sandy-Bridge.patch
new file mode 100644
index 0000000..046351c
--- /dev/null
+++ b/0262-Workaround-possible-CPUID-bug-in-Sandy-Bridge.patch
@@ -0,0 +1,78 @@
+From 60364b439a80c217174e1830e0b7507d6f4538c4 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Fri, 4 Aug 2023 09:27:39 +0800
+Subject: [PATCH 08/28] Workaround possible CPUID bug in Sandy Bridge.
+
+Don't access leaf 7 subleaf 1 unless subleaf 0 says it is
+supported via EAX.
+
+Intel documentation says invalid subleaves return 0. We had been
+relying on that behavior instead of checking the max sublef number.
+
+It appears that some Sandy Bridge CPUs return at least the subleaf 0
+EDX value for subleaf 1. Best guess is that this is a bug in a
+microcode patch since all of the bits we're seeing set in EDX were
+introduced after Sandy Bridge was originally released.
+
+This is causing avxvnniint16 to be incorrectly enabled with
+-march=native on these CPUs.
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h (get_available_features): Check
+	max_subleaf_level for valid subleaf before use CPUID.
+---
+ gcc/common/config/i386/cpuinfo.h | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 28b2ff0b0..316ad3cb3 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -647,7 +647,9 @@ get_available_features (struct __processor_model *cpu_model,
+   /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
+   if (max_cpuid_level >= 7)
+     {
+-      __cpuid_count (7, 0, eax, ebx, ecx, edx);
++      unsigned int max_subleaf_level;
++
++      __cpuid_count (7, 0, max_subleaf_level, ebx, ecx, edx);
+       if (ebx & bit_BMI)
+ 	set_feature (FEATURE_BMI);
+       if (ebx & bit_SGX)
+@@ -759,18 +761,21 @@ get_available_features (struct __processor_model *cpu_model,
+ 	    set_feature (FEATURE_AVX512FP16);
+ 	}
+ 
+-      __cpuid_count (7, 1, eax, ebx, ecx, edx);
+-      if (eax & bit_HRESET)
+-	set_feature (FEATURE_HRESET);
+-      if (avx_usable)
+-	{
+-	  if (eax & bit_AVXVNNI)
+-	    set_feature (FEATURE_AVXVNNI);
+-	}
+-      if (avx512_usable)
++      if (max_subleaf_level >= 1)
+ 	{
+-	  if (eax & bit_AVX512BF16)
+-	    set_feature (FEATURE_AVX512BF16);
++	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
++	  if (eax & bit_HRESET)
++	    set_feature (FEATURE_HRESET);
++	  if (avx_usable)
++	    {
++	      if (eax & bit_AVXVNNI)
++		set_feature (FEATURE_AVXVNNI);
++	    }
++	  if (avx512_usable)
++	    {
++	      if (eax & bit_AVX512BF16)
++		set_feature (FEATURE_AVX512BF16);
++	    }
+ 	}
+     }
+ 
+-- 
+2.31.1
+
diff --git a/0263-Software-mitigation-Disable-gather-generation-in-vec.patch b/0263-Software-mitigation-Disable-gather-generation-in-vec.patch
new file mode 100644
index 0000000..2a1e4e7
--- /dev/null
+++ b/0263-Software-mitigation-Disable-gather-generation-in-vec.patch
@@ -0,0 +1,220 @@
+From cfffbec938afdc45c31db5ec282ce21ad1ba2dc7 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Thu, 10 Aug 2023 11:41:39 +0800
+Subject: [PATCH 09/28] Software mitigation: Disable gather generation in
+ vectorization for GDS affected Intel Processors.
+
+For more details of GDS (Gather Data Sampling), refer to
+https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/gather-data-sampling.html
+
+After microcode update, there's performance regression. To avoid that,
+the patch disables gather generation in autovectorization but uses
+gather scalar emulation instead.
+
+gcc/ChangeLog:
+
+	* config/i386/i386-options.cc (m_GDS): New macro.
+	* config/i386/x86-tune.def (X86_TUNE_USE_GATHER_2PARTS): Don't
+	enable for m_GDS.
+	(X86_TUNE_USE_GATHER_4PARTS): Ditto.
+	(X86_TUNE_USE_GATHER): Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/avx2-gather-2.c: Adjust options to keep
+	gather vectorization.
+	* gcc.target/i386/avx2-gather-6.c: Ditto.
+	* gcc.target/i386/avx512f-pr88464-1.c: Ditto.
+	* gcc.target/i386/avx512f-pr88464-5.c: Ditto.
+	* gcc.target/i386/avx512vl-pr88464-1.c: Ditto.
+	* gcc.target/i386/avx512vl-pr88464-11.c: Ditto.
+	* gcc.target/i386/avx512vl-pr88464-3.c: Ditto.
+	* gcc.target/i386/avx512vl-pr88464-9.c: Ditto.
+	* gcc.target/i386/pr88531-1b.c: Ditto.
+	* gcc.target/i386/pr88531-1c.c: Ditto.
+
+(cherry picked from commit 3064d1f5c48cb6ce1b4133570dd08ecca8abb52d)
+---
+ gcc/config/i386/i386-options.cc                     | 5 +++++
+ gcc/config/i386/x86-tune.def                        | 9 ++++++---
+ gcc/testsuite/gcc.target/i386/avx2-gather-2.c       | 2 +-
+ gcc/testsuite/gcc.target/i386/avx2-gather-6.c       | 2 +-
+ gcc/testsuite/gcc.target/i386/avx512f-pr88464-1.c   | 2 +-
+ gcc/testsuite/gcc.target/i386/avx512f-pr88464-5.c   | 2 +-
+ gcc/testsuite/gcc.target/i386/avx512vl-pr88464-1.c  | 2 +-
+ gcc/testsuite/gcc.target/i386/avx512vl-pr88464-11.c | 2 +-
+ gcc/testsuite/gcc.target/i386/avx512vl-pr88464-3.c  | 2 +-
+ gcc/testsuite/gcc.target/i386/avx512vl-pr88464-9.c  | 2 +-
+ gcc/testsuite/gcc.target/i386/pr88531-1b.c          | 2 +-
+ gcc/testsuite/gcc.target/i386/pr88531-1c.c          | 2 +-
+ 12 files changed, 21 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index fb2ed942f..9617fc162 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -137,6 +137,11 @@ along with GCC; see the file COPYING3.  If not see
+ #define m_GOLDMONT_PLUS (HOST_WIDE_INT_1U<
+Date: Thu, 10 Aug 2023 16:26:13 +0800
+Subject: [PATCH 10/28] Support -m[no-]gather -m[no-]scatter to enable/disable
+ vectorization for all gather/scatter instructions
+
+Rename original use_gather to use_gather_8parts, Support
+-mtune-ctrl={,^}use_gather to set/clear tune features
+use_gather_{2parts, 4parts, 8parts}. Support the new option -mgather
+as alias of -mtune-ctrl=, use_gather, ^use_gather.
+
+Similar for use_scatter.
+
+gcc/ChangeLog:
+
+	* config/i386/i386-builtins.cc
+	(ix86_vectorize_builtin_gather): Adjust for use_gather_8parts.
+	* config/i386/i386-options.cc (parse_mtune_ctrl_str):
+	Set/Clear tune features use_{gather,scatter}_{2parts, 4parts,
+	8parts} for -mtune-crtl={,^}{use_gather,use_scatter}.
+	* config/i386/i386.cc (ix86_vectorize_builtin_scatter): Adjust
+	for use_scatter_8parts
+	* config/i386/i386.h (TARGET_USE_GATHER): Rename to ..
+	(TARGET_USE_GATHER_8PARTS): .. this.
+	(TARGET_USE_SCATTER): Rename to ..
+	(TARGET_USE_SCATTER_8PARTS): .. this.
+	* config/i386/x86-tune.def (X86_TUNE_USE_GATHER): Rename to
+	(X86_TUNE_USE_GATHER_8PARTS): .. this.
+	(X86_TUNE_USE_SCATTER): Rename to
+	(X86_TUNE_USE_SCATTER_8PARTS): .. this.
+	* config/i386/i386.opt: Add new options mgather, mscatter.
+
+(cherry picked from commit b2a927fb5343db363ea4361da0d6bcee227b6737)
+---
+ gcc/config/i386/i386-builtins.cc |  2 +-
+ gcc/config/i386/i386-options.cc  | 54 +++++++++++++++++++++++---------
+ gcc/config/i386/i386.cc          |  2 +-
+ gcc/config/i386/i386.h           |  8 ++---
+ gcc/config/i386/i386.opt         |  4 +++
+ gcc/config/i386/x86-tune.def     |  4 +--
+ 6 files changed, 52 insertions(+), 22 deletions(-)
+
+diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
+index 050c6228a..8ed32e14f 100644
+--- a/gcc/config/i386/i386-builtins.cc
++++ b/gcc/config/i386/i386-builtins.cc
+@@ -1790,7 +1790,7 @@ ix86_vectorize_builtin_gather (const_tree mem_vectype,
+ 	  ? !TARGET_USE_GATHER_2PARTS
+ 	  : (known_eq (TYPE_VECTOR_SUBPARTS (mem_vectype), 4u)
+ 	     ? !TARGET_USE_GATHER_4PARTS
+-	     : !TARGET_USE_GATHER)))
++	     : !TARGET_USE_GATHER_8PARTS)))
+     return NULL_TREE;
+ 
+   if ((TREE_CODE (index_type) != INTEGER_TYPE
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 9617fc162..3df1f0c41 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -1705,20 +1705,46 @@ parse_mtune_ctrl_str (struct gcc_options *opts, bool dump)
+           curr_feature_string++;
+           clear = true;
+         }
+-      for (i = 0; i < X86_TUNE_LAST; i++)
+-        {
+-          if (!strcmp (curr_feature_string, ix86_tune_feature_names[i]))
+-            {
+-              ix86_tune_features[i] = !clear;
+-              if (dump)
+-                fprintf (stderr, "Explicitly %s feature %s\n",
+-                         clear ? "clear" : "set", ix86_tune_feature_names[i]);
+-              break;
+-            }
+-        }
+-      if (i == X86_TUNE_LAST)
+-	error ("unknown parameter to option %<-mtune-ctrl%>: %s",
+-	       clear ? curr_feature_string - 1 : curr_feature_string);
++
++      if (!strcmp (curr_feature_string, "use_gather"))
++	{
++	  ix86_tune_features[X86_TUNE_USE_GATHER_2PARTS] = !clear;
++	  ix86_tune_features[X86_TUNE_USE_GATHER_4PARTS] = !clear;
++	  ix86_tune_features[X86_TUNE_USE_GATHER_8PARTS] = !clear;
++	  if (dump)
++	    fprintf (stderr, "Explicitly %s features use_gather_2parts,"
++		     " use_gather_4parts, use_gather_8parts\n",
++		     clear ? "clear" : "set");
++
++	}
++      else if (!strcmp (curr_feature_string, "use_scatter"))
++	{
++	  ix86_tune_features[X86_TUNE_USE_SCATTER_2PARTS] = !clear;
++	  ix86_tune_features[X86_TUNE_USE_SCATTER_4PARTS] = !clear;
++	  ix86_tune_features[X86_TUNE_USE_SCATTER_8PARTS] = !clear;
++	  if (dump)
++	    fprintf (stderr, "Explicitly %s features use_scatter_2parts,"
++		     " use_scatter_4parts, use_scatter_8parts\n",
++		     clear ? "clear" : "set");
++	}
++      else
++	{
++	  for (i = 0; i < X86_TUNE_LAST; i++)
++	    {
++	      if (!strcmp (curr_feature_string, ix86_tune_feature_names[i]))
++		{
++		  ix86_tune_features[i] = !clear;
++		  if (dump)
++		    fprintf (stderr, "Explicitly %s feature %s\n",
++			     clear ? "clear" : "set", ix86_tune_feature_names[i]);
++		  break;
++		}
++	    }
++
++	  if (i == X86_TUNE_LAST)
++	    error ("unknown parameter to option %<-mtune-ctrl%>: %s",
++		   clear ? curr_feature_string - 1 : curr_feature_string);
++	}
+       curr_feature_string = next_feature_string;
+     }
+   while (curr_feature_string);
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index 479fc6010..e75d37023 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -18937,7 +18937,7 @@ ix86_vectorize_builtin_scatter (const_tree vectype,
+       ? !TARGET_USE_SCATTER_2PARTS
+       : (known_eq (TYPE_VECTOR_SUBPARTS (vectype), 4u)
+ 	 ? !TARGET_USE_SCATTER_4PARTS
+-	 : !TARGET_USE_SCATTER))
++	 : !TARGET_USE_SCATTER_8PARTS))
+     return NULL_TREE;
+ 
+   if ((TREE_CODE (index_type) != INTEGER_TYPE
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 688aaabd3..aaa136ba0 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -403,10 +403,10 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
+ 	ix86_tune_features[X86_TUNE_USE_GATHER_4PARTS]
+ #define TARGET_USE_SCATTER_4PARTS \
+ 	ix86_tune_features[X86_TUNE_USE_SCATTER_4PARTS]
+-#define TARGET_USE_GATHER \
+-	ix86_tune_features[X86_TUNE_USE_GATHER]
+-#define TARGET_USE_SCATTER \
+-	ix86_tune_features[X86_TUNE_USE_SCATTER]
++#define TARGET_USE_GATHER_8PARTS \
++	ix86_tune_features[X86_TUNE_USE_GATHER_8PARTS]
++#define TARGET_USE_SCATTER_8PARTS \
++	ix86_tune_features[X86_TUNE_USE_SCATTER_8PARTS]
+ #define TARGET_FUSE_CMP_AND_BRANCH_32 \
+ 	ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH_32]
+ #define TARGET_FUSE_CMP_AND_BRANCH_64 \
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 498fb454d..b154110d8 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -1222,3 +1222,7 @@ Instructions number above which STFL stall penalty can be compensated.
+ munroll-only-small-loops
+ Target Var(ix86_unroll_only_small_loops) Init(0) Save
+ Enable conservative small loop unrolling.
++
++mscatter
++Target Alias(mtune-ctrl=, use_scatter, ^use_scatter)
++Enable vectorization for scatter instruction.
+diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def
+index 4392709fc..bdb455d20 100644
+--- a/gcc/config/i386/x86-tune.def
++++ b/gcc/config/i386/x86-tune.def
+@@ -488,13 +488,13 @@ DEF_TUNE (X86_TUNE_USE_SCATTER_4PARTS, "use_scatter_4parts",
+ 
+ /* X86_TUNE_USE_GATHER: Use gather instructions for vectors with 8 or more
+    elements.  */
+-DEF_TUNE (X86_TUNE_USE_GATHER, "use_gather",
++DEF_TUNE (X86_TUNE_USE_GATHER_8PARTS, "use_gather_8parts",
+ 	  ~(m_ZNVER1 | m_ZNVER2 | m_ZNVER4 | m_ALDERLAKE
+ 	    | m_GENERIC | m_GDS))
+ 
+ /* X86_TUNE_USE_SCATTER: Use scater instructions for vectors with 8 or more
+    elements.  */
+-DEF_TUNE (X86_TUNE_USE_SCATTER, "use_scatter",
++DEF_TUNE (X86_TUNE_USE_SCATTER_8PARTS, "use_scatter_8parts",
+ 	  ~(m_ZNVER4))
+ 
+ /* X86_TUNE_AVOID_128FMA_CHAINS: Avoid creating loops with tight 128bit or
+-- 
+2.31.1
+
diff --git a/0265-Remove-constraint-modifier-for-fcmaddcph-fmaddcph-fc.patch b/0265-Remove-constraint-modifier-for-fcmaddcph-fmaddcph-fc.patch
new file mode 100644
index 0000000..e2084f6
--- /dev/null
+++ b/0265-Remove-constraint-modifier-for-fcmaddcph-fmaddcph-fc.patch
@@ -0,0 +1,129 @@
+From 764518a35e90a3e13c469275da9c3c7002fe1982 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Fri, 8 Sep 2023 09:22:43 +0800
+Subject: [PATCH 11/28] Remove constraint modifier % for
+ fcmaddcph/fmaddcph/fcmulcph since there're not commutative.
+
+gcc/ChangeLog:
+
+	PR target/111306
+	PR target/111335
+	* config/i386/sse.md (int_comm): New int_attr.
+	(fma__):
+	Remove % for Complex conjugate operations since they're not
+	commutative.
+	(fma___pair): Ditto.
+	(___mask): Ditto.
+	(cmul3): Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/pr111306.c: New test.
+
+(cherry picked from commit f197392a16ffb1327f1d12ff8ff05f9295e015cb)
+---
+ gcc/config/i386/sse.md                   | 16 ++++++++---
+ gcc/testsuite/gcc.target/i386/pr111306.c | 36 ++++++++++++++++++++++++
+ 2 files changed, 48 insertions(+), 4 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/pr111306.c
+
+diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
+index 3af159896..f25dd5f2b 100644
+--- a/gcc/config/i386/sse.md
++++ b/gcc/config/i386/sse.md
+@@ -6318,6 +6318,14 @@
+ 	[(UNSPEC_COMPLEX_FMA_PAIR "fmaddc")
+ 	 (UNSPEC_COMPLEX_FCMA_PAIR "fcmaddc")])
+ 
++(define_int_attr int_comm
++	[(UNSPEC_COMPLEX_FMA "")
++	 (UNSPEC_COMPLEX_FMA_PAIR "")
++	 (UNSPEC_COMPLEX_FCMA "")
++	 (UNSPEC_COMPLEX_FCMA_PAIR "")
++	 (UNSPEC_COMPLEX_FMUL "%")
++	 (UNSPEC_COMPLEX_FCMUL "")])
++
+ (define_int_attr conj_op
+ 	[(UNSPEC_COMPLEX_FMA "")
+ 	 (UNSPEC_COMPLEX_FCMA "_conj")
+@@ -6431,7 +6439,7 @@
+ (define_insn "fma__"
+   [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ 	(unspec:VF_AVX512FP16VL
+-	  [(match_operand:VF_AVX512FP16VL 1 "" "%v")
++	  [(match_operand:VF_AVX512FP16VL 1 "" "v")
+ 	   (match_operand:VF_AVX512FP16VL 2 "" "")
+ 	   (match_operand:VF_AVX512FP16VL 3 "" "0")]
+ 	   UNSPEC_COMPLEX_F_C_MA))]
+@@ -6495,7 +6503,7 @@
+ (define_insn "fma___pair"
+  [(set (match_operand:VF1_AVX512VL 0 "register_operand" "=&v")
+        (unspec:VF1_AVX512VL
+-	 [(match_operand:VF1_AVX512VL 1 "vector_operand" "%v")
++	 [(match_operand:VF1_AVX512VL 1 "vector_operand" "v")
+ 	  (match_operand:VF1_AVX512VL 2 "bcst_vector_operand" "vmBr")
+ 	  (match_operand:VF1_AVX512VL 3 "vector_operand" "0")]
+ 	  UNSPEC_COMPLEX_F_C_MA_PAIR))]
+@@ -6562,7 +6570,7 @@
+   [(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 1 "nonimmediate_operand" "v")
+ 	     (match_operand:VF_AVX512FP16VL 2 "nonimmediate_operand" "")
+ 	     (match_operand:VF_AVX512FP16VL 3 "register_operand" "0")]
+ 	     UNSPEC_COMPLEX_F_C_MA)
+@@ -6586,7 +6594,7 @@
+ (define_insn "__"
+   [(set (match_operand:VF_AVX512FP16VL 0 "register_operand" "=&v")
+ 	  (unspec:VF_AVX512FP16VL
+-	    [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "%v")
++	    [(match_operand:VF_AVX512FP16VL 1 "nonimmediate_operand" "v")
+ 	     (match_operand:VF_AVX512FP16VL 2 "nonimmediate_operand" "")]
+ 	     UNSPEC_COMPLEX_F_C_MUL))]
+   "TARGET_AVX512FP16 && "
+diff --git a/gcc/testsuite/gcc.target/i386/pr111306.c b/gcc/testsuite/gcc.target/i386/pr111306.c
+new file mode 100644
+index 000000000..541725ebd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/pr111306.c
+@@ -0,0 +1,36 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */
++/* { dg-require-effective-target avx512fp16 } */
++
++#define AVX512FP16
++#include "avx512f-helper.h"
++
++__attribute__((optimize("O2"),noipa))
++void func1(_Float16 *a, _Float16 *b, int n, _Float16 *c) {
++  __m512h rA = _mm512_loadu_ph(a);
++  for (int i = 0; i < n; i += 32) {
++    __m512h rB = _mm512_loadu_ph(b + i);
++    _mm512_storeu_ph(c + i, _mm512_fcmul_pch(rB, rA));
++  }
++}
++
++void
++test_512 (void)
++{
++  int n = 32;
++  _Float16 a[n], b[n], c[n];
++  _Float16 exp[n];
++  for (int i = 1; i <= n; i++) {
++    a[i - 1] = i & 1 ? -i : i;
++    b[i - 1] = i;
++  }
++
++  func1(a, b, n, c);
++  for (int i = 0; i < n / 32; i += 2) {
++    if (c[i] != a[i] * b[i] + a[i+1] * b[i+1]
++	|| c[i+1] != a[i] * b[i+1] - a[i+1]*b[i])
++      __builtin_abort ();
++    }
++}
++
++
+-- 
+2.31.1
+
diff --git a/0266-Disparage-slightly-for-the-alternative-which-move-DF.patch b/0266-Disparage-slightly-for-the-alternative-which-move-DF.patch
new file mode 100644
index 0000000..5e8bd67
--- /dev/null
+++ b/0266-Disparage-slightly-for-the-alternative-which-move-DF.patch
@@ -0,0 +1,106 @@
+From afd539adfe762adb57863299a11987b7e20e7987 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Wed, 5 Jul 2023 13:45:11 +0800
+Subject: [PATCH 12/28] Disparage slightly for the alternative which move
+ DFmode between SSE_REGS and GENERAL_REGS.
+
+For testcase
+
+void __cond_swap(double* __x, double* __y) {
+  bool __r = (*__x < *__y);
+  auto __tmp = __r ? *__x : *__y;
+  *__y = __r ? *__y : *__x;
+  *__x = __tmp;
+}
+
+GCC-14 with -O2 and -march=x86-64 options generates the following code:
+
+__cond_swap(double*, double*):
+        movsd   xmm1, QWORD PTR [rdi]
+        movsd   xmm0, QWORD PTR [rsi]
+        comisd  xmm0, xmm1
+        jbe     .L2
+        movq    rax, xmm1
+        movapd  xmm1, xmm0
+        movq    xmm0, rax
+.L2:
+        movsd   QWORD PTR [rsi], xmm1
+        movsd   QWORD PTR [rdi], xmm0
+        ret
+
+rax is used to save and restore DFmode value. In RA both GENERAL_REGS
+and SSE_REGS cost zero since we didn't disparage the
+alternative in movdf_internal pattern, according to register
+allocation order, GENERAL_REGS is allocated. The patch add ? for
+alternative (r,v) and (v,r) just like we did for movsf/hf/bf_internal
+pattern, after that we get optimal RA.
+
+__cond_swap:
+.LFB0:
+	.cfi_startproc
+	movsd	(%rdi), %xmm1
+	movsd	(%rsi), %xmm0
+	comisd	%xmm1, %xmm0
+	jbe	.L2
+	movapd	%xmm1, %xmm2
+	movapd	%xmm0, %xmm1
+	movapd	%xmm2, %xmm0
+.L2:
+	movsd	%xmm1, (%rsi)
+	movsd	%xmm0, (%rdi)
+	ret
+
+gcc/ChangeLog:
+
+	PR target/110170
+	* config/i386/i386.md (movdf_internal): Disparage slightly for
+	2 alternatives (r,v) and (v,r) by adding constraint modifier
+	'?'.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/pr110170-3.c: New test.
+
+(cherry picked from commit 37a231cc7594d12ba0822077018aad751a6fb94e)
+---
+ gcc/config/i386/i386.md                    |  4 ++--
+ gcc/testsuite/gcc.target/i386/pr110170-3.c | 11 +++++++++++
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/pr110170-3.c
+
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index be07be10d..71691f598 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -3582,9 +3582,9 @@
+ ;; Possible store forwarding (partial memory) stall in alternatives 4, 6 and 7.
+ (define_insn "*movdf_internal"
+   [(set (match_operand:DF 0 "nonimmediate_operand"
+-    "=Yf*f,m   ,Yf*f,?r ,!o,?*r ,!o,!o,?r,?m,?r,?r,v,v,v,m,*x,*x,*x,m ,r ,v,r  ,o ,r  ,m")
++    "=Yf*f,m   ,Yf*f,?r ,!o,?*r ,!o,!o,?r,?m,?r,?r,v,v,v,m,*x,*x,*x,m ,?r,?v,r  ,o ,r  ,m")
+ 	(match_operand:DF 1 "general_operand"
+-    "Yf*fm,Yf*f,G   ,roF,r ,*roF,*r,F ,rm,rC,C ,F ,C,v,m,v,C ,*x,m ,*x,v,r ,roF,rF,rmF,rC"))]
++    "Yf*fm,Yf*f,G   ,roF,r ,*roF,*r,F ,rm,rC,C ,F ,C,v,m,v,C ,*x,m ,*x, v, r,roF,rF,rmF,rC"))]
+   "!(MEM_P (operands[0]) && MEM_P (operands[1]))
+    && (lra_in_progress || reload_completed
+        || !CONST_DOUBLE_P (operands[1])
+diff --git a/gcc/testsuite/gcc.target/i386/pr110170-3.c b/gcc/testsuite/gcc.target/i386/pr110170-3.c
+new file mode 100644
+index 000000000..70daa89e9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/pr110170-3.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-options "-O2 -fno-if-conversion -fno-if-conversion2" } */
++/* { dg-final { scan-assembler-not {(?n)movq.*r} } } */
++
++void __cond_swap(double* __x, double* __y) {
++  _Bool __r = (*__x < *__y);
++  double __tmp = __r ? *__x : *__y;
++  *__y = __r ? *__y : *__x;
++  *__x = __tmp;
++}
++
+-- 
+2.31.1
+
diff --git a/0267-Fix-wrong-code-due-to-vec_merge-pcmp-to-blendvb-spli.patch b/0267-Fix-wrong-code-due-to-vec_merge-pcmp-to-blendvb-spli.patch
new file mode 100644
index 0000000..32ce46d
--- /dev/null
+++ b/0267-Fix-wrong-code-due-to-vec_merge-pcmp-to-blendvb-spli.patch
@@ -0,0 +1,163 @@
+From 88516507757932c1e67ce99d240596935971d2d0 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Thu, 9 Nov 2023 13:20:05 +0800
+Subject: [PATCH 13/28] Fix wrong code due to vec_merge + pcmp to blendvb
+ splitter.
+
+gcc/ChangeLog:
+
+	PR target/112443
+	* config/i386/sse.md (*avx2_pcmp3_4): Fix swap condition
+	from LT to GT since there's not in the pattern.
+	(*avx2_pcmp3_5): Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.target/i386/pr112443.C: New test.
+
+(cherry picked from commit 9a0cc04b9c9b02426762892b88efc5c44ba546bd)
+---
+ gcc/config/i386/sse.md                   |   4 +-
+ gcc/testsuite/g++.target/i386/pr112443.C | 108 +++++++++++++++++++++++
+ 2 files changed, 110 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/testsuite/g++.target/i386/pr112443.C
+
+diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
+index f25dd5f2b..23b858ab2 100644
+--- a/gcc/config/i386/sse.md
++++ b/gcc/config/i386/sse.md
+@@ -16358,7 +16358,7 @@
+ 	     (match_dup 4))]
+ 	     UNSPEC_BLENDV))]
+ {
+-  if (INTVAL (operands[5]) == 1)
++  if (INTVAL (operands[5]) == 5)
+     std::swap (operands[1], operands[2]);
+   operands[3] = gen_lowpart (mode, operands[3]);
+ })
+@@ -16388,7 +16388,7 @@
+ 	     (match_dup 4))]
+ 	     UNSPEC_BLENDV))]
+ {
+-  if (INTVAL (operands[5]) == 1)
++  if (INTVAL (operands[5]) == 5)
+     std::swap (operands[1], operands[2]);
+ })
+ 
+diff --git a/gcc/testsuite/g++.target/i386/pr112443.C b/gcc/testsuite/g++.target/i386/pr112443.C
+new file mode 100644
+index 000000000..ebfa9b4a7
+--- /dev/null
++++ b/gcc/testsuite/g++.target/i386/pr112443.C
+@@ -0,0 +1,108 @@
++/* { dg-do run } */
++/* { dg-require-effective-target avx512bw } */
++/* { dg-require-effective-target avx512vl } */
++/* { dg-options "-O2 -std=c++17 -mavx512bw -mavx512vl" } */
++
++#include 
++#include 
++#include 
++#include 
++
++#define AVX512BW
++#define AVX512VL
++
++#include "avx512f-helper.h"
++
++struct TensorIteratorBase{
++  char* in;
++  char* out;
++
++  void for_each(std::function loop){
++    loop(out, in, 32);
++  }    
++};
++
++class Vectorized {
++protected:
++  __m256i values;
++
++  static inline __m256i invert(const __m256i& v) {
++    const auto ones = _mm256_set1_epi64x(-1);
++    return _mm256_xor_si256(ones, v);
++  }
++public:
++  operator __m256i() const {
++    return values;
++  }
++
++  static constexpr int size() {
++    return 32;
++  }
++
++  Vectorized() {}
++  Vectorized(__m256i v) : values(v) {}
++  Vectorized(uint8_t v) { values = _mm256_set1_epi8(v); }
++  static Vectorized blendv(const Vectorized& a, const Vectorized& b,
++			   const Vectorized& mask) {
++    return _mm256_blendv_epi8(a, b, mask);
++  }
++  static Vectorized loadu(const void* ptr) {
++    return _mm256_loadu_si256(reinterpret_cast(ptr));
++  }
++  void store(void* ptr) const {
++    _mm256_storeu_si256(reinterpret_cast<__m256i*>(ptr), values);
++  }
++
++  Vectorized operator<(const Vectorized& other) const {
++    __m256i max = _mm256_max_epu8(values, other);
++    return invert(_mm256_cmpeq_epi8(max, values));
++  }
++  Vectorized operator-(const Vectorized& b) {
++    return _mm256_sub_epi8(values, b);
++  }
++};
++
++std::ostream& operator<<(std::ostream& stream, const Vectorized& vec) {
++  uint8_t buf[Vectorized::size()];
++  vec.store(buf);
++  stream << "vec[";
++  for (int i = 0; i != Vectorized::size(); i++) {
++    if (i != 0)
++      stream << ", ";
++    stream << buf[i]*1;
++  }
++  stream << "]";
++  return stream;
++}
++
++void run(TensorIteratorBase iter){
++  Vectorized zero_vec(0);
++  Vectorized one_vec(1);
++
++  iter.for_each([=](char* out, char* in, int64_t size) {
++    for (int64_t i = 0; i <= size - Vectorized::size(); i += Vectorized::size()) {
++      auto self_vec = Vectorized::loadu(in + i);
++      auto left = Vectorized::blendv(zero_vec, one_vec, zero_vec < self_vec);
++      auto right = Vectorized::blendv(zero_vec, one_vec, self_vec < zero_vec);
++      auto outv = left - right;
++      outv.store(out + i);
++    }
++  });
++}
++
++void
++test_256 (){
++  char in[32];
++  char out[32];
++  for(auto& x: in) x = 1;
++  run(TensorIteratorBase{in, out});
++  Vectorized::loadu (out);
++  for (int i = 0; i != 32; i++)
++    if (out[i] != 1)
++      __builtin_abort ();
++}
++
++void
++test_128 ()
++{
++}
+-- 
+2.31.1
+
diff --git a/0268-Don-t-assume-it-s-AVX_U128_CLEAN-after-call_insn-who.patch b/0268-Don-t-assume-it-s-AVX_U128_CLEAN-after-call_insn-who.patch
new file mode 100644
index 0000000..3d2f9bb
--- /dev/null
+++ b/0268-Don-t-assume-it-s-AVX_U128_CLEAN-after-call_insn-who.patch
@@ -0,0 +1,151 @@
+From 204ffa7f503411ccac0161c951726274648b6374 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Thu, 7 Dec 2023 09:17:27 +0800
+Subject: [PATCH 14/28] Don't assume it's AVX_U128_CLEAN after call_insn whose
+ abi.mode_clobber(V4DImode) deosn't contains all SSE_REGS.
+
+If the function desn't clobber any sse registers or only clobber
+128-bit part, then vzeroupper isn't issued before the function exit.
+the status not CLEAN but ANY after the function.
+
+Also for sibling_call, it's safe to issue an vzeroupper. Also there
+could be missing vzeroupper since there's no mode_exit for
+sibling_call_p.
+
+gcc/ChangeLog:
+
+	PR target/112891
+	* config/i386/i386.cc (ix86_avx_u128_mode_after): Return
+	AVX_U128_ANY if callee_abi doesn't clobber all_sse_regs to
+	align with ix86_avx_u128_mode_needed.
+	(ix86_avx_u128_mode_needed): Return AVX_U128_ClEAN for
+	sibling_call.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/pr112891.c: New test.
+	* gcc.target/i386/pr112891-2.c: New test.
+
+(cherry picked from commit fc189a08f5b7ad5889bd4c6b320c1dd99dd5d642)
+---
+ gcc/config/i386/i386.cc                    | 22 +++++++++++++---
+ gcc/testsuite/gcc.target/i386/pr112891-2.c | 30 ++++++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/pr112891.c   | 29 +++++++++++++++++++++
+ 3 files changed, 78 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/pr112891-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/pr112891.c
+
+diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
+index e75d37023..60f3296b0 100644
+--- a/gcc/config/i386/i386.cc
++++ b/gcc/config/i386/i386.cc
+@@ -14416,8 +14416,12 @@ ix86_avx_u128_mode_needed (rtx_insn *insn)
+ 	 modes wider than 256 bits.  It's only safe to issue a
+ 	 vzeroupper if all SSE registers are clobbered.  */
+       const function_abi &abi = insn_callee_abi (insn);
+-      if (!hard_reg_set_subset_p (reg_class_contents[SSE_REGS],
+-				  abi.mode_clobbers (V4DImode)))
++      /* Should be safe to issue an vzeroupper before sibling_call_p.
++	 Also there not mode_exit for sibling_call, so there could be
++	 missing vzeroupper for that.  */
++      if (!(SIBLING_CALL_P (insn)
++	    || hard_reg_set_subset_p (reg_class_contents[SSE_REGS],
++				      abi.mode_clobbers (V4DImode))))
+ 	return AVX_U128_ANY;
+ 
+       return AVX_U128_CLEAN;
+@@ -14555,7 +14559,19 @@ ix86_avx_u128_mode_after (int mode, rtx_insn *insn)
+       bool avx_upper_reg_found = false;
+       note_stores (insn, ix86_check_avx_upper_stores, &avx_upper_reg_found);
+ 
+-      return avx_upper_reg_found ? AVX_U128_DIRTY : AVX_U128_CLEAN;
++      if (avx_upper_reg_found)
++	return AVX_U128_DIRTY;
++
++      /* If the function desn't clobber any sse registers or only clobber
++	 128-bit part, Then vzeroupper isn't issued before the function exit.
++	 the status not CLEAN but ANY after the function.  */
++      const function_abi &abi = insn_callee_abi (insn);
++      if (!(SIBLING_CALL_P (insn)
++	    || hard_reg_set_subset_p (reg_class_contents[SSE_REGS],
++				      abi.mode_clobbers (V4DImode))))
++	return AVX_U128_ANY;
++
++      return  AVX_U128_CLEAN;
+     }
+ 
+   /* Otherwise, return current mode.  Remember that if insn
+diff --git a/gcc/testsuite/gcc.target/i386/pr112891-2.c b/gcc/testsuite/gcc.target/i386/pr112891-2.c
+new file mode 100644
+index 000000000..164c3985d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/pr112891-2.c
+@@ -0,0 +1,30 @@
++/* { dg-do compile } */
++/* { dg-options "-mavx2 -O3" } */
++/* { dg-final { scan-assembler-times "vzeroupper" 1 } } */
++
++void
++__attribute__((noinline))
++bar (double* a)
++{
++  a[0] = 1.0;
++  a[1] = 2.0;
++}
++
++double
++__attribute__((noinline))
++foo (double* __restrict a, double* b)
++{
++  a[0] += b[0];
++  a[1] += b[1];
++  a[2] += b[2];
++  a[3] += b[3];
++  bar (b);
++  return a[5] + b[5];
++}
++
++double
++foo1 (double* __restrict a, double* b)
++{
++  double c = foo (a, b);
++  return __builtin_exp (c);
++}
+diff --git a/gcc/testsuite/gcc.target/i386/pr112891.c b/gcc/testsuite/gcc.target/i386/pr112891.c
+new file mode 100644
+index 000000000..dbf6c6794
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/pr112891.c
+@@ -0,0 +1,29 @@
++/* { dg-do compile } */
++/* { dg-options "-mavx2 -O3" } */
++/* { dg-final { scan-assembler-times "vzeroupper" 1 } } */
++
++void
++__attribute__((noinline))
++bar (double* a)
++{
++  a[0] = 1.0;
++  a[1] = 2.0;
++}
++
++void
++__attribute__((noinline))
++foo (double* __restrict a, double* b)
++{
++  a[0] += b[0];
++  a[1] += b[1];
++  a[2] += b[2];
++  a[3] += b[3];
++  bar (b);
++}
++
++double
++foo1 (double* __restrict a, double* b)
++{
++  foo (a, b);
++  return __builtin_exp (b[1]);
++}
+-- 
+2.31.1
+
diff --git a/0269-Disable-FMADD-in-chains-for-Zen4-and-generic.patch b/0269-Disable-FMADD-in-chains-for-Zen4-and-generic.patch
new file mode 100644
index 0000000..b0de504
--- /dev/null
+++ b/0269-Disable-FMADD-in-chains-for-Zen4-and-generic.patch
@@ -0,0 +1,142 @@
+From 19ee37b11702c86d7ed271e9e1d00e23cc4ab93c Mon Sep 17 00:00:00 2001
+From: Jan Hubicka 
+Date: Fri, 29 Dec 2023 23:51:03 +0100
+Subject: [PATCH 15/28] Disable FMADD in chains for Zen4 and generic
+
+this patch disables use of FMA in matrix multiplication loop for generic (for
+x86-64-v3) and zen4.  I tested this on zen4 and Xenon Gold Gold 6212U.
+
+For Intel this is neutral both on the matrix multiplication microbenchmark
+(attached) and spec2k17 where the difference was within noise for Core.
+
+On core the micro-benchmark runs as follows:
+
+With FMA:
+
+       578,500,241      cycles:u                         #    3.645 GHz
+                ( +-  0.12% )
+       753,318,477      instructions:u                   #    1.30  insn per
+cycle              ( +-  0.00% )
+       125,417,701      branches:u                       #  790.227 M/sec
+                ( +-  0.00% )
+          0.159146 +- 0.000363 seconds time elapsed  ( +-  0.23% )
+
+No FMA:
+
+       577,573,960      cycles:u                         #    3.514 GHz
+                ( +-  0.15% )
+       878,318,479      instructions:u                   #    1.52  insn per
+cycle              ( +-  0.00% )
+       125,417,702      branches:u                       #  763.035 M/sec
+                ( +-  0.00% )
+          0.164734 +- 0.000321 seconds time elapsed  ( +-  0.19% )
+
+So the cycle count is unchanged and discrete multiply+add takes same time as
+FMA.
+
+While on zen:
+
+With FMA:
+         484875179      cycles:u                         #    3.599 GHz
+             ( +-  0.05% )  (82.11%)
+         752031517      instructions:u                   #    1.55  insn per
+cycle
+         125106525      branches:u                       #  928.712 M/sec
+             ( +-  0.03% )  (85.09%)
+            128356      branch-misses:u                  #    0.10% of all
+branches          ( +-  0.06% )  (83.58%)
+
+No FMA:
+         375875209      cycles:u                         #    3.592 GHz
+             ( +-  0.08% )  (80.74%)
+         875725341      instructions:u                   #    2.33  insn per
+cycle
+         124903825      branches:u                       #    1.194 G/sec
+             ( +-  0.04% )  (84.59%)
+          0.105203 +- 0.000188 seconds time elapsed  ( +-  0.18% )
+
+The diffrerence is that Cores understand the fact that fmadd does not need
+all three parameters to start computation, while Zen cores doesn't.
+
+Since this seems noticeable win on zen and not loss on Core it seems like good
+default for generic.
+
+float a[SIZE][SIZE];
+float b[SIZE][SIZE];
+float c[SIZE][SIZE];
+
+void init(void)
+{
+   int i, j, k;
+   for(i=0; i
+Date: Fri, 16 Sep 2022 13:59:01 +0800
+Subject: [PATCH 16/28] Initial Raptorlake Support
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h:
+	(get_intel_cpu): Handle Raptorlake.
+	* common/config/i386/i386-common.cc:
+	(processor_alias_table): Add Raptorlake.
+
+(cherry picked from commit 470a0659b508d684148f362c4dc0eccf5a83a23e)
+---
+ gcc/common/config/i386/cpuinfo.h      | 2 ++
+ gcc/common/config/i386/i386-common.cc | 2 ++
+ 2 files changed, 4 insertions(+)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 316ad3cb3..13d0f4cd8 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -508,6 +508,8 @@ get_intel_cpu (struct __processor_model *cpu_model,
+     case 0x97:
+     case 0x9a:
+       /* Alder Lake.  */
++    case 0xb7:
++      /* Raptor Lake.  */
+       cpu = "alderlake";
+       CHECK___builtin_cpu_is ("corei7");
+       CHECK___builtin_cpu_is ("alderlake");
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index f650e255f..c1d700f89 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -1939,6 +1939,8 @@ const pta processor_alias_table[] =
+     M_CPU_SUBTYPE (INTEL_COREI7_SAPPHIRERAPIDS), P_PROC_AVX512F},
+   {"alderlake", PROCESSOR_ALDERLAKE, CPU_HASWELL, PTA_ALDERLAKE,
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
++  {"raptorlake", PROCESSOR_ALDERLAKE, CPU_HASWELL, PTA_ALDERLAKE,
++    M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
+   {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+     M_CPU_TYPE (INTEL_BONNELL), P_PROC_SSSE3},
+   {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+-- 
+2.31.1
+
diff --git a/0271-Initial-Meteorlake-Support.patch b/0271-Initial-Meteorlake-Support.patch
new file mode 100644
index 0000000..c2e825b
--- /dev/null
+++ b/0271-Initial-Meteorlake-Support.patch
@@ -0,0 +1,49 @@
+From 87cea29ede520f4a5af01dff7071ab1d23bd47b5 Mon Sep 17 00:00:00 2001
+From: "Hu, Lin1" 
+Date: Fri, 16 Sep 2022 11:25:13 +0800
+Subject: [PATCH 17/28] Initial Meteorlake Support
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h:
+	(get_intel_cpu): Handle Meteorlake.
+	* common/config/i386/i386-common.cc:
+	(processor_alias_table): Add Meteorlake.
+
+(cherry picked from commit fd206f0e95fb6f41b96eaaaab1dc0c30378e5e08)
+---
+ gcc/common/config/i386/cpuinfo.h      | 4 ++++
+ gcc/common/config/i386/i386-common.cc | 2 ++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 13d0f4cd8..37af92d6b 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -510,6 +510,10 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       /* Alder Lake.  */
+     case 0xb7:
+       /* Raptor Lake.  */
++    case 0xb5:
++    case 0xaa:
++    case 0xac:
++      /* Meteor Lake.  */
+       cpu = "alderlake";
+       CHECK___builtin_cpu_is ("corei7");
+       CHECK___builtin_cpu_is ("alderlake");
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index c1d700f89..cfee672fb 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -1941,6 +1941,8 @@ const pta processor_alias_table[] =
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
+   {"raptorlake", PROCESSOR_ALDERLAKE, CPU_HASWELL, PTA_ALDERLAKE,
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
++  {"meteorlake", PROCESSOR_ALDERLAKE, CPU_HASWELL, PTA_ALDERLAKE,
++    M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
+   {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+     M_CPU_TYPE (INTEL_BONNELL), P_PROC_SSSE3},
+   {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+-- 
+2.31.1
+
diff --git a/0272-Support-Intel-AMX-FP16-ISA.patch b/0272-Support-Intel-AMX-FP16-ISA.patch
new file mode 100644
index 0000000..67eda4d
--- /dev/null
+++ b/0272-Support-Intel-AMX-FP16-ISA.patch
@@ -0,0 +1,691 @@
+From c11301c7780213ddf46a0bcdb06079af485f431c Mon Sep 17 00:00:00 2001
+From: Hongyu Wang 
+Date: Fri, 4 Nov 2022 15:50:55 +0800
+Subject: [PATCH 18/28] Support Intel AMX-FP16 ISA
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h (get_available_features): Detect
+	amx-fp16.
+	* common/config/i386/i386-common.cc (OPTION_MASK_ISA2_AMX_FP16_SET,
+	OPTION_MASK_ISA2_AMX_FP16_UNSET): New macros.
+	(ix86_handle_option): Handle -mamx-fp16.
+	* common/config/i386/i386-cpuinfo.h (enum processor_features):
+	Add FEATURE_AMX_FP16.
+	* common/config/i386/i386-isas.h: Add ISA_NAME_TABLE_ENTRY for
+	amx-fp16.
+	* config.gcc: Add amxfp16intrin.h.
+	* config/i386/cpuid.h (bit_AMX_FP16): New.
+	* config/i386/i386-c.cc (ix86_target_macros_internal): Define
+	__AMX_FP16__.
+	* config/i386/i386-isa.def: Add DEF_PTA for AMX_FP16.
+	* config/i386/i386-options.cc (isa2_opts): Add -mamx-fp16.
+	(ix86_valid_target_attribute_inner_p): Add new ATTR.
+	(ix86_option_override_internal): Handle AMX-FP16.
+	* config/i386/i386.opt: Add -mamx-fp16.
+	* config/i386/immintrin.h: Include amxfp16intrin.h.
+	* doc/extend.texi: Document -mamx-fp16.
+	* doc/invoke.texi: Document amx-fp16.
+	* doc/sourcebuild.texi: Document amx_fp16.
+	* config/i386/amxfp16intrin.h: New file.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.dg/other/i386-2.C: Add -mamx-fp16.
+	* g++.dg/other/i386-3.C: Ditto.
+	* gcc.target/i386/sse-12.c: Ditto.
+	* gcc.target/i386/sse-13.c: Ditto.
+	* gcc.target/i386/sse-14.c: Ditto.
+	* gcc.target/i386/sse-22.c: Ditto.
+	* gcc.target/i386/sse-23.c: Ditto.
+	* lib/target-supports.exp: (check_effective_target_amx_fp16):
+	New proc.
+	* gcc.target/i386/funcspec-56.inc: Add new target attribute.
+	* gcc.target/i386/amx-check.h: Add AMX_FP16.
+	* gcc.target/i386/amx-helper.h: New file to support amx-fp16.
+	* gcc.target/i386/amxfp16-asmatt-1.c: New test.
+	* gcc.target/i386/amxfp16-asmintel-1.c: Ditto.
+	* gcc.target/i386/amxfp16-dpfp16ps-2.c: Ditto.
+
+Co-authored-by: Haochen Jiang 
+
+(cherry picked from commit 2b4a03962a0fe18cadc944d90f1fb85a40004226)
+---
+ gcc/common/config/i386/cpuinfo.h              |  5 ++
+ gcc/common/config/i386/i386-common.cc         | 15 +++++
+ gcc/common/config/i386/i386-cpuinfo.h         |  1 +
+ gcc/common/config/i386/i386-isas.h            |  1 +
+ gcc/config.gcc                                |  3 +-
+ gcc/config/i386/amxfp16intrin.h               | 46 ++++++++++++++
+ gcc/config/i386/cpuid.h                       |  1 +
+ gcc/config/i386/i386-c.cc                     |  2 +
+ gcc/config/i386/i386-isa.def                  |  1 +
+ gcc/config/i386/i386-options.cc               |  4 +-
+ gcc/config/i386/i386.opt                      |  4 ++
+ gcc/config/i386/immintrin.h                   |  2 +
+ gcc/doc/extend.texi                           |  5 ++
+ gcc/doc/invoke.texi                           |  9 ++-
+ gcc/doc/sourcebuild.texi                      |  3 +
+ gcc/testsuite/g++.dg/other/i386-2.C           |  2 +-
+ gcc/testsuite/g++.dg/other/i386-3.C           |  2 +-
+ gcc/testsuite/gcc.target/i386/amx-check.h     |  3 +
+ gcc/testsuite/gcc.target/i386/amx-helper.h    | 61 +++++++++++++++++++
+ .../gcc.target/i386/amxfp16-asmatt-1.c        | 13 ++++
+ .../gcc.target/i386/amxfp16-asmintel-1.c      | 10 +++
+ .../gcc.target/i386/amxfp16-dpfp16ps-2.c      | 57 +++++++++++++++++
+ gcc/testsuite/gcc.target/i386/funcspec-56.inc |  2 +
+ gcc/testsuite/gcc.target/i386/sse-12.c        |  2 +-
+ gcc/testsuite/gcc.target/i386/sse-13.c        |  2 +-
+ gcc/testsuite/gcc.target/i386/sse-14.c        |  2 +-
+ gcc/testsuite/gcc.target/i386/sse-22.c        |  4 +-
+ gcc/testsuite/gcc.target/i386/sse-23.c        |  2 +-
+ gcc/testsuite/lib/target-supports.exp         | 11 ++++
+ 29 files changed, 262 insertions(+), 13 deletions(-)
+ create mode 100644 gcc/config/i386/amxfp16intrin.h
+ create mode 100644 gcc/testsuite/gcc.target/i386/amx-helper.h
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxfp16-asmatt-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxfp16-asmintel-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxfp16-dpfp16ps-2.c
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 37af92d6b..5951a30aa 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -783,6 +783,11 @@ get_available_features (struct __processor_model *cpu_model,
+ 		set_feature (FEATURE_AVX512BF16);
+ 	    }
+ 	}
++      if (amx_usable)
++	{
++	  if (eax & bit_AMX_FP16)
++	    set_feature (FEATURE_AMX_FP16);
++	}
+     }
+ 
+   /* Get Advanced Features at level 0xd (eax = 0xd, ecx = 1). */
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index cfee672fb..922db33ee 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -107,6 +107,7 @@ along with GCC; see the file COPYING3.  If not see
+ #define OPTION_MASK_ISA2_AMX_TILE_SET OPTION_MASK_ISA2_AMX_TILE
+ #define OPTION_MASK_ISA2_AMX_INT8_SET OPTION_MASK_ISA2_AMX_INT8
+ #define OPTION_MASK_ISA2_AMX_BF16_SET OPTION_MASK_ISA2_AMX_BF16
++#define OPTION_MASK_ISA2_AMX_FP16_SET OPTION_MASK_ISA2_AMX_FP16
+ 
+ /* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same
+    as -msse4.2.  */
+@@ -275,6 +276,7 @@ along with GCC; see the file COPYING3.  If not see
+ #define OPTION_MASK_ISA2_KL_UNSET \
+   (OPTION_MASK_ISA2_KL | OPTION_MASK_ISA2_WIDEKL_UNSET)
+ #define OPTION_MASK_ISA2_WIDEKL_UNSET OPTION_MASK_ISA2_WIDEKL
++#define OPTION_MASK_ISA2_AMX_FP16_UNSET OPTION_MASK_ISA2_AMX_FP16
+ 
+ /* SSE4 includes both SSE4.1 and SSE4.2.  -mno-sse4 should the same
+    as -mno-sse4.1. */
+@@ -1125,6 +1127,19 @@ ix86_handle_option (struct gcc_options *opts,
+ 	}
+       return true;
+ 
++    case OPT_mamx_fp16:
++      if (value)
++	{
++	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AMX_FP16_SET;
++	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AMX_FP16_SET;
++	}
++      else
++	{
++	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AMX_FP16_UNSET;
++	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AMX_FP16_UNSET;
++	}
++      return true;
++
+     case OPT_mfma:
+       if (value)
+ 	{
+diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
+index 82996ebb3..8f22897de 100644
+--- a/gcc/common/config/i386/i386-cpuinfo.h
++++ b/gcc/common/config/i386/i386-cpuinfo.h
+@@ -240,6 +240,7 @@ enum processor_features
+   FEATURE_X86_64_V2,
+   FEATURE_X86_64_V3,
+   FEATURE_X86_64_V4,
++  FEATURE_AMX_FP16,
+   CPU_FEATURE_MAX
+ };
+ 
+diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
+index 2d0646a68..95bab6da2 100644
+--- a/gcc/common/config/i386/i386-isas.h
++++ b/gcc/common/config/i386/i386-isas.h
+@@ -175,4 +175,5 @@ ISA_NAMES_TABLE_START
+   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_ENTRY("amx-fp16", FEATURE_AMX_FP16, P_NONE, "-mamx-fp16")
+ ISA_NAMES_TABLE_END
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 4a0ae9328..e2b4a23dc 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -423,7 +423,8 @@ 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 avx512fp16intrin.h avx512fp16vlintrin.h"
++		       mwaitintrin.h avx512fp16intrin.h avx512fp16vlintrin.h
++		       amxfp16intrin.h"
+ 	;;
+ ia64-*-*)
+ 	extra_headers=ia64intrin.h
+diff --git a/gcc/config/i386/amxfp16intrin.h b/gcc/config/i386/amxfp16intrin.h
+new file mode 100644
+index 000000000..6a114741a
+--- /dev/null
++++ b/gcc/config/i386/amxfp16intrin.h
+@@ -0,0 +1,46 @@
++/* Copyright (C) 2020 Free Software Foundation, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3, or (at your option)
++   any later version.
++
++   GCC is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   Under Section 7 of GPL version 3, you are granted additional
++   permissions described in the GCC Runtime Library Exception, version
++   3.1, as published by the Free Software Foundation.
++
++   You should have received a copy of the GNU General Public License and
++   a copy of the GCC Runtime Library Exception along with this program;
++   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
++   .  */
++
++#if !defined _IMMINTRIN_H_INCLUDED
++#error "Never use  directly; include  instead."
++#endif
++
++#ifndef _AMXFP16INTRIN_H_INCLUDED
++#define _AMXFP16INTRIN_H_INCLUDED
++
++#if defined(__x86_64__)
++#define _tile_dpfp16ps_internal(dst,src1,src2)			\
++  __asm__ volatile \
++  ("{tdpfp16ps\t%%tmm"#src2", %%tmm"#src1", %%tmm"#dst"|tdpfp16ps\t%%tmm"#dst", %%tmm"#src1", %%tmm"#src2"}" ::)
++
++#define _tile_dpfp16ps(dst,src1,src2)				\
++  _tile_dpfp16ps_internal (dst,src1,src2)
++
++#endif
++
++#ifdef __DISABLE_AMX_FP16__
++#undef __DISABLE_AMX_FP16__
++#pragma GCC pop_options
++#endif /* __DISABLE_AMX_FP16__ */
++
++#endif /* _AMXFP16INTRIN_H_INCLUDED */
+diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
+index 8b3dc2b1d..d6cd8d1bf 100644
+--- a/gcc/config/i386/cpuid.h
++++ b/gcc/config/i386/cpuid.h
+@@ -27,6 +27,7 @@
+ /* %eax */
+ #define bit_AVXVNNI	(1 << 4)
+ #define bit_AVX512BF16	(1 << 5)
++#define bit_AMX_FP16	(1 << 21)
+ #define bit_HRESET	(1 << 22)
+ 
+ /* %ecx */
+diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc
+index 3fec4c7e2..4269f29e6 100644
+--- a/gcc/config/i386/i386-c.cc
++++ b/gcc/config/i386/i386-c.cc
+@@ -633,6 +633,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+     def_or_undef (parse_in, "__WIDEKL__");
+   if (isa_flag2 & OPTION_MASK_ISA2_AVXVNNI)
+     def_or_undef (parse_in, "__AVXVNNI__");
++  if (isa_flag2 & OPTION_MASK_ISA2_AMX_FP16)
++    def_or_undef (parse_in, "__AMX_FP16__");
+   if (TARGET_IAMCU)
+     {
+       def_or_undef (parse_in, "__iamcu");
+diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def
+index 83659d0be..c7305c01b 100644
+--- a/gcc/config/i386/i386-isa.def
++++ b/gcc/config/i386/i386-isa.def
+@@ -109,3 +109,4 @@ DEF_PTA(KL)
+ DEF_PTA(WIDEKL)
+ DEF_PTA(AVXVNNI)
+ DEF_PTA(AVX512FP16)
++DEF_PTA(AMX_FP16)
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 3df1f0c41..3edb7094e 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -230,7 +230,8 @@ static struct ix86_target_opts isa2_opts[] =
+   { "-mkl",		OPTION_MASK_ISA2_KL },
+   { "-mwidekl", 	OPTION_MASK_ISA2_WIDEKL },
+   { "-mavxvnni",	OPTION_MASK_ISA2_AVXVNNI },
+-  { "-mavx512fp16",	OPTION_MASK_ISA2_AVX512FP16 }
++  { "-mavx512fp16",	OPTION_MASK_ISA2_AVX512FP16 },
++  { "-mamx-fp16",       OPTION_MASK_ISA2_AMX_FP16 }
+ };
+ static struct ix86_target_opts isa_opts[] =
+ {
+@@ -1074,6 +1075,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
+     IX86_ATTR_ISA ("hreset", OPT_mhreset),
+     IX86_ATTR_ISA ("avxvnni",   OPT_mavxvnni),
+     IX86_ATTR_ISA ("avx512fp16", OPT_mavx512fp16),
++    IX86_ATTR_ISA ("amx-fp16", OPT_mamx_fp16),
+ 
+     /* enum options */
+     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index b154110d8..52c6f02ee 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -1226,3 +1226,7 @@ Enable conservative small loop unrolling.
+ mscatter
+ Target Alias(mtune-ctrl=, use_scatter, ^use_scatter)
+ Enable vectorization for scatter instruction.
++
++mamx-fp16
++Target Mask(ISA2_AMX_FP16) Var(ix86_isa_flags2) Save
++Support AMX-FP16 built-in functions and code generation.
+diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
+index 6afd78c2b..0447ca4b2 100644
+--- a/gcc/config/i386/immintrin.h
++++ b/gcc/config/i386/immintrin.h
+@@ -128,4 +128,6 @@
+ 
+ #include 
+ 
++#include 
++
+ #endif /* _IMMINTRIN_H_INCLUDED */
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 33a776a79..4ba9d34cd 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -7038,6 +7038,11 @@ Enable/disable the generation of the WIDEKL instructions.
+ @cindex @code{target("avxvnni")} function attribute, x86
+ Enable/disable the generation of the AVXVNNI instructions.
+ 
++@item amx-fp16
++@itemx no-amx-fp16
++@cindex @code{target("amx-fp16")} function attribute, x86
++Enable/disable the generation of the AMX-FP16 instructions.
++
+ @item cld
+ @itemx no-cld
+ @cindex @code{target("cld")} function attribute, x86
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 3a48655e5..d25f13217 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1428,7 +1428,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
++-mavx512fp16 -mamx-fp16 @gol
+ -mcldemote  -mms-bitfields  -mno-align-stringops  -minline-all-stringops @gol
+ -minline-stringops-dynamically  -mstringop-strategy=@var{alg} @gol
+ -mkl -mwidekl @gol
+@@ -32442,6 +32442,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
+ @need 200
+ @itemx -mwidekl
+ @opindex mwidekl
++@need 200
++@itemx -mamx-fp16
++@opindex mamx-fp16
+ These switches enable the use of instructions in the MMX, SSE,
+ SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF,
+ AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA,
+@@ -32451,8 +32454,8 @@ 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, AVX512-FP16
+-or CLDEMOTE extended instruction sets. Each has a corresponding
++UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI, AVX512-FP16,
++AMX-FP16 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
+diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
+index 71c04841d..b64b62dee 100644
+--- a/gcc/doc/sourcebuild.texi
++++ b/gcc/doc/sourcebuild.texi
+@@ -2472,6 +2472,9 @@ Target supports the execution of @code{amx-int8} instructions.
+ @item amx_bf16
+ Target supports the execution of @code{amx-bf16} instructions.
+ 
++@item amx_fp16
++Target supports the execution of @code{amx-fp16} instructions.
++
+ @item cell_hw
+ Test system can execute AltiVec and Cell PPU instructions.
+ 
+diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
+index fba3d1ac6..57a6357aa 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 -mavx512fp16" } */
++/* { 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 -mamx-fp16" } */
+ 
+ /* 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 5cc0fa834..1947547d6 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 -mavx512fp16" } */
++/* { 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 -mamx-fp16" } */
+ 
+ /* 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/gcc.target/i386/amx-check.h b/gcc/testsuite/gcc.target/i386/amx-check.h
+index 6fff5ff46..27dd37bf9 100644
+--- a/gcc/testsuite/gcc.target/i386/amx-check.h
++++ b/gcc/testsuite/gcc.target/i386/amx-check.h
+@@ -213,6 +213,9 @@ main ()
+ #ifdef AMX_BF16
+       && __builtin_cpu_supports ("amx-bf16")
+ #endif
++#ifdef AMX_FP16
++      && __builtin_cpu_supports ("amx-fp16")
++#endif
+ #ifdef __linux__
+       && request_perm_xtile_data ()
+ #endif
+diff --git a/gcc/testsuite/gcc.target/i386/amx-helper.h b/gcc/testsuite/gcc.target/i386/amx-helper.h
+new file mode 100644
+index 000000000..fe24d7067
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amx-helper.h
+@@ -0,0 +1,61 @@
++#ifndef AMX_HELPER_H_INCLUDED
++#define AMX_HELPER_H_INCLUDED
++#if defined(AMX_FP16)
++#include 
++#include 
++#endif
++#include "amx-check.h"
++
++typedef union
++{
++  _Float16 f16;
++  uint16_t u;
++} union16f_uw;
++
++#if defined(AMX_FP16)
++/* Transformation functions between fp16/float */
++static uint16_t make_f32_fp16 (float f)
++{
++  union16f_uw tmp;
++  __m128 b = _mm_set_ss (f);
++  __m128h a;
++  tmp.f16 = _mm_cvtsh_h (_mm_cvtss_sh (a, b));
++  return tmp.u;
++}
++
++static float make_fp16_f32 (uint16_t fp)
++{
++  union16f_uw tmp;
++  tmp.u = fp;
++  __m128h b = _mm_set_sh (tmp.f16);
++  __m128 a;
++  return _mm_cvtss_f32 (_mm_cvtsh_ss (a, b));
++}
++
++/* Init tile buffer with fp16 pairs */
++void init_fp16_max_tile_buffer (uint8_t* buf)
++{
++  int i, j;
++  uint16_t* ptr = (uint16_t *) buf;
++
++  for (i = 0; i < 16; i++)
++    for (j = 0; j < 32; j++)
++    {
++      float f = 2.5f * i + 1.25f * j;
++      ptr[i * 32 + j] = make_f32_fp16 (f);
++    }
++}
++
++/* Init tile fp16 pair buffer with zero */
++void init_fp16_max_tile_zero_buffer (uint8_t* buf)
++{
++  int i, j;
++  uint16_t* ptr = (uint16_t *) buf;
++
++  for (i = 0; i < 16; i++)
++    for (j = 0; j < 32; j++)
++      ptr[i * 32 + j] = make_f32_fp16 (0.0f);
++}
++#endif
++
++#endif
+diff --git a/gcc/testsuite/gcc.target/i386/amxfp16-asmatt-1.c b/gcc/testsuite/gcc.target/i386/amxfp16-asmatt-1.c
+new file mode 100644
+index 000000000..09ae6d408
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxfp16-asmatt-1.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-options "-O2 -mamx-fp16" } */
++/* { dg-final { scan-assembler "tdpfp16ps\[ \\t]+\[^\n\]*%tmm3+\[^\n\]*%tmm2+\[^\n\]*%tmm1"  } } */
++#include 
++
++#define TMM1 1
++#define TMM2 2
++#define TMM3 3
++
++void TEST ()
++{
++  _tile_dpfp16ps (TMM1, TMM2, TMM3);
++}
+diff --git a/gcc/testsuite/gcc.target/i386/amxfp16-asmintel-1.c b/gcc/testsuite/gcc.target/i386/amxfp16-asmintel-1.c
+new file mode 100644
+index 000000000..a8dff945f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxfp16-asmintel-1.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-require-effective-target masm_intel } */
++/* { dg-options "-O2 -mamx-fp16 -masm=intel" } */
++/* { dg-final { scan-assembler "tdpfp16ps\[ \\t]+\[^\n\]*%tmm1+\[^\n\]*%tmm2+\[^\n\]*%tmm3"  } } */
++#include 
++
++void TEST ()
++{
++  _tile_dpfp16ps (1, 2, 3);
++}
+diff --git a/gcc/testsuite/gcc.target/i386/amxfp16-dpfp16ps-2.c b/gcc/testsuite/gcc.target/i386/amxfp16-dpfp16ps-2.c
+new file mode 100644
+index 000000000..2d359a689
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxfp16-dpfp16ps-2.c
+@@ -0,0 +1,57 @@
++/* { dg-do run { target { ! ia32 } } } */
++/* { dg-require-effective-target amx_tile } */
++/* { dg-require-effective-target amx_fp16 } */
++/* { dg-require-effective-target avx512fp16 } */
++/* { dg-options "-O2 -mamx-tile -mamx-fp16 -mavx512fp16" } */
++#define AMX_FP16
++#define DO_TEST test_amx_fp16_dpfp16ps
++void test_amx_fp16_dpfp16ps ();
++#include "amx-helper.h"
++
++void calc_matrix_dpfp16ps (__tile *dst, __tile *src1, __tile *src2)
++{
++  uint16_t *src1_buf = (uint16_t *)src1->buf;
++  uint16_t *src2_buf = (uint16_t *)src2->buf;
++  float *dst_buf = (float *)dst->buf;
++  
++  int M = src1->rows;
++  int N = src1->colsb / 4;
++  int K = src2->colsb / 4;
++  int i, j, k, t;
++
++  for (i = 0; i < M; i++)
++    for (j = 0; j < N; j++)
++      for (k = 0; k < K; k++)
++	for (t = 0; t < 2; t+=2)
++	  {    
++	    dst_buf[i * K + k] += 
++	      (make_fp16_f32 (src1_buf[i * 2 * N + 2 * j + t]) *
++	      make_fp16_f32 (src2_buf[j * 2 * K + 2 * k + t])) +
++	      (make_fp16_f32 (src1_buf[i * 2 * N + 2 * j + t + 1]) *
++	      make_fp16_f32 (src2_buf[j * 2 * K + 2 * k + t + 1]));
++	  }
++
++}
++
++void test_amx_fp16_dpfp16ps ()
++{
++  __tilecfg_u cfg;
++  __tile dst, dst_ref, src1, src2;
++  uint8_t tmp_dst_buf[1024], tmp_dst_zero_buf[1024];
++
++  init_fp16_max_tile_buffer (tmp_dst_buf);
++  init_fp16_max_tile_zero_buffer (tmp_dst_zero_buf);
++
++  init_tile_config (&cfg);
++  init_tile_reg_and_src_with_buffer (1, dst, tmp_dst_zero_buf);
++  init_tile_reg_and_src_with_buffer (2, src1, tmp_dst_buf);
++  init_tile_reg_and_src_with_buffer (3, src2, tmp_dst_buf);
++
++  calc_matrix_dpfp16ps (&dst, &src1, &src2);
++  
++  _tile_dpfp16ps (1, 2, 3);
++  _tile_stored (1, dst_ref.buf, _STRIDE);
++
++  if (!check_float_tile_register (&dst_ref, &dst))
++    abort ();
++}
+diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+index f34e7a977..b00cfff03 100644
+--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
++++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+@@ -80,6 +80,7 @@ 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_amx_fp16 (void)		__attribute__((__target__("amx-fp16")));
+ 
+ extern void test_no_sgx (void)			__attribute__((__target__("no-sgx")));
+ extern void test_no_avx5124fmaps(void)		__attribute__((__target__("no-avx5124fmaps")));
+@@ -161,6 +162,7 @@ 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_no_amx_fp16 (void)		__attribute__((__target__("no-amx-fp16")));
+ 
+ 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/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c
+index 375d4d1b4..9ab4a7e0c 100644
+--- a/gcc/testsuite/gcc.target/i386/sse-12.c
++++ b/gcc/testsuite/gcc.target/i386/sse-12.c
+@@ -3,7 +3,7 @@
+    popcntintrin.h gfniintrin.h and mm_malloc.h are usable
+    with -O -std=c89 -pedantic-errors.  */
+ /* { dg-do compile } */
+-/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni" } */
++/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mamx-fp16" } */
+ 
+ #include 
+ 
+diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
+index e285c307d..a1e453a98 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 -mavx512fp16" } */
++/* { 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 -mamx-fp16" } */
+ /* { dg-add-options bind_pic_locally } */
+ 
+ #include 
+diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
+index f41493b93..eaa1a8d81 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 -mavx512fp16" } */
++/* { 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 -mamx-fp16" } */
+ /* { dg-add-options bind_pic_locally } */
+ 
+ #include 
+diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
+index 31492ef36..19afe639d 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,avx512fp16")
++#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,amx-fp16")
+ #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,avx512fp16")
++#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,amx-fp16")
+ #endif
+ #include 
+ test_1 (_cvtss_sh, unsigned short, float, 1)
+diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
+index b398fd144..151201d97 100644
+--- a/gcc/testsuite/gcc.target/i386/sse-23.c
++++ b/gcc/testsuite/gcc.target/i386/sse-23.c
+@@ -843,6 +843,6 @@
+ #define __builtin_ia32_vpclmulqdq_v2di(A, B, C)  __builtin_ia32_vpclmulqdq_v2di(A, B, 1) 
+ #define __builtin_ia32_vpclmulqdq_v8di(A, B, C)  __builtin_ia32_vpclmulqdq_v8di(A, B, 1) 
+ 
+-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16")
++#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,amx-fp16")
+ 
+ #include 
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index c858bd93b..0d83c780c 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -9972,6 +9972,17 @@ proc check_effective_target_amx_bf16 { } {
+     } "-mamx-bf16" ]
+ }
+ 
++# Return 1 if amx-fp16 instructions can be compiled.
++proc check_effective_target_amx_fp16 { } {
++    return [check_no_compiler_messages amx_fp16 object {
++	void
++	foo ()
++	{
++	    __asm__ volatile ("tdpfp16ps\t%%tmm1, %%tmm2, %%tmm3" ::);
++	}
++    } "-mamx-fp16" ]
++}
++
+ # Return 1 if vpclmulqdq instructions can be compiled.
+ proc check_effective_target_vpclmulqdq { } {
+     return [check_no_compiler_messages vpclmulqdq object {
+-- 
+2.31.1
+
diff --git a/0273-Support-Intel-prefetchit0-t1.patch b/0273-Support-Intel-prefetchit0-t1.patch
new file mode 100644
index 0000000..a6c777f
--- /dev/null
+++ b/0273-Support-Intel-prefetchit0-t1.patch
@@ -0,0 +1,902 @@
+From 42a38c8abaa28f67e26b9af3f434fe0107894e7d Mon Sep 17 00:00:00 2001
+From: Haochen Jiang 
+Date: Fri, 4 Nov 2022 15:01:05 +0800
+Subject: [PATCH 19/28] Support Intel prefetchit0/t1
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h (get_available_features):
+	Detect PREFETCHI.
+	* common/config/i386/i386-common.cc
+	(OPTION_MASK_ISA2_PREFETCHI_SET,
+	OPTION_MASK_ISA2_PREFETCHI_UNSET): New.
+	(ix86_handle_option): Handle -mprefetchi.
+	* common/config/i386/i386-cpuinfo.h
+	(enum processor_features): Add FEATURE_PREFETCHI.
+	* common/config/i386/i386-isas.h: Add ISA_NAME_TABLE_ENTRY
+	for prefetchi.
+	* config.gcc: Add prfchiintrin.h.
+	* config/i386/cpuid.h (bit_PREFETCHI): New.
+	* config/i386/i386-builtin-types.def:
+	Add DEF_FUNCTION_TYPE (VOID, PCVOID, INT)
+	and DEF_FUNCTION_TYPE (VOID, PCVOID, INT, INT, INT).
+	* config/i386/i386-builtin.def (BDESC): Add new builtins.
+	* config/i386/i386-c.cc (ix86_target_macros_internal):
+	Define __PREFETCHI__.
+	* config/i386/i386-expand.cc: Handle new builtins.
+	* config/i386/i386-isa.def (PREFETCHI):
+	Add DEF_PTA(PREFETCHI).
+	* config/i386/i386-options.cc
+	(ix86_valid_target_attribute_inner_p): Handle prefetchi.
+	* config/i386/i386.md (prefetchi): New define_insn.
+	* config/i386/i386.opt: Add option -mprefetchi.
+	* config/i386/predicates.md (local_func_symbolic_operand):
+	New predicates.
+	* config/i386/x86gprintrin.h: Include prfchiintrin.h.
+	* config/i386/xmmintrin.h (enum _mm_hint): New enum for
+	prefetchi.
+	(_mm_prefetch): Handle the highest bit of enum.
+	* doc/extend.texi: Document prefetchi.
+	* doc/invoke.texi: Document -mprefetchi.
+	* doc/sourcebuild.texi: Document target prefetchi.
+	* config/i386/prfchiintrin.h: New file.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.dg/other/i386-2.C: Add -mprefetchi.
+	* g++.dg/other/i386-3.C: Ditto.
+	* gcc.target/i386/avx-1.c: Ditto.
+	* gcc.target/i386/funcspec-56.inc: Add new target attribute.
+	* gcc.target/i386/sse-13.c: Add -mprefetchi.
+	* gcc.target/i386/sse-23.c: Ditto.
+	* gcc.target/i386/x86gprintrin-1.c: Ditto.
+	* gcc.target/i386/x86gprintrin-2.c: Ditto.
+	* gcc.target/i386/x86gprintrin-3.c: Ditto.
+	* gcc.target/i386/x86gprintrin-4.c: Ditto.
+	* gcc.target/i386/x86gprintrin-5.c: Ditto.
+	* gcc.target/i386/prefetchi-1.c: New test.
+	* gcc.target/i386/prefetchi-2.c: Ditto.
+	* gcc.target/i386/prefetchi-3.c: Ditto.
+	* gcc.target/i386/prefetchi-4.c: Ditto.
+
+Co-authored-by: Hongtao Liu 
+---
+ gcc/common/config/i386/cpuinfo.h              |  2 +
+ gcc/common/config/i386/i386-common.cc         | 15 ++++
+ gcc/common/config/i386/i386-cpuinfo.h         |  1 +
+ gcc/common/config/i386/i386-isas.h            |  1 +
+ gcc/config.gcc                                |  2 +-
+ gcc/config/i386/cpuid.h                       |  1 +
+ gcc/config/i386/i386-builtin-types.def        |  4 +
+ gcc/config/i386/i386-builtin.def              |  4 +
+ gcc/config/i386/i386-c.cc                     |  2 +
+ gcc/config/i386/i386-expand.cc                | 77 +++++++++++++++++++
+ gcc/config/i386/i386-isa.def                  |  1 +
+ gcc/config/i386/i386-options.cc               |  4 +-
+ gcc/config/i386/i386.md                       | 23 ++++++
+ gcc/config/i386/i386.opt                      |  4 +
+ gcc/config/i386/predicates.md                 | 15 ++++
+ gcc/config/i386/prfchiintrin.h                | 49 ++++++++++++
+ gcc/config/i386/x86gprintrin.h                |  2 +
+ gcc/config/i386/xmmintrin.h                   |  7 +-
+ gcc/doc/extend.texi                           |  5 ++
+ gcc/doc/invoke.texi                           |  7 +-
+ gcc/doc/sourcebuild.texi                      |  3 +
+ gcc/testsuite/g++.dg/other/i386-2.C           |  2 +-
+ gcc/testsuite/g++.dg/other/i386-3.C           |  2 +-
+ gcc/testsuite/gcc.target/i386/avx-1.c         |  4 +-
+ gcc/testsuite/gcc.target/i386/funcspec-56.inc |  2 +
+ gcc/testsuite/gcc.target/i386/prefetchi-1.c   | 40 ++++++++++
+ gcc/testsuite/gcc.target/i386/prefetchi-2.c   | 26 +++++++
+ gcc/testsuite/gcc.target/i386/prefetchi-3.c   | 20 +++++
+ gcc/testsuite/gcc.target/i386/prefetchi-4.c   | 19 +++++
+ gcc/testsuite/gcc.target/i386/sse-13.c        |  4 +-
+ gcc/testsuite/gcc.target/i386/sse-23.c        |  4 +-
+ .../gcc.target/i386/x86gprintrin-1.c          |  2 +-
+ .../gcc.target/i386/x86gprintrin-2.c          |  2 +-
+ .../gcc.target/i386/x86gprintrin-3.c          |  2 +-
+ .../gcc.target/i386/x86gprintrin-4.c          |  2 +-
+ .../gcc.target/i386/x86gprintrin-5.c          |  2 +-
+ 36 files changed, 343 insertions(+), 19 deletions(-)
+ create mode 100644 gcc/config/i386/prfchiintrin.h
+ create mode 100644 gcc/testsuite/gcc.target/i386/prefetchi-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/prefetchi-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/prefetchi-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/prefetchi-4.c
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 5951a30aa..f17e88144 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -772,6 +772,8 @@ get_available_features (struct __processor_model *cpu_model,
+ 	  __cpuid_count (7, 1, eax, ebx, ecx, edx);
+ 	  if (eax & bit_HRESET)
+ 	    set_feature (FEATURE_HRESET);
++	  if (edx & bit_PREFETCHI)
++	    set_feature (FEATURE_PREFETCHI);
+ 	  if (avx_usable)
+ 	    {
+ 	      if (eax & bit_AVXVNNI)
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index 922db33ee..c8cf532cf 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -108,6 +108,7 @@ along with GCC; see the file COPYING3.  If not see
+ #define OPTION_MASK_ISA2_AMX_INT8_SET OPTION_MASK_ISA2_AMX_INT8
+ #define OPTION_MASK_ISA2_AMX_BF16_SET OPTION_MASK_ISA2_AMX_BF16
+ #define OPTION_MASK_ISA2_AMX_FP16_SET OPTION_MASK_ISA2_AMX_FP16
++#define OPTION_MASK_ISA2_PREFETCHI_SET OPTION_MASK_ISA2_PREFETCHI
+ 
+ /* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same
+    as -msse4.2.  */
+@@ -277,6 +278,7 @@ along with GCC; see the file COPYING3.  If not see
+   (OPTION_MASK_ISA2_KL | OPTION_MASK_ISA2_WIDEKL_UNSET)
+ #define OPTION_MASK_ISA2_WIDEKL_UNSET OPTION_MASK_ISA2_WIDEKL
+ #define OPTION_MASK_ISA2_AMX_FP16_UNSET OPTION_MASK_ISA2_AMX_FP16
++#define OPTION_MASK_ISA2_PREFETCHI_UNSET OPTION_MASK_ISA2_PREFETCHI
+ 
+ /* SSE4 includes both SSE4.1 and SSE4.2.  -mno-sse4 should the same
+    as -mno-sse4.1. */
+@@ -1140,6 +1142,19 @@ ix86_handle_option (struct gcc_options *opts,
+ 	}
+       return true;
+ 
++    case OPT_mprefetchi:
++      if (value)
++	{
++	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_PREFETCHI_SET;
++	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_PREFETCHI_SET;
++	}
++      else
++	{
++	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_PREFETCHI_UNSET;
++	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_PREFETCHI_UNSET;
++	}
++      return true;
++
+     case OPT_mfma:
+       if (value)
+ 	{
+diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
+index 8f22897de..95b078acf 100644
+--- a/gcc/common/config/i386/i386-cpuinfo.h
++++ b/gcc/common/config/i386/i386-cpuinfo.h
+@@ -241,6 +241,7 @@ enum processor_features
+   FEATURE_X86_64_V3,
+   FEATURE_X86_64_V4,
+   FEATURE_AMX_FP16,
++  FEATURE_PREFETCHI,
+   CPU_FEATURE_MAX
+ };
+ 
+diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
+index 95bab6da2..6caf06249 100644
+--- a/gcc/common/config/i386/i386-isas.h
++++ b/gcc/common/config/i386/i386-isas.h
+@@ -176,4 +176,5 @@ ISA_NAMES_TABLE_START
+   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_ENTRY("amx-fp16", FEATURE_AMX_FP16, P_NONE, "-mamx-fp16")
++  ISA_NAMES_TABLE_ENTRY("prefetchi", FEATURE_PREFETCHI, P_NONE, "-mprefetchi")
+ ISA_NAMES_TABLE_END
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index e2b4a23dc..81012c651 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -424,7 +424,7 @@ i[34567]86-*-* | x86_64-*-*)
+ 		       amxbf16intrin.h x86gprintrin.h uintrintrin.h
+ 		       hresetintrin.h keylockerintrin.h avxvnniintrin.h
+ 		       mwaitintrin.h avx512fp16intrin.h avx512fp16vlintrin.h
+-		       amxfp16intrin.h"
++		       amxfp16intrin.h prfchiintrin.h"
+ 	;;
+ ia64-*-*)
+ 	extra_headers=ia64intrin.h
+diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
+index d6cd8d1bf..21100149a 100644
+--- a/gcc/config/i386/cpuid.h
++++ b/gcc/config/i386/cpuid.h
+@@ -50,6 +50,7 @@
+ 
+ /* %edx */
+ #define bit_CMPXCHG8B	(1 << 8)
++#define bit_PREFETCHI	(1 << 14)
+ #define bit_CMOV	(1 << 15)
+ #define bit_MMX		(1 << 23)
+ #define bit_FXSAVE	(1 << 24)
+diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
+index e33f06ab3..ff3b0af84 100644
+--- a/gcc/config/i386/i386-builtin-types.def
++++ b/gcc/config/i386/i386-builtin-types.def
+@@ -1387,3 +1387,7 @@ DEF_FUNCTION_TYPE (V32HF, V32HF)
+ DEF_FUNCTION_TYPE_ALIAS (V8HF_FTYPE_V8HF, ROUND)
+ DEF_FUNCTION_TYPE_ALIAS (V16HF_FTYPE_V16HF, ROUND)
+ DEF_FUNCTION_TYPE_ALIAS (V32HF_FTYPE_V32HF, ROUND)
++
++# PREFETCHI builtins
++DEF_FUNCTION_TYPE (VOID, PCVOID, INT)
++DEF_FUNCTION_TYPE (VOID, PCVOID, INT, INT, INT)
+diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
+index 2b1d6c733..d3ab21eea 100644
+--- a/gcc/config/i386/i386-builtin.def
++++ b/gcc/config/i386/i386-builtin.def
+@@ -469,6 +469,10 @@ BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesdecwide2
+ BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesencwide128kl_u8", IX86_BUILTIN_AESENCWIDE128KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+ BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesencwide256kl_u8", IX86_BUILTIN_AESENCWIDE256KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+ 
++/* PREFETCHI */
++BDESC (0, 0, CODE_FOR_prefetchi, "__builtin_ia32_prefetchi", IX86_BUILTIN_PREFETCHI, UNKNOWN, (int) VOID_FTYPE_PCVOID_INT)
++BDESC (0, 0, CODE_FOR_nothing, "__builtin_ia32_prefetch", IX86_BUILTIN_PREFETCH, UNKNOWN, (int) VOID_FTYPE_PCVOID_INT_INT_INT)
++
+ BDESC_END (SPECIAL_ARGS, PURE_ARGS)
+ 
+ /* AVX */
+diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc
+index 4269f29e6..00880bd17 100644
+--- a/gcc/config/i386/i386-c.cc
++++ b/gcc/config/i386/i386-c.cc
+@@ -635,6 +635,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+     def_or_undef (parse_in, "__AVXVNNI__");
+   if (isa_flag2 & OPTION_MASK_ISA2_AMX_FP16)
+     def_or_undef (parse_in, "__AMX_FP16__");
++  if (isa_flag2 & OPTION_MASK_ISA2_PREFETCHI)
++    def_or_undef (parse_in, "__PREFETCHI__");
+   if (TARGET_IAMCU)
+     {
+       def_or_undef (parse_in, "__iamcu");
+diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
+index 77dda5dd4..bc2e61980 100644
+--- a/gcc/config/i386/i386-expand.cc
++++ b/gcc/config/i386/i386-expand.cc
+@@ -12850,6 +12850,83 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
+ 	return target;
+       }
+ 
++    case IX86_BUILTIN_PREFETCH:
++      {
++	arg0 = CALL_EXPR_ARG (exp, 0); // const void *
++	arg1 = CALL_EXPR_ARG (exp, 1); // const int
++	arg2 = CALL_EXPR_ARG (exp, 2); // const int
++	arg3 = CALL_EXPR_ARG (exp, 3); // const int
++
++	op0 = expand_normal (arg0);
++	op1 = expand_normal (arg1);
++	op2 = expand_normal (arg2);
++	op3 = expand_normal (arg3);
++
++	if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
++	  {
++	    error ("second, third and fourth argument must be a const");
++	    return const0_rtx;
++	  }
++
++	if (INTVAL (op3) == 1)
++	  {
++	    if (TARGET_64BIT
++		&& local_func_symbolic_operand (op0, GET_MODE (op0)))
++	      emit_insn (gen_prefetchi (op0, op2));
++	    else
++	      {
++		warning (0, "instruction prefetch applies when in 64-bit mode"
++			    " with RIP-relative addressing and"
++			    " option %<-mprefetchi%>;"
++			    " they stay NOPs otherwise");
++		emit_insn (gen_nop ());
++	      }
++	  }
++	else
++	  {
++	    if (!address_operand (op0, VOIDmode))
++	      {
++		op0 = convert_memory_address (Pmode, op0);
++		op0 = copy_addr_to_reg (op0);
++	      }
++	    emit_insn (gen_prefetch (op0, op1, op2));
++	  }
++
++	return 0;
++      }
++
++    case IX86_BUILTIN_PREFETCHI:
++      {
++	arg0 = CALL_EXPR_ARG (exp, 0); // const void *
++	arg1 = CALL_EXPR_ARG (exp, 1); // const int
++
++	op0 = expand_normal (arg0);
++	op1 = expand_normal (arg1);
++
++	if (!CONST_INT_P (op1))
++	  {
++	    error ("second argument must be a const");
++	    return const0_rtx;
++	  }
++
++	/* GOT/PLT_PIC should not be available for instruction prefetch.
++	   It must be real instruction address.  */
++	if (TARGET_64BIT
++	    && local_func_symbolic_operand (op0, GET_MODE (op0)))
++	  emit_insn (gen_prefetchi (op0, op1));
++	else
++	  {
++	    /* Ignore the hint.  */
++	    warning (0, "instruction prefetch applies when in 64-bit mode"
++			" with RIP-relative addressing and"
++			" option %<-mprefetchi%>;"
++			" they stay NOPs otherwise");
++	    emit_insn (gen_nop ());
++	  }
++
++	return 0;
++      }
++
+     case IX86_BUILTIN_VEC_INIT_V2SI:
+     case IX86_BUILTIN_VEC_INIT_V4HI:
+     case IX86_BUILTIN_VEC_INIT_V8QI:
+diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def
+index c7305c01b..744a7df85 100644
+--- a/gcc/config/i386/i386-isa.def
++++ b/gcc/config/i386/i386-isa.def
+@@ -110,3 +110,4 @@ DEF_PTA(WIDEKL)
+ DEF_PTA(AVXVNNI)
+ DEF_PTA(AVX512FP16)
+ DEF_PTA(AMX_FP16)
++DEF_PTA(PREFETCHI)
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 3edb7094e..724375f02 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -231,7 +231,8 @@ static struct ix86_target_opts isa2_opts[] =
+   { "-mwidekl", 	OPTION_MASK_ISA2_WIDEKL },
+   { "-mavxvnni",	OPTION_MASK_ISA2_AVXVNNI },
+   { "-mavx512fp16",	OPTION_MASK_ISA2_AVX512FP16 },
+-  { "-mamx-fp16",       OPTION_MASK_ISA2_AMX_FP16 }
++  { "-mamx-fp16",       OPTION_MASK_ISA2_AMX_FP16 },
++  { "-mprefetchi",      OPTION_MASK_ISA2_PREFETCHI }
+ };
+ static struct ix86_target_opts isa_opts[] =
+ {
+@@ -1076,6 +1077,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
+     IX86_ATTR_ISA ("avxvnni",   OPT_mavxvnni),
+     IX86_ATTR_ISA ("avx512fp16", OPT_mavx512fp16),
+     IX86_ATTR_ISA ("amx-fp16", OPT_mamx_fp16),
++    IX86_ATTR_ISA ("prefetchi",   OPT_mprefetchi),
+ 
+     /* enum options */
+     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index 71691f598..f08c2cfb1 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -329,6 +329,9 @@
+ 
+   ;; For HRESET support
+   UNSPECV_HRESET
++
++  ;; For PREFETCHI support
++  UNSPECV_PREFETCHI
+ ])
+ 
+ ;; Constants to represent rounding modes in the ROUND instruction
+@@ -22907,6 +22910,26 @@
+ 	(symbol_ref "memory_address_length (operands[0], false)"))
+    (set_attr "memory" "none")])
+ 
++(define_insn "prefetchi"
++  [(unspec_volatile [(match_operand 0 "local_func_symbolic_operand" "p")
++		     (match_operand:SI 1 "const_int_operand")]
++		    UNSPECV_PREFETCHI)]
++  "TARGET_PREFETCHI && TARGET_64BIT"
++{
++  static const char * const patterns[2] = {
++    "prefetchit1\t%0", "prefetchit0\t%0"
++  };
++
++  int locality = INTVAL (operands[1]);
++  gcc_assert (IN_RANGE (locality, 2, 3));
++
++  return patterns[locality - 2];
++}
++  [(set_attr "type" "sse")
++   (set (attr "length_address")
++	(symbol_ref "memory_address_length (operands[0], false)"))
++   (set_attr "memory" "none")])
++
+ (define_expand "stack_protect_set"
+   [(match_operand 0 "memory_operand")
+    (match_operand 1 "memory_operand")]
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 52c6f02ee..50cd114f6 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -1230,3 +1230,7 @@ Enable vectorization for scatter instruction.
+ mamx-fp16
+ Target Mask(ISA2_AMX_FP16) Var(ix86_isa_flags2) Save
+ Support AMX-FP16 built-in functions and code generation.
++
++mprefetchi
++Target Mask(ISA2_PREFETCHI) Var(ix86_isa_flags2) Save
++Support PREFETCHI built-in functions and code generation.
+diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
+index ac02c61ac..774178b78 100644
+--- a/gcc/config/i386/predicates.md
++++ b/gcc/config/i386/predicates.md
+@@ -610,6 +610,21 @@
+   return false;
+ })
+ 
++(define_predicate "local_func_symbolic_operand"
++  (match_operand 0 "local_symbolic_operand")
++{
++  if (GET_CODE (op) == CONST
++      && GET_CODE (XEXP (op, 0)) == PLUS
++      && CONST_INT_P (XEXP (XEXP (op, 0), 1)))
++    op = XEXP (XEXP (op, 0), 0);
++
++  if (GET_CODE (op) == SYMBOL_REF
++      && !SYMBOL_REF_FUNCTION_P (op))
++    return false;
++
++  return true;
++})
++
+ ;; Test for a legitimate @GOTOFF operand.
+ ;;
+ ;; VxWorks does not impose a fixed gap between segments; the run-time
+diff --git a/gcc/config/i386/prfchiintrin.h b/gcc/config/i386/prfchiintrin.h
+new file mode 100644
+index 000000000..06deef488
+--- /dev/null
++++ b/gcc/config/i386/prfchiintrin.h
+@@ -0,0 +1,49 @@
++/* Copyright (C) 2022 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
++   .  */
++
++#if !defined _X86GPRINTRIN_H_INCLUDED
++# error "Never use  directly; include  instead."
++#endif
++
++#ifndef _PRFCHIINTRIN_H_INCLUDED
++#define _PRFCHIINTRIN_H_INCLUDED
++
++#ifdef __x86_64__
++
++extern __inline void
++__attribute__((__gnu_inline__, __always_inline__, __artificial__))
++_m_prefetchit0 (void* __P)
++{
++  __builtin_ia32_prefetchi (__P, 3);
++}
++
++extern __inline void
++__attribute__((__gnu_inline__, __always_inline__, __artificial__))
++_m_prefetchit1 (void* __P)
++{
++  __builtin_ia32_prefetchi (__P, 2);
++}
++
++#endif
++
++#endif /* _PRFCHIINTRIN_H_INCLUDED */
+diff --git a/gcc/config/i386/x86gprintrin.h b/gcc/config/i386/x86gprintrin.h
+index e0be01d5e..0768aa0d7 100644
+--- a/gcc/config/i386/x86gprintrin.h
++++ b/gcc/config/i386/x86gprintrin.h
+@@ -72,6 +72,8 @@
+ 
+ #include 
+ 
++#include 
++
+ #include 
+ 
+ #include 
+diff --git a/gcc/config/i386/xmmintrin.h b/gcc/config/i386/xmmintrin.h
+index f1c704a2d..7fb179430 100644
+--- a/gcc/config/i386/xmmintrin.h
++++ b/gcc/config/i386/xmmintrin.h
+@@ -36,6 +36,8 @@
+ /* Constants for use with _mm_prefetch.  */
+ enum _mm_hint
+ {
++  _MM_HINT_IT0 = 19,
++  _MM_HINT_IT1 = 18,
+   /* _MM_HINT_ET is _MM_HINT_T with set 3rd bit.  */
+   _MM_HINT_ET0 = 7,
+   _MM_HINT_ET1 = 6,
+@@ -51,11 +53,12 @@ enum _mm_hint
+ extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+ _mm_prefetch (const void *__P, enum _mm_hint __I)
+ {
+-  __builtin_prefetch (__P, (__I & 0x4) >> 2, __I & 0x3);
++  __builtin_ia32_prefetch (__P, (__I & 0x4) >> 2,
++			   __I & 0x3, (__I & 0x10) >> 4);
+ }
+ #else
+ #define _mm_prefetch(P, I) \
+-  __builtin_prefetch ((P), ((I & 0x4) >> 2), (I & 0x3))
++  __builtin_ia32_prefetch ((P), ((I) & 0x4) >> 2, ((I) & 0x3), ((I) & 0x10) >> 4)
+ #endif
+ 
+ #ifndef __SSE__
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 4ba9d34cd..cb987f469 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -7043,6 +7043,11 @@ Enable/disable the generation of the AVXVNNI instructions.
+ @cindex @code{target("amx-fp16")} function attribute, x86
+ Enable/disable the generation of the AMX-FP16 instructions.
+ 
++@item prefetchi
++@itemx no-prefetchi
++@cindex @code{target("prefetchi")} function attribute, x86
++Enable/disable the generation of the PREFETCHI instructions.
++
+ @item cld
+ @itemx no-cld
+ @cindex @code{target("cld")} function attribute, x86
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index d25f13217..211b970c0 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1428,7 +1428,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 -mamx-fp16 @gol
++-mavx512fp16 -mamx-fp16 -mprefetchi @gol
+ -mcldemote  -mms-bitfields  -mno-align-stringops  -minline-all-stringops @gol
+ -minline-stringops-dynamically  -mstringop-strategy=@var{alg} @gol
+ -mkl -mwidekl @gol
+@@ -32445,6 +32445,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
+ @need 200
+ @itemx -mamx-fp16
+ @opindex mamx-fp16
++@need 200
++@itemx -mprefetchi
++@opindex mprefetchi
+ These switches enable the use of instructions in the MMX, SSE,
+ SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF,
+ AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA,
+@@ -32455,7 +32458,7 @@ 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, AVX512-FP16,
+-AMX-FP16 or CLDEMOTE extended instruction sets. Each has a corresponding
++AMX-FP16, PREFETCHI 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
+diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
+index b64b62dee..c68e492dc 100644
+--- a/gcc/doc/sourcebuild.texi
++++ b/gcc/doc/sourcebuild.texi
+@@ -2496,6 +2496,9 @@ Target does not require strict alignment.
+ @item pie_copyreloc
+ The x86-64 target linker supports PIE with copy reloc.
+ 
++@item prefetchi
++Target supports the execution of @code{prefetchi} instructions.
++
+ @item rdrand
+ Target supports x86 @code{rdrand} instruction.
+ 
+diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
+index 57a6357aa..72ed5fed0 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 -mavx512fp16 -mamx-fp16" } */
++/* { 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 -mamx-fp16 -mprefetchi" } */
+ 
+ /* 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 1947547d6..9dd53653f 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 -mavx512fp16 -mamx-fp16" } */
++/* { 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 -mamx-fp16 -mprefetchi" } */
+ 
+ /* 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/gcc.target/i386/avx-1.c b/gcc/testsuite/gcc.target/i386/avx-1.c
+index 154e7b3b1..2b46e1b87 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 -mavx512fp16 -mavx512vl" } */
++/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -m3dnow -mavx -mavx2 -maes -mpclmul -mgfni -mavx512bw -mavx512fp16 -mavx512vl -mprefetchi" } */
+ /* { dg-add-options bind_pic_locally } */
+ 
+ #include 
+@@ -153,7 +153,7 @@
+ #define __builtin_ia32_shufpd(A, B, N) __builtin_ia32_shufpd(A, B, 0)
+ 
+ /* xmmintrin.h */
+-#define __builtin_prefetch(P, A, I) __builtin_prefetch(P, 0, _MM_HINT_NTA)
++#define __builtin_ia32_prefetch(A, B, C, D) __builtin_ia32_prefetch(A, 0, 3, 0)
+ #define __builtin_ia32_pshufw(A, N) __builtin_ia32_pshufw(A, 0)
+ #define __builtin_ia32_vec_set_v4hi(A, D, N) \
+   __builtin_ia32_vec_set_v4hi(A, D, 0)
+diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+index b00cfff03..9f073f78c 100644
+--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
++++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+@@ -81,6 +81,7 @@ 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_amx_fp16 (void)		__attribute__((__target__("amx-fp16")));
++extern void test_prefetchi (void)               __attribute__((__target__("prefetchi")));
+ 
+ extern void test_no_sgx (void)			__attribute__((__target__("no-sgx")));
+ extern void test_no_avx5124fmaps(void)		__attribute__((__target__("no-avx5124fmaps")));
+@@ -163,6 +164,7 @@ 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_no_amx_fp16 (void)		__attribute__((__target__("no-amx-fp16")));
++extern void test_no_prefetchi (void)            __attribute__((__target__("no-prefetchi")));
+ 
+ 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/prefetchi-1.c b/gcc/testsuite/gcc.target/i386/prefetchi-1.c
+new file mode 100644
+index 000000000..80f25e70e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/prefetchi-1.c
+@@ -0,0 +1,40 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-options "-mprefetchi -O2" } */
++/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+" 2 } } */
++/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+" 2 } } */
++
++#include 
++
++int
++bar (int a)
++{
++  return a + 1;
++}
++
++int
++foo1 (int b)
++{
++  _mm_prefetch (bar, _MM_HINT_IT0);
++  return bar (b) + 1;
++}
++
++int
++foo2 (int b)
++{
++  _mm_prefetch (bar, _MM_HINT_IT1);
++  return bar (b) + 1;
++}
++
++int
++foo3 (int b)
++{
++  _m_prefetchit0 (bar);
++  return bar (b) + 1;
++}
++
++int
++foo4 (int b)
++{
++  _m_prefetchit1 (bar);
++  return bar (b) + 1;
++}
+diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-2.c b/gcc/testsuite/gcc.target/i386/prefetchi-2.c
+new file mode 100644
+index 000000000..e05ce9c73
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/prefetchi-2.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile { target { ia32 } } } */
++/* { dg-options "-mprefetchi -O2" } */
++/* { dg-final { scan-assembler-not "\[ \\t\]+prefetchit0" } } */
++/* { dg-final { scan-assembler-not "\[ \\t\]+prefetchit1" } } */
++
++#include 
++
++int
++bar (int a)
++{
++  return a + 1;
++}
++
++int
++foo1 (int b)
++{
++  __builtin_ia32_prefetch (bar, 0, 3, 1); /* { dg-warning "instruction prefetch applies when in 64-bit mode with RIP-relative addressing and option '-mprefetchi'; they stay NOPs otherwise" } */
++  return bar (b) + 1;
++}
++
++int
++foo2 (int b)
++{
++  __builtin_ia32_prefetchi (bar, 2); /* { dg-warning "instruction prefetch applies when in 64-bit mode with RIP-relative addressing and option '-mprefetchi'; they stay NOPs otherwise" } */
++  return bar (b) + 1;
++}
+diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-3.c b/gcc/testsuite/gcc.target/i386/prefetchi-3.c
+new file mode 100644
+index 000000000..f0a4173d2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/prefetchi-3.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-mprefetchi -O2" } */
++/* { dg-final { scan-assembler-not "prefetchit0" } } */
++/* { dg-final { scan-assembler-not "prefetchit1" } } */
++
++#include 
++
++void* p;
++
++void extern
++prefetchi_test1 (void)
++{
++  __builtin_ia32_prefetchi (p, 2); /* { dg-warning "instruction prefetch applies when in 64-bit mode with RIP-relative addressing and option '-mprefetchi'; they stay NOPs otherwise" } */
++}
++
++void extern
++prefetchi_test2 (void)
++{
++  __builtin_ia32_prefetch (p, 0, 3, 1); /* { dg-warning "instruction prefetch applies when in 64-bit mode with RIP-relative addressing and option '-mprefetchi'; they stay NOPs otherwise" } */
++} 
+diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-4.c b/gcc/testsuite/gcc.target/i386/prefetchi-4.c
+new file mode 100644
+index 000000000..73ae596d1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/prefetchi-4.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O0" } */
++
++#include 
++
++void* p;
++
++void extern
++prefetch_test (void)
++{
++  __builtin_ia32_prefetch (p, 0, 3, 0);
++  __builtin_ia32_prefetch (p, 0, 2, 0);
++  __builtin_ia32_prefetch (p, 0, 1, 0);
++  __builtin_ia32_prefetch (p, 0, 0, 0);
++  __builtin_ia32_prefetch (p, 1, 3, 0);
++  __builtin_ia32_prefetch (p, 1, 2, 0);
++  __builtin_ia32_prefetch (p, 1, 1, 0);
++  __builtin_ia32_prefetch (p, 1, 0, 0);
++}
+diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
+index a1e453a98..db7c0fc7a 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 -mavx512fp16 -mamx-fp16" } */
++/* { 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 -mamx-fp16 -mprefetchi" } */
+ /* { dg-add-options bind_pic_locally } */
+ 
+ #include 
+@@ -125,7 +125,7 @@
+ #define __builtin_ia32_shufpd(A, B, N) __builtin_ia32_shufpd(A, B, 0)
+ 
+ /* xmmintrin.h */
+-#define __builtin_prefetch(P, A, I) __builtin_prefetch(P, 0, _MM_HINT_NTA)
++#define __builtin_ia32_prefetch(A, B, C, D) __builtin_ia32_prefetch(A, 0, 3, 0)
+ #define __builtin_ia32_pshufw(A, N) __builtin_ia32_pshufw(A, 0)
+ #define __builtin_ia32_vec_set_v4hi(A, D, N) \
+   __builtin_ia32_vec_set_v4hi(A, D, 0)
+diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
+index 151201d97..741694e87 100644
+--- a/gcc/testsuite/gcc.target/i386/sse-23.c
++++ b/gcc/testsuite/gcc.target/i386/sse-23.c
+@@ -94,7 +94,7 @@
+ #define __builtin_ia32_shufpd(A, B, N) __builtin_ia32_shufpd(A, B, 0)
+ 
+ /* xmmintrin.h */
+-#define __builtin_prefetch(P, A, I) __builtin_prefetch(P, 0, _MM_HINT_NTA)
++#define __builtin_ia32_prefetch(A, B, C, D) __builtin_ia32_prefetch(A, 0, 3, 0)
+ #define __builtin_ia32_pshufw(A, N) __builtin_ia32_pshufw(A, 0)
+ #define __builtin_ia32_vec_set_v4hi(A, D, N) \
+   __builtin_ia32_vec_set_v4hi(A, D, 0)
+@@ -843,6 +843,6 @@
+ #define __builtin_ia32_vpclmulqdq_v2di(A, B, C)  __builtin_ia32_vpclmulqdq_v2di(A, B, 1) 
+ #define __builtin_ia32_vpclmulqdq_v8di(A, B, C)  __builtin_ia32_vpclmulqdq_v8di(A, B, 1) 
+ 
+-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,amx-fp16")
++#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,amx-fp16,prefetchi")
+ 
+ #include 
+diff --git a/gcc/testsuite/gcc.target/i386/x86gprintrin-1.c b/gcc/testsuite/gcc.target/i386/x86gprintrin-1.c
+index 293be094b..efe7df13b 100644
+--- a/gcc/testsuite/gcc.target/i386/x86gprintrin-1.c
++++ b/gcc/testsuite/gcc.target/i386/x86gprintrin-1.c
+@@ -1,7 +1,7 @@
+ /* Test that  is usable with -O -std=c89 -pedantic-errors.  */
+ /* { dg-do compile } */
+ /* { dg-options "-O -std=c89 -pedantic-errors -march=x86-64 -madx -mbmi -mbmi2 -mcldemote -mclflushopt -mclwb -mclzero -menqcmd -mfsgsbase -mfxsr -mhreset -mlzcnt -mlwp -mmovdiri -mmwaitx -mpconfig -mpopcnt -mpku -mptwrite -mrdpid -mrdrnd -mrdseed -mrtm -mserialize -msgx -mshstk -mtbm -mtsxldtrk -mwaitpkg -mwbnoinvd -mxsave -mxsavec -mxsaveopt -mxsaves -mno-sse -mno-mmx" } */
+-/* { dg-additional-options "-muintr" { target { ! ia32 } } }  */
++/* { dg-additional-options "-muintr -mprefetchi" { target { ! ia32 } } }  */
+ 
+ #include 
+ 
+diff --git a/gcc/testsuite/gcc.target/i386/x86gprintrin-2.c b/gcc/testsuite/gcc.target/i386/x86gprintrin-2.c
+index c63302757..5f6970df6 100644
+--- a/gcc/testsuite/gcc.target/i386/x86gprintrin-2.c
++++ b/gcc/testsuite/gcc.target/i386/x86gprintrin-2.c
+@@ -1,7 +1,7 @@
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -Werror-implicit-function-declaration -march=x86-64 -madx -mbmi -mbmi2 -mcldemote -mclflushopt -mclwb -mclzero -menqcmd -mfsgsbase -mfxsr -mhreset -mlzcnt -mlwp -mmovdiri -mmwaitx -mpconfig -mpopcnt -mpku -mptwrite -mrdpid -mrdrnd -mrdseed -mrtm -mserialize -msgx -mshstk -mtbm -mtsxldtrk -mwaitpkg -mwbnoinvd -mxsave -mxsavec -mxsaveopt -mxsaves -mno-sse -mno-mmx" } */
+ /* { dg-add-options bind_pic_locally } */
+-/* { dg-additional-options "-muintr" { target { ! ia32 } } }  */
++/* { dg-additional-options "-muintr -mprefetchi" { target { ! ia32 } } }  */
+ 
+ /* Test that the intrinsics in  compile with optimization.
+    All of them are defined as inline functions that reference the proper
+diff --git a/gcc/testsuite/gcc.target/i386/x86gprintrin-3.c b/gcc/testsuite/gcc.target/i386/x86gprintrin-3.c
+index 3a7e1f4a1..5c075c375 100644
+--- a/gcc/testsuite/gcc.target/i386/x86gprintrin-3.c
++++ b/gcc/testsuite/gcc.target/i386/x86gprintrin-3.c
+@@ -1,7 +1,7 @@
+ /* { dg-do compile } */
+ /* { dg-options "-O0 -Werror-implicit-function-declaration -march=x86-64 -madx -mbmi -mbmi2 -mcldemote -mclflushopt -mclwb -mclzero -menqcmd -mfsgsbase -mfxsr -mhreset -mlzcnt -mlwp -mmovdiri -mmwaitx -mpconfig -mpopcnt -mpku -mptwrite -mrdpid -mrdrnd -mrdseed -mrtm -mserialize -msgx -mshstk -mtbm -mtsxldtrk -mwaitpkg -mwbnoinvd -mxsave -mxsavec -mxsaveopt -mxsaves -mno-sse -mno-mmx" } */
+ /* { dg-add-options bind_pic_locally } */
+-/* { dg-additional-options "-muintr" { target { ! ia32 } } }  */
++/* { dg-additional-options "-muintr -mprefetchi" { target { ! ia32 } } }  */
+ 
+ /* Test that the intrinsics in  compile without optimization.
+    All of them are defined as inline functions that reference the proper
+diff --git a/gcc/testsuite/gcc.target/i386/x86gprintrin-4.c b/gcc/testsuite/gcc.target/i386/x86gprintrin-4.c
+index d8a6126e5..bda4ecea3 100644
+--- a/gcc/testsuite/gcc.target/i386/x86gprintrin-4.c
++++ b/gcc/testsuite/gcc.target/i386/x86gprintrin-4.c
+@@ -15,7 +15,7 @@
+ 
+ #ifndef DIFFERENT_PRAGMAS
+ #ifdef __x86_64__
+-#pragma GCC target ("adx,bmi,bmi2,fsgsbase,fxsr,hreset,lwp,lzcnt,popcnt,rdrnd,rdseed,tbm,rtm,serialize,tsxldtrk,uintr,xsaveopt")
++#pragma GCC target ("adx,bmi,bmi2,fsgsbase,fxsr,hreset,lwp,lzcnt,popcnt,prefetchi,rdrnd,rdseed,tbm,rtm,serialize,tsxldtrk,uintr,xsaveopt")
+ #else
+ #pragma GCC target ("adx,bmi,bmi2,fsgsbase,fxsr,hreset,lwp,lzcnt,popcnt,rdrnd,rdseed,tbm,rtm,serialize,tsxldtrk,xsaveopt")
+ #endif
+diff --git a/gcc/testsuite/gcc.target/i386/x86gprintrin-5.c b/gcc/testsuite/gcc.target/i386/x86gprintrin-5.c
+index 9ef66fdad..4aadfd0b3 100644
+--- a/gcc/testsuite/gcc.target/i386/x86gprintrin-5.c
++++ b/gcc/testsuite/gcc.target/i386/x86gprintrin-5.c
+@@ -28,7 +28,7 @@
+ #define __builtin_ia32_xabort(M) __builtin_ia32_xabort(1)
+ 
+ #ifdef __x86_64__
+-#pragma GCC target ("adx,bmi,bmi2,clflushopt,clwb,clzero,enqcmd,fsgsbase,fxsr,hreset,lwp,lzcnt,mwaitx,pconfig,pku,popcnt,rdpid,rdrnd,rdseed,tbm,rtm,serialize,sgx,tsxldtrk,uintr,xsavec,xsaveopt,xsaves,wbnoinvd")
++#pragma GCC target ("adx,bmi,bmi2,clflushopt,clwb,clzero,enqcmd,fsgsbase,fxsr,hreset,lwp,lzcnt,mwaitx,pconfig,pku,popcnt,prefetchi,rdpid,rdrnd,rdseed,tbm,rtm,serialize,sgx,tsxldtrk,uintr,xsavec,xsaveopt,xsaves,wbnoinvd")
+ #else
+ #pragma GCC target ("adx,bmi,bmi2,clflushopt,clwb,clzero,enqcmd,fsgsbase,fxsr,hreset,lwp,lzcnt,mwaitx,pconfig,pku,popcnt,rdpid,rdrnd,rdseed,tbm,rtm,serialize,sgx,tsxldtrk,xsavec,xsaveopt,xsaves,wbnoinvd")
+ #endif
+-- 
+2.31.1
+
diff --git a/0274-Initial-Granite-Rapids-Support.patch b/0274-Initial-Granite-Rapids-Support.patch
new file mode 100644
index 0000000..db78329
--- /dev/null
+++ b/0274-Initial-Granite-Rapids-Support.patch
@@ -0,0 +1,277 @@
+From 7f0f8b585cf60b4c09bca42b5339995c2cc74633 Mon Sep 17 00:00:00 2001
+From: Haochen Jiang 
+Date: Mon, 7 Nov 2022 11:04:57 +0800
+Subject: [PATCH 20/28] Initial Granite Rapids Support
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h
+	(get_intel_cpu): Handle Granite Rapids.
+	* common/config/i386/i386-common.cc:
+	(processor_names): Add graniterapids.
+	(processor_alias_table): Ditto.
+	* common/config/i386/i386-cpuinfo.h
+	(enum processor_subtypes): Add INTEL_GRANTIERAPIDS.
+	* config.gcc: Add -march=graniterapids.
+	* config/i386/driver-i386.cc (host_detect_local_cpu):
+	Handle graniterapids.
+	* config/i386/i386-c.cc (ix86_target_macros_internal):
+	Ditto.
+	* config/i386/i386-options.cc (m_GRANITERAPIDS): New.
+	(processor_cost_table): Add graniterapids.
+	* config/i386/i386.h (enum processor_type):
+	Add PROCESSOR_GRANITERAPIDS.
+	(PTA_GRANITERAPIDS): Ditto.
+	* doc/extend.texi: Add graniterapids.
+	* doc/invoke.texi: Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.target/i386/mv16.C: Add graniterapids.
+	* gcc.target/i386/funcspec-56.inc: Handle new march.
+
+(cherry picked from commit 339ffc5a792dd66647392a235f2f7f6344c5359e)
+---
+ gcc/common/config/i386/cpuinfo.h              |  9 +++++++++
+ gcc/common/config/i386/i386-common.cc         |  3 +++
+ gcc/common/config/i386/i386-cpuinfo.h         |  1 +
+ gcc/config.gcc                                |  2 +-
+ gcc/config/i386/driver-i386.cc                |  5 ++++-
+ gcc/config/i386/i386-c.cc                     |  7 +++++++
+ gcc/config/i386/i386-options.cc               |  4 +++-
+ gcc/config/i386/i386.h                        |  3 +++
+ gcc/doc/extend.texi                           |  3 +++
+ gcc/doc/invoke.texi                           | 11 +++++++++++
+ gcc/testsuite/g++.target/i386/mv16.C          |  6 ++++++
+ gcc/testsuite/gcc.target/i386/funcspec-56.inc |  1 +
+ 12 files changed, 52 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index f17e88144..1f75ff1ca 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -528,6 +528,15 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       cpu_model->__cpu_type = INTEL_COREI7;
+       cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS;
+       break;
++    case 0xad:
++    case 0xae:
++      /* Granite Rapids.  */
++      cpu = "graniterapids";
++      CHECK___builtin_cpu_is ("corei7");
++      CHECK___builtin_cpu_is ("graniterapids");
++      cpu_model->__cpu_type = INTEL_COREI7;
++      cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS;
++      break;
+     case 0x17:
+     case 0x1d:
+       /* Penryn.  */
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index c8cf532cf..1aa163463 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -1855,6 +1855,7 @@ const char *const processor_names[] =
+   "sapphirerapids",
+   "alderlake",
+   "rocketlake",
++  "graniterapids",
+   "intel",
+   "geode",
+   "k6",
+@@ -1973,6 +1974,8 @@ const pta processor_alias_table[] =
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
+   {"meteorlake", PROCESSOR_ALDERLAKE, CPU_HASWELL, PTA_ALDERLAKE,
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
++  {"graniterapids", PROCESSOR_GRANITERAPIDS, CPU_HASWELL, PTA_GRANITERAPIDS,
++    M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS), P_PROC_AVX512F},
+   {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+     M_CPU_TYPE (INTEL_BONNELL), P_PROC_SSSE3},
+   {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
+index 95b078acf..7b2d4d242 100644
+--- a/gcc/common/config/i386/i386-cpuinfo.h
++++ b/gcc/common/config/i386/i386-cpuinfo.h
+@@ -92,6 +92,7 @@ enum processor_subtypes
+   AMDFAM19H_ZNVER3,
+   INTEL_COREI7_ROCKETLAKE,
+   AMDFAM19H_ZNVER4,
++  INTEL_COREI7_GRANITERAPIDS,
+   CPU_SUBTYPE_MAX
+ };
+ 
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 81012c651..9bad238e3 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -670,7 +670,7 @@ slm nehalem westmere sandybridge ivybridge haswell broadwell bonnell \
+ silvermont knl knm skylake-avx512 cannonlake icelake-client icelake-server \
+ skylake goldmont goldmont-plus tremont cascadelake tigerlake cooperlake \
+ sapphirerapids alderlake rocketlake eden-x2 nano nano-1000 nano-2000 nano-3000 \
+-nano-x2 eden-x4 nano-x4 x86-64 x86-64-v2 x86-64-v3 x86-64-v4 native"
++nano-x2 eden-x4 nano-x4 x86-64 x86-64-v2 x86-64-v3 x86-64-v4 graniterapids native"
+ 
+ # Additional x86 processors supported by --with-cpu=.  Each processor
+ # MUST be separated by exactly one space.
+diff --git a/gcc/config/i386/driver-i386.cc b/gcc/config/i386/driver-i386.cc
+index 3b5161aed..ea8c3d8d1 100644
+--- a/gcc/config/i386/driver-i386.cc
++++ b/gcc/config/i386/driver-i386.cc
+@@ -576,8 +576,11 @@ const char *host_detect_local_cpu (int argc, const char **argv)
+ 	      /* This is unknown family 0x6 CPU.  */
+ 	      if (has_feature (FEATURE_AVX))
+ 		{
++		  /* Assume Granite Rapids.  */
++		  if (has_feature (FEATURE_AMX_FP16))
++		    cpu = "graniterapids";
+ 		  /* Assume Tiger Lake */
+-		  if (has_feature (FEATURE_AVX512VP2INTERSECT))
++		  else if (has_feature (FEATURE_AVX512VP2INTERSECT))
+ 		    cpu = "tigerlake";
+ 		  /* Assume Sapphire Rapids.  */
+ 		  else if (has_feature (FEATURE_TSXLDTRK))
+diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc
+index 00880bd17..04f1dd682 100644
+--- a/gcc/config/i386/i386-c.cc
++++ b/gcc/config/i386/i386-c.cc
+@@ -242,6 +242,10 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+       def_or_undef (parse_in, "__sapphirerapids");
+       def_or_undef (parse_in, "__sapphirerapids__");
+       break;
++    case PROCESSOR_GRANITERAPIDS:
++      def_or_undef (parse_in, "__graniterapids");
++      def_or_undef (parse_in, "__graniterapids__");
++      break;
+     case PROCESSOR_ALDERLAKE:
+       def_or_undef (parse_in, "__alderlake");
+       def_or_undef (parse_in, "__alderlake__");
+@@ -419,6 +423,9 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+     case PROCESSOR_ROCKETLAKE:
+       def_or_undef (parse_in, "__tune_rocketlake__");
+       break;
++    case PROCESSOR_GRANITERAPIDS:
++      def_or_undef (parse_in, "__tune_graniterapids__");
++      break;
+     case PROCESSOR_INTEL:
+     case PROCESSOR_GENERIC:
+       break;
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 724375f02..6645e3259 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -127,10 +127,11 @@ along with GCC; see the file COPYING3.  If not see
+ #define m_SAPPHIRERAPIDS (HOST_WIDE_INT_1U<
+Date: Wed, 31 May 2023 10:45:00 +0800
+Subject: [PATCH 21/28] Support Intel AMX-COMPLEX
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h (get_available_features):
+	Detect AMX-COMPLEX.
+	* common/config/i386/i386-common.cc
+	(OPTION_MASK_ISA2_AMX_COMPLEX_SET,
+	OPTION_MASK_ISA2_AMX_COMPLEX_UNSET): New.
+	(ix86_handle_option): Handle -mamx-complex.
+	* common/config/i386/i386-cpuinfo.h (enum processor_features):
+	Add FEATURE_AMX_COMPLEX.
+	* common/config/i386/i386-isas.h: Add ISA_NAME_TABLE_ENTRY for
+	amx-complex.
+	* config.gcc: Add amxcomplexintrin.h.
+	* config/i386/cpuid.h (bit_AMX_COMPLEX): New.
+	* config/i386/i386-c.cc (ix86_target_macros_internal): Define
+	__AMX_COMPLEX__.
+	* config/i386/i386-isa.def (AMX_COMPLEX): Add DEF_PTA(AMX_COMPLEX).
+	* config/i386/i386-options.cc (ix86_valid_target_attribute_inner_p):
+	Handle amx-complex.
+	* config/i386/i386.opt: Add option -mamx-complex.
+	* config/i386/immintrin.h: Include amxcomplexintrin.h.
+	* doc/extend.texi: Document amx-complex.
+	* doc/invoke.texi: Document -mamx-complex.
+	* doc/sourcebuild.texi: Document target amx-complex.
+	* config/i386/amxcomplexintrin.h: New file.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.dg/other/i386-2.C: Add -mamx-complex.
+	* g++.dg/other/i386-3.C: Ditto.
+	* gcc.target/i386/amx-check.h: Add cpu check for AMX-COMPLEX.
+	* gcc.target/i386/amx-helper.h: Add amx-complex support.
+	* gcc.target/i386/funcspec-56.inc: Add new target attribute.
+	* gcc.target/i386/sse-12.c: Add -mamx-complex.
+	* gcc.target/i386/sse-13.c: Ditto.
+	* gcc.target/i386/sse-14.c: Ditto.
+	* gcc.target/i386/sse-22.c: Add amx-complex.
+	* gcc.target/i386/sse-23.c: Ditto.
+	* lib/target-supports.exp (check_effective_target_amx_complex): New.
+	* gcc.target/i386/amxcomplex-asmatt-1.c: New test.
+	* gcc.target/i386/amxcomplex-asmintel-1.c: Ditto.
+	* gcc.target/i386/amxcomplex-cmmimfp16ps-2.c: Ditto.
+	* gcc.target/i386/amxcomplex-cmmrlfp16ps-2.c: Ditto.
+---
+ gcc/common/config/i386/cpuinfo.h              |  2 +
+ gcc/common/config/i386/i386-common.cc         | 19 +++++-
+ gcc/common/config/i386/i386-cpuinfo.h         |  1 +
+ gcc/common/config/i386/i386-isas.h            |  2 +
+ gcc/config.gcc                                |  2 +-
+ gcc/config/i386/amxcomplexintrin.h            | 59 +++++++++++++++++++
+ gcc/config/i386/cpuid.h                       |  1 +
+ gcc/config/i386/i386-c.cc                     |  2 +
+ gcc/config/i386/i386-isa.def                  |  1 +
+ gcc/config/i386/i386-options.cc               |  4 +-
+ gcc/config/i386/i386.opt                      |  4 ++
+ gcc/config/i386/immintrin.h                   |  2 +
+ gcc/doc/extend.texi                           |  5 ++
+ gcc/doc/invoke.texi                           |  7 ++-
+ gcc/doc/sourcebuild.texi                      |  3 +
+ gcc/testsuite/g++.dg/other/i386-2.C           |  2 +-
+ gcc/testsuite/g++.dg/other/i386-3.C           |  2 +-
+ gcc/testsuite/gcc.target/i386/amx-check.h     |  3 +
+ gcc/testsuite/gcc.target/i386/amx-helper.h    |  4 +-
+ .../gcc.target/i386/amxcomplex-asmatt-1.c     | 15 +++++
+ .../gcc.target/i386/amxcomplex-asmintel-1.c   | 12 ++++
+ .../i386/amxcomplex-cmmimfp16ps-2.c           | 53 +++++++++++++++++
+ .../i386/amxcomplex-cmmrlfp16ps-2.c           | 53 +++++++++++++++++
+ gcc/testsuite/gcc.target/i386/funcspec-56.inc |  2 +
+ gcc/testsuite/gcc.target/i386/sse-12.c        |  2 +-
+ gcc/testsuite/gcc.target/i386/sse-13.c        |  2 +-
+ gcc/testsuite/gcc.target/i386/sse-14.c        |  2 +-
+ gcc/testsuite/gcc.target/i386/sse-22.c        |  4 +-
+ gcc/testsuite/gcc.target/i386/sse-23.c        |  2 +-
+ gcc/testsuite/lib/target-supports.exp         | 11 ++++
+ 30 files changed, 268 insertions(+), 15 deletions(-)
+ create mode 100644 gcc/config/i386/amxcomplexintrin.h
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxcomplex-asmatt-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxcomplex-asmintel-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxcomplex-cmmimfp16ps-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/amxcomplex-cmmrlfp16ps-2.c
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 1f75ff1ca..39d3351db 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -798,6 +798,8 @@ get_available_features (struct __processor_model *cpu_model,
+ 	{
+ 	  if (eax & bit_AMX_FP16)
+ 	    set_feature (FEATURE_AMX_FP16);
++	  if (edx & bit_AMX_COMPLEX)
++	    set_feature (FEATURE_AMX_COMPLEX);
+ 	}
+     }
+ 
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index 1aa163463..87e8afe9b 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -109,6 +109,8 @@ along with GCC; see the file COPYING3.  If not see
+ #define OPTION_MASK_ISA2_AMX_BF16_SET OPTION_MASK_ISA2_AMX_BF16
+ #define OPTION_MASK_ISA2_AMX_FP16_SET OPTION_MASK_ISA2_AMX_FP16
+ #define OPTION_MASK_ISA2_PREFETCHI_SET OPTION_MASK_ISA2_PREFETCHI
++#define OPTION_MASK_ISA2_AMX_COMPLEX_SET \
++  (OPTION_MASK_ISA2_AMX_TILE | OPTION_MASK_ISA2_AMX_COMPLEX)
+ 
+ /* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same
+    as -msse4.2.  */
+@@ -269,7 +271,8 @@ along with GCC; see the file COPYING3.  If not see
+ #define OPTION_MASK_ISA2_SERIALIZE_UNSET OPTION_MASK_ISA2_SERIALIZE
+ #define OPTION_MASK_ISA2_AVX512VP2INTERSECT_UNSET OPTION_MASK_ISA2_AVX512VP2INTERSECT
+ #define OPTION_MASK_ISA2_TSXLDTRK_UNSET OPTION_MASK_ISA2_TSXLDTRK
+-#define OPTION_MASK_ISA2_AMX_TILE_UNSET OPTION_MASK_ISA2_AMX_TILE
++#define OPTION_MASK_ISA2_AMX_TILE_UNSET \
++  (OPTION_MASK_ISA2_AMX_TILE | OPTION_MASK_ISA2_AMX_COMPLEX_UNSET)
+ #define OPTION_MASK_ISA2_AMX_INT8_UNSET OPTION_MASK_ISA2_AMX_INT8
+ #define OPTION_MASK_ISA2_AMX_BF16_UNSET OPTION_MASK_ISA2_AMX_BF16
+ #define OPTION_MASK_ISA2_UINTR_UNSET OPTION_MASK_ISA2_UINTR
+@@ -279,6 +282,7 @@ along with GCC; see the file COPYING3.  If not see
+ #define OPTION_MASK_ISA2_WIDEKL_UNSET OPTION_MASK_ISA2_WIDEKL
+ #define OPTION_MASK_ISA2_AMX_FP16_UNSET OPTION_MASK_ISA2_AMX_FP16
+ #define OPTION_MASK_ISA2_PREFETCHI_UNSET OPTION_MASK_ISA2_PREFETCHI
++#define OPTION_MASK_ISA2_AMX_COMPLEX_UNSET OPTION_MASK_ISA2_AMX_COMPLEX
+ 
+ /* SSE4 includes both SSE4.1 and SSE4.2.  -mno-sse4 should the same
+    as -mno-sse4.1. */
+@@ -1155,6 +1159,19 @@ ix86_handle_option (struct gcc_options *opts,
+ 	}
+       return true;
+ 
++    case OPT_mamx_complex:
++      if (value)
++	{
++	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AMX_COMPLEX_SET;
++	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AMX_COMPLEX_SET;
++	}
++      else
++	{
++	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AMX_COMPLEX_UNSET;
++	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AMX_COMPLEX_UNSET;
++	}
++      return true;
++
+     case OPT_mfma:
+       if (value)
+ 	{
+diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
+index 7b2d4d242..56020faac 100644
+--- a/gcc/common/config/i386/i386-cpuinfo.h
++++ b/gcc/common/config/i386/i386-cpuinfo.h
+@@ -243,6 +243,7 @@ enum processor_features
+   FEATURE_X86_64_V4,
+   FEATURE_AMX_FP16,
+   FEATURE_PREFETCHI,
++  FEATURE_AMX_COMPLEX,
+   CPU_FEATURE_MAX
+ };
+ 
+diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h
+index 6caf06249..cbef68479 100644
+--- a/gcc/common/config/i386/i386-isas.h
++++ b/gcc/common/config/i386/i386-isas.h
+@@ -177,4 +177,6 @@ ISA_NAMES_TABLE_START
+   ISA_NAMES_TABLE_ENTRY("x86-64-v4", FEATURE_X86_64_V4, P_X86_64_V4, NULL)
+   ISA_NAMES_TABLE_ENTRY("amx-fp16", FEATURE_AMX_FP16, P_NONE, "-mamx-fp16")
+   ISA_NAMES_TABLE_ENTRY("prefetchi", FEATURE_PREFETCHI, P_NONE, "-mprefetchi")
++  ISA_NAMES_TABLE_ENTRY("amx-complex", FEATURE_AMX_COMPLEX,
++			P_NONE, "-mamx-complex")
+ ISA_NAMES_TABLE_END
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 9bad238e3..ca5c8f8a0 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -424,7 +424,7 @@ i[34567]86-*-* | x86_64-*-*)
+ 		       amxbf16intrin.h x86gprintrin.h uintrintrin.h
+ 		       hresetintrin.h keylockerintrin.h avxvnniintrin.h
+ 		       mwaitintrin.h avx512fp16intrin.h avx512fp16vlintrin.h
+-		       amxfp16intrin.h prfchiintrin.h"
++		       amxfp16intrin.h prfchiintrin.h amxcomplexintrin.h"
+ 	;;
+ ia64-*-*)
+ 	extra_headers=ia64intrin.h
+diff --git a/gcc/config/i386/amxcomplexintrin.h b/gcc/config/i386/amxcomplexintrin.h
+new file mode 100644
+index 000000000..6ea1eca04
+--- /dev/null
++++ b/gcc/config/i386/amxcomplexintrin.h
+@@ -0,0 +1,59 @@
++/* Copyright (C) 2023 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
++   .  */
++
++#if !defined _IMMINTRIN_H_INCLUDED
++#error "Never use  directly; include  instead."
++#endif
++
++#ifndef _AMXCOMPLEXINTRIN_H_INCLUDED
++#define _AMXCOMPLEXINTRIN_H_INCLUDED
++
++#if !defined(__AMX_COMPLEX__)
++#pragma GCC push_options
++#pragma GCC target("amx-complex")
++#define __DISABLE_AMX_COMPLEX__
++#endif /* __AMX_COMPLEX__ */
++
++#if defined(__x86_64__)
++#define _tile_cmmimfp16ps_internal(src1_dst,src2,src3)				\
++  __asm__ volatile\
++  ("{tcmmimfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmimfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::)
++
++#define _tile_cmmrlfp16ps_internal(src1_dst,src2,src3)				\
++  __asm__ volatile\
++  ("{tcmmrlfp16ps\t%%tmm"#src3", %%tmm"#src2", %%tmm"#src1_dst"|tcmmrlfp16ps\t%%tmm"#src1_dst", %%tmm"#src2", %%tmm"#src3"}" ::)
++
++#define _tile_cmmimfp16ps(src1_dst,src2,src3)					\
++  _tile_cmmimfp16ps_internal (src1_dst, src2, src3)
++
++#define _tile_cmmrlfp16ps(src1_dst,src2,src3)					\
++  _tile_cmmrlfp16ps_internal (src1_dst, src2, src3)
++
++#endif
++
++#ifdef __DISABLE_AMX_COMPLEX__
++#undef __DISABLE_AMX_COMPLEX__
++#pragma GCC pop_options
++#endif /* __DISABLE_AMX_COMPLEX__ */
++
++#endif /* _AMXCOMPLEXINTRIN_H_INCLUDED */
+diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
+index 21100149a..530a45fad 100644
+--- a/gcc/config/i386/cpuid.h
++++ b/gcc/config/i386/cpuid.h
+@@ -136,6 +136,7 @@
+ #define bit_AMX_BF16    (1 << 22)
+ #define bit_AMX_TILE    (1 << 24)
+ #define bit_AMX_INT8    (1 << 25)
++#define bit_AMX_COMPLEX (1 << 8)
+ 
+ /* Extended State Enumeration Sub-leaf (%eax == 0xd, %ecx == 1) */
+ #define bit_XSAVEOPT	(1 << 0)
+diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc
+index 04f1dd682..5e0ac278c 100644
+--- a/gcc/config/i386/i386-c.cc
++++ b/gcc/config/i386/i386-c.cc
+@@ -644,6 +644,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+     def_or_undef (parse_in, "__AMX_FP16__");
+   if (isa_flag2 & OPTION_MASK_ISA2_PREFETCHI)
+     def_or_undef (parse_in, "__PREFETCHI__");
++  if (isa_flag2 & OPTION_MASK_ISA2_AMX_COMPLEX)
++    def_or_undef (parse_in, "__AMX_COMPLEX__");
+   if (TARGET_IAMCU)
+     {
+       def_or_undef (parse_in, "__iamcu");
+diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def
+index 744a7df85..7445b1bf7 100644
+--- a/gcc/config/i386/i386-isa.def
++++ b/gcc/config/i386/i386-isa.def
+@@ -111,3 +111,4 @@ DEF_PTA(AVXVNNI)
+ DEF_PTA(AVX512FP16)
+ DEF_PTA(AMX_FP16)
+ DEF_PTA(PREFETCHI)
++DEF_PTA(AMX_COMPLEX)
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 6645e3259..7efd25084 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -233,7 +233,8 @@ static struct ix86_target_opts isa2_opts[] =
+   { "-mavxvnni",	OPTION_MASK_ISA2_AVXVNNI },
+   { "-mavx512fp16",	OPTION_MASK_ISA2_AVX512FP16 },
+   { "-mamx-fp16",       OPTION_MASK_ISA2_AMX_FP16 },
+-  { "-mprefetchi",      OPTION_MASK_ISA2_PREFETCHI }
++  { "-mprefetchi",      OPTION_MASK_ISA2_PREFETCHI },
++  { "-mamx-complex",	OPTION_MASK_ISA2_AMX_COMPLEX }
+ };
+ static struct ix86_target_opts isa_opts[] =
+ {
+@@ -1080,6 +1081,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
+     IX86_ATTR_ISA ("avx512fp16", OPT_mavx512fp16),
+     IX86_ATTR_ISA ("amx-fp16", OPT_mamx_fp16),
+     IX86_ATTR_ISA ("prefetchi",   OPT_mprefetchi),
++    IX86_ATTR_ISA ("amx-complex", OPT_mamx_complex),
+ 
+     /* enum options */
+     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 50cd114f6..fba94f3f6 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -1234,3 +1234,7 @@ Support AMX-FP16 built-in functions and code generation.
+ mprefetchi
+ Target Mask(ISA2_PREFETCHI) Var(ix86_isa_flags2) Save
+ Support PREFETCHI built-in functions and code generation.
++
++mamx-complex
++Target Mask(ISA2_AMX_COMPLEX) Var(ix86_isa_flags2) Save
++Support AMX-COMPLEX built-in functions and code generation.
+diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
+index 0447ca4b2..bd819c7f4 100644
+--- a/gcc/config/i386/immintrin.h
++++ b/gcc/config/i386/immintrin.h
+@@ -124,6 +124,8 @@
+ 
+ #include 
+ 
++#include 
++
+ #include 
+ 
+ #include 
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index ba9faf4b2..d7b0bc802 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -7048,6 +7048,11 @@ Enable/disable the generation of the AMX-FP16 instructions.
+ @cindex @code{target("prefetchi")} function attribute, x86
+ Enable/disable the generation of the PREFETCHI instructions.
+ 
++@cindex @code{target("amx-complex")} function attribute, x86
++@item amx-complex
++@itemx no-amx-complex
++Enable/disable the generation of the AMX-COMPLEX instructions.
++
+ @item cld
+ @itemx no-cld
+ @cindex @code{target("cld")} function attribute, x86
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 8ca831dc1..186b33481 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1428,7 +1428,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 -mamx-fp16 -mprefetchi @gol
++-mavx512fp16 -mamx-fp16 -mprefetchi -mamx-complex @gol
+ -mcldemote  -mms-bitfields  -mno-align-stringops  -minline-all-stringops @gol
+ -minline-stringops-dynamically  -mstringop-strategy=@var{alg} @gol
+ -mkl -mwidekl @gol
+@@ -32459,6 +32459,9 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
+ @need 200
+ @itemx -mprefetchi
+ @opindex mprefetchi
++@need 200
++@opindex mamx-complex
++@itemx -mamx-complex
+ These switches enable the use of instructions in the MMX, SSE,
+ SSE2, SSE3, SSSE3, SSE4, SSE4A, SSE4.1, SSE4.2, AVX, AVX2, AVX512F, AVX512PF,
+ AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA,
+@@ -32469,7 +32472,7 @@ 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, AVX512-FP16,
+-AMX-FP16, PREFETCHI or CLDEMOTE extended instruction sets. Each has a corresponding
++AMX-FP16, PREFETCHI, AMX-COMPLEX 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
+diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
+index c68e492dc..454fae11a 100644
+--- a/gcc/doc/sourcebuild.texi
++++ b/gcc/doc/sourcebuild.texi
+@@ -2472,6 +2472,9 @@ Target supports the execution of @code{amx-int8} instructions.
+ @item amx_bf16
+ Target supports the execution of @code{amx-bf16} instructions.
+ 
++@item amx_complex
++Target supports the execution of @code{amx-complex} instructions.
++
+ @item amx_fp16
+ Target supports the execution of @code{amx-fp16} instructions.
+ 
+diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
+index 72ed5fed0..ae1b8f632 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 -mavx512fp16 -mamx-fp16 -mprefetchi" } */
++/* { 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 -mamx-fp16 -mprefetchi -mamx-complex" } */
+ 
+ /* 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 9dd53653f..783e35774 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 -mavx512fp16 -mamx-fp16 -mprefetchi" } */
++/* { 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 -mamx-fp16 -mprefetchi -mamx-complex" } */
+ 
+ /* 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/gcc.target/i386/amx-check.h b/gcc/testsuite/gcc.target/i386/amx-check.h
+index 27dd37bf9..f1a04cf1f 100644
+--- a/gcc/testsuite/gcc.target/i386/amx-check.h
++++ b/gcc/testsuite/gcc.target/i386/amx-check.h
+@@ -216,6 +216,9 @@ main ()
+ #ifdef AMX_FP16
+       && __builtin_cpu_supports ("amx-fp16")
+ #endif
++#ifdef AMX_COMPLEX
++      && __builtin_cpu_supports ("amx-complex")
++#endif
+ #ifdef __linux__
+       && request_perm_xtile_data ()
+ #endif
+diff --git a/gcc/testsuite/gcc.target/i386/amx-helper.h b/gcc/testsuite/gcc.target/i386/amx-helper.h
+index fe24d7067..6ed9f5eb3 100644
+--- a/gcc/testsuite/gcc.target/i386/amx-helper.h
++++ b/gcc/testsuite/gcc.target/i386/amx-helper.h
+@@ -1,6 +1,6 @@
+ #ifndef AMX_HELPER_H_INCLUDED
+ #define AMX_HELPER_H_INCLUDED
+-#if defined(AMX_FP16)
++#if defined(AMX_FP16) || defined(AMX_COMPLEX)
+ #include 
+ #include 
+ #endif
+@@ -12,7 +12,7 @@ typedef union
+   uint16_t u;
+ } union16f_uw;
+ 
+-#if defined(AMX_FP16)
++#if defined(AMX_FP16) || defined(AMX_COMPLEX)
+ /* Transformation functions between fp16/float */
+ static uint16_t make_f32_fp16 (float f)
+ {
+diff --git a/gcc/testsuite/gcc.target/i386/amxcomplex-asmatt-1.c b/gcc/testsuite/gcc.target/i386/amxcomplex-asmatt-1.c
+new file mode 100644
+index 000000000..b6745e34b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxcomplex-asmatt-1.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-options "-O2 -mamx-complex" } */
++/* { dg-final { scan-assembler "tcmmimfp16ps\[ \\t]+\[^\n\]*%tmm3+\[^\n\]*%tmm2+\[^\n\]*%tmm1"  } } */
++/* { dg-final { scan-assembler "tcmmrlfp16ps\[ \\t]+\[^\n\]*%tmm3+\[^\n\]*%tmm2+\[^\n\]*%tmm1"  } } */
++#include 
++
++#define TMM1 1
++#define TMM2 2
++#define TMM3 3
++
++void TEST()
++{
++  _tile_cmmimfp16ps (TMM1, TMM2, TMM3);
++  _tile_cmmrlfp16ps (TMM1, TMM2, TMM3);
++}
+diff --git a/gcc/testsuite/gcc.target/i386/amxcomplex-asmintel-1.c b/gcc/testsuite/gcc.target/i386/amxcomplex-asmintel-1.c
+new file mode 100644
+index 000000000..305465e88
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxcomplex-asmintel-1.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-require-effective-target masm_intel } */
++/* { dg-options "-O2 -mamx-complex -masm=intel" } */
++/* { dg-final { scan-assembler "tcmmimfp16ps\[ \\t]+\[^\n\]*%tmm1+\[^\n\]*%tmm2+\[^\n\]*%tmm3"  } } */
++/* { dg-final { scan-assembler "tcmmrlfp16ps\[ \\t]+\[^\n\]*%tmm1+\[^\n\]*%tmm2+\[^\n\]*%tmm3"  } } */
++#include 
++
++void TEST()
++{
++  _tile_cmmimfp16ps (1, 2, 3);
++  _tile_cmmrlfp16ps (1, 2, 3);
++}
+diff --git a/gcc/testsuite/gcc.target/i386/amxcomplex-cmmimfp16ps-2.c b/gcc/testsuite/gcc.target/i386/amxcomplex-cmmimfp16ps-2.c
+new file mode 100644
+index 000000000..6e3762c9f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxcomplex-cmmimfp16ps-2.c
+@@ -0,0 +1,53 @@
++/* { dg-do run { target { ! ia32 } } } */
++/* { dg-require-effective-target amx_complex } */
++/* { dg-require-effective-target avx512fp16 } */
++/* { dg-options "-O2 -mamx-complex -mavx512fp16" } */
++#define AMX_COMPLEX
++#define DO_TEST test_amx_complex_cmmimfp16ps
++void test_amx_complex_cmmimfp16ps ();
++#include "amx-helper.h"
++
++void calc_matrix_cmmimfp16ps (__tile *dst, __tile *src1, __tile *src2)
++{
++  uint16_t *src1_buf = (uint16_t *) src1->buf;
++  uint16_t *src2_buf = (uint16_t *) src2->buf;
++  float *dst_buf = (float *) dst->buf;
++  
++  int M = src1->rows;
++  int N = src1->colsb / 4;
++  int K = src2->colsb / 4;
++  int i, j, k, t;
++
++  for (i = 0; i < M; i++)
++    for (j = 0; j < N; j++)
++      for (k = 0; k < K; k++)
++	for (t = 0; t < 2; t+=2)
++	  dst_buf[i * N + k] +=
++	  (make_fp16_f32(src1_buf[i * 2 * N + 2 * j + t]) *
++	    make_fp16_f32(src2_buf[j * 2 * K + 2 * k + t + 1])) +
++	  (make_fp16_f32(src1_buf[i * 2 * N + 2 * j + t + 1]) *
++	    make_fp16_f32(src2_buf[j * 2 * K + 2 * k + t]));
++}
++
++void test_amx_complex_cmmimfp16ps ()
++{
++  __tilecfg_u cfg;
++  __tile dst, dst_ref, src1, src2;
++  uint8_t tmp_dst_buf[1024], tmp_dst_zero_buf[1024];
++
++  init_fp16_max_tile_buffer (tmp_dst_buf);
++  init_fp16_max_tile_zero_buffer (tmp_dst_zero_buf);
++
++  init_tile_config (&cfg);
++  init_tile_reg_and_src_with_buffer (1, dst, tmp_dst_zero_buf);
++  init_tile_reg_and_src_with_buffer (2, src1, tmp_dst_buf);
++  init_tile_reg_and_src_with_buffer (3, src2, tmp_dst_buf);
++
++  calc_matrix_cmmimfp16ps (&dst, &src1, &src2);
++  
++  _tile_cmmimfp16ps (1, 2, 3);
++  _tile_stored (1, dst_ref.buf, _STRIDE);
++
++  if (!check_tile_register (&dst_ref, &dst))
++        abort ();
++}
+diff --git a/gcc/testsuite/gcc.target/i386/amxcomplex-cmmrlfp16ps-2.c b/gcc/testsuite/gcc.target/i386/amxcomplex-cmmrlfp16ps-2.c
+new file mode 100644
+index 000000000..15940708a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/amxcomplex-cmmrlfp16ps-2.c
+@@ -0,0 +1,53 @@
++/* { dg-do run { target { ! ia32 } } } */
++/* { dg-require-effective-target amx_complex } */
++/* { dg-require-effective-target avx512fp16 } */
++/* { dg-options "-O2 -mamx-complex -mavx512fp16" } */
++#define AMX_COMPLEX
++#define DO_TEST test_amx_complex_cmmrlfp16ps
++void test_amx_complex_cmmrlfp16ps();
++#include "amx-helper.h"
++
++void calc_matrix_cmmrlfp16ps (__tile *dst, __tile *src1, __tile *src2)
++{
++  uint16_t *src1_buf = (uint16_t *) src1->buf;
++  uint16_t *src2_buf = (uint16_t *) src2->buf;
++  float *dst_buf = (float *) dst->buf;
++  
++  int M = src1->rows;
++  int N = src1->colsb / 4;
++  int K = src2->colsb / 4;
++  int i, j, k, t;
++
++  for (i = 0; i < M; i++)
++    for (j = 0; j < N; j++)
++      for (k = 0; k < K; k++)
++	for (t = 0; t < 2; t+=2)
++	  dst_buf[i * N + k] += 
++	    (make_fp16_f32 (src1_buf[i * 2 * N + 2 * j + t]) *
++	      make_fp16_f32 (src2_buf[j * 2 * K + 2 * k + t])) -
++	    (make_fp16_f32 (src1_buf[i * 2 * N + 2 * j + t + 1]) *
++	      make_fp16_f32 (src2_buf[j * 2 * K + 2 * k + t + 1]));
++}
++
++void test_amx_complex_cmmrlfp16ps ()
++{
++  __tilecfg_u cfg;
++  __tile dst, dst_ref, src1, src2;
++  uint8_t tmp_dst_buf[1024], tmp_dst_zero_buf[1024];
++
++  init_fp16_max_tile_buffer (tmp_dst_buf);
++  init_fp16_max_tile_zero_buffer (tmp_dst_zero_buf);
++
++  init_tile_config (&cfg);
++  init_tile_reg_and_src_with_buffer (1, dst, tmp_dst_zero_buf);
++  init_tile_reg_and_src_with_buffer (2, src1, tmp_dst_buf);
++  init_tile_reg_and_src_with_buffer (3, src2, tmp_dst_buf);
++
++  calc_matrix_cmmrlfp16ps (&dst, &src1, &src2);
++  
++  _tile_cmmrlfp16ps (1, 2, 3);
++  _tile_stored (1, dst_ref.buf, _STRIDE);
++
++  if (!check_tile_register (&dst_ref, &dst))
++        abort ();
++}
+diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+index bdcfdbc88..1a2f3b83d 100644
+--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
++++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+@@ -82,6 +82,7 @@ extern void test_avxvnni (void)			__attribute__((__target__("avxvnni")));
+ extern void test_avx512fp16 (void)		__attribute__((__target__("avx512fp16")));
+ extern void test_amx_fp16 (void)		__attribute__((__target__("amx-fp16")));
+ extern void test_prefetchi (void)               __attribute__((__target__("prefetchi")));
++extern void test_amx_complex (void)		__attribute__((__target__("amx-complex")));
+ 
+ extern void test_no_sgx (void)			__attribute__((__target__("no-sgx")));
+ extern void test_no_avx5124fmaps(void)		__attribute__((__target__("no-avx5124fmaps")));
+@@ -165,6 +166,7 @@ extern void test_no_avxvnni (void)		__attribute__((__target__("no-avxvnni")));
+ extern void test_no_avx512fp16 (void)		__attribute__((__target__("no-avx512fp16")));
+ extern void test_no_amx_fp16 (void)		__attribute__((__target__("no-amx-fp16")));
+ extern void test_no_prefetchi (void)            __attribute__((__target__("no-prefetchi")));
++extern void test_no_amx_complex (void)		__attribute__((__target__("no-amx-complex")));
+ 
+ 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/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c
+index 9ab4a7e0c..d2aadd506 100644
+--- a/gcc/testsuite/gcc.target/i386/sse-12.c
++++ b/gcc/testsuite/gcc.target/i386/sse-12.c
+@@ -3,7 +3,7 @@
+    popcntintrin.h gfniintrin.h and mm_malloc.h are usable
+    with -O -std=c89 -pedantic-errors.  */
+ /* { dg-do compile } */
+-/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mamx-fp16" } */
++/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512vbmi2 -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect -mserialize -mtsxldtrk -mamx-tile -mamx-int8 -mamx-bf16 -mkl -mwidekl -mavxvnni -mamx-fp16 -mamx-complex" } */
+ 
+ #include 
+ 
+diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
+index db7c0fc7a..c39382836 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 -mavx512fp16 -mamx-fp16 -mprefetchi" } */
++/* { 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 -mamx-fp16 -mprefetchi -mamx-complex" } */
+ /* { dg-add-options bind_pic_locally } */
+ 
+ #include 
+diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
+index eaa1a8d81..c34ac1aec 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 -mavx512fp16 -mamx-fp16" } */
++/* { 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 -mamx-fp16 -mamx-complex" } */
+ /* { dg-add-options bind_pic_locally } */
+ 
+ #include 
+diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
+index 19afe639d..c3667b829 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,avx512fp16,amx-fp16")
++#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,amx-fp16,amx-complex")
+ #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,avx512fp16,amx-fp16")
++#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,amx-fp16,amx-complex")
+ #endif
+ #include 
+ test_1 (_cvtss_sh, unsigned short, float, 1)
+diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
+index 741694e87..756b6eb9c 100644
+--- a/gcc/testsuite/gcc.target/i386/sse-23.c
++++ b/gcc/testsuite/gcc.target/i386/sse-23.c
+@@ -843,6 +843,6 @@
+ #define __builtin_ia32_vpclmulqdq_v2di(A, B, C)  __builtin_ia32_vpclmulqdq_v2di(A, B, 1) 
+ #define __builtin_ia32_vpclmulqdq_v8di(A, B, C)  __builtin_ia32_vpclmulqdq_v8di(A, B, 1) 
+ 
+-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect,serialize,tsxldtrk,amx-tile,amx-int8,amx-bf16,kl,widekl,avxvnni,avx512fp16,amx-fp16,prefetchi")
++#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,amx-fp16,prefetchi,amx-complex")
+ 
+ #include 
+diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
+index 0d83c780c..d404058fd 100644
+--- a/gcc/testsuite/lib/target-supports.exp
++++ b/gcc/testsuite/lib/target-supports.exp
+@@ -9421,6 +9421,17 @@ proc check_effective_target_avxvnni { } {
+     } "-mavxvnni" ]
+ }
+ 
++# Return 1 if amx-complex instructions can be compiled.
++proc check_effective_target_amx_complex { } {
++    return [check_no_compiler_messages amx_complex object {
++	void
++	foo ()
++	{
++	  __asm__ volatile ("tcmmimfp16ps\t%%tmm1, %%tmm2, %%tmm3" ::);
++	}
++    } "-mamx-complex" ]
++}
++
+ # Return 1 if sse instructions can be compiled.
+ proc check_effective_target_sse { } {
+     return [check_no_compiler_messages sse object {
+-- 
+2.31.1
+
diff --git a/0276-i386-Add-AMX-COMPLEX-to-Granite-Rapids.patch b/0276-i386-Add-AMX-COMPLEX-to-Granite-Rapids.patch
new file mode 100644
index 0000000..5c69aff
--- /dev/null
+++ b/0276-i386-Add-AMX-COMPLEX-to-Granite-Rapids.patch
@@ -0,0 +1,30 @@
+From 40469a6119085e4c4741bcaeb9418606d28b40c4 Mon Sep 17 00:00:00 2001
+From: Haochen Jiang 
+Date: Fri, 31 Mar 2023 10:49:14 +0800
+Subject: [PATCH 22/28] i386: Add AMX-COMPLEX to Granite Rapids
+
+gcc/Changelog:
+
+	* config/i386/i386.h (PTA_GRANITERAPIDS): Add PTA_AMX_COMPLEX.
+
+(cherry picked from commit afa87bd5f7b126e20268aa959441cde2e02bba0e)
+---
+ gcc/config/i386/i386.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 75953defc..56d7794dc 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2358,7 +2358,7 @@ constexpr wide_int_bitmask PTA_ALDERLAKE = PTA_TREMONT | PTA_ADX | PTA_AVX
+   | PTA_PCONFIG | PTA_PKU | PTA_VAES | PTA_VPCLMULQDQ | PTA_SERIALIZE
+   | PTA_HRESET | PTA_KL | PTA_WIDEKL | PTA_AVXVNNI;
+ constexpr wide_int_bitmask PTA_GRANITERAPIDS = PTA_SAPPHIRERAPIDS | PTA_AMX_FP16
+-  | PTA_PREFETCHI;
++  | PTA_PREFETCHI | PTA_AMX_COMPLEX;
+ constexpr wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
+   | PTA_AVX5124FMAPS | PTA_AVX512VPOPCNTDQ;
+ constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
+-- 
+2.31.1
+
diff --git a/0277-Initial-Granite-Rapids-D-Support.patch b/0277-Initial-Granite-Rapids-D-Support.patch
new file mode 100644
index 0000000..def6e96
--- /dev/null
+++ b/0277-Initial-Granite-Rapids-D-Support.patch
@@ -0,0 +1,212 @@
+From 125e5d448538f7534e0fe3df9b7947cf41605b51 Mon Sep 17 00:00:00 2001
+From: "Mo, Zewei" 
+Date: Mon, 3 Jul 2023 11:00:26 +0800
+Subject: [PATCH 23/28] Initial Granite Rapids D Support
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h
+	(get_intel_cpu): Handle Granite Rapids D.
+	* common/config/i386/i386-common.cc:
+	(processor_alias_table): Add graniterapids-d.
+	* common/config/i386/i386-cpuinfo.h
+	(enum processor_subtypes): Add INTEL_COREI7_GRANITERAPIDS_D.
+	* config.gcc: Add -march=graniterapids-d.
+	* config/i386/driver-i386.cc (host_detect_local_cpu):
+	Handle graniterapids-d.
+	* config/i386/i386.h: (PTA_GRANITERAPIDS_D): New.
+	* doc/extend.texi: Add graniterapids-d.
+	* doc/invoke.texi: Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* g++.target/i386/mv16.C: Add graniterapids-d.
+	* gcc.target/i386/funcspec-56.inc: Handle new march.
+
+(cherry picked from commit a0cb65d34cc141571e870fb3b53b3ff47ae3338d)
+---
+ gcc/common/config/i386/cpuinfo.h              |  9 ++++++++-
+ gcc/common/config/i386/i386-common.cc         |  2 ++
+ gcc/common/config/i386/i386-cpuinfo.h         |  1 +
+ gcc/config.gcc                                |  3 ++-
+ gcc/config/i386/driver-i386.cc                |  5 ++++-
+ gcc/config/i386/i386.h                        |  4 +++-
+ gcc/doc/extend.texi                           |  3 +++
+ gcc/doc/invoke.texi                           | 11 +++++++++++
+ gcc/testsuite/g++.target/i386/mv16.C          |  6 ++++++
+ gcc/testsuite/gcc.target/i386/funcspec-56.inc |  1 +
+ 10 files changed, 41 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 39d3351db..1e53248ef 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -529,7 +529,6 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       cpu_model->__cpu_subtype = INTEL_COREI7_SAPPHIRERAPIDS;
+       break;
+     case 0xad:
+-    case 0xae:
+       /* Granite Rapids.  */
+       cpu = "graniterapids";
+       CHECK___builtin_cpu_is ("corei7");
+@@ -537,6 +536,14 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       cpu_model->__cpu_type = INTEL_COREI7;
+       cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS;
+       break;
++    case 0xae:
++      /* Granite Rapids D.  */
++      cpu = "graniterapids-d";
++      CHECK___builtin_cpu_is ("corei7");
++      CHECK___builtin_cpu_is ("graniterapids-d");
++      cpu_model->__cpu_type = INTEL_COREI7;
++      cpu_model->__cpu_subtype = INTEL_COREI7_GRANITERAPIDS_D;
++      break;
+     case 0x17:
+     case 0x1d:
+       /* Penryn.  */
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index 87e8afe9b..28f468f48 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -1993,6 +1993,8 @@ const pta processor_alias_table[] =
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
+   {"graniterapids", PROCESSOR_GRANITERAPIDS, CPU_HASWELL, PTA_GRANITERAPIDS,
+     M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS), P_PROC_AVX512F},
++  {"graniterapids-d", PROCESSOR_GRANITERAPIDS, CPU_HASWELL, PTA_GRANITERAPIDS_D,
++    M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS_D), P_PROC_AVX512F},
+   {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+     M_CPU_TYPE (INTEL_BONNELL), P_PROC_SSSE3},
+   {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h
+index 56020faac..a32f32c97 100644
+--- a/gcc/common/config/i386/i386-cpuinfo.h
++++ b/gcc/common/config/i386/i386-cpuinfo.h
+@@ -93,6 +93,7 @@ enum processor_subtypes
+   INTEL_COREI7_ROCKETLAKE,
+   AMDFAM19H_ZNVER4,
+   INTEL_COREI7_GRANITERAPIDS,
++  INTEL_COREI7_GRANITERAPIDS_D,
+   CPU_SUBTYPE_MAX
+ };
+ 
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index ca5c8f8a0..3108ac4eb 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -670,7 +670,8 @@ slm nehalem westmere sandybridge ivybridge haswell broadwell bonnell \
+ silvermont knl knm skylake-avx512 cannonlake icelake-client icelake-server \
+ skylake goldmont goldmont-plus tremont cascadelake tigerlake cooperlake \
+ sapphirerapids alderlake rocketlake eden-x2 nano nano-1000 nano-2000 nano-3000 \
+-nano-x2 eden-x4 nano-x4 x86-64 x86-64-v2 x86-64-v3 x86-64-v4 graniterapids native"
++nano-x2 eden-x4 nano-x4 x86-64 x86-64-v2 x86-64-v3 x86-64-v4 graniterapids \
++graniterapids-d native"
+ 
+ # Additional x86 processors supported by --with-cpu=.  Each processor
+ # MUST be separated by exactly one space.
+diff --git a/gcc/config/i386/driver-i386.cc b/gcc/config/i386/driver-i386.cc
+index ea8c3d8d1..e3bca4b49 100644
+--- a/gcc/config/i386/driver-i386.cc
++++ b/gcc/config/i386/driver-i386.cc
+@@ -576,8 +576,11 @@ const char *host_detect_local_cpu (int argc, const char **argv)
+ 	      /* This is unknown family 0x6 CPU.  */
+ 	      if (has_feature (FEATURE_AVX))
+ 		{
++		  /* Assume Granite Rapids D.  */
++		  if (has_feature (FEATURE_AMX_COMPLEX))
++		    cpu = "graniterapids-d";
+ 		  /* Assume Granite Rapids.  */
+-		  if (has_feature (FEATURE_AMX_FP16))
++		  else if (has_feature (FEATURE_AMX_FP16))
+ 		    cpu = "graniterapids";
+ 		  /* Assume Tiger Lake */
+ 		  else if (has_feature (FEATURE_AVX512VP2INTERSECT))
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 56d7794dc..eda3e5e5b 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2358,7 +2358,9 @@ constexpr wide_int_bitmask PTA_ALDERLAKE = PTA_TREMONT | PTA_ADX | PTA_AVX
+   | PTA_PCONFIG | PTA_PKU | PTA_VAES | PTA_VPCLMULQDQ | PTA_SERIALIZE
+   | PTA_HRESET | PTA_KL | PTA_WIDEKL | PTA_AVXVNNI;
+ constexpr wide_int_bitmask PTA_GRANITERAPIDS = PTA_SAPPHIRERAPIDS | PTA_AMX_FP16
+-  | PTA_PREFETCHI | PTA_AMX_COMPLEX;
++  | PTA_PREFETCHI;
++constexpr wide_int_bitmask PTA_GRANITERAPIDS_D = PTA_GRANITERAPIDS
++  | PTA_AMX_COMPLEX;
+ constexpr wide_int_bitmask PTA_KNM = PTA_KNL | PTA_AVX5124VNNIW
+   | PTA_AVX5124FMAPS | PTA_AVX512VPOPCNTDQ;
+ constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index d7b0bc802..674db2f1a 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -21837,6 +21837,9 @@ Intel Core i7 Rocketlake CPU.
+ @item graniterapids
+ Intel Core i7 graniterapids CPU.
+ 
++@item graniterapids-d
++Intel Core i7 graniterapids D CPU.
++
+ @item bonnell
+ Intel Atom Bonnell CPU.
+ 
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 186b33481..a2ec060fd 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -31626,6 +31626,17 @@ MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
+ SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16,
+ AVX512BF16, AMX-FP16 and PREFETCHI instruction set support.
+ 
++@item graniterapids-d
++Intel graniterapids D CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
++SSSE3, SSE4.1, SSE4.2, POPCNT, CX16, SAHF, FXSR, AVX, XSAVE, PCLMUL, FSGSBASE,
++RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW,
++AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
++AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2,
++VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB,
++MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
++SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16,
++AVX512BF16, AMX-FP16, PREFETCHI and AMX-COMPLEX instruction set support.
++
+ @item k6
+ AMD K6 CPU with MMX instruction set support.
+ 
+diff --git a/gcc/testsuite/g++.target/i386/mv16.C b/gcc/testsuite/g++.target/i386/mv16.C
+index 65cc24f32..17b1fc722 100644
+--- a/gcc/testsuite/g++.target/i386/mv16.C
++++ b/gcc/testsuite/g++.target/i386/mv16.C
+@@ -96,6 +96,10 @@ int __attribute__ ((target("arch=graniterapids"))) foo () {
+   return 26;
+ }
+ 
++int __attribute__ ((target("arch=graniterapids-d"))) foo () {
++  return 28;
++}
++
+ int main ()
+ {
+   int val = foo ();
+@@ -136,6 +140,8 @@ int main ()
+     assert (val == 24);
+   else if (__builtin_cpu_is ("graniterapids"))
+     assert (val == 25);
++  else if (__builtin_cpu_is ("graniterapids-d"))
++    assert (val == 26);
+   else
+     assert (val == 0);
+ 
+diff --git a/gcc/testsuite/gcc.target/i386/funcspec-56.inc b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+index 1a2f3b83d..f0f3397a7 100644
+--- a/gcc/testsuite/gcc.target/i386/funcspec-56.inc
++++ b/gcc/testsuite/gcc.target/i386/funcspec-56.inc
+@@ -191,6 +191,7 @@ extern void test_arch_sapphirerapids (void)	__attribute__((__target__("arch=sapp
+ extern void test_arch_alderlake (void)          __attribute__((__target__("arch=alderlake")));
+ extern void test_arch_rocketlake (void)         __attribute__((__target__("arch=rocketlake")));
+ extern void test_arch_graniterapids (void)	__attribute__((__target__("arch=graniterapids")));
++extern void test_arch_graniterapids_d (void)	__attribute__((__target__("arch=graniterapids-d")));
+ extern void test_arch_k8 (void)			__attribute__((__target__("arch=k8")));
+ extern void test_arch_k8_sse3 (void)		__attribute__((__target__("arch=k8-sse3")));
+ extern void test_arch_opteron (void)		__attribute__((__target__("arch=opteron")));
+-- 
+2.31.1
+
diff --git a/0278-Correct-Granite-Rapids-D-documentation.patch b/0278-Correct-Granite-Rapids-D-documentation.patch
new file mode 100644
index 0000000..18e756a
--- /dev/null
+++ b/0278-Correct-Granite-Rapids-D-documentation.patch
@@ -0,0 +1,48 @@
+From a809a6a416af4d08f7feeadfdd5d1f5a76a830b5 Mon Sep 17 00:00:00 2001
+From: Haochen Jiang 
+Date: Thu, 20 Jul 2023 10:47:18 +0800
+Subject: [PATCH 24/28] Correct Granite Rapids{, D} documentation
+
+gcc/Changelog:
+
+	* doc/invoke.texi: Remove AVX512VP2INTERSECT in
+	Granite Rapids{, D} from documentation.
+
+(cherry picked from commit 38daaaa91438d3f635a10bf5d5181c3b29f07df9)
+---
+ gcc/doc/invoke.texi | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index a2ec060fd..4d3eccdb2 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -31622,9 +31622,9 @@ RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW,
+ AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
+ AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2,
+ VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB,
+-MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
+-SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16,
+-AVX512BF16, AMX-FP16 and PREFETCHI instruction set support.
++MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK,
++UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512-FP16, AVX512BF16, AMX-FP16
++and PREFETCHI instruction set support.
+ 
+ @item graniterapids-d
+ Intel graniterapids D CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3,
+@@ -31633,9 +31633,9 @@ RDRND, F16C, AVX2, BMI, BMI2, LZCNT, FMA, MOVBE, HLE, RDSEED, ADCX, PREFETCHW,
+ AES, CLFLUSHOPT, XSAVEC, XSAVES, SGX, AVX512F, AVX512VL, AVX512BW, AVX512DQ,
+ AVX512CD, PKU, AVX512VBMI, AVX512IFMA, SHA, AVX512VNNI, GFNI, VAES, AVX512VBMI2,
+ VPCLMULQDQ, AVX512BITALG, RDPID, AVX512VPOPCNTDQ, PCONFIG, WBNOINVD, CLWB,
+-MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG,
+-SERIALIZE, TSXLDTRK, UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16,
+-AVX512BF16, AMX-FP16, PREFETCHI and AMX-COMPLEX instruction set support.
++MOVDIRI, MOVDIR64B, ENQCMD, CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, TSXLDTRK,
++UINTR, AMX-BF16, AMX-TILE, AMX-INT8, AVX-VNNI, AVX512FP16, AVX512BF16, AMX-FP16,
++PREFETCHI and AMX-COMPLEX instruction set support.
+ 
+ @item k6
+ AMD K6 CPU with MMX instruction set support.
+-- 
+2.31.1
+
diff --git a/0279-i386-Remove-Meteorlake-s-family_model.patch b/0279-i386-Remove-Meteorlake-s-family_model.patch
new file mode 100644
index 0000000..13e5dc9
--- /dev/null
+++ b/0279-i386-Remove-Meteorlake-s-family_model.patch
@@ -0,0 +1,30 @@
+From 62852213bc6d3e56804ca05826bb95a3a2fe4eba Mon Sep 17 00:00:00 2001
+From: "Hu, Lin1" 
+Date: Thu, 15 Dec 2022 15:51:18 +0800
+Subject: [PATCH 25/28] i386: Remove Meteorlake's family_model
+
+gcc/ChangeLog:
+
+	* common/config/i386/cpuinfo.h (get_intel_cpu): Remove case 0xb5
+	for meteorlake.
+
+(cherry picked from commit 9e74b7ec0b218364905e3e7de5c41e8148ffc61b)
+---
+ gcc/common/config/i386/cpuinfo.h | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 1e53248ef..348bc0c12 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -510,7 +510,6 @@ get_intel_cpu (struct __processor_model *cpu_model,
+       /* Alder Lake.  */
+     case 0xb7:
+       /* Raptor Lake.  */
+-    case 0xb5:
+     case 0xaa:
+     case 0xac:
+       /* Meteor Lake.  */
+-- 
+2.31.1
+
diff --git a/0280-x86-Update-model-values-for-Alderlake-Rocketlake-and.patch b/0280-x86-Update-model-values-for-Alderlake-Rocketlake-and.patch
new file mode 100644
index 0000000..4abff3f
--- /dev/null
+++ b/0280-x86-Update-model-values-for-Alderlake-Rocketlake-and.patch
@@ -0,0 +1,33 @@
+From 73042aa18fe70aa30a9c7c760b08e642560ecccd Mon Sep 17 00:00:00 2001
+From: "Cui, Lili" 
+Date: Thu, 29 Jun 2023 03:10:35 +0000
+Subject: [PATCH 26/28] x86: Update model values for Alderlake, Rocketlake and
+ Raptorlake.
+
+Update model values for Alderlake, Rocketlake and Raptorlake according to SDM.
+
+gcc/ChangeLog
+
+	* common/config/i386/cpuinfo.h (get_intel_cpu): Remove model value 0xa8
+	from Rocketlake, move model value 0xbf from Alderlake to Raptorlake.
+
+(cherry picked from commit e510c3be13a8ccdf1fc1b27c2501c126d493f335)
+---
+ gcc/common/config/i386/cpuinfo.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index 348bc0c12..f9bcb6fad 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -509,6 +509,7 @@ get_intel_cpu (struct __processor_model *cpu_model,
+     case 0x9a:
+       /* Alder Lake.  */
+     case 0xb7:
++    case 0xbf:
+       /* Raptor Lake.  */
+     case 0xaa:
+     case 0xac:
+-- 
+2.31.1
+
diff --git a/0281-x86-Update-model-values-for-Raptorlake.patch b/0281-x86-Update-model-values-for-Raptorlake.patch
new file mode 100644
index 0000000..eace6b3
--- /dev/null
+++ b/0281-x86-Update-model-values-for-Raptorlake.patch
@@ -0,0 +1,32 @@
+From 3dbe28984e0f9c24d6670cfba42983bc32c08b0a Mon Sep 17 00:00:00 2001
+From: "Cui, Lili" 
+Date: Mon, 14 Aug 2023 02:06:00 +0000
+Subject: [PATCH 27/28] x86: Update model values for Raptorlake.
+
+Update model values for Raptorlake according to SDM.
+
+gcc/ChangeLog
+
+	* common/config/i386/cpuinfo.h (get_intel_cpu): Add model value 0xba
+	to Raptorlake.
+
+(cherry picked from commit 614052dd4ea083e086712809c754ffebd9361316)
+---
+ gcc/common/config/i386/cpuinfo.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h
+index f9bcb6fad..da1568fd1 100644
+--- a/gcc/common/config/i386/cpuinfo.h
++++ b/gcc/common/config/i386/cpuinfo.h
+@@ -509,6 +509,7 @@ get_intel_cpu (struct __processor_model *cpu_model,
+     case 0x9a:
+       /* Alder Lake.  */
+     case 0xb7:
++    case 0xba:
+     case 0xbf:
+       /* Raptor Lake.  */
+     case 0xaa:
+-- 
+2.31.1
+
diff --git a/0282-Fix-target_clone-arch-graniterapids-d.patch b/0282-Fix-target_clone-arch-graniterapids-d.patch
new file mode 100644
index 0000000..54abd2e
--- /dev/null
+++ b/0282-Fix-target_clone-arch-graniterapids-d.patch
@@ -0,0 +1,159 @@
+From 8db0f3cd29bd7f937ffa01dd1100360fbbf5b6f4 Mon Sep 17 00:00:00 2001
+From: liuhongt 
+Date: Tue, 22 Aug 2023 18:18:31 +0800
+Subject: [PATCH 28/28] Fix target_clone ("arch=graniterapids-d")
+
+Both "graniterapid-d" and "graniterapids" are attached with
+PROCESSOR_GRANITERAPID in processor_alias_table but mapped to
+different __cpu_subtype in get_intel_cpu.
+
+And get_builtin_code_for_version will try to match the first
+PROCESSOR_GRANITERAPIDS in processor_alias_table which maps to
+"granitepraids" here.
+
+861      else if (new_target->arch_specified && new_target->arch > 0)
+1862        for (i = 0; i < pta_size; i++)
+1863          if (processor_alias_table[i].processor == new_target->arch)
+1864            {
+1865              const pta *arch_info = &processor_alias_table[i];
+1866              switch (arch_info->priority)
+1867                {
+1868                default:
+1869                  arg_str = arch_info->name;
+
+This mismatch makes dispatch_function_versions check the preidcate
+of__builtin_cpu_is ("graniterapids") for "graniterapids-d" and causes
+the issue.
+The patch explicitly adds PROCESSOR_GRANITERAPIDS_D to make a distinction.
+
+For "alderlake","raptorlake", "meteorlake" they share same isa, cost,
+tuning, and mapped to the same __cpu_type/__cpu_subtype in
+get_intel_cpu, so no need to add PROCESSOR_RAPTORLAKE and others.
+
+gcc/ChangeLog:
+
+	* common/config/i386/i386-common.cc (processor_names): Add new
+	member graniterapids-s.
+	* config/i386/i386-options.cc (processor_alias_table): Update
+	table with and PROCESSOR_GRANITERAPIDS_D.
+	(m_GRANITERAPID_D): New macro.
+	(m_CORE_AVX512): Add m_GRANITERAPIDS_D.
+	(processor_cost_table): Add icelake_cost for
+	PROCESSOR_GRANITERAPIDS_D.
+	* config/i386/i386.h (enum processor_type): Add new member
+	PROCESSOR_GRANITERAPIDS_D.
+	* config/i386/i386-c.cc (ix86_target_macros_internal): Handle
+	PROCESSOR_GRANITERAPIDS_D
+---
+ gcc/common/config/i386/i386-common.cc | 6 ++++--
+ gcc/config/i386/i386-c.cc             | 8 ++++++++
+ gcc/config/i386/i386-options.cc       | 4 +++-
+ gcc/config/i386/i386.h                | 3 ++-
+ 4 files changed, 17 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc
+index 28f468f48..bec6801ce 100644
+--- a/gcc/common/config/i386/i386-common.cc
++++ b/gcc/common/config/i386/i386-common.cc
+@@ -1873,6 +1873,7 @@ const char *const processor_names[] =
+   "alderlake",
+   "rocketlake",
+   "graniterapids",
++  "graniterapids-d",
+   "intel",
+   "geode",
+   "k6",
+@@ -1993,8 +1994,9 @@ const pta processor_alias_table[] =
+     M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2},
+   {"graniterapids", PROCESSOR_GRANITERAPIDS, CPU_HASWELL, PTA_GRANITERAPIDS,
+     M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS), P_PROC_AVX512F},
+-  {"graniterapids-d", PROCESSOR_GRANITERAPIDS, CPU_HASWELL, PTA_GRANITERAPIDS_D,
+-    M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS_D), P_PROC_AVX512F},
++  {"graniterapids-d", PROCESSOR_GRANITERAPIDS_D, CPU_HASWELL,
++    PTA_GRANITERAPIDS_D, M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS_D),
++    P_PROC_AVX512F},
+   {"bonnell", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+     M_CPU_TYPE (INTEL_BONNELL), P_PROC_SSSE3},
+   {"atom", PROCESSOR_BONNELL, CPU_ATOM, PTA_BONNELL,
+diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc
+index 5e0ac278c..49f0db2b8 100644
+--- a/gcc/config/i386/i386-c.cc
++++ b/gcc/config/i386/i386-c.cc
+@@ -246,6 +246,10 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+       def_or_undef (parse_in, "__graniterapids");
+       def_or_undef (parse_in, "__graniterapids__");
+       break;
++    case PROCESSOR_GRANITERAPIDS_D:
++      def_or_undef (parse_in, "__graniterapids_d");
++      def_or_undef (parse_in, "__graniterapids_d__");
++      break;
+     case PROCESSOR_ALDERLAKE:
+       def_or_undef (parse_in, "__alderlake");
+       def_or_undef (parse_in, "__alderlake__");
+@@ -254,6 +258,7 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+       def_or_undef (parse_in, "__rocketlake");
+       def_or_undef (parse_in, "__rocketlake__");
+       break;
++
+     /* use PROCESSOR_max to not set/unset the arch macro.  */
+     case PROCESSOR_max:
+       break;
+@@ -426,6 +431,9 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
+     case PROCESSOR_GRANITERAPIDS:
+       def_or_undef (parse_in, "__tune_graniterapids__");
+       break;
++    case PROCESSOR_GRANITERAPIDS_D:
++      def_or_undef (parse_in, "__tune_graniterapids_d__");
++      break;
+     case PROCESSOR_INTEL:
+     case PROCESSOR_GENERIC:
+       break;
+diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
+index 7efd25084..86932d719 100644
+--- a/gcc/config/i386/i386-options.cc
++++ b/gcc/config/i386/i386-options.cc
+@@ -128,10 +128,11 @@ along with GCC; see the file COPYING3.  If not see
+ #define m_ALDERLAKE (HOST_WIDE_INT_1U<
+Date: Mon, 22 Jul 2024 14:06:18 +0800
+Subject: [PATCH 1/2] i386: Change prefetchi output template
+
+For prefetchi instructions, RIP-relative address is explicitly mentioned
+for operand and assembler obeys that rule strictly. This makes
+instruction like:
+
+	prefetchit0	bar
+
+got illegal for assembler, which should be a broad usage for prefetchi.
+
+Change to %a to explicitly add (%rip) after function label to make it
+legal in assembler so that it could pass to linker to get the real address.
+
+gcc/ChangeLog:
+
+	* config/i386/i386.md (prefetchi): Change to %a.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/prefetchi-1.c: Check (%rip).
+
+Reference:
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=
+062e46a813799684c6f900815fd22451d6294ae1
+---
+ gcc/config/i386/i386.md                     | 2 +-
+ gcc/testsuite/gcc.target/i386/prefetchi-1.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index f08c2cfb1..1b733008e 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -22917,7 +22917,7 @@
+   "TARGET_PREFETCHI && TARGET_64BIT"
+ {
+   static const char * const patterns[2] = {
+-    "prefetchit1\t%0", "prefetchit0\t%0"
++    "prefetchit1\t%a0", "prefetchit0\t%a0"
+   };
+ 
+   int locality = INTVAL (operands[1]);
+diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-1.c b/gcc/testsuite/gcc.target/i386/prefetchi-1.c
+index 80f25e70e..03dfdc55e 100644
+--- a/gcc/testsuite/gcc.target/i386/prefetchi-1.c
++++ b/gcc/testsuite/gcc.target/i386/prefetchi-1.c
+@@ -1,7 +1,7 @@
+ /* { dg-do compile { target { ! ia32 } } } */
+ /* { dg-options "-mprefetchi -O2" } */
+-/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+" 2 } } */
+-/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+" 2 } } */
++/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+bar\\(%rip\\)" 2 } } */
++/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+bar\\(%rip\\)" 2 } } */
+ 
+ #include 
+ 
+-- 
+2.31.1
+
diff --git a/0284-i386-Add-non-optimize-prefetchi-intrins.patch b/0284-i386-Add-non-optimize-prefetchi-intrins.patch
new file mode 100644
index 0000000..2a450e8
--- /dev/null
+++ b/0284-i386-Add-non-optimize-prefetchi-intrins.patch
@@ -0,0 +1,92 @@
+From c19afda0ee549d294fd5714c63db24bcd4570d03 Mon Sep 17 00:00:00 2001
+From: Haochen Jiang 
+Date: Thu, 25 Jul 2024 16:16:05 +0800
+Subject: [PATCH 2/2] i386: Add non-optimize prefetchi intrins
+
+Under -O0, with the "newly" introduced intrins, the variable will be
+transformed as mem instead of the origin symbol_ref. The compiler will
+then treat the operand as invalid and turn the operation into nop, which
+is not expected. Use macro for non-optimize to keep the variable as
+symbol_ref just as how prefetch intrin does.
+
+gcc/ChangeLog:
+
+	* config/i386/prfchiintrin.h
+	(_m_prefetchit0): Add macro for non-optimized option.
+	(_m_prefetchit1): Ditto.
+
+gcc/testsuite/ChangeLog:
+
+	* gcc.target/i386/prefetchi-1b.c: New test.
+
+Reference:
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=
+b4524c4430ba9771265bd9fc31e69a3f35dfe117
+---
+ gcc/config/i386/prfchiintrin.h               |  9 +++++++
+ gcc/testsuite/gcc.target/i386/prefetchi-1b.c | 26 ++++++++++++++++++++
+ 2 files changed, 35 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/i386/prefetchi-1b.c
+
+diff --git a/gcc/config/i386/prfchiintrin.h b/gcc/config/i386/prfchiintrin.h
+index 06deef488..1e3d42dc3 100644
+--- a/gcc/config/i386/prfchiintrin.h
++++ b/gcc/config/i386/prfchiintrin.h
+@@ -30,6 +30,7 @@
+ 
+ #ifdef __x86_64__
+ 
++#ifdef __OPTIMIZE__
+ extern __inline void
+ __attribute__((__gnu_inline__, __always_inline__, __artificial__))
+ _m_prefetchit0 (void* __P)
+@@ -43,6 +44,14 @@ _m_prefetchit1 (void* __P)
+ {
+   __builtin_ia32_prefetchi (__P, 2);
+ }
++#else
++#define _m_prefetchit0(P)	\
++  __builtin_ia32_prefetchi(P, 3)
++
++#define _m_prefetchit1(P)	\
++  __builtin_ia32_prefetchi(P, 2)
++
++#endif
+ 
+ #endif
+ 
+diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-1b.c b/gcc/testsuite/gcc.target/i386/prefetchi-1b.c
+new file mode 100644
+index 000000000..93139554d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/prefetchi-1b.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile { target { ! ia32 } } } */
++/* { dg-options "-mprefetchi -O0" } */
++/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+bar\\(%rip\\)" 1 } } */
++/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+bar\\(%rip\\)" 1 } } */
++
++#include 
++
++int
++bar (int a)
++{
++  return a + 1;
++}
++
++int
++foo1 (int b)
++{
++  _m_prefetchit0 (bar);
++  return bar (b) + 1;
++}
++
++int
++foo2 (int b)
++{
++  _m_prefetchit1 (bar);
++  return bar (b) + 1;
++}
+-- 
+2.31.1
+
diff --git a/0285-SME-Recover-hip09-and-hip11-in-aarch64-cores.def.patch b/0285-SME-Recover-hip09-and-hip11-in-aarch64-cores.def.patch
new file mode 100644
index 0000000..24dacd1
--- /dev/null
+++ b/0285-SME-Recover-hip09-and-hip11-in-aarch64-cores.def.patch
@@ -0,0 +1,32 @@
+From 239f0637307ff2f6afb1473e99d0bb0eaf8946b2 Mon Sep 17 00:00:00 2001
+From: xiezhiheng 
+Date: Fri, 23 Aug 2024 15:37:17 +0800
+Subject: [PATCH 154/157] [SME] Recover hip09 and hip11 in aarch64-cores.def
+
+---
+ gcc/config/aarch64/aarch64-cores.def | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
+index f069c81cf..3337fd1a0 100644
+--- a/gcc/config/aarch64/aarch64-cores.def
++++ b/gcc/config/aarch64/aarch64-cores.def
+@@ -130,6 +130,7 @@ AARCH64_CORE("a64fx", a64fx, a64fx, V8_2A,  (F16, SVE), a64fx, 0x46, 0x001, -1)
+ 
+ /* HiSilicon ('H') cores. */
+ AARCH64_CORE("tsv110",  tsv110, tsv110, V8_2A,  (CRYPTO, F16), tsv110,   0x48, 0xd01, -1)
++AARCH64_CORE("hip09", hip09, hip09, V8_5A,  (SVE, I8MM, F32MM, F64MM, PROFILE, PREDRES), hip09, 0x48, 0xd02, 0x0)
+ 
+ /* ARMv8.3-A Architecture Processors.  */
+ 
+@@ -171,6 +172,7 @@ AARCH64_CORE("cortex-a710",  cortexa710, cortexa57, V9A,  (SVE2_BITPERM, MEMTAG,
+ AARCH64_CORE("cortex-x2",  cortexx2, cortexa57, V9A,  (SVE2_BITPERM, MEMTAG, I8MM, BF16), neoversen2, 0x41, 0xd48, -1)
+ 
+ AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversen2, 0x41, 0xd49, -1)
++AARCH64_CORE("hip11", hip11, hip11, V8_5A,  (SVE, SVE2, F16), hip11, 0x48, 0xd22, -1)
+ 
+ AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1)
+ AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1)
+-- 
+2.33.0
+
diff --git a/0286-Try-to-use-AI-model-to-guide-optimization.patch b/0286-Try-to-use-AI-model-to-guide-optimization.patch
new file mode 100644
index 0000000..a697dcc
--- /dev/null
+++ b/0286-Try-to-use-AI-model-to-guide-optimization.patch
@@ -0,0 +1,671 @@
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index fcfa54697..f42aeb8e8 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1449,6 +1449,7 @@ OBJS = \
+ 	inchash.o \
+ 	incpath.o \
+ 	init-regs.o \
++	ipa-hardware-detection.o \
+ 	internal-fn.o \
+ 	ipa-struct-reorg/ipa-struct-reorg.o \
+ 	ipa-cp.o \
+diff --git a/gcc/common.opt b/gcc/common.opt
+index fd98382fa..99e626641 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -185,6 +185,9 @@ const char *main_input_basename
+ Variable
+ int main_input_baselength
+ 
++Variable
++bool optimize_maximum
++
+ ; The base name used for auxiliary output files.
+ ; dump_base_name minus dump_base_ext.
+ 
+@@ -469,6 +472,10 @@ Ofast
+ Common Optimization
+ Optimize for speed disregarding exact standards compliance.
+ 
++Om
++Common Optimization
++Optimize for maximizing radical optimization.
++
+ Og
+ Common Optimization
+ Optimize for debugging experience rather than speed or size.
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 309ecc3d9..ad853af9a 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -18637,6 +18637,134 @@ aarch64_sve_adjust_stmt_cost (class vec_info *vinfo, vect_cost_for_stmt kind,
+   return stmt_cost;
+ }
+ 
++/* Check whether in C language or LTO with only C language.  */
++extern bool lang_c_p (void);
++
++static void
++override_C_optimize_options (struct gcc_options *opts)
++{
++  opts->x_flag_ipa_reorder_fields = 1;
++  opts->x_flag_ipa_struct_reorg = 6;
++  opts->x_struct_layout_optimize_level = 6;
++  opts->x_flag_gnu89_inline = 1;
++  opts->x_flag_ccmp2 = 1;
++  opts->x_flag_array_widen_compare = 1;
++  opts->x_flag_convert_minmax = 1;
++  opts->x_flag_tree_slp_transpose_vectorize = 1;
++  opts->x_param_max_inline_insns_auto = 64;
++  opts->x_param_inline_unit_growth = 96;
++}
++
++/* Check whether in CPP language or LTO with only CPP language.  */
++static bool
++lang_cpp_p (void)
++{
++  const char *language_string = lang_hooks.name;
++  if (!language_string)
++    {
++      return false;
++    }
++  if (lang_GNU_CXX ())
++    {
++      return true;
++    }
++  else if (strcmp (language_string, "GNU GIMPLE") == 0) // for LTO check
++    {
++      unsigned i = 0;
++      tree t = NULL_TREE;
++      FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, t)
++	{
++	  language_string = TRANSLATION_UNIT_LANGUAGE (t);
++	  if (language_string == NULL
++	      || strncmp (lang_hooks.name, "GNU C++", 7))
++	    {
++	      return false;
++	    }
++	}
++      return true;
++    }
++  return false;
++}
++
++static void
++override_CPP_optimize_options (struct gcc_options *opts)
++{
++  opts->x_flag_finite_loops = 1;
++  opts->x_flag_omit_frame_pointer = 1;
++  opts->x_flag_sized_deallocation = 0;
++  opts->x_flag_loop_elim = 1;
++  opts->x_flag_convert_minmax = 1;
++  opts->x_param_early_inlining_insns = 256;
++  opts->x_param_max_inline_insns_auto = 128;
++  opts->x_param_inline_unit_growth = 256;
++  opts->x_flag_cmlt_arith = 1;
++}
++
++static void
++override_optimize_options_1 (struct gcc_options *opts)
++{
++  opts->x_flag_split_ldp_stp = 1;
++  opts->x_flag_if_conversion_gimple = 1;
++  opts->x_flag_ifcvt_allow_complicated_cmps = 1;
++  opts->x_param_ifcvt_allow_register_renaming = 2;
++  opts->x_param_max_rtl_if_conversion_unpredictable_cost = 48;
++  opts->x_param_max_rtl_if_conversion_predictable_cost = 48;
++}
++
++static void
++override_Fortran_optimize_options (struct gcc_options *opts)
++{
++  opts->x_flag_unroll_loops = 1;
++  opts->x_flag_unconstrained_commons = 1;
++  opts->x_param_ipa_cp_eval_threshold = 1;
++  opts->x_param_ipa_cp_unit_growth = 80;
++  opts->x_param_ipa_cp_max_recursive_depth = 8;
++  opts->x_param_large_unit_insns = 30000;
++  opts->x_flag_ira_loop_pressure = 1;
++  opts->x_flag_inline_functions_called_once = 0;
++  opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
++  opts->x_flag_delayed_branch = 1;
++  opts->x_flag_gcse_las = 1;
++  opts->x_flag_gcse_sm = 1;
++  opts->x_flag_ipa_pta = 1;
++  opts->x_flag_reorder_blocks_and_partition = 1;
++  opts->x_flag_reorder_blocks = 1;
++  opts->x_flag_crypto_accel_aes = 1;
++  opts->x_param_flexible_seg_len = 1;
++}
++
++/* Reset the optimize option.
++   After checking the model result, this function can
++   reset the more appropriate options.  */
++static void
++reset_machine_option (struct gcc_options *opts)
++{
++  if (!(opts->x_optimize_maximum)
++      || strstr (opts->x_aarch64_tune_string, "hip09") == NULL)
++    {
++      return;
++    }
++
++  const char *ai_infer_level = getenv ("AI_INFER_LEVEL");
++  if (ai_infer_level)
++    {
++      override_optimize_options_1 (opts);
++      if (lang_c_p ())
++	{
++	  override_C_optimize_options (opts);
++	}
++      else if (lang_cpp_p ())
++	{
++	  override_CPP_optimize_options (opts);
++	}
++      else if (lang_GNU_Fortran ())
++	{
++	  override_Fortran_optimize_options (opts);
++	}
++    }
++}
++
++
+ /* STMT_COST is the cost calculated for STMT_INFO, which has cost kind KIND
+    and which when vectorized would operate on vector type VECTYPE.  Add the
+    cost of any embedded operations.  */
+@@ -20089,6 +20217,7 @@ aarch64_override_options_internal (struct gcc_options *opts)
+       && opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level)
+     opts->x_flag_prefetch_loop_arrays = 1;
+ 
++  reset_machine_option (opts);
+   aarch64_override_options_after_change_1 (opts);
+ }
+ 
+diff --git a/gcc/ipa-hardware-detection.cc b/gcc/ipa-hardware-detection.cc
+new file mode 100644
+index 000000000..8085a8c65
+--- /dev/null
++++ b/gcc/ipa-hardware-detection.cc
+@@ -0,0 +1,243 @@
++/* Hardware Detection.
++   Copyright (C) 2024-2024 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
++.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "backend.h"
++#include "target.h"
++#include "tree.h"
++#include "gimple.h"
++#include "tree-pass.h"
++#include "gimple-ssa.h"
++#include "tree-pretty-print.h"
++#include "fold-const.h"
++#include "gimplify.h"
++#include "gimple-iterator.h"
++#include "tree-ssa-loop-manip.h"
++#include "tree-ssa-loop.h"
++#include "ssa.h"
++#include "tree-into-ssa.h"
++#include "cfganal.h"
++#include "cfgloop.h"
++#include "gimple-pretty-print.h"
++#include "tree-cfg.h"
++#include "cgraph.h"
++#include "print-tree.h"
++#include "cfghooks.h"
++#include "gimple-fold.h"
++#include "gimplify-me.h"
++
++namespace {
++
++/* Build a binary operation and gimplify it.  Emit code before GSI.
++   Return the gimple_val holding the result.  */
++
++static tree
++gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
++		 tree type, tree a, tree b)
++{
++  tree ret;
++
++  ret = fold_build2_loc (gimple_location (gsi_stmt (*gsi)), code, type, a, b);
++  return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
++				   GSI_SAME_STMT);
++}
++
++static basic_block
++create_abort_bb (basic_block last_bb)
++{
++  basic_block bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  gimple_stmt_iterator gsi = gsi_last_bb (bb);
++  tree fn = builtin_decl_implicit (BUILT_IN_ABORT);
++  gimple *g = gimple_build_call (fn, 0);
++  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
++  return bb;
++}
++
++static basic_block
++create_part_bb (basic_block last_bb, tree part_base)
++{
++  basic_block bb = create_empty_bb (last_bb);
++  if (last_bb->loop_father != NULL)
++    {
++      add_bb_to_loop (bb, last_bb->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  gimple_stmt_iterator gsi = gsi_last_bb (bb);
++  gsi_insert_after (&gsi, gimple_build_nop (), GSI_NEW_STMT);
++  /* This number is used to efficiently identify the supported part range.  */
++  tree part_cond = gimplify_build2 (
++		     &gsi, PLUS_EXPR, unsigned_type_node, part_base,
++		     build_int_cst (unsigned_type_node, 4294963967));
++  gcond *cond = gimple_build_cond (LE_EXPR, part_cond,
++				   build_int_cst (unsigned_type_node, 2),
++				   NULL_TREE, NULL_TREE);
++  gimple_set_location (cond, input_location);
++  gsi_insert_before (&gsi, cond, GSI_SAME_STMT);
++  gsi_remove (&gsi, true);
++  return bb;
++}
++
++static void
++create_detection_bb ()
++{
++  edge old_e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
++  basic_block ret_bb = old_e->dest;
++
++  basic_block detection_bb = create_empty_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
++  if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father != NULL)
++    {
++      add_bb_to_loop (detection_bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father);
++      loops_state_set (LOOPS_NEED_FIXUP);
++    }
++  tree cpuid_decl = build_decl (input_location, VAR_DECL,
++				get_identifier ("cpuid"), unsigned_type_node);
++  add_local_decl (cfun, cpuid_decl);
++
++  gimple_stmt_iterator gsi = gsi_last_bb (detection_bb);
++  vec *outputs = NULL;
++  tree purpose = build_string (strlen ("=r"), "=r");
++  tree output = build_tree_list (
++		  build_tree_list (NULL_TREE, purpose), cpuid_decl);
++  vec_safe_push (outputs, output);
++  gasm *asm_stmt = gimple_build_asm_vec (
++		     "mrs %0, MIDR_EL1", NULL, outputs, NULL, NULL);
++  gsi_insert_after (&gsi, asm_stmt, GSI_NEW_STMT);
++  gsi_insert_after (&gsi, gimple_build_nop (), GSI_NEW_STMT);
++
++  tree implementer = gimplify_build2 (
++		       &gsi, RSHIFT_EXPR, unsigned_type_node, cpuid_decl,
++		       build_int_cst (unsigned_type_node, 24));
++  tree part_base = gimplify_build2 (
++		     &gsi, RSHIFT_EXPR, unsigned_type_node, cpuid_decl,
++		     build_int_cst (unsigned_type_node, 4));
++  tree part = gimplify_build2 (
++		&gsi, BIT_AND_EXPR, unsigned_type_node, part_base,
++		build_int_cst (unsigned_type_node, 4095));
++  gcond *implementer_cond = gimple_build_cond (
++			      EQ_EXPR, implementer,
++			      build_int_cst (unsigned_type_node, 72),
++			      NULL_TREE, NULL_TREE);
++  gimple_set_location (implementer_cond, input_location);
++  gsi_insert_before (&gsi, implementer_cond, GSI_SAME_STMT);
++  gsi_remove (&gsi, true);
++
++  basic_block part_bb = create_part_bb (detection_bb, part);
++  basic_block abort_bb = create_abort_bb (part_bb);
++
++  remove_edge_raw (old_e);
++  make_single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun),
++			 detection_bb, EDGE_FALLTHRU);
++  edge etrue = make_edge (detection_bb, part_bb, EDGE_TRUE_VALUE);
++  etrue->probability = profile_probability::likely ();
++  edge efalse = make_edge (detection_bb, abort_bb, EDGE_FALSE_VALUE);
++  efalse->probability = profile_probability::unlikely ();
++  edge part_true = make_edge (part_bb, ret_bb, EDGE_TRUE_VALUE);
++  part_true->probability = profile_probability::likely ();
++  edge part_false = make_edge (part_bb, abort_bb, EDGE_FALSE_VALUE);
++  part_false->probability = profile_probability::unlikely ();
++  make_single_succ_edge (abort_bb, ret_bb, EDGE_FALLTHRU);
++  if (dom_info_available_p (CDI_DOMINATORS))
++    {
++      set_immediate_dominator (CDI_DOMINATORS, part_bb, detection_bb);
++      set_immediate_dominator (CDI_DOMINATORS, ret_bb, detection_bb);
++      set_immediate_dominator (CDI_DOMINATORS, abort_bb, detection_bb);
++    }
++}
++
++const pass_data pass_data_ipa_hardware_detection =
++{
++  SIMPLE_IPA_PASS,
++  "hardware_detection",
++  OPTGROUP_NONE,
++  TV_IPA_HARDWARE_DETECTION,
++  (PROP_cfg | PROP_ssa),
++  0,
++  0,
++  0,
++  (TODO_update_ssa | TODO_verify_all)
++};
++
++class pass_ipa_hardware_detection : public simple_ipa_opt_pass
++{
++public:
++  pass_ipa_hardware_detection (gcc::context *ctxt)
++    : simple_ipa_opt_pass (pass_data_ipa_hardware_detection, ctxt)
++  {}
++
++  virtual bool gate (function *);
++  virtual unsigned int execute (function *);
++}; // class pass_ipa_hardware_detection
++
++bool
++pass_ipa_hardware_detection::gate (function *)
++{
++  const char *ai_infer_level = getenv ("AI_INFER_LEVEL");
++  return (ai_infer_level
++	  && optimize_maximum > 0
++	  /* Only enable in lto or whole_program.  */
++	  && (in_lto_p || flag_whole_program));
++}
++
++unsigned int
++pass_ipa_hardware_detection::execute (function *)
++{
++  unsigned int ret = 0;
++  cgraph_node *cnode;
++  FOR_EACH_FUNCTION (cnode)
++    {
++      if (!cnode->real_symbol_p ())
++	{
++	  continue;
++	}
++      if (cnode->definition)
++	{
++	  if (!cnode->has_gimple_body_p () || cnode->inlined_to)
++	      continue;
++
++	  cnode->get_body ();
++	  function *fn = DECL_STRUCT_FUNCTION (cnode->decl);
++	  if (!fn)
++	      continue;
++
++	  if (DECL_NAME (cnode->decl)
++      	      && MAIN_NAME_P (DECL_NAME (cnode->decl)))
++	    {
++	      push_cfun (fn);
++	      calculate_dominance_info (CDI_DOMINATORS);
++
++	      create_detection_bb ();
++
++	      cgraph_edge::rebuild_edges ();
++	      free_dominance_info (CDI_DOMINATORS);
++	      pop_cfun ();
++	    }
++	}
++    }
++  return ret;
++}
++} // anon namespace
++
++simple_ipa_opt_pass *
++make_pass_ipa_hardware_detection (gcc::context *ctxt)
++{
++  return new pass_ipa_hardware_detection (ctxt);
++}
+diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
+index 489a6e02a..12c3f7299 100644
+--- a/gcc/opts-common.cc
++++ b/gcc/opts-common.cc
+@@ -992,6 +992,158 @@ opts_concat (const char *first, ...)
+   return newstr;
+ }
+ 
++typedef int64_t (*run_ai_model_func)(int, const char **,
++				     const char *, int, int64_t *);
++#define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
++#define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
++#define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
++
++static int64_t
++ai_infer_optimization (int argc, const char **argv,
++		       const char *mcpu_option,
++		       int argc_hw, int64_t *argv_hw)
++{
++  /* Load dependent AI-framework libraries.  */
++  void *onnxruntime_lib_handle = NULL;
++  const char *onnxruntime_lib_path = "libonnxruntime.so";
++
++  onnxruntime_lib_handle = dlopen (onnxruntime_lib_path,
++				   RTLD_LAZY | RTLD_GLOBAL);
++  if (!onnxruntime_lib_handle)
++    {
++      return -1;
++    }
++
++  void *ai4c_lib_handle = NULL;
++  const char *ai4c_lib_path = "libONNXRunner.so";
++
++  ai4c_lib_handle = dlopen (ai4c_lib_path, RTLD_LAZY | RTLD_GLOBAL);
++  if (!ai4c_lib_handle)
++    {
++      return -1;
++    }
++
++  /* Clear any existing error.  */
++  dlerror ();
++
++  /* Run AI4Compiler model.  */
++  if (ai4c_lib_handle == NULL || onnxruntime_lib_handle == NULL)
++    {
++      return -1;
++    }
++
++  run_ai_model_func run_ai_model;
++  PTR_UNION_TYPE (run_ai_model_func) run_ai_model_func_union;
++  PTR_UNION_AS_VOID_PTR (run_ai_model_func_union)
++    = dlsym (ai4c_lib_handle, "runONNXModelOptimizer");
++  run_ai_model = PTR_UNION_AS_CAST_PTR (run_ai_model_func_union);
++  if (!run_ai_model)
++    {
++      dlclose (ai4c_lib_handle);
++      dlclose (onnxruntime_lib_handle);
++      return -1;
++    }
++  int64_t model_pred = (*run_ai_model) (argc, argv,
++					mcpu_option, argc_hw, argv_hw);
++
++  if (ai4c_lib_handle)
++    dlclose (ai4c_lib_handle);
++
++  if (onnxruntime_lib_handle)
++    dlclose (onnxruntime_lib_handle);
++
++  if (model_pred == 1)
++    putenv ("AI_INFER_LEVEL=1");
++  return model_pred;
++}
++
++static int
++handle_lto_option (unsigned int lang_mask,
++		   unsigned int num_decoded_options,
++		   unsigned int argc,
++		   const char **argv,
++		   struct cl_decoded_option *&opt_array)
++{
++  int ret = 0;
++  char *lan = "";
++  char *compiler = xstrdup (argv[0]);
++  lan = strrchr (compiler, '/');
++  if (lan != NULL)
++    lan ++;
++  else
++    lan = compiler;
++  if (strstr (lan, "gcc") != NULL)
++    {
++      opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array, argc + 2);
++      const char* lto_flag = "-flto=8";
++      decode_cmdline_option (<o_flag, lang_mask,
++			     &opt_array[num_decoded_options]);
++      ret++;
++      const char* ltopartition_flag = "-flto-partition=one";
++      decode_cmdline_option (<opartition_flag, lang_mask,
++			     &opt_array[num_decoded_options + 1]);
++      ret++;
++    }
++  else if (strstr (lan, "g++") != NULL
++	   || strstr (lan, "gfortran") != NULL)
++    {
++      opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array, argc + 1);
++      const char* lto_flag = "-flto=8";
++      decode_cmdline_option (<o_flag, lang_mask,
++			     &opt_array[num_decoded_options]);
++      ret++;
++    }
++  if (compiler)
++    free (compiler);
++  return ret;
++}
++
++static int
++handle_machine_option (unsigned int lang_mask,
++		       unsigned int num_decoded_options,
++		       unsigned int argc,
++		       const char **argv,
++		       struct cl_decoded_option *&opt_array)
++{
++  int ret = 0;
++  bool flag_Om = false;
++  bool flag_hip09 = false;
++  for (unsigned i = 1; i < argc; i ++)
++    {
++      if (strcmp (argv[i], "-Om") == 0)
++	flag_Om = true;
++      if (strstr (argv[i], "mcpu=hip09") != NULL)
++	flag_hip09 = true;
++    }
++  if (!flag_hip09 || !flag_Om)
++    {
++      return ret;
++    }
++
++  const char *ai_infer_level = getenv ("AI_INFER_LEVEL");
++  if (ai_infer_level)
++    {
++      return ret;
++    }
++  int argc_hw = 6;
++  int64_t argv_hw[argc_hw] = {
++    global_options.x_param_simultaneous_prefetches,
++    global_options.x_param_l1_cache_size,
++    global_options.x_param_l1_cache_line_size,
++    global_options.x_param_l2_cache_size,
++    global_options.x_param_prefetch_latency,
++    global_options.x_param_ipa_prefetch_distance_factor};
++  int64_t output_pred = ai_infer_optimization (
++			  argc, argv, "hip09", argc_hw, argv_hw);
++  if (output_pred != 1)
++    {
++      return ret;
++    }
++
++  return handle_lto_option (lang_mask, num_decoded_options,
++			    argc, argv, opt_array);
++}
++
+ /* Decode command-line options (ARGC and ARGV being the arguments of
+    main) into an array, setting *DECODED_OPTIONS to a pointer to that
+    array and *DECODED_OPTIONS_COUNT to the number of entries in the
+@@ -1090,6 +1242,9 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv,
+       num_decoded_options++;
+     }
+ 
++  num_decoded_options += handle_machine_option (lang_mask, num_decoded_options,
++						argc, argv, opt_array);
++
+   *decoded_options = opt_array;
+   *decoded_options_count = num_decoded_options;
+   prune_options (decoded_options, decoded_options_count, lang_mask);
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index e34e5ee8e..d97f6079f 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -780,6 +780,14 @@ default_options_optimization (struct gcc_options *opts,
+ 	  opts->x_optimize_debug = 1;
+ 	  break;
+ 
++	case OPT_Om:
++	  /* -Om adds flags to -O3.  */
++	  opts->x_optimize_size = 0;
++	  opts->x_optimize = 3;
++	  opts->x_optimize_maximum = true;
++	  opts->x_optimize_debug = 0;
++	  break;
++
+ 	case OPT_fopenacc:
+ 	  if (opt->value)
+ 	    openacc_mode = true;
+@@ -2733,6 +2741,8 @@ common_handle_option (struct gcc_options *opts,
+ 	  &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
+       break;
+ 
++    case OPT_Om:
++      break;
+     case OPT_O:
+     case OPT_Os:
+     case OPT_Ofast:
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 8797f166f..690d344c0 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -179,6 +179,7 @@ along with GCC; see the file COPYING3.  If not see
+      passes are executed after partitioning and thus see just parts of the
+      compiled unit.  */
+   INSERT_PASSES_AFTER (all_late_ipa_passes)
++  NEXT_PASS (pass_ipa_hardware_detection);
+   NEXT_PASS (pass_ipa_pta);
+   /* FIXME: this should be a normal IP pass.  */
+   NEXT_PASS (pass_ipa_struct_reorg);
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 8e7510eb3..bd8c9a4f7 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -81,6 +81,7 @@ DEFTIMEVAR (TV_IPA_CONSTANT_PROP     , "ipa cp")
+ DEFTIMEVAR (TV_IPA_INLINING          , "ipa inlining heuristics")
+ DEFTIMEVAR (TV_IPA_FNSPLIT           , "ipa function splitting")
+ DEFTIMEVAR (TV_IPA_COMDATS	     , "ipa comdats")
++DEFTIMEVAR (TV_IPA_HARDWARE_DETECTION, "ipa detection")
+ DEFTIMEVAR (TV_IPA_PREFETCH	     , "ipa prefetch")
+ DEFTIMEVAR (TV_IPA_STRUCT_REORG      , "ipa struct reorg optimization")
+ DEFTIMEVAR (TV_IPA_OPT		     , "ipa various optimizations")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 1c983ef71..ee873f0b2 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -528,6 +528,8 @@ extern ipa_opt_pass_d *make_pass_ipa_icp (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt);
++extern simple_ipa_opt_pass *make_pass_ipa_hardware_detection (gcc::context *
++							      ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_prefetch (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_struct_reorg (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt);
diff --git a/0287-Add-dynamic-memory-access-checks.patch b/0287-Add-dynamic-memory-access-checks.patch
new file mode 100644
index 0000000..e23d8f6
--- /dev/null
+++ b/0287-Add-dynamic-memory-access-checks.patch
@@ -0,0 +1,774 @@
+From 08fb60d0a0707af4004b20358f4a921e4ae6cca6 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Thu, 22 Aug 2024 15:23:36 +0800
+Subject: [PATCH 156/157] Add dynamic memory access checks
+
+Signed-off-by: Diachkov Ilia 
+---
+ gcc/ipa-prefetch.cc | 622 +++++++++++++++++++++++++++++++++++++-------
+ gcc/params.opt      |   4 +
+ 2 files changed, 525 insertions(+), 101 deletions(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index 94290ea9c..b000d4d75 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -368,6 +368,7 @@ typedef std::map memref_tree_map;
+ typedef std::set stmt_set;
+ typedef std::set tree_set;
+ typedef std::map tree_map;
++typedef std::map tree_poly_offset_map;
+ 
+ tree_memref_map *tm_map;
+ funct_mrs_map *fmrs_map;
+@@ -710,6 +711,20 @@ get_mem_ref_address_ssa_name (tree mem, tree base)
+   return NULL_TREE;
+ }
+ 
++static void
++dump_base_addr (tree base_addr)
++{
++  if (base_addr)
++    {
++      fprintf (dump_file, "Base addr (%s): ",
++	      get_tree_code_name (TREE_CODE (base_addr)));
++      print_generic_expr (dump_file, base_addr);
++    }
++  else
++    fprintf (dump_file, "Base addr (%s): ", "null");
++  fprintf (dump_file, "\n");
++}
++
+ static void
+ analyse_mem_ref (gimple *stmt, tree mem, memref_t* mr)
+ {
+@@ -736,14 +751,7 @@ analyse_mem_ref (gimple *stmt, tree mem, memref_t* mr)
+       {
+ 	tree base_addr = get_mem_ref_address_ssa_name (mem, base);
+ 	if (dump_file)
+-	  {
+-	    fprintf (dump_file, "Base addr (%s): ",
+-		     base_addr ? get_tree_code_name (TREE_CODE (base_addr))
+-			       : "null");
+-	    if (base_addr)
+-	      print_generic_expr (dump_file, base_addr);
+-	    fprintf (dump_file, "\n");
+-	  }
++	  dump_base_addr (base_addr);
+ 	if (base_addr)
+ 	  {
+ 	    mr->base = analyse_addr_eval (base_addr, mr);
+@@ -1187,7 +1195,7 @@ reduce_memref_set (memref_set *set, vec &vec)
+ }
+ 
+ static void
+-find_nearest_common_dominator (memref_t *mr, basic_block &dom)
++find_nearest_common_post_dominator (memref_t *mr, basic_block &dom)
+ {
+   for (unsigned int i = 0; i < mr->stmts.length (); i++)
+     {
+@@ -1196,7 +1204,7 @@ find_nearest_common_dominator (memref_t *mr, basic_block &dom)
+       if (dom == bb)
+ 	continue;
+       if (dom)
+-	dom = nearest_common_dominator (CDI_DOMINATORS, dom, bb);
++	dom = nearest_common_dominator (CDI_POST_DOMINATORS, dom, bb);
+       else
+ 	dom = bb;
+     }
+@@ -1495,10 +1503,13 @@ gimple_copy_and_remap (gimple *stmt)
+ 
+ static gimple *
+ gimple_copy_and_remap_memref_stmts (memref_t *mr, gimple_seq &stmts,
+-				    int last_idx, stmt_set &processed)
++				    int first_idx, int last_idx,
++				    stmt_set &processed)
+ {
+   gimple *last_stmt = NULL;
+-  for (int i = mr->stmts.length () - 1; i >= last_idx ; i--)
++  if (first_idx == 0)
++    first_idx = mr->stmts.length () - 1;
++  for (int i = first_idx; i >= last_idx; i--)
+     {
+       if (processed.count (mr->stmts[i]))
+ 	continue;
+@@ -1515,6 +1526,436 @@ gimple_copy_and_remap_memref_stmts (memref_t *mr, gimple_seq &stmts,
+   return last_stmt;
+ }
+ 
++/* Check if prefetch insertion may be always unsafe in this case.  For now
++   reject cases with access to arrays with no domain or with no elements.  */
++
++static bool
++check_prefetch_safety (vec &mrs, memref_t *cmr)
++{
++  for (unsigned int i = 0; i < mrs.length (); i++)
++    {
++      memref_t *mr = mrs[i];
++      if (mr == cmr || mr->used_mrs.empty ())
++	continue;
++      bool is_store;
++      tree *mem = simple_mem_ref_in_stmt (mr->stmts[0], &is_store);
++      if (mem == NULL || TREE_CODE (*mem) != ARRAY_REF)
++	continue;
++      tree array = TREE_OPERAND (*mem, 0);
++      tree atype = TREE_TYPE (array);
++      gcc_assert (atype);
++      tree domain = TYPE_DOMAIN (atype);
++      if (!domain || !tree_fits_uhwi_p (TYPE_MIN_VALUE (domain))
++	  || !tree_fits_uhwi_p (TYPE_MAX_VALUE (domain)))
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Unsupported array type: ");
++	      print_generic_expr (dump_file, atype);
++	      fprintf (dump_file, "\n");
++	    }
++	  return false;
++	}
++      unsigned HOST_WIDE_INT min_val = tree_to_uhwi (TYPE_MIN_VALUE (domain));
++      unsigned HOST_WIDE_INT max_val = tree_to_uhwi (TYPE_MAX_VALUE (domain));
++      if (min_val == 0 && max_val == 0)
++	{
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Unsupported array type's bounds: ");
++	      print_generic_expr (dump_file, atype);
++	      fprintf (dump_file, "\n");
++	    }
++	  return false;
++	}
++    }
++  return true;
++}
++
++/* Collect base addresses which we need to check.  */
++
++static void
++collect_base_addresses (vec &used_mr_vec, HOST_WIDE_INT dist_val,
++			memref_t *comp_mr, tree_poly_offset_map &offset_map)
++{
++  if (dump_file)
++    fprintf (dump_file, "Collect base addresses which we need to check.\n");
++  for (unsigned int i = 0; i < used_mr_vec.length (); i++)
++    {
++      memref_t *mr = used_mr_vec[i];
++      if (mr == comp_mr || mr->used_mrs.empty ())
++	continue;
++      bool is_store;
++      tree *mem = simple_mem_ref_in_stmt (mr->stmts[0], &is_store);
++      if (mem == NULL || TREE_CODE (*mem) != MEM_REF)
++	continue;
++      tree base = get_base_address (*mem);
++      tree base_addr = get_mem_ref_address_ssa_name (*mem, base);
++      if (!base_addr)
++	continue;
++      if (dump_file)
++	{
++	  dump_base_addr (base_addr);
++	  if (base)
++	    {
++	      fprintf (dump_file, "Base:");
++	      print_generic_expr (dump_file, base);
++	      fprintf (dump_file, "\n");
++	    }
++	}
++      if (!TREE_OPERAND (base, 1))
++	continue;
++      poly_offset_int curr_offset = mem_ref_offset (base);
++      poly_offset_int saved_offset = 0;
++      if (offset_map.count (base_addr))
++	{
++	  saved_offset = offset_map[base_addr];
++	  if ((dist_val > 0 && known_gt (curr_offset, saved_offset))
++	      || (dist_val < 0 && known_lt (curr_offset, saved_offset)))
++	    offset_map[base_addr] = curr_offset;
++	  else if (dump_file)
++	    fprintf (dump_file, "Off: step=%ld gt=%d lt=%d\n", dist_val,
++		     known_gt (curr_offset, saved_offset),
++		     known_lt (curr_offset, saved_offset));
++	}
++      else
++	offset_map[base_addr] = curr_offset;
++    }
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Final list of base addresses:\n");
++      for (tree_poly_offset_map::iterator it1 = offset_map.begin ();
++	   it1 != offset_map.end (); ++it1)
++	{
++	  tree base_addr = it1->first;
++	  poly_offset_int off = it1->second;
++	  fprintf (dump_file, "Base:");
++	  print_generic_expr (dump_file, base_addr);
++	  HOST_WIDE_INT val = estimated_poly_value (off.force_shwi (),
++						    POLY_VALUE_LIKELY);
++	  fprintf (dump_file, "\nOff: %ld\n", val);
++	}
++      fprintf (dump_file, "Finish collecting base addresses.\n");
++    }
++}
++
++/* Return true if we need page check to access memory at this address.  */
++
++static bool
++need_page_check (tree base_addr, tree_set &checked_base_addrs)
++{
++  if (dump_file)
++    dump_base_addr (base_addr);
++  if (base_addr == NULL)
++    {
++      if (dump_file)
++	fprintf (dump_file, "Base address not found\n");
++      return false;
++    }
++  if (checked_base_addrs.count (base_addr))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Base address is already checked\n");
++      return false;
++    }
++  return true;
++}
++
++/* Insert instructions to check the original address and newly evaluated
++   adress for prefetch correspond the same page.  */
++
++static gimple *
++insert_page_check (tree addr, tree_poly_offset_map &offset_map,
++		   gimple_seq &stmts)
++{
++  poly_offset_int offset = 0;
++  if (offset_map.count (addr))
++    offset = offset_map[addr];
++  tree addr_type = TREE_TYPE (addr);
++  tree utype = unsigned_type_for (addr_type);
++  tree new_addr = build_int_cst (addr_type, 0);
++  if (decl_map->count (addr))
++    new_addr = (*decl_map)[addr];
++  tree t1 = make_ssa_name (utype);
++  tree t2 = make_ssa_name (utype);
++  unsigned long long pmask = ~(param_ipa_prefetch_pagesize - 1);
++  tree pmask_cst = build_int_cst (utype, pmask);
++  tree off_tree = wide_int_to_tree (sizetype, offset);
++  gcc_assert (TREE_CODE (addr_type) == POINTER_TYPE);
++  tree addr_with_offset = gimple_build (&stmts, POINTER_PLUS_EXPR,
++					addr_type, addr, off_tree);
++  tree conv_addr = make_ssa_name (utype);
++  tree conv_new_addr = make_ssa_name (utype);
++  gimple *conv1 = gimple_build_assign (conv_addr,
++				       fold_convert (utype, addr_with_offset));
++  gimple *conv2 = gimple_build_assign (conv_new_addr,
++				       fold_convert (utype, new_addr));
++  gimple *paddr = gimple_build_assign (t1, BIT_AND_EXPR,
++				       conv_addr, pmask_cst);
++  gimple *new_paddr = gimple_build_assign (t2, BIT_AND_EXPR,
++					   conv_new_addr, pmask_cst);
++  gcond *cond = gimple_build_cond (EQ_EXPR, t1, t2, NULL, NULL);
++  gimple_seq_add_stmt (&stmts, conv1);
++  gimple_seq_add_stmt (&stmts, paddr);
++  gimple_seq_add_stmt (&stmts, conv2);
++  gimple_seq_add_stmt (&stmts, new_paddr);
++  gimple_seq_add_stmt (&stmts, cond);
++  return cond;
++}
++
++/* Check if this array access needs dynamic address verification.  Support only
++   arrays with 1-d indexing.  */
++
++static bool
++need_array_index_check (tree mem)
++{
++  /* Check pattern: t1 = (type) t0; ld/st array[t1].  If any index of type (t0)
++     does not go beyond the bounds of the array, we don't need the check.  */
++  tree array = TREE_OPERAND (mem, 0);
++  tree atype = TREE_TYPE (array);
++  tree index = TREE_OPERAND (mem, 1);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Array ind: ");
++      print_generic_expr (dump_file, index);
++      fprintf (dump_file, "\nMem: ");
++      print_generic_expr (dump_file, array);
++      fprintf (dump_file, "\nInd type: ");
++      print_generic_expr (dump_file, TREE_TYPE (index));
++      fprintf (dump_file, "\nMem type: ");
++      print_generic_expr (dump_file, atype);
++      fprintf (dump_file, "\n");
++    }
++  tree domain = TYPE_DOMAIN (atype);
++  if (!domain || !tree_fits_uhwi_p (TYPE_MIN_VALUE (domain))
++      || !tree_fits_uhwi_p (TYPE_MAX_VALUE (domain)))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Unsupported array type domain.\n");
++      return true;
++    }
++  unsigned HOST_WIDE_INT min_val = tree_to_uhwi (TYPE_MIN_VALUE (domain));
++  unsigned HOST_WIDE_INT max_val = tree_to_uhwi (TYPE_MAX_VALUE (domain));
++  if (dump_file)
++    fprintf (dump_file, "Array bounds (%ld, %ld)\n", min_val, max_val);
++  if (TREE_CODE (index) != SSA_NAME)
++    return true;
++
++  gimple *stmt = SSA_NAME_DEF_STMT (index);
++  if (!is_gimple_assign (stmt))
++    {
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Is not assign, stop analysis: ");
++	  print_gimple_stmt (dump_file, stmt, 3, TDF_DETAILS);
++	}
++      return true;
++    }
++  tree *lhs = gimple_assign_lhs_ptr (stmt);
++  tree *rhs = gimple_assign_rhs1_ptr (stmt);
++  tree lhs_type = TREE_TYPE (*lhs);
++  tree rhs_type = TREE_TYPE (*rhs);
++  tree ind_type = (TYPE_PRECISION (lhs_type) < TYPE_PRECISION (rhs_type))
++		  ? lhs_type : rhs_type;
++  if (!ind_type || !tree_fits_uhwi_p (TYPE_MIN_VALUE (ind_type))
++      || !tree_fits_uhwi_p (TYPE_MAX_VALUE (ind_type)))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Unsupported index type.\n");
++      return true;
++    }
++  int prec = tree_to_uhwi (TYPE_SIZE (ind_type));
++  unsigned HOST_WIDE_INT t_max_val = tree_to_uhwi (TYPE_MAX_VALUE (ind_type));
++  unsigned HOST_WIDE_INT t_min_val = tree_to_uhwi (TYPE_MIN_VALUE (ind_type));
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Index type (%d, %ld, %ld): ", prec,
++	       t_min_val, t_max_val);
++      print_generic_expr (dump_file, ind_type);
++      fprintf (dump_file, "\n");
++    }
++  return !((t_max_val <= max_val) && (t_min_val >= min_val));
++}
++
++/* Insert instructions to check the new index is within the array bounds.  */
++
++static gimple *
++insert_index_check (tree mem, gimple_seq &stmts)
++{
++  if (dump_file)
++    fprintf (dump_file, "Insert array index check\n");
++  tree atype = TREE_TYPE (TREE_OPERAND (mem, 0));
++  tree ind = TREE_OPERAND (mem, 1);
++  if (decl_map->count (ind))
++    ind = (*decl_map)[ind];
++  tree domain = TYPE_DOMAIN (atype);
++  gcc_assert (domain && tree_fits_uhwi_p (TYPE_MIN_VALUE (domain))
++	      && tree_fits_uhwi_p (TYPE_MAX_VALUE (domain)));
++
++  tree ind_min_val = TYPE_MIN_VALUE (domain);
++  tree ind_max_val = TYPE_MAX_VALUE (domain);
++  tree t1 = make_ssa_name (boolean_type_node);
++  tree t2 = make_ssa_name (boolean_type_node);
++  tree t3 = make_ssa_name (boolean_type_node);
++  t1 = fold_build2 (LE_EXPR, boolean_type_node, ind, ind_max_val);
++  t2 = fold_build2 (GE_EXPR, boolean_type_node, ind, ind_min_val);
++  t3 = fold_build2 (TRUTH_ANDIF_EXPR, boolean_type_node, t1, t2);
++  gcond *cond = gimple_build_cond (EQ_EXPR, t3, boolean_true_node, NULL, NULL);
++  gimple_seq_add_stmt (&stmts, cond);
++  return cond;
++}
++
++/* Insert safety checks for memory access stmts newly created to evaluate
++   prefetch addresses.  */
++
++static void
++process_used_mr (memref_t *mr, tree_poly_offset_map &offset_map,
++		 tree_set &checked_base_addrs, gimple_seq &stmts,
++		 vec &bbends)
++{
++  bool is_store;
++  tree *mem = simple_mem_ref_in_stmt (mr->stmts[0], &is_store);
++  if (mem == NULL)
++    return;
++  if (dump_file)
++    {
++      fprintf (dump_file, "MR (%d) maybe need to insert address check: ",
++	       mr->mr_id);
++      print_generic_expr (dump_file, *mem);
++      fprintf (dump_file, "\n");
++    }
++  gimple *bbend = NULL;
++  if (TREE_CODE (*mem) == MEM_REF)
++    {
++      tree base = get_base_address (*mem);
++      tree base_addr = get_mem_ref_address_ssa_name (*mem, base);
++      if (!need_page_check (base_addr, checked_base_addrs))
++	return;
++      bbend = insert_page_check (base_addr, offset_map, stmts);
++      checked_base_addrs.insert (base_addr);
++    }
++  else if (TREE_CODE (*mem) == ARRAY_REF && need_array_index_check (*mem))
++    bbend = insert_index_check (*mem, stmts);
++  if (bbend)
++    bbends.safe_push (bbend);
++}
++
++/* Create new variables and insert new stmts to evaluate prefetch addresses.  */
++
++static void
++create_stmts_for_used_mrs (vec &used_mr_vec, vec &bbends,
++			   gimple_seq &stmts, stmt_set &processed_stmts,
++			   HOST_WIDE_INT dist_val, memref_t *comp_mr)
++{
++  tree_poly_offset_map offset_map;
++  collect_base_addresses (used_mr_vec, dist_val, comp_mr, offset_map);
++
++  /* Insert stmts to evaluate prefetch addresses.  */
++  tree_set checked_base_addrs;
++  for (unsigned int i = 0; i < used_mr_vec.length (); i++)
++    {
++      memref_t *mr = used_mr_vec[i];
++      if (mr == comp_mr)
++	continue;
++      gimple *last_stmt = gimple_copy_and_remap_memref_stmts (mr, stmts, 0, 1,
++							      processed_stmts);
++      if (last_stmt && dump_file)
++	{
++	  fprintf (dump_file, "MR (%d) new mem: ", mr->mr_id);
++	  print_generic_expr (dump_file, gimple_assign_lhs (last_stmt));
++	  fprintf (dump_file, "\n");
++	}
++      if (!mr->used_mrs.empty ())
++	process_used_mr (mr, offset_map, checked_base_addrs, stmts, bbends);
++      last_stmt = gimple_copy_and_remap_memref_stmts (mr, stmts, 0, 0,
++						      processed_stmts);
++    }
++}
++
++/* Insert prefetch instructions.  */
++
++static void
++insert_prefetch_stmts (vec &pcalls, gimple_seq &stmts,
++		       gimple *&last_pref, vec &vmrs,
++		       stmt_set &processed_stmts)
++{
++  if (dump_file)
++    fprintf (dump_file, "Evaluate addresses and insert prefetch insns.\n");
++
++  tree local;
++  switch (param_ipa_prefetch_locality)
++    {
++    case 0:
++      local = integer_zero_node;
++      break;
++    case 1:
++      local = integer_one_node;
++      break;
++    case 2:
++      local = build_int_cst (integer_type_node, 2);
++      break;
++    default:
++    case 3:
++      local = integer_three_node;
++      break;
++    }
++  tree_set prefetched_addrs;
++  for (unsigned int i = 0; i < vmrs.length (); i++)
++    {
++      memref_t *mr = vmrs[i];
++      /* Don't need to copy the last stmt, since we insert prefetch insn
++	 instead of it.  */
++      gimple_copy_and_remap_memref_stmts (mr, stmts, 0, 1, processed_stmts);
++      gimple *last_stmt = mr->stmts[0];
++      gcc_assert (last_stmt);
++
++      tree old_addr = get_mem_ref_address_ssa_name (mr->mem, NULL_TREE);
++      tree new_addr = old_addr;
++      if (decl_map->count (old_addr))
++	new_addr = (*decl_map)[old_addr];
++      if (prefetched_addrs.count (new_addr))
++	continue;
++      /* Insert prefetch intrinsic call.  */
++      tree write_p = mr->is_store ? integer_one_node : integer_zero_node;
++      last_pref = gimple_build_call (builtin_decl_explicit (BUILT_IN_PREFETCH),
++				     3, new_addr, write_p, local);
++      pcalls.safe_push (last_pref);
++      gimple_seq_add_stmt (&stmts, last_pref);
++      prefetched_addrs.insert (new_addr);
++
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Insert %d prefetch stmt:\n", i);
++	  print_gimple_stmt (dump_file, last_pref, 0);
++	}
++    }
++}
++
++/* Split bbs after condition stmts and fix control flow graph.  */
++
++static void
++correct_cfg (vec &bbends, gimple *last_pref, basic_block &dom_bb)
++{
++  edge e_last = split_block (dom_bb, last_pref);
++  if (!bbends.length () || last_pref == NULL)
++    return;
++  for (int i = bbends.length () - 1; i >= 0; i--)
++    {
++      gimple *bbend = bbends[i];
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Split dom_bb after condition stmts:\n");
++	  print_gimple_stmt (dump_file, bbend, 0);
++	}
++      basic_block last_bb = e_last->dest;
++      edge e = split_block (dom_bb, bbend);
++      e->flags &= ~EDGE_FALLTHRU;
++      e->flags |= EDGE_TRUE_VALUE;
++      edge e_false = make_edge (dom_bb, last_bb, EDGE_FALSE_VALUE);
++      e_false->probability = profile_probability::never ();
++    }
++}
++
+ static void
+ create_cgraph_edge (cgraph_node *n, gimple *stmt)
+ {
+@@ -1529,6 +1970,17 @@ create_cgraph_edge (cgraph_node *n, gimple *stmt)
+   ipa_call_summaries->get_create (e);
+ }
+ 
++/* Modify cgraph inserting calls to prefetch intrinsics.  */
++
++static void
++modify_ipa_info (cgraph_node *n, vec &pcalls)
++{
++  for (unsigned i = 0; i < pcalls.length (); i++)
++    create_cgraph_edge (n, pcalls[i]);
++  ipa_update_overall_fn_summary (n);
++  renumber_gimple_stmt_uids (DECL_STRUCT_FUNCTION (n->decl));
++}
++
+ /* Insert prefetch intrinsics in this function, return nonzero on success.  */
+ 
+ static int
+@@ -1607,6 +2059,18 @@ optimize_function (cgraph_node *n, function *fn)
+       return 0;
+     }
+ 
++  vec used_mr_vec = vNULL;
++  for (memref_set::const_iterator it = used_mrs.begin ();
++       it != used_mrs.end (); it++)
++    used_mr_vec.safe_push (*it);
++  used_mr_vec.qsort (memref_id_cmp);
++  if (!check_prefetch_safety (used_mr_vec, comp_mr))
++    {
++      if (dump_file)
++	fprintf (dump_file, "Prefetching may be unsafe.  Skip the case.\n");
++      return 0;
++    }
++
+   /* Filter out memrefs with the same memory references.
+      TODO: maybe do the same with used mrs.  */
+   vec vmrs = vNULL;
+@@ -1616,18 +2080,18 @@ optimize_function (cgraph_node *n, function *fn)
+   /* TODO: maybe it is useful to process also used_mrs.  */
+   basic_block dom_bb = NULL;
+   for (unsigned int i = 0; i < vmrs.length (); i++)
+-    find_nearest_common_dominator (vmrs[i], dom_bb);
++    find_nearest_common_post_dominator (vmrs[i], dom_bb);
+ 
+   if (!dom_bb)
+     {
+       if (dump_file)
+-	fprintf (dump_file, "Dominator bb for MRs is not found.  "
++	fprintf (dump_file, "Post dominator bb for MRs is not found.  "
+ 		 "Skip the case.\n");
+       return 0;
+     }
+   else if (dump_file)
+     {
+-      fprintf (dump_file, "Dominator bb %d for MRs:\n", dom_bb->index);
++      fprintf (dump_file, "Post dominator bb %d for MRs:\n", dom_bb->index);
+       gimple_dump_bb (dump_file, dom_bb, 0, dump_flags);
+       fprintf (dump_file, "\n");
+     }
+@@ -1636,19 +2100,33 @@ optimize_function (cgraph_node *n, function *fn)
+   gimple *last_used = NULL;
+   for (gimple_stmt_iterator si = gsi_last_bb (dom_bb); !gsi_end_p (si);
+        gsi_prev (&si))
+-    if (comp_mr->stmts[0] == gsi_stmt (si))
+-      {
+-	last_used = gsi_stmt (si);
+-	if (dump_file)
++    {
++      bool found = false;
++      for (unsigned int i = 0; i < vmrs.length (); i++)
++	/* TODO: take into account only those MRs that should be
++	   checked memory.  */
++	if (vmrs[i]->stmts[0] == gsi_stmt (si))
+ 	  {
+-	    fprintf (dump_file, "Last used stmt in dominator bb:\n");
+-	    print_gimple_stmt (dump_file, last_used, 0);
++	    found = true;
++	    break;
+ 	  }
+-	break;
+-      }
++      if (found || comp_mr->stmts[0] == gsi_stmt (si))
++	{
++	  last_used = gsi_stmt (si);
++	  if (dump_file)
++	    {
++	      fprintf (dump_file, "Last used stmt in post dominator bb:\n");
++	      print_gimple_stmt (dump_file, last_used, 0);
++	    }
++	  break;
++	}
++    }
+ 
+-  split_block (dom_bb, last_used);
+-  gimple_stmt_iterator gsi = gsi_last_bb (dom_bb);
++  gimple_stmt_iterator gsi;
++  if (last_used)
++    gsi = gsi_for_stmt (last_used);
++  else
++    gsi = gsi_last_bb (dom_bb);
+ 
+   /* Create new inc var.  Insert new_var = old_var + step * factor.  */
+   decl_map = new tree_map;
+@@ -1660,7 +2138,7 @@ optimize_function (cgraph_node *n, function *fn)
+   stmt_set processed_stmts;
+   if (!dominated_by_p (CDI_DOMINATORS, dom_bb, gimple_bb (comp_mr->stmts[0])))
+     {
+-      gimple *tmp = gimple_copy_and_remap_memref_stmts (comp_mr, stmts, 0,
++      gimple *tmp = gimple_copy_and_remap_memref_stmts (comp_mr, stmts, 0, 0,
+ 							processed_stmts);
+       inc_var = gimple_assign_lhs (tmp);
+     }
+@@ -1683,86 +2161,26 @@ optimize_function (cgraph_node *n, function *fn)
+       fprintf (dump_file, "\n");
+     }
+ 
+-  /* Create other new vars.  Insert new stmts.  */
+-  vec used_mr_vec = vNULL;
+-  for (memref_set::const_iterator it = used_mrs.begin ();
+-       it != used_mrs.end (); it++)
+-    used_mr_vec.safe_push (*it);
+-  used_mr_vec.qsort (memref_id_cmp);
+-
+-  for (unsigned int j = 0; j < used_mr_vec.length (); j++)
+-    {
+-      memref_t *mr = used_mr_vec[j];
+-      if (mr == comp_mr)
+-	continue;
+-      gimple *last_stmt = gimple_copy_and_remap_memref_stmts (mr, stmts, 0,
+-							      processed_stmts);
+-      gcc_assert (last_stmt);
+-      if (dump_file)
+-	{
+-	  fprintf (dump_file, "MR (%d) new mem: ", mr->mr_id);
+-	  print_generic_expr (dump_file, gimple_assign_lhs (last_stmt));
+-	  fprintf (dump_file, "\n");
+-	}
+-    }
+-  /* On new load check page fault.  */
+-  /* Insert prefetch instructions.  */
+-  if (dump_file)
+-    fprintf (dump_file, "Evaluate addresses and insert prefetch insn.\n");
++  vec bbends = vNULL;
++  create_stmts_for_used_mrs (used_mr_vec, bbends, stmts, processed_stmts,
++			     dist_val, comp_mr);
+ 
+   vec pcalls = vNULL;
+-  tree local;
+-  switch (param_ipa_prefetch_locality)
+-    {
+-    case 0:
+-      local = integer_zero_node;
+-      break;
+-    case 1:
+-      local = integer_one_node;
+-      break;
+-    case 2:
+-      local = build_int_cst (integer_type_node, 2);
+-      break;
+-    default:
+-    case 3:
+-      local = integer_three_node;
+-      break;
+-    }
+-  tree_set prefetched_addrs;
+-  for (unsigned int j = 0; j < vmrs.length (); j++)
+-    {
+-      memref_t *mr = vmrs[j];
+-      /* Don't need to copy the last stmt, since we insert prefetch insn
+-	 instead of it.  */
+-      gimple_copy_and_remap_memref_stmts (mr, stmts, 1, processed_stmts);
+-      gimple *last_stmt = mr->stmts[0];
+-      gcc_assert (last_stmt);
+-      tree write_p = mr->is_store ? integer_one_node : integer_zero_node;
+-      tree addr = get_mem_ref_address_ssa_name (mr->mem, NULL_TREE);
+-      if (decl_map->count (addr))
+-	addr = (*decl_map)[addr];
+-      if (prefetched_addrs.count (addr))
+-	continue;
+-      last_stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_PREFETCH),
+-				     3, addr, write_p, local);
+-      pcalls.safe_push (last_stmt);
+-      gimple_seq_add_stmt (&stmts, last_stmt);
+-      prefetched_addrs.insert (addr);
+-      if (dump_file)
+-	{
+-	  fprintf (dump_file, "Insert %d prefetch stmt:\n", j);
+-	  print_gimple_stmt (dump_file, last_stmt, 0);
+-	}
+-    }
+-
++  gimple *last_pref = NULL;
++  insert_prefetch_stmts (pcalls, stmts, last_pref, vmrs, processed_stmts);
+   gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++
++  correct_cfg (bbends, last_pref, dom_bb);
++
+   delete decl_map;
+ 
+-  /* Modify cgraph inserting calls to prefetch intrinsics.  */
+-  for (unsigned i = 0; i < pcalls.length (); i++)
+-    create_cgraph_edge (n, pcalls[i]);
+-  ipa_update_overall_fn_summary (n);
+-  renumber_gimple_stmt_uids (DECL_STRUCT_FUNCTION (n->decl));
++  modify_ipa_info (n, pcalls);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "After optimization:\n");
++      dump_function_to_file (cfun->decl, dump_file, (dump_flags_t)0);
++    }
+ 
+   return 1;
+ }
+@@ -1781,8 +2199,10 @@ insert_prefetch ()
+ 	fprintf (dump_file, "Optimize function %s\n", n->dump_name ());
+       push_cfun (DECL_STRUCT_FUNCTION (n->decl));
+       calculate_dominance_info (CDI_DOMINATORS);
++      calculate_dominance_info (CDI_POST_DOMINATORS);
+       res |= optimize_function (n, fn);
+       free_dominance_info (CDI_DOMINATORS);
++      free_dominance_info (CDI_POST_DOMINATORS);
+       pop_cfun ();
+     }
+   return res;
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 747d0f829..fc700ab79 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -317,6 +317,10 @@ The factor represents the number of inductive variable incrementations to evalua
+ Common Joined UInteger Var(param_ipa_prefetch_locality) Init(3) IntegerRange(0, 3) Param Optimization
+ The flag represents temporal locality value between 0 and 3, the higher value means the higher temporal locality in the data.
+ 
++-param=ipa-prefetch-pagesize=
++Common Joined UInteger Var(param_ipa_prefetch_pagesize) Init(4096) Param Optimization
++The flag represents current pagesize for runtime checks of memory access addresses.
++
+ -param=ira-loop-reserved-regs=
+ Common Joined UInteger Var(param_ira_loop_reserved_regs) Init(2) Param Optimization
+ The number of registers in each class kept unused by loop invariant motion.
+-- 
+2.33.0
+
diff --git a/0288-Enable-macro-use-commandline.patch b/0288-Enable-macro-use-commandline.patch
new file mode 100644
index 0000000..cafe01b
--- /dev/null
+++ b/0288-Enable-macro-use-commandline.patch
@@ -0,0 +1,207 @@
+From 7a578a8725f8fd7d92fcbbac14841ea7e8d0870f Mon Sep 17 00:00:00 2001
+From: zhangxiaohua 
+Date: Sun, 25 Aug 2024 23:08:53 +0800
+Subject: [PATCH 157/157] Enable macro-use-commandline
+
+Signed-off-by: zhangxiaohua 
+---
+ gcc/c-family/c-opts.cc                        |  4 +++
+ gcc/c-family/c.opt                            |  4 +++
+ gcc/doc/cppopts.texi                          |  4 +++
+ gcc/doc/invoke.texi                           |  1 +
+ .../gcc.dg/cpp/macro-use-cmdline-1.c          | 26 ++++++++++++++
+ .../gcc.dg/cpp/macro-use-cmdline-2.c          | 34 +++++++++++++++++++
+ libcpp/include/cpplib.h                       |  3 ++
+ libcpp/init.cc                                |  1 +
+ libcpp/macro.cc                               | 16 ++++++++-
+ 9 files changed, 92 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-2.c
+
+diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
+index 5134f6128..744b54dc3 100644
+--- a/gcc/c-family/c-opts.cc
++++ b/gcc/c-family/c-opts.cc
+@@ -527,6 +527,10 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
+ 	cpp_opts->track_macro_expansion = 2;
+       break;
+ 
++    case OPT_fmacro_use_commandline:
++      cpp_opts->macro_use_commandline = 1;
++      break;
++
+     case OPT_fexec_charset_:
+       cpp_opts->narrow_charset = arg;
+       break;
+diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
+index 07da40ef4..a36c27f07 100644
+--- a/gcc/c-family/c.opt
++++ b/gcc/c-family/c.opt
+@@ -2012,6 +2012,10 @@ ftrack-macro-expansion=
+ C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+ -ftrack-macro-expansion=<0|1|2>	Track locations of tokens coming from macro expansion and display them in error messages.
+ 
++fmacro-use-commandline
++C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
++Preferentially use options from the commandline.
++
+ fpretty-templates
+ C++ ObjC++ Var(flag_pretty_templates) Init(1)
+ Do not pretty-print template specializations as the template signature followed by the arguments.
+diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
+index c0a92b370..8c8a81eac 100644
+--- a/gcc/doc/cppopts.texi
++++ b/gcc/doc/cppopts.texi
+@@ -277,6 +277,10 @@ correct column numbers in warnings or errors, even if tabs appear on the
+ line.  If the value is less than 1 or greater than 100, the option is
+ ignored.  The default is 8.
+ 
++@item -fmacro-use-commandline
++@opindex fmacro-use-commandline
++Preferentially use options from the command line.
++
+ @item -ftrack-macro-expansion@r{[}=@var{level}@r{]}
+ @opindex ftrack-macro-expansion
+ Track locations of tokens across macro expansions. This allows the
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index bdd8b9429..2ff7d860d 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -630,6 +630,7 @@ Objective-C and Objective-C++ Dialects}.
+ -fexec-charset=@var{charset}  -fextended-identifiers  @gol
+ -finput-charset=@var{charset}  -flarge-source-files  @gol
+ -fmacro-prefix-map=@var{old}=@var{new} -fmax-include-depth=@var{depth} @gol
++-fmacro-use-commandline @gol
+ -fno-canonical-system-headers  -fpch-deps  -fpch-preprocess  @gol
+ -fpreprocessed  -ftabstop=@var{width}  -ftrack-macro-expansion  @gol
+ -fwide-exec-charset=@var{charset}  -fworking-directory @gol
+diff --git a/gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-1.c b/gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-1.c
+new file mode 100644
+index 000000000..f85d9c268
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-1.c
+@@ -0,0 +1,26 @@
++/*
++   { dg-options "-fmacro-use-commandline -DTEST_MACRO=1 -DTEST_MACRO=20" }
++   { dg-do compile }
++   { dg-do run }
++*/
++
++/* { dg-warning "-:redefined" "redef TEST_MACRO"      { target *-*-* } 0  }
++   { dg-message "-:previous"  "prev def TEST_MACRO"   { target *-*-* } 0  }
++*/
++
++#if DEBUG
++extern int puts (const char *);
++#else
++#define puts(X)
++#endif
++extern void abort (void);
++
++#define err(str) do { puts(str); abort(); } while (0)
++
++int main (int argc, char *argv[])
++{
++  int macroValue = TEST_MACRO;
++  if (macroValue != 20)
++    err("macroValue");
++  return 0;
++}
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-2.c b/gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-2.c
+new file mode 100644
+index 000000000..99d92d1e4
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/cpp/macro-use-cmdline-2.c
+@@ -0,0 +1,34 @@
++/*
++   { dg-options "-fmacro-use-commandline -DTEST_MACRO=1" }
++   { dg-do compile }
++   { dg-do run }
++*/
++
++#define TEST_MACRO 300
++#define TEST_MACRO_1 400
++/*
++   { dg-warning "-:redefined" "redef TEST_MACRO"      { target *-*-* } 7  }
++   { dg-message "-:previous"  "prev def TEST_MACRO"   { target *-*-* } 0  }
++*/
++
++#if DEBUG
++extern int puts (const char *);
++#else
++#define puts(X)
++#endif
++
++extern void abort (void);
++
++#define err(str) do { puts(str); abort(); } while (0)
++
++int main (int argc, char *argv[])
++{
++  int macroValue = TEST_MACRO;
++  if (macroValue != 1)
++    err("macroValue");
++
++  int macroValue1 = TEST_MACRO_1;
++  if (macroValue1 != 400)
++    err("macroValue1");
++  return 0;
++}
+\ No newline at end of file
+diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
+index 3eba6f74b..c6101ca01 100644
+--- a/libcpp/include/cpplib.h
++++ b/libcpp/include/cpplib.h
+@@ -471,6 +471,9 @@ struct cpp_options
+      consumes the highest amount of memory.  */
+   unsigned char track_macro_expansion;
+ 
++  /* Use the options on the command line first.  */
++  unsigned char macro_use_commandline;
++
+   /* Nonzero means handle C++ alternate operator names.  */
+   unsigned char operator_names;
+ 
+diff --git a/libcpp/init.cc b/libcpp/init.cc
+index f4ab83d21..47be60a36 100644
+--- a/libcpp/init.cc
++++ b/libcpp/init.cc
+@@ -215,6 +215,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
+      cpp_options::track_macro_expansion to learn about the other
+      values.  */
+   CPP_OPTION (pfile, track_macro_expansion) = 2;
++  CPP_OPTION (pfile, macro_use_commandline) = 0;
+   CPP_OPTION (pfile, warn_normalize) = normalized_C;
+   CPP_OPTION (pfile, warn_literal_suffix) = 1;
+   CPP_OPTION (pfile, canonical_system_headers)
+diff --git a/libcpp/macro.cc b/libcpp/macro.cc
+index 8ebf360c0..aa9e4ffa6 100644
+--- a/libcpp/macro.cc
++++ b/libcpp/macro.cc
+@@ -3852,7 +3852,21 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
+ 				 node->value.macro->line, 0,
+ 			 "this is the location of the previous definition");
+ 	}
+-      _cpp_free_definition (node);
++#define LOCATION_FROM_LINEMAP 0
++#define MIN_LINE_OF_MACRO_BEEN_OVERRIDDEN 96
++#define MAX_LINE_OF_MACRO_BEEN_OVERRIDDEN 128
++     if (CPP_OPTION (pfile, macro_use_commandline)
++	    && node->value.macro->line >= MIN_LINE_OF_MACRO_BEEN_OVERRIDDEN
++	    && node->value.macro->line <= MAX_LINE_OF_MACRO_BEEN_OVERRIDDEN
++	    && pfile->forced_token_location == LOCATION_FROM_LINEMAP)
++	{
++	  cpp_pedwarning_with_line (pfile, CPP_W_NONE,
++	    node->value.macro->line, 0,
++	    "use the previous definition from commandline");
++	    return false;
++	}
++	else
++	   _cpp_free_definition (node);
+     }
+ 
+   /* Enter definition in hash table.  */
+-- 
+2.33.0
+
diff --git a/0289-tree-ssa-loop-crc.cc-TARGET_CRC32-may-be-not-defined.patch b/0289-tree-ssa-loop-crc.cc-TARGET_CRC32-may-be-not-defined.patch
new file mode 100644
index 0000000..0581808
--- /dev/null
+++ b/0289-tree-ssa-loop-crc.cc-TARGET_CRC32-may-be-not-defined.patch
@@ -0,0 +1,35 @@
+From 63f99f46e851aecc070496a0e688a0d118c820a4 Mon Sep 17 00:00:00 2001
+From: YunQiang Su 
+Date: Mon, 2 Sep 2024 17:57:52 +0800
+Subject: [PATCH] tree-ssa-loop-crc.cc: TARGET_CRC32 may be not defined
+
+TARGET_CRC32 may be not defined on some architectures, RISC-V is one example.
+---
+ gcc/tree-ssa-loop-crc.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/gcc/tree-ssa-loop-crc.cc b/gcc/tree-ssa-loop-crc.cc
+index b9c2f71ca..7eee9446d 100644
+--- a/gcc/tree-ssa-loop-crc.cc
++++ b/gcc/tree-ssa-loop-crc.cc
+@@ -1227,6 +1227,9 @@ convert_to_new_loop (class loop *loop)
+ static unsigned int
+ tree_ssa_loop_crc ()
+ {
++#ifndef TARGET_CRC32
++  return 0;
++#else
+   if (TARGET_CRC32 == false)
+     {
+       warning (OPT____,"The loop-crc optimization is not working." \
+@@ -1269,6 +1272,7 @@ tree_ssa_loop_crc ()
+       }
+   }
+   return todo;
++#endif
+ }
+ 
+ /* Loop crc.  */
+-- 
+2.33.0
+
diff --git a/0290-Add-ipa-prefetch-test-for-gcc-s-case.patch b/0290-Add-ipa-prefetch-test-for-gcc-s-case.patch
new file mode 100644
index 0000000..4545420
--- /dev/null
+++ b/0290-Add-ipa-prefetch-test-for-gcc-s-case.patch
@@ -0,0 +1,209 @@
+From 0534ae05fc313c0d449b48ffe3e01642b644e6d2 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Fri, 6 Sep 2024 10:40:50 +0800
+Subject: [PATCH 1/2] Add ipa-prefetch test for gcc's case
+
+---
+ gcc/ipa-prefetch.cc                         |   4 +-
+ gcc/testsuite/gcc.dg/ipa/ipa-prefetch-gcc.c | 167 ++++++++++++++++++++
+ 2 files changed, 170 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-prefetch-gcc.c
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index b000d4d75..8e628390b 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -1668,6 +1668,8 @@ static gimple *
+ insert_page_check (tree addr, tree_poly_offset_map &offset_map,
+ 		   gimple_seq &stmts)
+ {
++  if (dump_file)
++    fprintf (dump_file, "Insert page check.\n");
+   poly_offset_int offset = 0;
+   if (offset_map.count (addr))
+     offset = offset_map[addr];
+@@ -1783,7 +1785,7 @@ static gimple *
+ insert_index_check (tree mem, gimple_seq &stmts)
+ {
+   if (dump_file)
+-    fprintf (dump_file, "Insert array index check\n");
++    fprintf (dump_file, "Insert array index check.\n");
+   tree atype = TREE_TYPE (TREE_OPERAND (mem, 0));
+   tree ind = TREE_OPERAND (mem, 1);
+   if (decl_map->count (ind))
+diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-prefetch-gcc.c b/gcc/testsuite/gcc.dg/ipa/ipa-prefetch-gcc.c
+new file mode 100644
+index 000000000..f1001c350
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/ipa/ipa-prefetch-gcc.c
+@@ -0,0 +1,167 @@
++/* { dg-do link } */
++/* { dg-options "-O3 -fipa-prefetch -flto -flto-partition=one -fdump-ipa-ipa_prefetch" } */
++/* { dg-require-effective-target lto } */
++
++/* Based on opensource gcc code.  */
++
++#include 
++#include 
++#include 
++
++#define SPARSESET_ELT_TYPE unsigned int
++#define ALLOCNO_NUM(A) ((A)->num)
++
++typedef struct sparseset_def
++{
++  SPARSESET_ELT_TYPE *dense;	/* Dense array.  */
++  SPARSESET_ELT_TYPE *sparse;	/* Sparse array.  */
++  SPARSESET_ELT_TYPE members;	/* Number of elements.  */
++  SPARSESET_ELT_TYPE size;	/* Maximum number of elements.  */
++  SPARSESET_ELT_TYPE iter;	/* Iterator index.  */
++  unsigned char iter_inc;	/* Iteration increment amount.  */
++  bool iterating;
++  SPARSESET_ELT_TYPE elms[2];   /* Combined dense and sparse arrays.  */
++} *sparseset;
++
++struct ira_allocno
++{
++  /* The allocno order number starting with 0.  Each allocno has an
++     unique number and the number is never changed for the
++     allocno.  */
++  int num;
++  /* Regno for allocno or cap.  */
++  int regno;
++  /*...*/
++};
++
++typedef struct ira_allocno_live_range *allocno_live_range_t;
++typedef struct ira_allocno *ira_allocno_t;
++
++struct ira_allocno_live_range
++{
++  /* Allocno whose live range is described by given structure.  */
++  ira_allocno_t allocno;
++  /* Program point range.  */
++  int start, finish;
++  /* Next structure describing program points where the allocno
++     lives.  */
++  allocno_live_range_t next;
++  /* Pointer to structures with the same start/finish.  */
++  allocno_live_range_t start_next, finish_next;
++};
++
++bool
++sparseset_bit_p (sparseset s, SPARSESET_ELT_TYPE e)
++{
++  SPARSESET_ELT_TYPE idx;
++
++  idx = s->sparse[e];
++
++  return idx < s->members && s->dense[idx] == e;
++}
++
++bool new_pseudos_p;
++int ira_max_point, ira_allocnos_num;
++allocno_live_range_t *ira_finish_point_ranges;
++
++static inline void
++sparseset_clear (sparseset s)
++{
++  s->members = 0;
++  s->iterating = false;
++}
++
++sparseset
++sparseset_alloc (SPARSESET_ELT_TYPE n_elms)
++{
++  unsigned int n_bytes = sizeof (struct sparseset_def)
++			 + ((n_elms - 1) * 2 * sizeof (SPARSESET_ELT_TYPE));
++
++  /* We use xcalloc rather than xmalloc to silence some valgrind uninitialized
++     read errors when accessing set->sparse[n] when "n" is not, and never has
++     been, in the set.  These uninitialized reads are expected, by design and
++     harmless.  If this turns into a performance problem due to some future
++     additional users of sparseset, we can revisit this decision.  */
++  sparseset set = (sparseset) calloc (1, n_bytes);
++  set->dense = &(set->elms[0]);
++  set->sparse = &(set->elms[n_elms]);
++  set->size = n_elms;
++  sparseset_clear (set);
++  return set;
++}
++
++void
++sparseset_insert_bit (sparseset s, SPARSESET_ELT_TYPE e, SPARSESET_ELT_TYPE idx)
++{
++  s->sparse[e] = idx;
++  s->dense[idx] = e;
++}
++
++void
++sparseset_swap (sparseset s, SPARSESET_ELT_TYPE idx1, SPARSESET_ELT_TYPE idx2)
++{
++  SPARSESET_ELT_TYPE tmp = s->dense[idx2];
++  sparseset_insert_bit (s, s->dense[idx1], idx2);
++  sparseset_insert_bit (s, tmp, idx1);
++}
++
++void __attribute__ ((noinline))
++sparseset_clear_bit (sparseset s, SPARSESET_ELT_TYPE e)
++{
++  if (sparseset_bit_p (s, e))
++    {
++      SPARSESET_ELT_TYPE idx = s->sparse[e];
++      SPARSESET_ELT_TYPE iter = s->iter;
++      SPARSESET_ELT_TYPE mem = s->members - 1;
++
++      /* If we are iterating over this set and we want to delete a
++	 member we've already visited, then we swap the element we
++	 want to delete with the element at the current iteration
++	 index so that it plays well together with the code below
++	 that actually removes the element.  */
++      if (s->iterating && idx <= iter)
++	{
++	  if (idx < iter)
++	    {
++	      sparseset_swap (s, idx, iter);
++	      idx = iter;
++	    }
++	  s->iter_inc = 0;
++	}
++
++      /* Replace the element we want to delete with the last element
++	 in the dense array and then decrement s->members, effectively
++	 removing the element we want to delete.  */
++      sparseset_insert_bit (s, s->dense[mem], idx);
++      s->members = mem;
++    }
++}
++
++allocno_live_range_t r;
++sparseset allocnos_live;
++
++void
++ira_flattening ()
++{
++  int i;
++
++  if (new_pseudos_p)
++    {
++      allocnos_live = sparseset_alloc (ira_allocnos_num);
++      for (i = 0; i < ira_max_point; i++)
++	{
++	  for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next)
++	    sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (r->allocno));
++	}
++    }
++}
++
++int main()
++{
++  ira_flattening ();
++  return 0;
++}
++
++/* { dg-final { scan-wpa-ipa-dump-times "Insert page check" 1 "ipa_prefetch"} } */
++/* { dg-final { scan-wpa-ipa-dump-times "Insert 0 prefetch stmt:" 1 "ipa_prefetch"} } */
++/* { dg-final { scan-wpa-ipa-dump-times "Split dom_bb after condition stmts:" 1 "ipa_prefetch"} } */
+-- 
+2.33.0
+
diff --git a/0291-Fix-settings-for-wide-operations-tests.patch b/0291-Fix-settings-for-wide-operations-tests.patch
new file mode 100644
index 0000000..1e368b6
--- /dev/null
+++ b/0291-Fix-settings-for-wide-operations-tests.patch
@@ -0,0 +1,73 @@
+From 411792b0bbb63715d8e90d46eb4f0d9c810ce8ba Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 00812787 
+Date: Tue, 3 Sep 2024 21:26:03 +0800
+Subject: [PATCH 2/2] Fix settings for wide operations tests
+
+Signed-off-by: lin-houzhong 
+---
+ gcc/testsuite/gcc.dg/double_sized_mul-1.c | 8 +++++---
+ gcc/testsuite/gcc.dg/double_sized_mul-2.c | 9 +++++----
+ gcc/testsuite/gcc.dg/uaddsub.c            | 6 ++++--
+ 3 files changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.dg/double_sized_mul-1.c b/gcc/testsuite/gcc.dg/double_sized_mul-1.c
+index d32a25223..b848e02de 100644
+--- a/gcc/testsuite/gcc.dg/double_sized_mul-1.c
++++ b/gcc/testsuite/gcc.dg/double_sized_mul-1.c
+@@ -1,7 +1,8 @@
+-/* { dg-do compile } */
++/* { dg-do compile { target aarch64*-*-* x86_64*-*-*} } */
+ /* fif-conversion-gimple and fuaddsub-overflow-match-all are required for
+    proper overflow detection in some cases.  */
+-/* { dg-options "-O2 -fif-conversion-gimple -march=armv8.2-a -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++/* { dg-options "-O2 -fif-conversion-gimple -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++/* { dg-additional-options "-march=armv8.2-a" { target aarch64*-*-* } } */
+ #include 
+ 
+ typedef unsigned __int128 uint128_t;
+@@ -138,4 +139,5 @@ uint128_t mul128_perm (uint64_t a, uint64_t b)
+   return res;
+ }
+ 
+-/* { dg-final { scan-tree-dump-times "double sized mul optimized: 1" 6 "widening_mul" } } */
++/* { dg-final { scan-tree-dump-times "double sized mul optimized: 1" 6 "widening_mul" { target aarch64*-*-* } } } */
++/* { dg-final { scan-tree-dump-times "double sized mul optimized: 1" 4 "widening_mul" { target x86_64*-*-* } } } */
+diff --git a/gcc/testsuite/gcc.dg/double_sized_mul-2.c b/gcc/testsuite/gcc.dg/double_sized_mul-2.c
+index ff35902b7..cf8f0aedd 100644
+--- a/gcc/testsuite/gcc.dg/double_sized_mul-2.c
++++ b/gcc/testsuite/gcc.dg/double_sized_mul-2.c
+@@ -1,7 +1,8 @@
+-/* { dg-do compile } */
+-/* fif-conversion-gimple is required for proper overflow detection
+-   in some cases.  */
+-/* { dg-options "-O2 -fif-conversion-gimple -march=armv8.2-a -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++/* { dg-do compile { target aarch64*-*-* x86_64*-*-*} } */
++/* fif-conversion-gimple and fuaddsub-overflow-match-all are required for
++   proper overflow detection in some cases.  */
++/* { dg-options "-O2 -fif-conversion-gimple -fuaddsub-overflow-match-all -fdump-tree-widening_mul-stats" } */
++/* { dg-additional-options "-march=armv8.2-a" { target aarch64*-*-* } } */
+ #include 
+ 
+ typedef unsigned __int128 uint128_t;
+diff --git a/gcc/testsuite/gcc.dg/uaddsub.c b/gcc/testsuite/gcc.dg/uaddsub.c
+index 96c26d308..dcb587fc8 100644
+--- a/gcc/testsuite/gcc.dg/uaddsub.c
++++ b/gcc/testsuite/gcc.dg/uaddsub.c
+@@ -1,5 +1,6 @@
+-/* { dg-do compile } */
++/* { dg-do compile { target aarch64*-*-* x86_64-*-* } } */
+ /* { dg-options "-O2 -fuaddsub-overflow-match-all -fdump-tree-optimized" } */
++/* { dg-additional-options "-march=armv8.2-a" { target aarch64*-*-* } } */
+ #include 
+ 
+ typedef unsigned __int128 uint128_t;
+@@ -140,4 +141,5 @@ uint256_t sub256 (uint128_t a, uint128_t b)
+ }
+ 
+ /* { dg-final { scan-tree-dump-times "= .ADD_OVERFLOW \\(a_\[0-9\]+\\(D\\), b_\[0-9\]+\\(D\\)\\)" 5 "optimized" } } */
+-/* { dg-final { scan-tree-dump-times "= .SUB_OVERFLOW \\(a_\[0-9\]+\\(D\\), b_\[0-9\]+\\(D\\)\\)" 5 "optimized" } } */
++/* { dg-final { scan-tree-dump-times "= .SUB_OVERFLOW \\(a_\[0-9\]+\\(D\\), b_\[0-9\]+\\(D\\)\\)" 5 "optimized" { target aarch64*-*-* } } } */
++/* { dg-final { scan-tree-dump-times "= .SUB_OVERFLOW \\(a_\[0-9\]+\\(D\\), b_\[0-9\]+\\(D\\)\\)" 4 "optimized" { target x86_64*-*-* } } } */
+-- 
+2.33.0
+
diff --git a/0292-Fix-errors-in-ipa-prefetch-IAORPF-and-IAOSJ0.patch b/0292-Fix-errors-in-ipa-prefetch-IAORPF-and-IAOSJ0.patch
new file mode 100644
index 0000000..13341df
--- /dev/null
+++ b/0292-Fix-errors-in-ipa-prefetch-IAORPF-and-IAOSJ0.patch
@@ -0,0 +1,42 @@
+From 808294bf0f32aaff1cc7e56a756b246d328b3402 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Fri, 6 Sep 2024 11:10:03 +0800
+Subject: [PATCH 2/3] Fix errors in ipa-prefetch (IAORPF and IAOSJ0)
+
+Signed-off-by: Diachkov Ilia 
+---
+ gcc/ipa-prefetch.cc | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index b000d4d75..74af55af0 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -1681,7 +1681,8 @@ insert_page_check (tree addr, tree_poly_offset_map &offset_map,
+   unsigned long long pmask = ~(param_ipa_prefetch_pagesize - 1);
+   tree pmask_cst = build_int_cst (utype, pmask);
+   tree off_tree = wide_int_to_tree (sizetype, offset);
+-  gcc_assert (TREE_CODE (addr_type) == POINTER_TYPE);
++  gcc_assert (TREE_CODE (addr_type) == POINTER_TYPE
++	      || TREE_CODE (addr_type) == REFERENCE_TYPE);
+   tree addr_with_offset = gimple_build (&stmts, POINTER_PLUS_EXPR,
+ 					addr_type, addr, off_tree);
+   tree conv_addr = make_ssa_name (utype);
+@@ -2082,11 +2083,11 @@ optimize_function (cgraph_node *n, function *fn)
+   for (unsigned int i = 0; i < vmrs.length (); i++)
+     find_nearest_common_post_dominator (vmrs[i], dom_bb);
+ 
+-  if (!dom_bb)
++  if (!dom_bb || dom_bb->index == ENTRY_BLOCK || dom_bb->index == EXIT_BLOCK)
+     {
+       if (dump_file)
+-	fprintf (dump_file, "Post dominator bb for MRs is not found.  "
+-		 "Skip the case.\n");
++	fprintf (dump_file, "Post dominator bb for MRs is not found or "
++		 "it's an entry/exit block.  Skip the case.\n");
+       return 0;
+     }
+   else if (dump_file)
+-- 
+2.33.0
+
diff --git a/0293-Fix-error-with-stmts-insertion-in-ipa-prefetch-for-I.patch b/0293-Fix-error-with-stmts-insertion-in-ipa-prefetch-for-I.patch
new file mode 100644
index 0000000..3c9ec25
--- /dev/null
+++ b/0293-Fix-error-with-stmts-insertion-in-ipa-prefetch-for-I.patch
@@ -0,0 +1,51 @@
+From bfb77997f423ffe3bdcbd8bb8d7f739fe51ce4f5 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Fri, 6 Sep 2024 11:36:11 +0800
+Subject: [PATCH 3/3] Fix error with stmts insertion in ipa-prefetch (for
+ IAO6R3)
+
+Signed-off-by: Diachkov Ilia 
+---
+ gcc/ipa-prefetch.cc | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index b000d4d75..6190c2ebb 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -2096,7 +2096,7 @@ optimize_function (cgraph_node *n, function *fn)
+       fprintf (dump_file, "\n");
+     }
+ 
+-  /* Try to find comp_mr's stmt in the dominator bb.  */
++  /* Try to find comp_mr's stmt in the post dominator bb.  */
+   gimple *last_used = NULL;
+   for (gimple_stmt_iterator si = gsi_last_bb (dom_bb); !gsi_end_p (si);
+        gsi_prev (&si))
+@@ -2168,7 +2168,22 @@ optimize_function (cgraph_node *n, function *fn)
+   vec pcalls = vNULL;
+   gimple *last_pref = NULL;
+   insert_prefetch_stmts (pcalls, stmts, last_pref, vmrs, processed_stmts);
+-  gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++
++  gimple *gstmt = gsi_stmt (gsi);
++  bool insert_after = last_used || gstmt == NULL || !is_ctrl_stmt (gstmt);
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Insert prefetch sequence %s stmt:\n",
++	       insert_after ? "after": "before");
++      if (gstmt)
++	print_gimple_stmt (dump_file, gstmt, 0);
++      else
++	fprintf (dump_file, "(no stmts)\n");
++    }
++  if (insert_after)
++    gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
++  else
++    gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);
+ 
+   correct_cfg (bbends, last_pref, dom_bb);
+ 
+-- 
+2.33.0
+
diff --git a/0294-Fix-errors-in-ipa-prefetch-IAO50J-and-IAO5H7.patch b/0294-Fix-errors-in-ipa-prefetch-IAO50J-and-IAO5H7.patch
new file mode 100644
index 0000000..43a88b8
--- /dev/null
+++ b/0294-Fix-errors-in-ipa-prefetch-IAO50J-and-IAO5H7.patch
@@ -0,0 +1,80 @@
+From cd79fc29d2cdb73836f8699355113e94b833e0e0 Mon Sep 17 00:00:00 2001
+From: Diachkov Ilia 
+Date: Wed, 11 Sep 2024 17:18:58 +0800
+Subject: [PATCH 2/2] Fix errors in ipa-prefetch(IAO50J and IAO5H7)
+
+Signed-off-by: Diachkov Ilia 
+---
+ gcc/ipa-prefetch.cc | 35 ++++++++++++++++++++++++++++++-----
+ 1 file changed, 30 insertions(+), 5 deletions(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index 5184687aa..685f9c267 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -2099,6 +2099,18 @@ optimize_function (cgraph_node *n, function *fn)
+       fprintf (dump_file, "\n");
+     }
+ 
++  /* Check that all used mrs dominate found post dominator bb.  This case
++     may be supported later by copying MR evaluation to the bb.  */
++  for (unsigned int i = 0; i < used_mr_vec.length (); i++)
++    if (!dominated_by_p (CDI_DOMINATORS, dom_bb,
++			 gimple_bb (used_mr_vec[i]->stmts[0])))
++      {
++	if (dump_file)
++	  fprintf (dump_file, "MR's (%d) bb is not dominate the found bb %d.  "
++		   "Skip the case.\n", used_mr_vec[i]->mr_id, dom_bb->index);
++	return 0;
++      }
++
+   /* Try to find comp_mr's stmt in the post dominator bb.  */
+   gimple *last_used = NULL;
+   for (gimple_stmt_iterator si = gsi_last_bb (dom_bb); !gsi_end_p (si);
+@@ -2133,17 +2145,29 @@ optimize_function (cgraph_node *n, function *fn)
+ 
+   /* Create new inc var.  Insert new_var = old_var + step * factor.  */
+   decl_map = new tree_map;
+-  gcc_assert (comp_mr->stmts[0] && gimple_assign_single_p (comp_mr->stmts[0]));
+-  tree inc_var = gimple_assign_lhs (comp_mr->stmts[0]);
++  gimple *old_inc_stmt = comp_mr->stmts[0];
++  gcc_assert (old_inc_stmt && gimple_assign_single_p (old_inc_stmt));
++  tree inc_var = gimple_assign_lhs (old_inc_stmt);
++  if (dump_file)
++    {
++      fprintf (dump_file, "Old inc stmt: ");
++      print_gimple_stmt (dump_file, old_inc_stmt, 0);
++    }
+   /* If old_var definition dominates the current use, just use it, otherwise
+      evaluate it just before new inc var evaluation.  */
+   gimple_seq stmts = NULL;
+   stmt_set processed_stmts;
+-  if (!dominated_by_p (CDI_DOMINATORS, dom_bb, gimple_bb (comp_mr->stmts[0])))
++  tree local_inc_var = inc_var;
++  if (!dominated_by_p (CDI_DOMINATORS, dom_bb, gimple_bb (old_inc_stmt)))
+     {
+       gimple *tmp = gimple_copy_and_remap_memref_stmts (comp_mr, stmts, 0, 0,
+ 							processed_stmts);
+-      inc_var = gimple_assign_lhs (tmp);
++      local_inc_var = gimple_assign_lhs (tmp);
++      if (dump_file)
++	{
++	  fprintf (dump_file, "Localized old inc stmt: ");
++	  print_gimple_stmt (dump_file, tmp, 0);
++	}
+     }
+   tree var_type = TREE_TYPE (inc_var);
+   enum tree_code inc_code;
+@@ -2155,7 +2179,8 @@ optimize_function (cgraph_node *n, function *fn)
+   HOST_WIDE_INT dist_val = tree_to_shwi (step)
+ 			   * param_ipa_prefetch_distance_factor;
+   tree dist = build_int_cst (TREE_TYPE (step), dist_val);
+-  tree new_inc_var = gimple_build (&stmts, inc_code, var_type, inc_var, dist);
++  tree new_inc_var = gimple_build (&stmts, inc_code, var_type, local_inc_var,
++				   dist);
+   (*decl_map)[inc_var] = new_inc_var;
+   if (dump_file)
+     {
+-- 
+2.33.0
+
diff --git a/0295-Fix-error-with-grouped_load-merge-in-slp-transpose-v.patch b/0295-Fix-error-with-grouped_load-merge-in-slp-transpose-v.patch
new file mode 100644
index 0000000..8540cd4
--- /dev/null
+++ b/0295-Fix-error-with-grouped_load-merge-in-slp-transpose-v.patch
@@ -0,0 +1,30 @@
+From 7b4cce4896cefefedba9545a9633585e086b7621 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Wed, 11 Sep 2024 18:26:22 +0800
+Subject: [PATCH 1/2] Fix error with grouped_load merge in
+ slp-transpose-vectorize (for IALR8B)
+
+---
+ gcc/tree-vect-slp.cc | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index e3e246977..d4870de43 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -3807,7 +3807,11 @@ vect_slp_grouped_load_find (bb_vec_info bb_vinfo, vec &visited,
+ 	 these two grouped loads need to be merged.  */
+       tree opb = get_op_base_address (first_element);
+       unsigned int grp_size_b = DR_GROUP_SIZE (first_element);
+-      if (opa == opb && grp_size_a == grp_size_b)
++      /* Ensure that the elements merge to load group meet the alignment condition (dr_misalignment) */
++      HOST_WIDE_INT diff = 0;
++      diff = (TREE_INT_CST_LOW (DR_INIT (first_element->dr_aux.dr))
++	      - TREE_INT_CST_LOW (DR_INIT (merge_first_element->dr_aux.dr)));
++      if (opa == opb && grp_size_a == grp_size_b && diff >= 0)
+ 	{
+ 	  res.safe_push (first_element);
+ 	  visited[i] = true;
+-- 
+2.33.0
+
diff --git a/0296-Fix-error-in-slp-transpose-vectorize-for-IAQFM3.patch b/0296-Fix-error-in-slp-transpose-vectorize-for-IAQFM3.patch
new file mode 100644
index 0000000..34862f2
--- /dev/null
+++ b/0296-Fix-error-in-slp-transpose-vectorize-for-IAQFM3.patch
@@ -0,0 +1,28 @@
+From b3a6a170bf1dc0e460e98a7fd02c92e6b036784a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Fri, 13 Sep 2024 14:13:07 +0800
+Subject: [PATCH 2/2] Fix error in slp-transpose-vectorize (for IAQFM3)
+
+---
+ gcc/tree-vect-slp.cc | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index d4870de43..d7e198dff 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -3811,7 +3811,10 @@ vect_slp_grouped_load_find (bb_vec_info bb_vinfo, vec &visited,
+       HOST_WIDE_INT diff = 0;
+       diff = (TREE_INT_CST_LOW (DR_INIT (first_element->dr_aux.dr))
+ 	      - TREE_INT_CST_LOW (DR_INIT (merge_first_element->dr_aux.dr)));
+-      if (opa == opb && grp_size_a == grp_size_b && diff >= 0)
++      if (opa == opb
++	  && grp_size_a == grp_size_b
++	  && diff >= 0
++	  && check_same_bb (first_element, merge_first_element))
+ 	{
+ 	  res.safe_push (first_element);
+ 	  visited[i] = true;
+-- 
+2.33.0
+
diff --git a/0297-Fix-grouped-load-merging-error-in-SLP-transpose-vectorization.patch b/0297-Fix-grouped-load-merging-error-in-SLP-transpose-vectorization.patch
new file mode 100644
index 0000000..21a24c0
--- /dev/null
+++ b/0297-Fix-grouped-load-merging-error-in-SLP-transpose-vectorization.patch
@@ -0,0 +1,26 @@
+From 8b30d71f881e15bfbc514f9b65fee178610e1536 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=E9=83=91=E6=99=A8=E5=8D=89?= 
+Date: Wed, 18 Sep 2024 10:48:55 +0800
+Subject: [PATCH] Fix error in slp-transpose-vectorize (for IARHFM)
+
+---
+ gcc/tree-vect-slp.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index d7e198dff..fbd638333 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -3814,7 +3814,8 @@ vect_slp_grouped_load_find (bb_vec_info bb_vinfo, vec &visited,
+       if (opa == opb
+ 	  && grp_size_a == grp_size_b
+ 	  && diff >= 0
+-	  && check_same_bb (first_element, merge_first_element))
++	  && check_same_bb (first_element, merge_first_element)
++	  && DR_PTR_INFO (first_element->dr_aux.dr) != DR_PTR_INFO (merge_first_element->dr_aux.dr))
+ 	{
+ 	  res.safe_push (first_element);
+ 	  visited[i] = true;
+-- 
+2.33.0
+
diff --git a/0298-Mark-prefetch-builtin-as-willreturn.patch b/0298-Mark-prefetch-builtin-as-willreturn.patch
new file mode 100644
index 0000000..7a489a5
--- /dev/null
+++ b/0298-Mark-prefetch-builtin-as-willreturn.patch
@@ -0,0 +1,99 @@
+From a252bbd11d22481a1e719ed36d800e2192abb369 Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 
+Date: Thu, 31 Oct 2024 15:49:27 +0800
+Subject: [PATCH 1/6] Mark prefetch builtin as willreturn
+
+Signed-off-by: Pronin Alexander 
+---
+ gcc/common.opt      |  4 ++++
+ gcc/gimple.cc       | 30 ++++++++++++++++++++++++++++++
+ gcc/gimple.h        |  1 +
+ gcc/tree-ssa-pre.cc |  4 +---
+ 4 files changed, 36 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 688d65e4d..be5fcc681 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1313,6 +1313,10 @@ fdelete-null-pointer-checks
+ Common Var(flag_delete_null_pointer_checks) Init(-1) Optimization
+ Delete useless null pointer checks.
+ 
++fbuiltin-will-return
++Common Var(flag_builtin_will_return) Optimization
++Consider some of the builtins as definitely returning.
++
+ fdevirtualize-at-ltrans
+ Common Var(flag_ltrans_devirtualize)
+ Stream extra data to support more aggressive devirtualization in LTO local transformation mode.
+diff --git a/gcc/gimple.cc b/gcc/gimple.cc
+index 9e62da426..04ca9f161 100644
+--- a/gcc/gimple.cc
++++ b/gcc/gimple.cc
+@@ -2998,6 +2998,36 @@ nonbarrier_call_p (gimple *call)
+   return false;
+ }
+ 
++static inline bool
++will_return_builtin_p (gimple *call)
++{
++  if (!flag_builtin_will_return)
++    return false;
++
++  if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
++    return false;
++
++  switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
++    {
++    case BUILT_IN_PREFETCH:
++      return true;
++    default:
++      return false;
++    }
++}
++
++bool
++will_return_call_p (gimple *call, function *fun)
++{
++  int flags = gimple_call_flags (call);
++  if (!(flags & (ECF_CONST|ECF_PURE))
++      || (flags & ECF_LOOPING_CONST_OR_PURE)
++      || stmt_can_throw_external (fun, call))
++    return will_return_builtin_p (call);
++
++  return true;
++}
++
+ /* Callback for walk_stmt_load_store_ops.
+  
+    Return TRUE if OP will dereference the tree stored in DATA, FALSE
+diff --git a/gcc/gimple.h b/gcc/gimple.h
+index 77a5a07e9..bb05a7664 100644
+--- a/gcc/gimple.h
++++ b/gcc/gimple.h
+@@ -1628,6 +1628,7 @@ extern bool gimple_asm_clobbers_memory_p (const gasm *);
+ extern void dump_decl_set (FILE *, bitmap);
+ extern bool nonfreeing_call_p (gimple *);
+ extern bool nonbarrier_call_p (gimple *);
++extern bool will_return_call_p (gimple *, function *);
+ extern bool infer_nonnull_range (gimple *, tree);
+ extern bool infer_nonnull_range_by_dereference (gimple *, tree);
+ extern bool infer_nonnull_range_by_attribute (gimple *, tree);
+diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
+index 98134b5d3..b5264133a 100644
+--- a/gcc/tree-ssa-pre.cc
++++ b/gcc/tree-ssa-pre.cc
+@@ -3988,9 +3988,7 @@ compute_avail (function *fun)
+ 		 that forbids hoisting possibly trapping expressions
+ 		 before it.  */
+ 	      int flags = gimple_call_flags (stmt);
+-	      if (!(flags & (ECF_CONST|ECF_PURE))
+-		  || (flags & ECF_LOOPING_CONST_OR_PURE)
+-		  || stmt_can_throw_external (fun, stmt))
++	      if (!will_return_call_p (stmt, fun))
+ 		/* Defer setting of BB_MAY_NOTRETURN to avoid it
+ 		   influencing the processing of the call itself.  */
+ 		set_bb_may_notreturn = true;
+-- 
+2.33.0
+
diff --git a/0299-Backport-Disallow-pointer-operands-for-and-partly-PR.patch b/0299-Backport-Disallow-pointer-operands-for-and-partly-PR.patch
new file mode 100644
index 0000000..c0a733c
--- /dev/null
+++ b/0299-Backport-Disallow-pointer-operands-for-and-partly-PR.patch
@@ -0,0 +1,156 @@
+From 3b109376d057342a31267ea4c9bd422d940874cb Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Thu, 31 Oct 2024 16:09:43 +0800
+Subject: [PATCH 2/6] [Backport]Disallow pointer operands for |,^ and partly
+ &[PR106878]
+
+Signed-off-by: Jakub Jelinek 
+---
+ gcc/match.pd                                  |  6 ++++-
+ .../gcc.c-torture/compile/pr106878.c          | 15 +++++++++++++
+ gcc/tree-cfg.cc                               | 22 ++++++++++++++++---
+ gcc/tree-ssa-reassoc.cc                       | 16 +++++++++++++-
+ 4 files changed, 54 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr106878.c
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 8f41c292f..822e065e8 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -1655,6 +1655,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+ 	 && (int_fits_type_p (@1, TREE_TYPE (@0))
+ 	     || tree_nop_conversion_p (TREE_TYPE (@0), type)))
+ 	|| types_match (@0, @1))
++       && !POINTER_TYPE_P (TREE_TYPE (@0))
++       && TREE_CODE (TREE_TYPE (@0)) != OFFSET_TYPE
+        /* ???  This transform conflicts with fold-const.cc doing
+ 	  Convert (T)(x & c) into (T)x & (T)c, if c is an integer
+ 	  constants (if x has signed type, the sign bit cannot be set
+@@ -1691,7 +1693,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+   (if (GIMPLE
+        && TREE_CODE (@1) != INTEGER_CST
+        && tree_nop_conversion_p (type, TREE_TYPE (@2))
+-       && types_match (type, @0))
++       && types_match (type, @0)
++       && !POINTER_TYPE_P (TREE_TYPE (@0))
++       && TREE_CODE (TREE_TYPE (@0)) != OFFSET_TYPE)
+    (bitop @0 (convert @1)))))
+ 
+ (for bitop (bit_and bit_ior)
+diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106878.c b/gcc/testsuite/gcc.c-torture/compile/pr106878.c
+new file mode 100644
+index 000000000..c84571894
+--- /dev/null
++++ b/gcc/testsuite/gcc.c-torture/compile/pr106878.c
+@@ -0,0 +1,15 @@
++/* PR tree-optimization/106878 */
++
++typedef __INTPTR_TYPE__ intptr_t;
++typedef __UINTPTR_TYPE__ uintptr_t;
++int a;
++
++int
++foo (const int *c)
++{
++  uintptr_t d = ((intptr_t) c | (intptr_t) &a) & 65535 << 16;
++  intptr_t e = (intptr_t) c;
++  if (d != (e & 65535 << 16))
++    return 1;
++  return 0;
++}
+diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
+index 48b52f785..d33aaec8c 100644
+--- a/gcc/tree-cfg.cc
++++ b/gcc/tree-cfg.cc
+@@ -4163,7 +4163,9 @@ verify_gimple_assign_binary (gassign *stmt)
+     case ROUND_MOD_EXPR:
+     case RDIV_EXPR:
+     case EXACT_DIV_EXPR:
+-      /* Disallow pointer and offset types for many of the binary gimple. */
++    case BIT_IOR_EXPR:
++    case BIT_XOR_EXPR:
++      /* Disallow pointer and offset types for many of the binary gimple.  */
+       if (POINTER_TYPE_P (lhs_type)
+ 	  || TREE_CODE (lhs_type) == OFFSET_TYPE)
+ 	{
+@@ -4178,9 +4180,23 @@ verify_gimple_assign_binary (gassign *stmt)
+ 
+     case MIN_EXPR:
+     case MAX_EXPR:
+-    case BIT_IOR_EXPR:
+-    case BIT_XOR_EXPR:
++      /* Continue with generic binary expression handling.  */
++      break;
++
+     case BIT_AND_EXPR:
++      if (POINTER_TYPE_P (lhs_type)
++	  && TREE_CODE (rhs2) == INTEGER_CST)
++	break;
++      /* Disallow pointer and offset types for many of the binary gimple.  */
++      if (POINTER_TYPE_P (lhs_type)
++	  || TREE_CODE (lhs_type) == OFFSET_TYPE)
++	{
++	  error ("invalid types for %qs", code_name);
++	  debug_generic_expr (lhs_type);
++	  debug_generic_expr (rhs1_type);
++	  debug_generic_expr (rhs2_type);
++	  return true;
++	}
+       /* Continue with generic binary expression handling.  */
+       break;
+ 
+diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
+index e3d521e32..6baef4764 100644
+--- a/gcc/tree-ssa-reassoc.cc
++++ b/gcc/tree-ssa-reassoc.cc
+@@ -3617,10 +3617,14 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
+ 	tree type2 = NULL_TREE;
+ 	bool strict_overflow_p = false;
+ 	candidates.truncate (0);
++	if (POINTER_TYPE_P (type1))
++	  type1 = pointer_sized_int_node;
+ 	for (j = i; j; j = chains[j - 1])
+ 	  {
+ 	    tree type = TREE_TYPE (ranges[j - 1].exp);
+ 	    strict_overflow_p |= ranges[j - 1].strict_overflow_p;
++	    if (POINTER_TYPE_P (type))
++	      type = pointer_sized_int_node;
+ 	    if ((b % 4) == 3)
+ 	      {
+ 		/* For the signed < 0 cases, the types should be
+@@ -3651,6 +3655,8 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
+ 	    tree type = TREE_TYPE (ranges[j - 1].exp);
+ 	    if (j == k)
+ 	      continue;
++	    if (POINTER_TYPE_P (type))
++	      type = pointer_sized_int_node;
+ 	    if ((b % 4) == 3)
+ 	      {
+ 		if (!useless_type_conversion_p (type1, type))
+@@ -3680,7 +3686,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
+ 		op = r->exp;
+ 		continue;
+ 	      }
+-	    if (id == l)
++	    if (id == l || POINTER_TYPE_P (TREE_TYPE (op)))
+ 	      {
+ 		code = (b % 4) == 3 ? BIT_NOT_EXPR : NOP_EXPR;
+ 		g = gimple_build_assign (make_ssa_name (type1), code, op);
+@@ -3704,6 +3710,14 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
+ 	    gimple_seq_add_stmt_without_update (&seq, g);
+ 	    op = gimple_assign_lhs (g);
+ 	  }
++	type1 = TREE_TYPE (ranges[k - 1].exp);
++	if (POINTER_TYPE_P (type1))
++	  {
++	    gimple *g
++	      = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, op);
++	    gimple_seq_add_stmt_without_update (&seq, g);
++	    op = gimple_assign_lhs (g);
++	  }
+ 	candidates.pop ();
+ 	if (update_range_test (&ranges[k - 1], NULL, candidates.address (),
+ 			       candidates.length (), opcode, ops, op,
+-- 
+2.33.0
+
diff --git a/0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch b/0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch
new file mode 100644
index 0000000..0eca175
--- /dev/null
+++ b/0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch
@@ -0,0 +1,55 @@
+From 91ef8899a80e493042fd2687ad89064c9f90cf17 Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 
+Date: Thu, 31 Oct 2024 16:14:34 +0800
+Subject: [PATCH 3/6] Remove erroneous pattern from gimple ifcvt
+
+Signed-off-by: Pronin Alexander  
+---
+ gcc/match.pd                          |  2 +-
+ gcc/testsuite/gcc.dg/ifcvt-gimple-1.c | 21 +++++++++++++++++++++
+ 2 files changed, 22 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/ifcvt-gimple-1.c
+
+diff --git a/gcc/match.pd b/gcc/match.pd
+index 8f41c292f..2dd6581d1 100644
+--- a/gcc/match.pd
++++ b/gcc/match.pd
+@@ -4276,7 +4276,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+ )
+ 
+ (if (flag_if_conversion_gimple)
+- (for simple_op (plus minus bit_and bit_ior bit_xor)
++ (for simple_op (plus minus bit_ior bit_xor)
+   (simplify
+    (cond @0 (simple_op @1 INTEGER_CST@2) @1)
+    (switch
+diff --git a/gcc/testsuite/gcc.dg/ifcvt-gimple-1.c b/gcc/testsuite/gcc.dg/ifcvt-gimple-1.c
+new file mode 100644
+index 000000000..381a4ad51
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/ifcvt-gimple-1.c
+@@ -0,0 +1,21 @@
++/* { dg-do run } */
++/* { dg-options "-O2 -fno-inline -fif-conversion-gimple" } */
++
++#include 
++
++void foo(int a, int *p) {
++    *p = a;
++}
++
++void verify (int a) {
++    if (a != 3)
++        abort ();
++}
++
++int main() {
++    int a = 0;
++    foo (3, &a);
++    int tmp = (a > 7) ? a & 1 : a;
++    verify (tmp);
++    return 0;
++}
+-- 
+2.33.0
+
diff --git a/0301-Add-required-check-for-iteration-through-uses.patch b/0301-Add-required-check-for-iteration-through-uses.patch
new file mode 100644
index 0000000..105f4f7
--- /dev/null
+++ b/0301-Add-required-check-for-iteration-through-uses.patch
@@ -0,0 +1,33 @@
+From ca24d352e98e357f4f7b8f0d262201765705a08a Mon Sep 17 00:00:00 2001
+From: Pronin Alexander 
+Date: Thu, 31 Oct 2024 16:31:33 +0800
+Subject: [PATCH 4/6] Add required check for iteration through uses
+
+Signed-off-by: Pronin Alexander  
+---
+ gcc/tree-ssa-math-opts.cc | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
+index 2c06b8a60..80c06fa01 100644
+--- a/gcc/tree-ssa-math-opts.cc
++++ b/gcc/tree-ssa-math-opts.cc
+@@ -4938,8 +4938,13 @@ convert_double_size_mul (gimple_stmt_iterator *gsi, gimple *stmt)
+ 
+   /* Find the mult low part getter.  */
+   FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, match[3])
+-    if (gimple_assign_rhs_code (use_stmt) == REALPART_EXPR)
+-      break;
++    {
++      if (!is_gimple_assign (use_stmt))
++	continue;
++
++      if (gimple_assign_rhs_code (use_stmt) == REALPART_EXPR)
++	break;
++    }
+ 
+   /* Create high and low (if needed) parts extractors.  */
+   /* Low part.  */
+-- 
+2.33.0
+
diff --git a/0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch b/0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch
new file mode 100644
index 0000000..da25a9e
--- /dev/null
+++ b/0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch
@@ -0,0 +1,158 @@
+From 210147e28d542a03588ba3c3fa473301a03bb687 Mon Sep 17 00:00:00 2001
+From: Gmyrikov Konstantin 
+Date: Thu, 31 Oct 2024 16:45:15 +0800
+Subject: [PATCH 6/6] Added param for optimization for merging bb's with cheap
+ insns.Zero param means turned off optimization(default implementation),One
+ means turned on
+
+Signed-off-by: Gmyrikov Konstantin  
+---
+ gcc/params.opt                  |  4 +++
+ gcc/testsuite/gcc.dg/if_comb1.c | 13 +++++++++
+ gcc/testsuite/gcc.dg/if_comb2.c | 13 +++++++++
+ gcc/testsuite/gcc.dg/if_comb3.c | 12 +++++++++
+ gcc/tree-ssa-ifcombine.cc       | 47 ++++++++++++++++++++++++++++++---
+ 5 files changed, 86 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/if_comb1.c
+ create mode 100644 gcc/testsuite/gcc.dg/if_comb2.c
+ create mode 100644 gcc/testsuite/gcc.dg/if_comb3.c
+
+diff --git a/gcc/params.opt b/gcc/params.opt
+index fc700ab79..3ddfaf5b2 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -789,6 +789,10 @@ Maximum number of VALUEs handled during a single find_base_term call.
+ Common Joined UInteger Var(param_max_vrp_switch_assertions) Init(10) Param Optimization
+ Maximum number of assertions to add along the default edge of a switch statement during VRP.
+ 
++-param=merge-assign-stmts-ifcombine=
++Common Joined UInteger Var(param_merge_assign_stmts_ifcombine) Init(0) IntegerRange(0, 1) Param Optimization
++Whether bb's with cheap gimple_assign stmts should be merged in the ifcombine pass.
++
+ -param=min-crossjump-insns=
+ Common Joined UInteger Var(param_min_crossjump_insns) Init(5) IntegerRange(1, 65536) Param Optimization
+ The minimum number of matching instructions to consider for crossjumping.
+diff --git a/gcc/testsuite/gcc.dg/if_comb1.c b/gcc/testsuite/gcc.dg/if_comb1.c
+new file mode 100644
+index 000000000..e00adc37d
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/if_comb1.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-Ofast -S --param=merge-assign-stmts-ifcombine=1 -fdump-tree-ifcombine" } */
++
++int foo (double a, double b, int c)
++{
++    if (c < 10 || a - b > 1.0)
++        return 0;
++    else 
++        return 1;
++}
++
++/* { dg-final { scan-tree-dump "optimizing two comparisons" "ifcombine"} } */
++/* { dg-final { scan-tree-dump "Merging blocks" "ifcombine"} } */
+diff --git a/gcc/testsuite/gcc.dg/if_comb2.c b/gcc/testsuite/gcc.dg/if_comb2.c
+new file mode 100644
+index 000000000..176e7e726
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/if_comb2.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-Ofast -S --param=merge-assign-stmts-ifcombine=1 -fdump-tree-ifcombine" } */
++
++int foo (int a, int b, int c)
++{
++    if (a > 1 || b * c < 10)
++        return 0;
++    else 
++        return 1;
++}
++
++/* { dg-final { scan-tree-dump "optimizing two comparisons" "ifcombine"} } */
++/* { dg-final { scan-tree-dump "Merging blocks" "ifcombine"} } */
+diff --git a/gcc/testsuite/gcc.dg/if_comb3.c b/gcc/testsuite/gcc.dg/if_comb3.c
+new file mode 100644
+index 000000000..aa2e4510c
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/if_comb3.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++/* { dg-options "-Ofast -S --param=merge-assign-stmts-ifcombine=1 -fdump-tree-ifcombine" } */
++
++int foo (int a, int b, int c)
++{
++    if (a > 1 && b + c < 10)
++        a++;
++    return a;
++}
++
++/* { dg-final { scan-tree-dump "optimizing two comparisons" "ifcombine"} } */
++/* { dg-final { scan-tree-dump "Merging blocks" "ifcombine"} } */
+diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
+index ce9bbebf9..264a8bcae 100644
+--- a/gcc/tree-ssa-ifcombine.cc
++++ b/gcc/tree-ssa-ifcombine.cc
+@@ -110,6 +110,18 @@ recognize_if_then_else (basic_block cond_bb,
+   return true;
+ }
+ 
++/* Verify if gimple insn cheap for param=merge-assign-stmts-ifcombine
++   optimization.  */
++
++bool is_insn_cheap (enum tree_code t)
++{
++  static enum tree_code cheap_insns[] = {MULT_EXPR, PLUS_EXPR, MINUS_EXPR};
++  for (int i = 0; i < sizeof (cheap_insns)/sizeof (enum tree_code); i++)
++    if (t == cheap_insns[i])
++      return 1;
++  return 0;
++}
++
+ /* Verify if the basic block BB does not have side-effects.  Return
+    true in this case, else false.  */
+ 
+@@ -572,9 +584,38 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
+ 	      = param_logical_op_non_short_circuit;
+ 	  if (!logical_op_non_short_circuit || sanitize_coverage_p ())
+ 	    return false;
+-	  /* Only do this optimization if the inner bb contains only the conditional. */
+-	  if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (inner_cond_bb)))
+-	    return false;
++	  if (param_merge_assign_stmts_ifcombine)
++	    {
++	      int number_cheap_insns = 0;
++	      int number_conds = 0;
++	      for (auto i = gsi_start_nondebug_after_labels_bb
++	           (outer_cond_bb); !gsi_end_p (i); gsi_next_nondebug (&i))
++	        if (gimple_code (gsi_stmt (i)) == GIMPLE_ASSIGN
++	            && is_insn_cheap (gimple_assign_rhs_code (gsi_stmt (i))))
++	          number_cheap_insns++;
++	        else if (gimple_code (gsi_stmt (i)) == GIMPLE_COND)
++	          number_conds++;
++	      for (auto i = gsi_start_nondebug_after_labels_bb
++	           (inner_cond_bb); !gsi_end_p (i); gsi_next_nondebug (&i))
++	        if (gimple_code (gsi_stmt (i)) == GIMPLE_ASSIGN
++	            && is_insn_cheap (gimple_assign_rhs_code (gsi_stmt (i))))
++	          number_cheap_insns++;
++	        else if (gimple_code (gsi_stmt (i)) == GIMPLE_COND)
++	          number_conds++;
++	      if (!(number_cheap_insns == 1 && number_conds == 2)
++	          && !gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb
++	          (inner_cond_bb)))
++	        return false;
++	    }
++	  else
++	    {
++	    /* Only do this optimization if the inner bb contains
++	    only the conditional.  */
++	      if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb
++	          (inner_cond_bb)))
++	        return false;
++	    }
++
+ 	  t1 = fold_build2_loc (gimple_location (inner_cond),
+ 				inner_cond_code,
+ 				boolean_type_node,
+-- 
+2.33.0
+
diff --git a/0303-Add-generation-of-stream-in-functions-for-pre-versio.patch b/0303-Add-generation-of-stream-in-functions-for-pre-versio.patch
new file mode 100644
index 0000000..dfa965b
--- /dev/null
+++ b/0303-Add-generation-of-stream-in-functions-for-pre-versio.patch
@@ -0,0 +1,6263 @@
+From 4789a6eae616df0b7d07901114c91a2099e4d56d Mon Sep 17 00:00:00 2001
+From: wangchunyang 
+Date: Wed, 13 Nov 2024 11:26:16 +0800
+Subject: [PATCH 1/2] Add generation of stream in functions for pre-version lto
+ objects
+
+---
+ gcc/lto-streamer.h    |    6 +
+ gcc/opt-read.awk      |    1 +
+ gcc/optc-save-gen.awk | 6044 ++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 6050 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
+index 597e9e405..9db1a20b3 100644
+--- a/gcc/lto-streamer.h
++++ b/gcc/lto-streamer.h
+@@ -943,12 +943,18 @@ void cl_target_option_stream_in (class data_in *,
+ 				 struct bitpack_d *,
+ 				 struct cl_target_option *);
+ 
++void cl_target_option_stream_in_prev (class data_in *,
++				 struct bitpack_d *,
++				 struct cl_target_option *);
++
+ void cl_optimization_stream_out (struct output_block *,
+ 				 struct bitpack_d *, struct cl_optimization *);
+ 
+ void cl_optimization_stream_in (class data_in *,
+ 				struct bitpack_d *, struct cl_optimization *);
+ 
++void cl_optimization_stream_in_prev (class data_in *,
++				struct bitpack_d *, struct cl_optimization *);
+ 
+ 
+ /* In lto-opts.cc.  */
+diff --git a/gcc/opt-read.awk b/gcc/opt-read.awk
+index ce3617c8d..624cf6e3d 100644
+--- a/gcc/opt-read.awk
++++ b/gcc/opt-read.awk
+@@ -71,6 +71,7 @@ BEGIN {
+ 			n_target_save++
+ 
+ 			extra_target_vars[n_extra_target_vars] = name
++			extra_target_vars_set[name] = 1
+ 			extra_target_var_types[n_extra_target_vars] = type
+ 			n_extra_target_vars++
+ 		}
+diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
+index 76e9b3cb9..7c012dd4e 100644
+--- a/gcc/optc-save-gen.awk
++++ b/gcc/optc-save-gen.awk
+@@ -174,6 +174,8 @@ print "  unsigned HOST_WIDE_INT mask = 0;";
+ j = 0;
+ k = 0;
+ for (i = 0; i < n_opt_other; i++) {
++	var_opt_other_j[var_opt_other[i]] = j;
++	var_opt_other_k[var_opt_other[i]] = k;
+ 	print "  if (opts_set->x_" var_opt_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -185,6 +187,8 @@ for (i = 0; i < n_opt_other; i++) {
+ }
+ 
+ for (i = 0; i < n_opt_int; i++) {
++	var_opt_int_j[var_opt_int[i]] = j;
++	var_opt_int_k[var_opt_int[i]] = k;
+ 	print "  if (opts_set->x_" var_opt_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -196,6 +200,8 @@ for (i = 0; i < n_opt_int; i++) {
+ }
+ 
+ for (i = 0; i < n_opt_enum; i++) {
++	var_opt_enum_j[var_opt_enum[i]] = j;
++	var_opt_enum_k[var_opt_enum[i]] = k;
+ 	print "  if (opts_set->x_" var_opt_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -207,6 +213,8 @@ for (i = 0; i < n_opt_enum; i++) {
+ }
+ 
+ for (i = 0; i < n_opt_short; i++) {
++	var_opt_short_j[var_opt_short[i]] = j;
++	var_opt_short_k[var_opt_short[i]] = k;
+ 	print "  if (opts_set->x_" var_opt_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -218,6 +226,8 @@ for (i = 0; i < n_opt_short; i++) {
+ }
+ 
+ for (i = 0; i < n_opt_char; i++) {
++	var_opt_char_j[var_opt_char[i]] = j;
++	var_opt_char_k[var_opt_char[i]] = k;
+ 	print "  if (opts_set->x_" var_opt_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -229,6 +239,8 @@ for (i = 0; i < n_opt_char; i++) {
+ }
+ 
+ for (i = 0; i < n_opt_string; i++) {
++	var_opt_string_j[var_opt_string[i]] = j;
++	var_opt_string_k[var_opt_string[i]] = k;
+ 	print "  if (opts_set->x_" var_opt_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -604,6 +616,8 @@ for (i = 0; i < n_extra_target_vars; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	extra_target_vars_j[extra_target_vars[i]] = j;
++	extra_target_vars_k[extra_target_vars[i]] = k;
+ 	print "  if (opts_set->x_" extra_target_vars[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -622,6 +636,8 @@ for (i = 0; i < n_target_other; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	var_target_other_j[var_target_other[i]] = j;
++	var_target_other_k[var_target_other[i]] = k;
+ 	print "  if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -636,6 +652,8 @@ for (i = 0; i < n_target_enum; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	var_target_enum_j[var_target_enum[i]] = j;
++	var_target_enum_k[var_target_enum[i]] = k;
+ 	print "  if (opts_set->x_" var_target_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -654,6 +672,8 @@ for (i = 0; i < n_target_int; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	var_target_int_j[var_target_int[i]] = j;
++	var_target_int_k[var_target_int[i]] = k;
+ 	print "  if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -668,6 +688,8 @@ for (i = 0; i < n_target_short; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	var_target_short_j[var_target_short[i]] = j;
++	var_target_short_k[var_target_short[i]] = k;
+ 	print "  if (opts_set->x_" var_target_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -682,6 +704,8 @@ for (i = 0; i < n_target_char; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	var_target_char_j[var_target_char[i]] = j;
++	var_target_char_k[var_target_char[i]] = k;
+ 	print "  if (opts_set->x_" var_target_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -696,6 +720,8 @@ for (i = 0; i < n_target_string; i++) {
+ 	if (j == 0 && k == 0) {
+ 		print "  unsigned HOST_WIDE_INT mask = 0;";
+ 	}
++	var_target_string_j[var_target_string[i]] = j;
++	var_target_string_k[var_target_string[i]] = k;
+ 	print "  if (opts_set->x_" var_target_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ 	j++;
+ 	if (j == 64) {
+@@ -1038,6 +1064,7 @@ for (i = 0; i < n_target_save; i++) {
+ 	sub(" *" name "$", "", type)
+ 	if (target_save_decl[i] ~ "^const char \\*+[_" alnum "]+$") {
+ 		var_target_str[n_target_str++] = name;
++		var_target_str_set[name] = 1;
+ 		string_options_names[name]++
+ 	}
+ 	else {
+@@ -1048,12 +1075,14 @@ for (i = 0; i < n_target_save; i++) {
+ 			sub("\\[.+", "", name)
+ 			sub(" [^ ]+$", "", type)
+ 			var_target_array[n_target_array] = name
++			var_target_array_set[name] = 1
+ 			var_target_array_type[n_target_array] = type
+ 			var_target_array_size[n_target_array++] = size
+ 		}
+ 		else {
+ 			var_target_val_type[n_target_val] = type;
+ 			var_target_val[n_target_val++] = name;
++			var_target_val_set[name] = 1;
+ 		}
+ 	}
+ }
+@@ -1069,17 +1098,21 @@ if (have_save) {
+ 
+ 			var_list_seen[name]++;
+ 			otype = var_type_struct(flags[i])
+-			if (otype ~ "^const char \\**$")
++			if (otype ~ "^const char \\**$") {
+ 				var_target_str[n_target_str++] = "x_" name;
++				var_target_str_set["x_" name] = 1;
++			}
+ 			else {
+ 				var_target_val_type[n_target_val] = otype;
+ 				var_target_val[n_target_val++] = "x_" name;
++				var_target_val_set["x_" name];
+ 			}
+ 		}
+ 	}
+ } else {
+ 	var_target_val_type[n_target_val] = "int";
+ 	var_target_val[n_target_val++] = "x_target_flags";
++	var_target_val_set["x_target_flags"] = 1;
+ }
+ 
+ for (i = 0; i < n_target_str; i++) {
+@@ -1253,6 +1286,224 @@ for (i = 0; i < n_target_int; i++) {
+ 
+ print "}";
+ 
++print "";
++print "/* Stream in target options  */";
++print "void";
++print "cl_target_option_stream_in_prev (struct data_in *data_in ATTRIBUTE_UNUSED,";
++print "                                 struct bitpack_d *bp ATTRIBUTE_UNUSED,";
++print "                                 struct cl_target_option *ptr ATTRIBUTE_UNUSED)";
++print "{";
++if ("x_aarch64_branch_protection_string" in var_target_str_set) {
++  print "  ptr->x_aarch64_branch_protection_string = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_aarch64_branch_protection_string)"
++  print "  ptr->x_aarch64_branch_protection_string = xstrdup (ptr->x_aarch64_branch_protection_string);"
++}
++else {
++  print "  bp_unpack_string (data_in, bp);"
++}
++if ("x_aarch64_override_tune_string" in var_target_str_set) {
++  print "  ptr->x_aarch64_override_tune_string = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_aarch64_override_tune_string)"
++  print "  ptr->x_aarch64_override_tune_string = xstrdup (ptr->x_aarch64_override_tune_string);"
++}
++else {
++  print "  bp_unpack_string (data_in, bp);"
++}
++if ("x_aarch64_asm_isa_flags" in var_target_val_set) {
++  print "  ptr->x_aarch64_asm_isa_flags = (aarch64_feature_flags) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_isa_flags" in var_target_val_set) {
++  print "  ptr->x_aarch64_isa_flags = (aarch64_feature_flags) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_selected_arch" in var_target_val_set) {
++  print "  ptr->x_selected_arch = (enum aarch64_arch) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_ra_sign_key" in var_target_val_set) {
++  print "  ptr->x_aarch64_ra_sign_key = (enum aarch64_key_type) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_selected_tune" in var_target_val_set) {
++  print "  ptr->x_selected_tune = (enum aarch64_processor) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_stack_protector_guard_offset" in var_target_val_set) {
++  print "  ptr->x_aarch64_stack_protector_guard_offset = (long) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_enable_bti" in var_target_val_set) {
++  print "  ptr->x_aarch64_enable_bti = (unsigned) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_cmodel_var" in var_target_val_set) {
++  print "  ptr->x_aarch64_cmodel_var = (enum aarch64_code_model ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_fix_a53_err835769" in var_target_val_set) {
++  print "  ptr->x_aarch64_fix_a53_err835769 = (signed char ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_fix_a53_err843419" in var_target_val_set) {
++  print "  ptr->x_aarch64_fix_a53_err843419 = (signed char ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_target_flags" in var_target_val_set) {
++  print "  ptr->x_target_flags = (/* - */ int ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_flag_omit_leaf_frame_pointer" in var_target_val_set) {
++  print "  ptr->x_flag_omit_leaf_frame_pointer = (signed char ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_flag_outline_atomics" in var_target_val_set) {
++  print "  ptr->x_aarch64_flag_outline_atomics = (signed char ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_pcrelative_literal_loads" in var_target_val_set) {
++  print "  ptr->x_pcrelative_literal_loads = (signed char ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_ra_sign_scope" in var_target_val_set) {
++  print "  ptr->x_aarch64_ra_sign_scope = (enum aarch64_function_type ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++if ("x_aarch64_tls_dialect" in var_target_val_set) {
++  print "  ptr->x_aarch64_tls_dialect = (enum aarch64_tls_type ) bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++print "  unsigned HOST_WIDE_INT explicit_mask_prev[1];"
++print "  for (size_t i = 0; i < 1; i++)"
++print "    explicit_mask_prev[i] = bp_unpack_value (bp, 64);"
++print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)"
++print "    ptr->explicit_mask[i] = 0;"
++if ("aarch64_asm_isa_flags" in extra_target_vars_k) {
++  k = extra_target_vars_k["aarch64_asm_isa_flags"]
++  j = extra_target_vars_j["aarch64_asm_isa_flags"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_isa_flags" in extra_target_vars_k) {
++  k = extra_target_vars_k["aarch64_isa_flags"]
++  j = extra_target_vars_j["aarch64_isa_flags"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("selected_arch" in extra_target_vars_k) {
++  k = extra_target_vars_k["selected_arch"]
++  j = extra_target_vars_j["selected_arch"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_ra_sign_key" in extra_target_vars_k) {
++  k = extra_target_vars_k["aarch64_ra_sign_key"]
++  j = extra_target_vars_j["aarch64_ra_sign_key"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("selected_tune" in extra_target_vars_k) {
++  k = extra_target_vars_k["selected_tune"]
++  j = extra_target_vars_j["selected_tune"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_stack_protector_guard_offset" in extra_target_vars_k) {
++  k = extra_target_vars_k["aarch64_stack_protector_guard_offset"]
++  j = extra_target_vars_j["aarch64_stack_protector_guard_offset"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_enable_bti" in extra_target_vars_k) {
++  k = extra_target_vars_k["aarch64_enable_bti"]
++  j = extra_target_vars_j["aarch64_enable_bti"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_cmodel_var" in var_target_enum_k) {
++  k = var_target_enum_k["aarch64_cmodel_var"]
++  j = var_target_enum_j["aarch64_cmodel_var"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_ra_sign_scope" in var_target_enum_k) {
++  k = var_target_enum_k["aarch64_ra_sign_scope"]
++  j = var_target_enum_j["aarch64_ra_sign_scope"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_tls_dialect" in var_target_enum_k) {
++  k = var_target_enum_k["aarch64_tls_dialect"]
++  j = var_target_enum_j["aarch64_tls_dialect"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_fix_a53_err835769" in var_target_char_k) {
++  k = var_target_char_k["aarch64_fix_a53_err835769"]
++  j = var_target_char_j["aarch64_fix_a53_err835769"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_fix_a53_err843419" in var_target_char_k) {
++  k = var_target_char_k["aarch64_fix_a53_err843419"]
++  j = var_target_char_j["aarch64_fix_a53_err843419"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_omit_leaf_frame_pointer" in var_target_char_k) {
++  k = var_target_char_k["flag_omit_leaf_frame_pointer"]
++  j = var_target_char_j["flag_omit_leaf_frame_pointer"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_flag_outline_atomics" in var_target_char_k) {
++  k = var_target_char_k["aarch64_flag_outline_atomics"]
++  j = var_target_char_j["aarch64_flag_outline_atomics"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("pcrelative_literal_loads" in var_target_char_k) {
++  k = var_target_char_k["pcrelative_literal_loads"]
++  j = var_target_char_j["pcrelative_literal_loads"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_branch_protection_string" in var_target_string_k) {
++  k = var_target_string_k["aarch64_branch_protection_string"]
++  j = var_target_string_j["aarch64_branch_protection_string"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("aarch64_override_tune_string" in var_target_string_k) {
++  k = var_target_string_k["aarch64_override_tune_string"]
++  j = var_target_string_j["aarch64_override_tune_string"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("target_flags" in var_target_explicit_mask) {
++  print "  ptr->explicit_mask_target_flags = bp_unpack_value (bp, 64);"
++}
++else {
++  print "  bp_unpack_value (bp, 64);"
++}
++print "}";
++print "";
++
+ print "/* free heap memory used by target options  */";
+ print "void";
+ print "cl_target_option_free (struct cl_target_option *ptr ATTRIBUTE_UNUSED)";
+@@ -1266,15 +1517,19 @@ print "}";
+ 
+ n_opt_val = 4;
+ var_opt_val[0] = "x_optimize"
++var_opt_val_set["x_optimize"] = 1
+ var_opt_val_type[0] = "char "
+ var_opt_hash[0] = 1;
+ var_opt_val[1] = "x_optimize_size"
++var_opt_val_set["x_optimize_size"] = 1
+ var_opt_val_type[1] = "char "
+ var_opt_hash[1] = 1;
+ var_opt_val[2] = "x_optimize_debug"
++var_opt_val_set["x_optimize_debug"] = 1
+ var_opt_val_type[2] = "char "
+ var_opt_hash[2] = 1;
+ var_opt_val[3] = "x_optimize_fast"
++var_opt_val_set["x_optimize_fast"] = 1
+ var_opt_val_type[3] = "char "
+ var_opt_hash[3] = 1;
+ for (i = 0; i < n_opts; i++) {
+@@ -1291,6 +1546,7 @@ for (i = 0; i < n_opts; i++) {
+ 		otype = var_type_struct(flags[i])
+ 		var_opt_val_type[n_opt_val] = otype;
+ 		var_opt_val[n_opt_val] = "x_" name;
++		var_opt_val_set["x_" name] = 1;
+ 		var_opt_hash[n_opt_val] = flag_set_p("Optimization", flags[i]);
+ 		var_opt_init[n_opt_val] = opt_args("Init", flags[i]);
+ 		n_opt_val++;
+@@ -1415,6 +1671,5792 @@ for (i = 0; i < n_opt_val; i++) {
+ print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+ print "    ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";
+ print "}";
++
++print "";
++print "/* Stream in optimization options  */";
++print "void";
++print "cl_optimization_stream_in_prev (struct data_in *data_in ATTRIBUTE_UNUSED,";
++print "                                struct bitpack_d *bp ATTRIBUTE_UNUSED,";
++print "                                struct cl_optimization *ptr ATTRIBUTE_UNUSED)";
++print "{";
++if ("x_optimize" in var_opt_val_set) {
++  print "  ptr->x_optimize = (char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_optimize_size" in var_opt_val_set) {
++  print "  ptr->x_optimize_size = (char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_optimize_debug" in var_opt_val_set) {
++  print "  ptr->x_optimize_debug = (char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_optimize_fast" in var_opt_val_set) {
++  print "  ptr->x_optimize_fast = (char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_align_loop_iterations" in var_opt_val_set) {
++  print "  ptr->x_param_align_loop_iterations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4 > (int ) 10)"
++  print "    ptr->x_param_align_loop_iterations ^= 4;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_align_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_align_threshold = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_align_threshold ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_protect_allocas" in var_opt_val_set) {
++  print "  ptr->x_param_asan_protect_allocas = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_asan_protect_allocas ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_instrument_reads" in var_opt_val_set) {
++  print "  ptr->x_param_asan_instrument_reads = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_asan_instrument_reads ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_instrument_writes" in var_opt_val_set) {
++  print "  ptr->x_param_asan_instrument_writes = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_asan_instrument_writes ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_instrumentation_with_call_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_asan_instrumentation_with_call_threshold = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (7000 > (int ) 10)"
++  print "    ptr->x_param_asan_instrumentation_with_call_threshold ^= 7000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_memintrin" in var_opt_val_set) {
++  print "  ptr->x_param_asan_memintrin = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_asan_memintrin ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_stack" in var_opt_val_set) {
++  print "  ptr->x_param_asan_stack = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_asan_stack ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_asan_use_after_return" in var_opt_val_set) {
++  print "  ptr->x_param_asan_use_after_return = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_asan_use_after_return ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_avg_loop_niter" in var_opt_val_set) {
++  print "  ptr->x_param_avg_loop_niter = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_avg_loop_niter ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_avoid_fma_max_bits" in var_opt_val_set) {
++  print "  ptr->x_param_avoid_fma_max_bits = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_builtin_expect_probability" in var_opt_val_set) {
++  print "  ptr->x_param_builtin_expect_probability = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (90 > (int ) 10)"
++  print "    ptr->x_param_builtin_expect_probability ^= 90;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_builtin_string_cmp_inline_length" in var_opt_val_set) {
++  print "  ptr->x_param_builtin_string_cmp_inline_length = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_builtin_string_cmp_inline_length ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_case_values_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_case_values_threshold = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_comdat_sharing_probability" in var_opt_val_set) {
++  print "  ptr->x_param_comdat_sharing_probability = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (20 > (int ) 10)"
++  print "    ptr->x_param_comdat_sharing_probability ^= 20;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_pointer_compression_size" in var_opt_val_set) {
++  print "  ptr->x_param_pointer_compression_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_pointer_compression_size ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_construct_interfere_size" in var_opt_val_set) {
++  print "  ptr->x_param_construct_interfere_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (0 > (int ) 10)"
++  print "    ptr->x_param_construct_interfere_size ^= 0;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_destruct_interfere_size" in var_opt_val_set) {
++  print "  ptr->x_param_destruct_interfere_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (0 > (int ) 10)"
++  print "    ptr->x_param_destruct_interfere_size ^= 0;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_dse_max_alias_queries_per_store" in var_opt_val_set) {
++  print "  ptr->x_param_dse_max_alias_queries_per_store = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (256 > (int ) 10)"
++  print "    ptr->x_param_dse_max_alias_queries_per_store ^= 256;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_dse_max_object_size" in var_opt_val_set) {
++  print "  ptr->x_param_dse_max_object_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (256 > (int ) 10)"
++  print "    ptr->x_param_dse_max_object_size ^= 256;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_early_inlining_insns" in var_opt_val_set) {
++  print "  ptr->x_param_early_inlining_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (6 > (int ) 10)"
++  print "    ptr->x_param_early_inlining_insns ^= 6;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_evrp_mode" in var_opt_val_set) {
++  print "  ptr->x_param_evrp_mode = (enum evrp_mode ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_evrp_sparse_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_evrp_sparse_threshold = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (800 > (int ) 10)"
++  print "    ptr->x_param_evrp_sparse_threshold ^= 800;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_evrp_switch_limit" in var_opt_val_set) {
++  print "  ptr->x_param_evrp_switch_limit = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_evrp_switch_limit ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_fsm_scale_path_blocks" in var_opt_val_set) {
++  print "  ptr->x_param_fsm_scale_path_blocks = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_fsm_scale_path_blocks ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_fsm_scale_path_stmts" in var_opt_val_set) {
++  print "  ptr->x_param_fsm_scale_path_stmts = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_fsm_scale_path_stmts ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_gcse_after_reload_critical_fraction" in var_opt_val_set) {
++  print "  ptr->x_param_gcse_after_reload_critical_fraction = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_gcse_after_reload_critical_fraction ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_gcse_after_reload_partial_fraction" in var_opt_val_set) {
++  print "  ptr->x_param_gcse_after_reload_partial_fraction = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_gcse_after_reload_partial_fraction ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_gcse_cost_distance_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_gcse_cost_distance_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_gcse_cost_distance_ratio ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_gcse_unrestricted_cost" in var_opt_val_set) {
++  print "  ptr->x_param_gcse_unrestricted_cost = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_gcse_unrestricted_cost ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_graphite_max_arrays_per_scop" in var_opt_val_set) {
++  print "  ptr->x_param_graphite_max_arrays_per_scop = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_graphite_max_arrays_per_scop ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_graphite_max_nb_scop_params" in var_opt_val_set) {
++  print "  ptr->x_param_graphite_max_nb_scop_params = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_graphite_max_nb_scop_params ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_hwasan_instrument_allocas" in var_opt_val_set) {
++  print "  ptr->x_param_hwasan_instrument_allocas = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_hwasan_instrument_allocas ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_hwasan_instrument_mem_intrinsics" in var_opt_val_set) {
++  print "  ptr->x_param_hwasan_instrument_mem_intrinsics = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_hwasan_instrument_mem_intrinsics ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_hwasan_instrument_reads" in var_opt_val_set) {
++  print "  ptr->x_param_hwasan_instrument_reads = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_hwasan_instrument_reads ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_hwasan_instrument_stack" in var_opt_val_set) {
++  print "  ptr->x_param_hwasan_instrument_stack = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_hwasan_instrument_stack ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_hwasan_instrument_writes" in var_opt_val_set) {
++  print "  ptr->x_param_hwasan_instrument_writes = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_hwasan_instrument_writes ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_hwasan_random_frame_tag" in var_opt_val_set) {
++  print "  ptr->x_param_hwasan_random_frame_tag = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_hwasan_random_frame_tag ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ifcvt_allow_register_renaming" in var_opt_val_set) {
++  print "  ptr->x_param_ifcvt_allow_register_renaming = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_inline_heuristics_hint_percent" in var_opt_val_set) {
++  print "  ptr->x_param_inline_heuristics_hint_percent = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_inline_heuristics_hint_percent ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_inline_min_speedup" in var_opt_val_set) {
++  print "  ptr->x_param_inline_min_speedup = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (30 > (int ) 10)"
++  print "    ptr->x_param_inline_min_speedup ^= 30;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_inline_unit_growth" in var_opt_val_set) {
++  print "  ptr->x_param_inline_unit_growth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_inline_unit_growth ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_eval_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_eval_threshold = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (500 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_eval_threshold ^= 500;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_large_unit_insns" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_large_unit_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16000 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_large_unit_insns ^= 16000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_loop_hint_bonus" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_loop_hint_bonus = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (64 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_loop_hint_bonus ^= 64;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_max_recursive_depth" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_max_recursive_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_max_recursive_depth ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_min_recursive_probability" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_min_recursive_probability = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_min_recursive_probability ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_profile_count_base" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_profile_count_base = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_profile_count_base ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_recursion_penalty" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_recursion_penalty = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_recursion_penalty ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_recursive_freq_factor" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_recursive_freq_factor = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (6 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_recursive_freq_factor ^= 6;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_single_call_penalty" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_single_call_penalty = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (15 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_single_call_penalty ^= 15;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_unit_growth" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_unit_growth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_unit_growth ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_cp_value_list_size" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_cp_value_list_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_ipa_cp_value_list_size ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_jump_function_lookups" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_jump_function_lookups = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_ipa_jump_function_lookups ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_max_aa_steps" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_max_aa_steps = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (25000 > (int ) 10)"
++  print "    ptr->x_param_ipa_max_aa_steps ^= 25000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_max_agg_items" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_max_agg_items = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_ipa_max_agg_items ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_max_loop_predicates" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_max_loop_predicates = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_ipa_max_loop_predicates ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_max_param_expr_ops" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_max_param_expr_ops = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_ipa_max_param_expr_ops ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_max_switch_predicate_bounds" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_max_switch_predicate_bounds = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (5 > (int ) 10)"
++  print "    ptr->x_param_ipa_max_switch_predicate_bounds ^= 5;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_prefetch_distance_factor" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_prefetch_distance_factor = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4 > (int ) 10)"
++  print "    ptr->x_param_ipa_prefetch_distance_factor ^= 4;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_prefetch_locality" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_prefetch_locality = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_ipa_prefetch_locality ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_prefetch_pagesize" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_prefetch_pagesize = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4096 > (int ) 10)"
++  print "    ptr->x_param_ipa_prefetch_pagesize ^= 4096;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_sra_max_replacements" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_sra_max_replacements = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_ipa_sra_max_replacements ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ipa_sra_ptr_growth_factor" in var_opt_val_set) {
++  print "  ptr->x_param_ipa_sra_ptr_growth_factor = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_ipa_sra_ptr_growth_factor ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ira_consider_dup_in_all_alts" in var_opt_val_set) {
++  print "  ptr->x_param_ira_consider_dup_in_all_alts = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_ira_consider_dup_in_all_alts ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ira_loop_reserved_regs" in var_opt_val_set) {
++  print "  ptr->x_param_ira_loop_reserved_regs = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_ira_loop_reserved_regs ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ira_max_conflict_table_size" in var_opt_val_set) {
++  print "  ptr->x_param_ira_max_conflict_table_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_ira_max_conflict_table_size ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ira_max_loops_num" in var_opt_val_set) {
++  print "  ptr->x_param_ira_max_loops_num = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_ira_max_loops_num ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_iv_always_prune_cand_set_bound" in var_opt_val_set) {
++  print "  ptr->x_param_iv_always_prune_cand_set_bound = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_iv_always_prune_cand_set_bound ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_iv_consider_all_candidates_bound" in var_opt_val_set) {
++  print "  ptr->x_param_iv_consider_all_candidates_bound = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_iv_consider_all_candidates_bound ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_iv_max_considered_uses" in var_opt_val_set) {
++  print "  ptr->x_param_iv_max_considered_uses = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (250 > (int ) 10)"
++  print "    ptr->x_param_iv_max_considered_uses ^= 250;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_jump_table_max_growth_ratio_for_size" in var_opt_val_set) {
++  print "  ptr->x_param_jump_table_max_growth_ratio_for_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (300 > (int ) 10)"
++  print "    ptr->x_param_jump_table_max_growth_ratio_for_size ^= 300;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_jump_table_max_growth_ratio_for_speed" in var_opt_val_set) {
++  print "  ptr->x_param_jump_table_max_growth_ratio_for_speed = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (800 > (int ) 10)"
++  print "    ptr->x_param_jump_table_max_growth_ratio_for_speed ^= 800;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_l1_cache_line_size" in var_opt_val_set) {
++  print "  ptr->x_param_l1_cache_line_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_l1_cache_line_size ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_l1_cache_size" in var_opt_val_set) {
++  print "  ptr->x_param_l1_cache_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (64 > (int ) 10)"
++  print "    ptr->x_param_l1_cache_size ^= 64;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_l2_cache_size" in var_opt_val_set) {
++  print "  ptr->x_param_l2_cache_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (512 > (int ) 10)"
++  print "    ptr->x_param_l2_cache_size ^= 512;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_large_function_growth" in var_opt_val_set) {
++  print "  ptr->x_param_large_function_growth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_large_function_growth ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_large_function_insns" in var_opt_val_set) {
++  print "  ptr->x_param_large_function_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2700 > (int ) 10)"
++  print "    ptr->x_param_large_function_insns ^= 2700;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_stack_frame_growth" in var_opt_val_set) {
++  print "  ptr->x_param_stack_frame_growth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_stack_frame_growth ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_large_stack_frame" in var_opt_val_set) {
++  print "  ptr->x_param_large_stack_frame = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (256 > (int ) 10)"
++  print "    ptr->x_param_large_stack_frame ^= 256;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_large_unit_insns" in var_opt_val_set) {
++  print "  ptr->x_param_large_unit_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10000 > (int ) 10)"
++  print "    ptr->x_param_large_unit_insns ^= 10000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_lim_expensive" in var_opt_val_set) {
++  print "  ptr->x_param_lim_expensive = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (20 > (int ) 10)"
++  print "    ptr->x_param_lim_expensive ^= 20;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_block_tile_size" in var_opt_val_set) {
++  print "  ptr->x_param_loop_block_tile_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (51 > (int ) 10)"
++  print "    ptr->x_param_loop_block_tile_size ^= 51;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_interchange_max_num_stmts" in var_opt_val_set) {
++  print "  ptr->x_param_loop_interchange_max_num_stmts = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (64 > (int ) 10)"
++  print "    ptr->x_param_loop_interchange_max_num_stmts ^= 64;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_interchange_stride_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_loop_interchange_stride_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_loop_interchange_stride_ratio ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_invariant_max_bbs_in_loop" in var_opt_val_set) {
++  print "  ptr->x_param_loop_invariant_max_bbs_in_loop = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10000 > (int ) 10)"
++  print "    ptr->x_param_loop_invariant_max_bbs_in_loop ^= 10000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_max_datarefs_for_datadeps" in var_opt_val_set) {
++  print "  ptr->x_param_loop_max_datarefs_for_datadeps = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_loop_max_datarefs_for_datadeps ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_versioning_max_inner_insns" in var_opt_val_set) {
++  print "  ptr->x_param_loop_versioning_max_inner_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_loop_versioning_max_inner_insns ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_loop_versioning_max_outer_insns" in var_opt_val_set) {
++  print "  ptr->x_param_loop_versioning_max_outer_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_loop_versioning_max_outer_insns ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_lra_inheritance_ebb_probability_cutoff" in var_opt_val_set) {
++  print "  ptr->x_param_lra_inheritance_ebb_probability_cutoff = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_lra_inheritance_ebb_probability_cutoff ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_lra_max_considered_reload_pseudos" in var_opt_val_set) {
++  print "  ptr->x_param_lra_max_considered_reload_pseudos = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (500 > (int ) 10)"
++  print "    ptr->x_param_lra_max_considered_reload_pseudos ^= 500;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_average_unrolled_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_average_unrolled_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (80 > (int ) 10)"
++  print "    ptr->x_param_max_average_unrolled_insns ^= 80;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_combine_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_combine_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4 > (int ) 10)"
++  print "    ptr->x_param_max_combine_insns ^= 4;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_unroll_iterations" in var_opt_val_set) {
++  print "  ptr->x_param_max_unroll_iterations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_max_unroll_iterations ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_completely_peel_times" in var_opt_val_set) {
++  print "  ptr->x_param_max_completely_peel_times = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_max_completely_peel_times ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_completely_peeled_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_completely_peeled_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_max_completely_peeled_insns ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_crossjump_edges" in var_opt_val_set) {
++  print "  ptr->x_param_max_crossjump_edges = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_crossjump_edges ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_cse_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_cse_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_max_cse_insns ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_cse_path_length" in var_opt_val_set) {
++  print "  ptr->x_param_max_cse_path_length = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_cse_path_length ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_cselib_memory_locations" in var_opt_val_set) {
++  print "  ptr->x_param_max_cselib_memory_locations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (500 > (int ) 10)"
++  print "    ptr->x_param_max_cselib_memory_locations ^= 500;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_debug_marker_count" in var_opt_val_set) {
++  print "  ptr->x_param_max_debug_marker_count = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100000 > (int ) 10)"
++  print "    ptr->x_param_max_debug_marker_count ^= 100000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_delay_slot_insn_search" in var_opt_val_set) {
++  print "  ptr->x_param_max_delay_slot_insn_search = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_delay_slot_insn_search ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_delay_slot_live_search" in var_opt_val_set) {
++  print "  ptr->x_param_max_delay_slot_live_search = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (333 > (int ) 10)"
++  print "    ptr->x_param_max_delay_slot_live_search ^= 333;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_dse_active_local_stores" in var_opt_val_set) {
++  print "  ptr->x_param_max_dse_active_local_stores = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (5000 > (int ) 10)"
++  print "    ptr->x_param_max_dse_active_local_stores ^= 5000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_early_inliner_max_iterations" in var_opt_val_set) {
++  print "  ptr->x_param_early_inliner_max_iterations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_early_inliner_max_iterations ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_find_base_term_values" in var_opt_val_set) {
++  print "  ptr->x_param_max_find_base_term_values = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_max_find_base_term_values ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_fsm_thread_length" in var_opt_val_set) {
++  print "  ptr->x_param_max_fsm_thread_length = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_fsm_thread_length ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_fsm_thread_path_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_fsm_thread_path_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_fsm_thread_path_insns ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_gcse_insertion_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_max_gcse_insertion_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (20 > (int ) 10)"
++  print "    ptr->x_param_max_gcse_insertion_ratio ^= 20;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_gcse_memory" in var_opt_val_set) {
++  print "  ptr->x_param_max_gcse_memory = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (131072 > (int ) 10)"
++  print "    ptr->x_param_max_gcse_memory ^= 131072;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_goto_duplication_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_goto_duplication_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_max_goto_duplication_insns ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_grow_copy_bb_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_grow_copy_bb_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_max_grow_copy_bb_insns ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_hoist_depth" in var_opt_val_set) {
++  print "  ptr->x_param_max_hoist_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (30 > (int ) 10)"
++  print "    ptr->x_param_max_hoist_depth ^= 30;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_inline_functions_called_once_insns" in var_opt_val_set) {
++  print "  ptr->x_param_inline_functions_called_once_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4000 > (int ) 10)"
++  print "    ptr->x_param_inline_functions_called_once_insns ^= 4000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_inline_functions_called_once_loop_depth" in var_opt_val_set) {
++  print "  ptr->x_param_inline_functions_called_once_loop_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (6 > (int ) 10)"
++  print "    ptr->x_param_inline_functions_called_once_loop_depth ^= 6;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_insns_auto" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_insns_auto = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (15 > (int ) 10)"
++  print "    ptr->x_param_max_inline_insns_auto ^= 15;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_insns_recursive_auto" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_insns_recursive_auto = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (450 > (int ) 10)"
++  print "    ptr->x_param_max_inline_insns_recursive_auto ^= 450;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_insns_recursive" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_insns_recursive = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (450 > (int ) 10)"
++  print "    ptr->x_param_max_inline_insns_recursive ^= 450;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_insns_single" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_insns_single = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (70 > (int ) 10)"
++  print "    ptr->x_param_max_inline_insns_single ^= 70;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_insns_size" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_insns_size = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_insns_small" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_insns_small = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_recursive_depth_auto" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_recursive_depth_auto = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_max_inline_recursive_depth_auto ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_inline_recursive_depth" in var_opt_val_set) {
++  print "  ptr->x_param_max_inline_recursive_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_max_inline_recursive_depth ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_isl_operations" in var_opt_val_set) {
++  print "  ptr->x_param_max_isl_operations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (350000 > (int ) 10)"
++  print "    ptr->x_param_max_isl_operations ^= 350000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_iterations_computation_cost" in var_opt_val_set) {
++  print "  ptr->x_param_max_iterations_computation_cost = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_iterations_computation_cost ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_iterations_to_track" in var_opt_val_set) {
++  print "  ptr->x_param_max_iterations_to_track = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_max_iterations_to_track ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_jump_thread_duplication_stmts" in var_opt_val_set) {
++  print "  ptr->x_param_max_jump_thread_duplication_stmts = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (15 > (int ) 10)"
++  print "    ptr->x_param_max_jump_thread_duplication_stmts ^= 15;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_last_value_rtl" in var_opt_val_set) {
++  print "  ptr->x_param_max_last_value_rtl = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10000 > (int ) 10)"
++  print "    ptr->x_param_max_last_value_rtl ^= 10000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_loop_header_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_loop_header_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (20 > (int ) 10)"
++  print "    ptr->x_param_max_loop_header_insns ^= 20;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_modulo_backtrack_attempts" in var_opt_val_set) {
++  print "  ptr->x_param_max_modulo_backtrack_attempts = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_max_modulo_backtrack_attempts ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_partial_antic_length" in var_opt_val_set) {
++  print "  ptr->x_param_max_partial_antic_length = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_partial_antic_length ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_peel_branches" in var_opt_val_set) {
++  print "  ptr->x_param_max_peel_branches = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_max_peel_branches ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_peel_times" in var_opt_val_set) {
++  print "  ptr->x_param_max_peel_times = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_max_peel_times ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_peeled_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_peeled_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_peeled_insns ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_pending_list_length" in var_opt_val_set) {
++  print "  ptr->x_param_max_pending_list_length = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_max_pending_list_length ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_pipeline_region_blocks" in var_opt_val_set) {
++  print "  ptr->x_param_max_pipeline_region_blocks = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (15 > (int ) 10)"
++  print "    ptr->x_param_max_pipeline_region_blocks ^= 15;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_pipeline_region_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_pipeline_region_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_max_pipeline_region_insns ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_pow_sqrt_depth" in var_opt_val_set) {
++  print "  ptr->x_param_max_pow_sqrt_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (5 > (int ) 10)"
++  print "    ptr->x_param_max_pow_sqrt_depth ^= 5;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_predicted_iterations" in var_opt_val_set) {
++  print "  ptr->x_param_max_predicted_iterations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_predicted_iterations ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_reload_search_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_reload_search_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_reload_search_insns ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_rtl_if_conversion_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_rtl_if_conversion_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_rtl_if_conversion_insns ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_rtl_if_conversion_predictable_cost" in var_opt_val_set) {
++  print "  ptr->x_param_max_rtl_if_conversion_predictable_cost = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (20 > (int ) 10)"
++  print "    ptr->x_param_max_rtl_if_conversion_predictable_cost ^= 20;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_rtl_if_conversion_unpredictable_cost" in var_opt_val_set) {
++  print "  ptr->x_param_max_rtl_if_conversion_unpredictable_cost = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_max_rtl_if_conversion_unpredictable_cost ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_sched_extend_regions_iters" in var_opt_val_set) {
++  print "  ptr->x_param_max_sched_extend_regions_iters = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_sched_insn_conflict_delay" in var_opt_val_set) {
++  print "  ptr->x_param_max_sched_insn_conflict_delay = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_max_sched_insn_conflict_delay ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_sched_ready_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_sched_ready_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_sched_ready_insns ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_sched_region_blocks" in var_opt_val_set) {
++  print "  ptr->x_param_max_sched_region_blocks = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_sched_region_blocks ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_sched_region_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_sched_region_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_max_sched_region_insns ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_slsr_candidate_scan" in var_opt_val_set) {
++  print "  ptr->x_param_max_slsr_candidate_scan = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_max_slsr_candidate_scan ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_speculative_devirt_maydefs" in var_opt_val_set) {
++  print "  ptr->x_param_max_speculative_devirt_maydefs = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_max_speculative_devirt_maydefs ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_stores_to_merge" in var_opt_val_set) {
++  print "  ptr->x_param_max_stores_to_merge = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (64 > (int ) 10)"
++  print "    ptr->x_param_max_stores_to_merge ^= 64;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_stores_to_sink" in var_opt_val_set) {
++  print "  ptr->x_param_max_stores_to_sink = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_max_stores_to_sink ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_tail_merge_comparisons" in var_opt_val_set) {
++  print "  ptr->x_param_max_tail_merge_comparisons = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_tail_merge_comparisons ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_tail_merge_iterations" in var_opt_val_set) {
++  print "  ptr->x_param_max_tail_merge_iterations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_max_tail_merge_iterations ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_tracked_strlens" in var_opt_val_set) {
++  print "  ptr->x_param_max_tracked_strlens = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10000 > (int ) 10)"
++  print "    ptr->x_param_max_tracked_strlens ^= 10000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_tree_if_conversion_phi_args" in var_opt_val_set) {
++  print "  ptr->x_param_max_tree_if_conversion_phi_args = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4 > (int ) 10)"
++  print "    ptr->x_param_max_tree_if_conversion_phi_args ^= 4;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_unroll_times" in var_opt_val_set) {
++  print "  ptr->x_param_max_unroll_times = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_max_unroll_times ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_unrolled_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_unrolled_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_max_unrolled_insns ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_unswitch_insns" in var_opt_val_set) {
++  print "  ptr->x_param_max_unswitch_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_max_unswitch_insns ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_unswitch_level" in var_opt_val_set) {
++  print "  ptr->x_param_max_unswitch_level = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_max_unswitch_level ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_variable_expansions" in var_opt_val_set) {
++  print "  ptr->x_param_max_variable_expansions = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_max_variable_expansions ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_vartrack_expr_depth" in var_opt_val_set) {
++  print "  ptr->x_param_max_vartrack_expr_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (12 > (int ) 10)"
++  print "    ptr->x_param_max_vartrack_expr_depth ^= 12;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_vartrack_reverse_op_size" in var_opt_val_set) {
++  print "  ptr->x_param_max_vartrack_reverse_op_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_max_vartrack_reverse_op_size ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_vartrack_size" in var_opt_val_set) {
++  print "  ptr->x_param_max_vartrack_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50000000 > (int ) 10)"
++  print "    ptr->x_param_max_vartrack_size ^= 50000000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_max_vrp_switch_assertions" in var_opt_val_set) {
++  print "  ptr->x_param_max_vrp_switch_assertions = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_max_vrp_switch_assertions ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_crossjump_insns" in var_opt_val_set) {
++  print "  ptr->x_param_min_crossjump_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (5 > (int ) 10)"
++  print "    ptr->x_param_min_crossjump_insns ^= 5;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_inline_recursive_probability" in var_opt_val_set) {
++  print "  ptr->x_param_min_inline_recursive_probability = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_min_inline_recursive_probability ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_insn_to_prefetch_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_min_insn_to_prefetch_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (9 > (int ) 10)"
++  print "    ptr->x_param_min_insn_to_prefetch_ratio ^= 9;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_loop_cond_split_prob" in var_opt_val_set) {
++  print "  ptr->x_param_min_loop_cond_split_prob = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (30 > (int ) 10)"
++  print "    ptr->x_param_min_loop_cond_split_prob ^= 30;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_pagesize" in var_opt_val_set) {
++  print "  ptr->x_param_min_pagesize = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4096 > (int ) 10)"
++  print "    ptr->x_param_min_pagesize ^= 4096;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_size_for_stack_sharing" in var_opt_val_set) {
++  print "  ptr->x_param_min_size_for_stack_sharing = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_min_size_for_stack_sharing ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_spec_prob" in var_opt_val_set) {
++  print "  ptr->x_param_min_spec_prob = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_min_spec_prob ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_min_vect_loop_bound" in var_opt_val_set) {
++  print "  ptr->x_param_min_vect_loop_bound = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_accesses" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_accesses = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_modref_max_accesses ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_adjustments" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_adjustments = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_modref_max_adjustments ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_bases" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_bases = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_modref_max_bases ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_depth" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (256 > (int ) 10)"
++  print "    ptr->x_param_modref_max_depth ^= 256;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_escape_points" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_escape_points = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (256 > (int ) 10)"
++  print "    ptr->x_param_modref_max_escape_points ^= 256;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_refs" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_refs = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_modref_max_refs ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_modref_max_tests" in var_opt_val_set) {
++  print "  ptr->x_param_modref_max_tests = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (64 > (int ) 10)"
++  print "    ptr->x_param_modref_max_tests ^= 64;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ldp_dependency_search_range" in var_opt_val_set) {
++  print "  ptr->x_param_ldp_dependency_search_range = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (16 > (int ) 10)"
++  print "    ptr->x_param_ldp_dependency_search_range ^= 16;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_parloops_chunk_size" in var_opt_val_set) {
++  print "  ptr->x_param_parloops_chunk_size = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_parloops_min_per_thread" in var_opt_val_set) {
++  print "  ptr->x_param_parloops_min_per_thread = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_parloops_min_per_thread ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_parloops_schedule" in var_opt_val_set) {
++  print "  ptr->x_param_parloops_schedule = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_partial_inlining_entry_probability" in var_opt_val_set) {
++  print "  ptr->x_param_partial_inlining_entry_probability = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (70 > (int ) 10)"
++  print "    ptr->x_param_partial_inlining_entry_probability ^= 70;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_predictable_branch_outcome" in var_opt_val_set) {
++  print "  ptr->x_param_predictable_branch_outcome = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_predictable_branch_outcome ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_prefetch_dynamic_strides" in var_opt_val_set) {
++  print "  ptr->x_param_prefetch_dynamic_strides = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_prefetch_dynamic_strides ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_prefetch_latency" in var_opt_val_set) {
++  print "  ptr->x_param_prefetch_latency = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_prefetch_latency ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_prefetch_min_insn_to_mem_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_prefetch_min_insn_to_mem_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_prefetch_min_insn_to_mem_ratio ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_prefetch_minimum_stride" in var_opt_val_set) {
++  print "  ptr->x_param_prefetch_minimum_stride = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (-1 > (int ) 10)"
++  print "    ptr->x_param_prefetch_minimum_stride ^= -1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ranger_debug" in var_opt_val_set) {
++  print "  ptr->x_param_ranger_debug = (enum ranger_debug ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ranger_logical_depth" in var_opt_val_set) {
++  print "  ptr->x_param_ranger_logical_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (6 > (int ) 10)"
++  print "    ptr->x_param_ranger_logical_depth ^= 6;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_relation_block_limit" in var_opt_val_set) {
++  print "  ptr->x_param_relation_block_limit = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (200 > (int ) 10)"
++  print "    ptr->x_param_relation_block_limit ^= 200;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_rpo_vn_max_loop_depth" in var_opt_val_set) {
++  print "  ptr->x_param_rpo_vn_max_loop_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (7 > (int ) 10)"
++  print "    ptr->x_param_rpo_vn_max_loop_depth ^= 7;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sccvn_max_alias_queries_per_access" in var_opt_val_set) {
++  print "  ptr->x_param_sccvn_max_alias_queries_per_access = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_sccvn_max_alias_queries_per_access ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_scev_max_expr_complexity" in var_opt_val_set) {
++  print "  ptr->x_param_scev_max_expr_complexity = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_scev_max_expr_complexity ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_scev_max_expr_size" in var_opt_val_set) {
++  print "  ptr->x_param_scev_max_expr_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_scev_max_expr_size ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sched_autopref_queue_depth" in var_opt_val_set) {
++  print "  ptr->x_param_sched_autopref_queue_depth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (-1 > (int ) 10)"
++  print "    ptr->x_param_sched_autopref_queue_depth ^= -1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sched_mem_true_dep_cost" in var_opt_val_set) {
++  print "  ptr->x_param_sched_mem_true_dep_cost = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_sched_mem_true_dep_cost ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sched_pressure_algorithm" in var_opt_val_set) {
++  print "  ptr->x_param_sched_pressure_algorithm = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_sched_pressure_algorithm ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sched_spec_prob_cutoff" in var_opt_val_set) {
++  print "  ptr->x_param_sched_spec_prob_cutoff = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (40 > (int ) 10)"
++  print "    ptr->x_param_sched_spec_prob_cutoff ^= 40;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sched_state_edge_prob_cutoff" in var_opt_val_set) {
++  print "  ptr->x_param_sched_state_edge_prob_cutoff = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_sched_state_edge_prob_cutoff ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_selsched_insns_to_rename" in var_opt_val_set) {
++  print "  ptr->x_param_selsched_insns_to_rename = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_selsched_insns_to_rename ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_selsched_max_lookahead" in var_opt_val_set) {
++  print "  ptr->x_param_selsched_max_lookahead = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_selsched_max_lookahead ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_selsched_max_sched_times" in var_opt_val_set) {
++  print "  ptr->x_param_selsched_max_sched_times = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_selsched_max_sched_times ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_semi_relayout_level" in var_opt_val_set) {
++  print "  ptr->x_semi_relayout_level = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_simultaneous_prefetches" in var_opt_val_set) {
++  print "  ptr->x_param_simultaneous_prefetches = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (3 > (int ) 10)"
++  print "    ptr->x_param_simultaneous_prefetches ^= 3;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sink_frequency_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_sink_frequency_threshold = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (75 > (int ) 10)"
++  print "    ptr->x_param_sink_frequency_threshold ^= 75;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sms_dfa_history" in var_opt_val_set) {
++  print "  ptr->x_param_sms_dfa_history = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sms_loop_average_count_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_sms_loop_average_count_threshold = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sms_max_ii_factor" in var_opt_val_set) {
++  print "  ptr->x_param_sms_max_ii_factor = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_sms_max_ii_factor ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sms_min_sc" in var_opt_val_set) {
++  print "  ptr->x_param_sms_min_sc = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_sms_min_sc ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sra_max_propagations" in var_opt_val_set) {
++  print "  ptr->x_param_sra_max_propagations = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (32 > (int ) 10)"
++  print "    ptr->x_param_sra_max_propagations ^= 32;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sra_max_scalarization_size_size" in var_opt_val_set) {
++  print "  ptr->x_param_sra_max_scalarization_size_size = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_sra_max_scalarization_size_speed" in var_opt_val_set) {
++  print "  ptr->x_param_sra_max_scalarization_size_speed = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ssa_name_def_chain_limit" in var_opt_val_set) {
++  print "  ptr->x_param_ssa_name_def_chain_limit = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (512 > (int ) 10)"
++  print "    ptr->x_param_ssa_name_def_chain_limit ^= 512;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_ssp_buffer_size" in var_opt_val_set) {
++  print "  ptr->x_param_ssp_buffer_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_ssp_buffer_size ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_stack_clash_protection_guard_size" in var_opt_val_set) {
++  print "  ptr->x_param_stack_clash_protection_guard_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (12 > (int ) 10)"
++  print "    ptr->x_param_stack_clash_protection_guard_size ^= 12;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_stack_clash_protection_probe_interval" in var_opt_val_set) {
++  print "  ptr->x_param_stack_clash_protection_probe_interval = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (12 > (int ) 10)"
++  print "    ptr->x_param_stack_clash_protection_probe_interval ^= 12;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_store_merging_allow_unaligned" in var_opt_val_set) {
++  print "  ptr->x_param_store_merging_allow_unaligned = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_store_merging_allow_unaligned ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_store_merging_max_size" in var_opt_val_set) {
++  print "  ptr->x_param_store_merging_max_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (65536 > (int ) 10)"
++  print "    ptr->x_param_store_merging_max_size ^= 65536;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_struct_reorg_cold_struct_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_struct_reorg_cold_struct_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_struct_reorg_cold_struct_ratio ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_switch_conversion_branch_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_switch_conversion_branch_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (8 > (int ) 10)"
++  print "    ptr->x_param_switch_conversion_branch_ratio ^= 8;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_threader_debug" in var_opt_val_set) {
++  print "  ptr->x_param_threader_debug = (enum threader_debug ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tm_max_aggregate_size" in var_opt_val_set) {
++  print "  ptr->x_param_tm_max_aggregate_size = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (9 > (int ) 10)"
++  print "    ptr->x_param_tm_max_aggregate_size ^= 9;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tracer_dynamic_coverage_feedback" in var_opt_val_set) {
++  print "  ptr->x_param_tracer_dynamic_coverage_feedback = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (95 > (int ) 10)"
++  print "    ptr->x_param_tracer_dynamic_coverage_feedback ^= 95;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tracer_dynamic_coverage" in var_opt_val_set) {
++  print "  ptr->x_param_tracer_dynamic_coverage = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (75 > (int ) 10)"
++  print "    ptr->x_param_tracer_dynamic_coverage ^= 75;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tracer_max_code_growth" in var_opt_val_set) {
++  print "  ptr->x_param_tracer_max_code_growth = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (100 > (int ) 10)"
++  print "    ptr->x_param_tracer_max_code_growth ^= 100;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tracer_min_branch_probability_feedback" in var_opt_val_set) {
++  print "  ptr->x_param_tracer_min_branch_probability_feedback = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (80 > (int ) 10)"
++  print "    ptr->x_param_tracer_min_branch_probability_feedback ^= 80;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tracer_min_branch_probability" in var_opt_val_set) {
++  print "  ptr->x_param_tracer_min_branch_probability = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_tracer_min_branch_probability ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tracer_min_branch_ratio" in var_opt_val_set) {
++  print "  ptr->x_param_tracer_min_branch_ratio = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_tracer_min_branch_ratio ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_tree_reassoc_width" in var_opt_val_set) {
++  print "  ptr->x_param_tree_reassoc_width = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_uninit_control_dep_attempts" in var_opt_val_set) {
++  print "  ptr->x_param_uninit_control_dep_attempts = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1000 > (int ) 10)"
++  print "    ptr->x_param_uninit_control_dep_attempts ^= 1000;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_uninlined_function_insns" in var_opt_val_set) {
++  print "  ptr->x_param_uninlined_function_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_uninlined_function_insns ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_uninlined_function_time" in var_opt_val_set) {
++  print "  ptr->x_param_uninlined_function_time = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_uninlined_function_thunk_insns" in var_opt_val_set) {
++  print "  ptr->x_param_uninlined_function_thunk_insns = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_uninlined_function_thunk_insns ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_uninlined_function_thunk_time" in var_opt_val_set) {
++  print "  ptr->x_param_uninlined_function_thunk_time = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_uninlined_function_thunk_time ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_unlikely_bb_count_fraction" in var_opt_val_set) {
++  print "  ptr->x_param_unlikely_bb_count_fraction = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (20 > (int ) 10)"
++  print "    ptr->x_param_unlikely_bb_count_fraction ^= 20;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_unroll_jam_max_unroll" in var_opt_val_set) {
++  print "  ptr->x_param_unroll_jam_max_unroll = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (4 > (int ) 10)"
++  print "    ptr->x_param_unroll_jam_max_unroll ^= 4;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_unroll_jam_min_percent" in var_opt_val_set) {
++  print "  ptr->x_param_unroll_jam_min_percent = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_unroll_jam_min_percent ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_use_after_scope_direct_emission_threshold" in var_opt_val_set) {
++  print "  ptr->x_param_use_after_scope_direct_emission_threshold = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (256 > (int ) 10)"
++  print "    ptr->x_param_use_after_scope_direct_emission_threshold ^= 256;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_flexible_seg_len" in var_opt_val_set) {
++  print "  ptr->x_param_flexible_seg_len = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (0 > (int ) 10)"
++  print "    ptr->x_param_flexible_seg_len ^= 0;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_epilogues_nomask" in var_opt_val_set) {
++  print "  ptr->x_param_vect_epilogues_nomask = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_vect_epilogues_nomask ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_induction_float" in var_opt_val_set) {
++  print "  ptr->x_param_vect_induction_float = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (1 > (int ) 10)"
++  print "    ptr->x_param_vect_induction_float ^= 1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_inner_loop_cost_factor" in var_opt_val_set) {
++  print "  ptr->x_param_vect_inner_loop_cost_factor = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (50 > (int ) 10)"
++  print "    ptr->x_param_vect_inner_loop_cost_factor ^= 50;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_max_peeling_for_alignment" in var_opt_val_set) {
++  print "  ptr->x_param_vect_max_peeling_for_alignment = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (-1 > (int ) 10)"
++  print "    ptr->x_param_vect_max_peeling_for_alignment ^= -1;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_max_version_for_alias_checks" in var_opt_val_set) {
++  print "  ptr->x_param_vect_max_version_for_alias_checks = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (10 > (int ) 10)"
++  print "    ptr->x_param_vect_max_version_for_alias_checks ^= 10;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_max_version_for_alignment_checks" in var_opt_val_set) {
++  print "  ptr->x_param_vect_max_version_for_alignment_checks = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (6 > (int ) 10)"
++  print "    ptr->x_param_vect_max_version_for_alignment_checks ^= 6;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vect_partial_vector_usage" in var_opt_val_set) {
++  print "  ptr->x_param_vect_partial_vector_usage = (int ) bp_unpack_var_len_int (bp);"
++  print "  if (2 > (int ) 10)"
++  print "    ptr->x_param_vect_partial_vector_usage ^= 2;"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vrp1_mode" in var_opt_val_set) {
++  print "  ptr->x_param_vrp1_mode = (enum vrp_mode ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_param_vrp2_mode" in var_opt_val_set) {
++  print "  ptr->x_param_vrp2_mode = (enum vrp_mode ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_warn_inline" in var_opt_val_set) {
++  print "  ptr->x_warn_inline = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_aggressive_loop_optimizations" in var_opt_val_set) {
++  print "  ptr->x_flag_aggressive_loop_optimizations = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_align_functions" in var_opt_val_set) {
++  print "  ptr->x_flag_align_functions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_str_align_functions" in var_opt_val_set) {
++  print "  ptr->x_str_align_functions = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_str_align_functions)"
++  print "    ptr->x_str_align_functions = xstrdup (ptr->x_str_align_functions);"
++}
++else
++  print "  bp_unpack_string (data_in, bp);"
++if ("x_flag_align_jumps" in var_opt_val_set) {
++  print "  ptr->x_flag_align_jumps = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_str_align_jumps" in var_opt_val_set) {
++  print "  ptr->x_str_align_jumps = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_str_align_jumps)"
++  print "    ptr->x_str_align_jumps = xstrdup (ptr->x_str_align_jumps);"
++}
++else
++  print "  bp_unpack_string (data_in, bp);"
++if ("x_flag_align_labels" in var_opt_val_set) {
++  print "  ptr->x_flag_align_labels = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_str_align_labels" in var_opt_val_set) {
++  print "  ptr->x_str_align_labels = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_str_align_labels)"
++  print "    ptr->x_str_align_labels = xstrdup (ptr->x_str_align_labels);"
++}
++else
++  print "  bp_unpack_string (data_in, bp);"
++if ("x_flag_align_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_align_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_str_align_loops" in var_opt_val_set) {
++  print "  ptr->x_str_align_loops = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_str_align_loops)"
++  print "    ptr->x_str_align_loops = xstrdup (ptr->x_str_align_loops);"
++}
++else
++  print "  bp_unpack_string (data_in, bp);"
++if ("x_flag_allocation_dce" in var_opt_val_set) {
++  print "  ptr->x_flag_allocation_dce = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_store_data_races" in var_opt_val_set) {
++  print "  ptr->x_flag_store_data_races = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_array_widen_compare" in var_opt_val_set) {
++  print "  ptr->x_flag_array_widen_compare = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_associative_math" in var_opt_val_set) {
++  print "  ptr->x_flag_associative_math = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_asynchronous_unwind_tables" in var_opt_val_set) {
++  print "  ptr->x_flag_asynchronous_unwind_tables = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_auto_inc_dec" in var_opt_val_set) {
++  print "  ptr->x_flag_auto_inc_dec = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_bit_tests" in var_opt_val_set) {
++  print "  ptr->x_flag_bit_tests = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_branch_on_count_reg" in var_opt_val_set) {
++  print "  ptr->x_flag_branch_on_count_reg = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_branch_probabilities" in var_opt_val_set) {
++  print "  ptr->x_flag_branch_probabilities = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_caller_saves" in var_opt_val_set) {
++  print "  ptr->x_flag_caller_saves = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ccmp2" in var_opt_val_set) {
++  print "  ptr->x_flag_ccmp2 = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_code_hoisting" in var_opt_val_set) {
++  print "  ptr->x_flag_code_hoisting = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_combine_stack_adjustments" in var_opt_val_set) {
++  print "  ptr->x_flag_combine_stack_adjustments = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_compare_elim_after_reload" in var_opt_val_set) {
++  print "  ptr->x_flag_compare_elim_after_reload = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_conserve_stack" in var_opt_val_set) {
++  print "  ptr->x_flag_conserve_stack = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_convert_minmax" in var_opt_val_set) {
++  print "  ptr->x_flag_convert_minmax = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_cprop_registers" in var_opt_val_set) {
++  print "  ptr->x_flag_cprop_registers = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_crossjumping" in var_opt_val_set) {
++  print "  ptr->x_flag_crossjumping = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_crypto_accel_aes" in var_opt_val_set) {
++  print "  ptr->x_flag_crypto_accel_aes = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_cse_follow_jumps" in var_opt_val_set) {
++  print "  ptr->x_flag_cse_follow_jumps = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_cx_fortran_rules" in var_opt_val_set) {
++  print "  ptr->x_flag_cx_fortran_rules = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_cx_limited_range" in var_opt_val_set) {
++  print "  ptr->x_flag_cx_limited_range = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_dce" in var_opt_val_set) {
++  print "  ptr->x_flag_dce = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_defer_pop" in var_opt_val_set) {
++  print "  ptr->x_flag_defer_pop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_delayed_branch" in var_opt_val_set) {
++  print "  ptr->x_flag_delayed_branch = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_delete_dead_exceptions" in var_opt_val_set) {
++  print "  ptr->x_flag_delete_dead_exceptions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_delete_null_pointer_checks" in var_opt_val_set) {
++  print "  ptr->x_flag_delete_null_pointer_checks = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_devirtualize" in var_opt_val_set) {
++  print "  ptr->x_flag_devirtualize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_devirtualize_speculatively" in var_opt_val_set) {
++  print "  ptr->x_flag_devirtualize_speculatively = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_dse" in var_opt_val_set) {
++  print "  ptr->x_flag_dse = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_early_inlining" in var_opt_val_set) {
++  print "  ptr->x_flag_early_inlining = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_exceptions" in var_opt_val_set) {
++  print "  ptr->x_flag_exceptions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_excess_precision" in var_opt_val_set) {
++  print "  ptr->x_flag_excess_precision = (enum excess_precision ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_expensive_optimizations" in var_opt_val_set) {
++  print "  ptr->x_flag_expensive_optimizations = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_finite_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_finite_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_finite_math_only" in var_opt_val_set) {
++  print "  ptr->x_flag_finite_math_only = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_float_store" in var_opt_val_set) {
++  print "  ptr->x_flag_float_store = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_fold_simple_inlines" in var_opt_val_set) {
++  print "  ptr->x_flag_fold_simple_inlines = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_forward_propagate" in var_opt_val_set) {
++  print "  ptr->x_flag_forward_propagate = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_fp_contract_mode" in var_opt_val_set) {
++  print "  ptr->x_flag_fp_contract_mode = (enum fp_contract_mode ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_fp_int_builtin_inexact" in var_opt_val_set) {
++  print "  ptr->x_flag_fp_int_builtin_inexact = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ftz" in var_opt_val_set) {
++  print "  ptr->x_flag_ftz = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_no_function_cse" in var_opt_val_set) {
++  print "  ptr->x_flag_no_function_cse = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_gcse" in var_opt_val_set) {
++  print "  ptr->x_flag_gcse = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_gcse_after_reload" in var_opt_val_set) {
++  print "  ptr->x_flag_gcse_after_reload = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_gcse_las" in var_opt_val_set) {
++  print "  ptr->x_flag_gcse_las = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_gcse_lm" in var_opt_val_set) {
++  print "  ptr->x_flag_gcse_lm = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_gcse_sm" in var_opt_val_set) {
++  print "  ptr->x_flag_gcse_sm = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_graphite" in var_opt_val_set) {
++  print "  ptr->x_flag_graphite = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_graphite_identity" in var_opt_val_set) {
++  print "  ptr->x_flag_graphite_identity = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_guess_branch_prob" in var_opt_val_set) {
++  print "  ptr->x_flag_guess_branch_prob = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_harden_compares" in var_opt_val_set) {
++  print "  ptr->x_flag_harden_compares = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_harden_conditional_branches" in var_opt_val_set) {
++  print "  ptr->x_flag_harden_conditional_branches = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_hoist_adjacent_loads" in var_opt_val_set) {
++  print "  ptr->x_flag_hoist_adjacent_loads = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_icp" in var_opt_val_set) {
++  print "  ptr->x_flag_icp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_icp_speculatively" in var_opt_val_set) {
++  print "  ptr->x_flag_icp_speculatively = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_if_conversion" in var_opt_val_set) {
++  print "  ptr->x_flag_if_conversion = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_if_conversion_gimple" in var_opt_val_set) {
++  print "  ptr->x_flag_if_conversion_gimple = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_if_conversion2" in var_opt_val_set) {
++  print "  ptr->x_flag_if_conversion2 = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ifcvt_allow_complicated_cmps" in var_opt_val_set) {
++  print "  ptr->x_flag_ifcvt_allow_complicated_cmps = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_indirect_inlining" in var_opt_val_set) {
++  print "  ptr->x_flag_indirect_inlining = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_no_inline" in var_opt_val_set) {
++  print "  ptr->x_flag_no_inline = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_inline_atomics" in var_opt_val_set) {
++  print "  ptr->x_flag_inline_atomics = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_inline_functions" in var_opt_val_set) {
++  print "  ptr->x_flag_inline_functions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_inline_functions_called_once" in var_opt_val_set) {
++  print "  ptr->x_flag_inline_functions_called_once = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_inline_small_functions" in var_opt_val_set) {
++  print "  ptr->x_flag_inline_small_functions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_bit_cp" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_bit_cp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_cp" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_cp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_cp_clone" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_cp_clone = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_ic" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_ic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_icf" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_icf = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_icf_functions" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_icf_functions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_icf_variables" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_icf_variables = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_modref" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_modref = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_prefetch" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_prefetch = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_profile" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_profile = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_pta" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_pta = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_pure_const" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_pure_const = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_ra" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_ra = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_reference" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_reference = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_reference_addressable" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_reference_addressable = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_reorder_fields" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_reorder_fields = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_sra" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_sra = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_stack_alignment" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_stack_alignment = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_strict_aliasing" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_strict_aliasing = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_struct_reorg" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_struct_reorg = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ipa_vrp" in var_opt_val_set) {
++  print "  ptr->x_flag_ipa_vrp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ira_algorithm" in var_opt_val_set) {
++  print "  ptr->x_flag_ira_algorithm = (enum ira_algorithm ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ira_hoist_pressure" in var_opt_val_set) {
++  print "  ptr->x_flag_ira_hoist_pressure = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ira_loop_pressure" in var_opt_val_set) {
++  print "  ptr->x_flag_ira_loop_pressure = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ira_region" in var_opt_val_set) {
++  print "  ptr->x_flag_ira_region = (enum ira_region ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ira_share_save_slots" in var_opt_val_set) {
++  print "  ptr->x_flag_ira_share_save_slots = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ira_share_spill_slots" in var_opt_val_set) {
++  print "  ptr->x_flag_ira_share_spill_slots = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_isolate_erroneous_paths_attribute" in var_opt_val_set) {
++  print "  ptr->x_flag_isolate_erroneous_paths_attribute = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_isolate_erroneous_paths_dereference" in var_opt_val_set) {
++  print "  ptr->x_flag_isolate_erroneous_paths_dereference = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ivopts" in var_opt_val_set) {
++  print "  ptr->x_flag_ivopts = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_jump_tables" in var_opt_val_set) {
++  print "  ptr->x_flag_jump_tables = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_keep_gc_roots_live" in var_opt_val_set) {
++  print "  ptr->x_flag_keep_gc_roots_live = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_kernel_pgo" in var_opt_val_set) {
++  print "  ptr->x_flag_kernel_pgo = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_lifetime_dse" in var_opt_val_set) {
++  print "  ptr->x_flag_lifetime_dse = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_limit_function_alignment" in var_opt_val_set) {
++  print "  ptr->x_flag_limit_function_alignment = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_live_patching" in var_opt_val_set) {
++  print "  ptr->x_flag_live_patching = (enum live_patching_level ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_live_range_shrinkage" in var_opt_val_set) {
++  print "  ptr->x_flag_live_range_shrinkage = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_loop_crc" in var_opt_val_set) {
++  print "  ptr->x_flag_loop_crc = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_loop_elim" in var_opt_val_set) {
++  print "  ptr->x_flag_loop_elim = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_loop_interchange" in var_opt_val_set) {
++  print "  ptr->x_flag_loop_interchange = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_loop_nest_optimize" in var_opt_val_set) {
++  print "  ptr->x_flag_loop_nest_optimize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_loop_parallelize_all" in var_opt_val_set) {
++  print "  ptr->x_flag_loop_parallelize_all = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unroll_jam" in var_opt_val_set) {
++  print "  ptr->x_flag_unroll_jam = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_lra_remat" in var_opt_val_set) {
++  print "  ptr->x_flag_lra_remat = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_errno_math" in var_opt_val_set) {
++  print "  ptr->x_flag_errno_math = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_merge_mull" in var_opt_val_set) {
++  print "  ptr->x_flag_merge_mull = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_modulo_sched" in var_opt_val_set) {
++  print "  ptr->x_flag_modulo_sched = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_modulo_sched_allow_regmoves" in var_opt_val_set) {
++  print "  ptr->x_flag_modulo_sched_allow_regmoves = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_move_loop_invariants" in var_opt_val_set) {
++  print "  ptr->x_flag_move_loop_invariants = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_move_loop_stores" in var_opt_val_set) {
++  print "  ptr->x_flag_move_loop_stores = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_non_call_exceptions" in var_opt_val_set) {
++  print "  ptr->x_flag_non_call_exceptions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_nothrow_opt" in var_opt_val_set) {
++  print "  ptr->x_flag_nothrow_opt = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_omit_frame_pointer" in var_opt_val_set) {
++  print "  ptr->x_flag_omit_frame_pointer = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_opt_info" in var_opt_val_set) {
++  print "  ptr->x_flag_opt_info = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_optimize_sibling_calls" in var_opt_val_set) {
++  print "  ptr->x_flag_optimize_sibling_calls = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_optimize_strlen" in var_opt_val_set) {
++  print "  ptr->x_flag_optimize_strlen = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_fp_model" in var_opt_val_set) {
++  print "  ptr->x_flag_fp_model = (enum fp_model ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_pack_struct" in var_opt_val_set) {
++  print "  ptr->x_flag_pack_struct = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_partial_inlining" in var_opt_val_set) {
++  print "  ptr->x_flag_partial_inlining = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_patchable_function_entry" in var_opt_val_set) {
++  print "  ptr->x_flag_patchable_function_entry = bp_unpack_string (data_in, bp);"
++  print "  if (ptr->x_flag_patchable_function_entry)"
++  print "    ptr->x_flag_patchable_function_entry = xstrdup (ptr->x_flag_patchable_function_entry);"
++}
++else
++  print "  bp_unpack_string (data_in, bp);"
++if ("x_flag_peel_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_peel_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_no_peephole" in var_opt_val_set) {
++  print "  ptr->x_flag_no_peephole = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_peephole2" in var_opt_val_set) {
++  print "  ptr->x_flag_peephole2 = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_plt" in var_opt_val_set) {
++  print "  ptr->x_flag_plt = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_predictive_commoning" in var_opt_val_set) {
++  print "  ptr->x_flag_predictive_commoning = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_prefetch_loop_arrays" in var_opt_val_set) {
++  print "  ptr->x_flag_prefetch_loop_arrays = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_printf_return_value" in var_opt_val_set) {
++  print "  ptr->x_flag_printf_return_value = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_profile_partial_training" in var_opt_val_set) {
++  print "  ptr->x_flag_profile_partial_training = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_profile_reorder_functions" in var_opt_val_set) {
++  print "  ptr->x_flag_profile_reorder_functions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_reciprocal_math" in var_opt_val_set) {
++  print "  ptr->x_flag_reciprocal_math = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ree" in var_opt_val_set) {
++  print "  ptr->x_flag_ree = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_pcc_struct_return" in var_opt_val_set) {
++  print "  ptr->x_flag_pcc_struct_return = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_rename_registers" in var_opt_val_set) {
++  print "  ptr->x_flag_rename_registers = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_reorder_blocks" in var_opt_val_set) {
++  print "  ptr->x_flag_reorder_blocks = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_reorder_blocks_algorithm" in var_opt_val_set) {
++  print "  ptr->x_flag_reorder_blocks_algorithm = (enum reorder_blocks_algorithm ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_reorder_blocks_and_partition" in var_opt_val_set) {
++  print "  ptr->x_flag_reorder_blocks_and_partition = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_reorder_functions" in var_opt_val_set) {
++  print "  ptr->x_flag_reorder_functions = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_rerun_cse_after_loop" in var_opt_val_set) {
++  print "  ptr->x_flag_rerun_cse_after_loop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_resched_modulo_sched" in var_opt_val_set) {
++  print "  ptr->x_flag_resched_modulo_sched = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_rounding_math" in var_opt_val_set) {
++  print "  ptr->x_flag_rounding_math = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_rtti" in var_opt_val_set) {
++  print "  ptr->x_flag_rtti = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_save_optimization_record" in var_opt_val_set) {
++  print "  ptr->x_flag_save_optimization_record = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_critical_path_heuristic" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_critical_path_heuristic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_dep_count_heuristic" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_dep_count_heuristic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_group_heuristic" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_group_heuristic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_interblock" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_interblock = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_last_insn_heuristic" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_last_insn_heuristic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_pressure" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_pressure = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_rank_heuristic" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_rank_heuristic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_speculative" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_speculative = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_spec_insn_heuristic" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_spec_insn_heuristic = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_speculative_load" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_speculative_load = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_speculative_load_dangerous" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_speculative_load_dangerous = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_stalled_insns" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_stalled_insns = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched_stalled_insns_dep" in var_opt_val_set) {
++  print "  ptr->x_flag_sched_stalled_insns_dep = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sched2_use_superblocks" in var_opt_val_set) {
++  print "  ptr->x_flag_sched2_use_superblocks = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_fusion" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_fusion = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_insns" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_insns = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_schedule_insns_after_reload" in var_opt_val_set) {
++  print "  ptr->x_flag_schedule_insns_after_reload = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_section_anchors" in var_opt_val_set) {
++  print "  ptr->x_flag_section_anchors = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sel_sched_pipelining" in var_opt_val_set) {
++  print "  ptr->x_flag_sel_sched_pipelining = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sel_sched_pipelining_outer_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_sel_sched_pipelining_outer_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_sel_sched_reschedule_pipelined" in var_opt_val_set) {
++  print "  ptr->x_flag_sel_sched_reschedule_pipelined = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_selective_scheduling" in var_opt_val_set) {
++  print "  ptr->x_flag_selective_scheduling = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_selective_scheduling2" in var_opt_val_set) {
++  print "  ptr->x_flag_selective_scheduling2 = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_semantic_interposition" in var_opt_val_set) {
++  print "  ptr->x_flag_semantic_interposition = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_short_enums" in var_opt_val_set) {
++  print "  ptr->x_flag_short_enums = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_short_wchar" in var_opt_val_set) {
++  print "  ptr->x_flag_short_wchar = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_shrink_wrap" in var_opt_val_set) {
++  print "  ptr->x_flag_shrink_wrap = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_shrink_wrap_separate" in var_opt_val_set) {
++  print "  ptr->x_flag_shrink_wrap_separate = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_signaling_nans" in var_opt_val_set) {
++  print "  ptr->x_flag_signaling_nans = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_signed_zeros" in var_opt_val_set) {
++  print "  ptr->x_flag_signed_zeros = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_simd_cost_model" in var_opt_val_set) {
++  print "  ptr->x_flag_simd_cost_model = (enum vect_cost_model ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_simdmath" in var_opt_val_set) {
++  print "  ptr->x_flag_simdmath = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_single_precision_constant" in var_opt_val_set) {
++  print "  ptr->x_flag_single_precision_constant = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_split_ivs_in_unroller" in var_opt_val_set) {
++  print "  ptr->x_flag_split_ivs_in_unroller = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_split_ldp_stp" in var_opt_val_set) {
++  print "  ptr->x_flag_split_ldp_stp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_split_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_split_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_split_paths" in var_opt_val_set) {
++  print "  ptr->x_flag_split_paths = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_split_wide_types" in var_opt_val_set) {
++  print "  ptr->x_flag_split_wide_types = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_split_wide_types_early" in var_opt_val_set) {
++  print "  ptr->x_flag_split_wide_types_early = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ssa_backprop" in var_opt_val_set) {
++  print "  ptr->x_flag_ssa_backprop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_ssa_phiopt" in var_opt_val_set) {
++  print "  ptr->x_flag_ssa_phiopt = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_stack_clash_protection" in var_opt_val_set) {
++  print "  ptr->x_flag_stack_clash_protection = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_stack_protect" in var_opt_val_set) {
++  print "  ptr->x_flag_stack_protect = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_stack_reuse" in var_opt_val_set) {
++  print "  ptr->x_flag_stack_reuse = (enum stack_reuse_level ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_stdarg_opt" in var_opt_val_set) {
++  print "  ptr->x_flag_stdarg_opt = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_store_merging" in var_opt_val_set) {
++  print "  ptr->x_flag_store_merging = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_strict_aliasing" in var_opt_val_set) {
++  print "  ptr->x_flag_strict_aliasing = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_strict_enums" in var_opt_val_set) {
++  print "  ptr->x_flag_strict_enums = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_strict_volatile_bitfields" in var_opt_val_set) {
++  print "  ptr->x_flag_strict_volatile_bitfields = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_thread_jumps" in var_opt_val_set) {
++  print "  ptr->x_flag_thread_jumps = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_threadsafe_statics" in var_opt_val_set) {
++  print "  ptr->x_flag_threadsafe_statics = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_toplevel_reorder" in var_opt_val_set) {
++  print "  ptr->x_flag_toplevel_reorder = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tracer" in var_opt_val_set) {
++  print "  ptr->x_flag_tracer = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_trapping_math" in var_opt_val_set) {
++  print "  ptr->x_flag_trapping_math = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_trapv" in var_opt_val_set) {
++  print "  ptr->x_flag_trapv = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_bit_ccp" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_bit_ccp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_builtin_call_dce" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_builtin_call_dce = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_ccp" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_ccp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_ch" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_ch = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_coalesce_vars" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_coalesce_vars = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_copy_prop" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_copy_prop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_cselim" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_cselim = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_dce" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_dce = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_dom" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_dom = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_dse" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_dse = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_forwprop" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_forwprop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_fre" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_fre = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_distribute_patterns" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_distribute_patterns = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_distribution" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_distribution = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_if_convert" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_if_convert = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_im" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_im = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_ivcanon" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_ivcanon = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_optimize" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_optimize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_loop_vectorize" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_loop_vectorize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_live_range_split" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_live_range_split = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_parallelize_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_parallelize_loops = (int ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_partial_pre" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_partial_pre = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_phiprop" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_phiprop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_pre" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_pre = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_pta" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_pta = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_reassoc" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_reassoc = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_scev_cprop" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_scev_cprop = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_sink" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_sink = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_slp_transpose_vectorize" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_slp_transpose_vectorize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_slp_vectorize" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_slp_vectorize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_slsr" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_slsr = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_sra" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_sra = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_switch_conversion" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_switch_conversion = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_tail_merge" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_tail_merge = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_ter" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_ter = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_vectorize" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_vectorize = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_tree_vrp" in var_opt_val_set) {
++  print "  ptr->x_flag_tree_vrp = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_auto_var_init" in var_opt_val_set) {
++  print "  ptr->x_flag_auto_var_init = (enum auto_init_type ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unconstrained_commons" in var_opt_val_set) {
++  print "  ptr->x_flag_unconstrained_commons = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unroll_all_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_unroll_all_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_cunroll_grow_size" in var_opt_val_set) {
++  print "  ptr->x_flag_cunroll_grow_size = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unroll_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_unroll_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unsafe_math_optimizations" in var_opt_val_set) {
++  print "  ptr->x_flag_unsafe_math_optimizations = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unswitch_loops" in var_opt_val_set) {
++  print "  ptr->x_flag_unswitch_loops = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_unwind_tables" in var_opt_val_set) {
++  print "  ptr->x_flag_unwind_tables = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_var_tracking" in var_opt_val_set) {
++  print "  ptr->x_flag_var_tracking = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_var_tracking_assignments" in var_opt_val_set) {
++  print "  ptr->x_flag_var_tracking_assignments = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_var_tracking_assignments_toggle" in var_opt_val_set) {
++  print "  ptr->x_flag_var_tracking_assignments_toggle = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_var_tracking_uninit" in var_opt_val_set) {
++  print "  ptr->x_flag_var_tracking_uninit = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_variable_expansion_in_unroller" in var_opt_val_set) {
++  print "  ptr->x_flag_variable_expansion_in_unroller = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_vect_cost_model" in var_opt_val_set) {
++  print "  ptr->x_flag_vect_cost_model = (enum vect_cost_model ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_version_loops_for_strides" in var_opt_val_set) {
++  print "  ptr->x_flag_version_loops_for_strides = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_value_profile_transformations" in var_opt_val_set) {
++  print "  ptr->x_flag_value_profile_transformations = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_web" in var_opt_val_set) {
++  print "  ptr->x_flag_web = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_wrapv" in var_opt_val_set) {
++  print "  ptr->x_flag_wrapv = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_wrapv_pointer" in var_opt_val_set) {
++  print "  ptr->x_flag_wrapv_pointer = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_debug_nonbind_markers_p" in var_opt_val_set) {
++  print "  ptr->x_debug_nonbind_markers_p = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_cmlt_arith" in var_opt_val_set) {
++  print "  ptr->x_flag_cmlt_arith = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_mlow_precision_div" in var_opt_val_set) {
++  print "  ptr->x_flag_mlow_precision_div = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_mrecip_low_precision_sqrt" in var_opt_val_set) {
++  print "  ptr->x_flag_mrecip_low_precision_sqrt = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_mlow_precision_sqrt" in var_opt_val_set) {
++  print "  ptr->x_flag_mlow_precision_sqrt = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++if ("x_flag_simdmath_64" in var_opt_val_set) {
++  print "  ptr->x_flag_simdmath_64 = (signed char ) bp_unpack_var_len_int (bp);"
++}
++else
++  print "  bp_unpack_var_len_int (bp);"
++print "  unsigned HOST_WIDE_INT explicit_mask_prev[9];"
++print "  for (size_t i = 0; i < 9; i++)"
++print "    explicit_mask_prev[i] = bp_unpack_value (bp, 64);"
++print "  for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)"
++print "    ptr->explicit_mask[i] = 0;"
++if ("param_align_loop_iterations" in var_opt_int_k) {
++  k = var_opt_int_k["param_align_loop_iterations"]
++  j = var_opt_int_j["param_align_loop_iterations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_align_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_align_threshold"]
++  j = var_opt_int_j["param_align_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_protect_allocas" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_protect_allocas"]
++  j = var_opt_int_j["param_asan_protect_allocas"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_instrument_reads" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_instrument_reads"]
++  j = var_opt_int_j["param_asan_instrument_reads"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_instrument_writes" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_instrument_writes"]
++  j = var_opt_int_j["param_asan_instrument_writes"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_instrumentation_with_call_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_instrumentation_with_call_threshold"]
++  j = var_opt_int_j["param_asan_instrumentation_with_call_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_memintrin" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_memintrin"]
++  j = var_opt_int_j["param_asan_memintrin"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_stack" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_stack"]
++  j = var_opt_int_j["param_asan_stack"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_asan_use_after_return" in var_opt_int_k) {
++  k = var_opt_int_k["param_asan_use_after_return"]
++  j = var_opt_int_j["param_asan_use_after_return"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_avg_loop_niter" in var_opt_int_k) {
++  k = var_opt_int_k["param_avg_loop_niter"]
++  j = var_opt_int_j["param_avg_loop_niter"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_avoid_fma_max_bits" in var_opt_int_k) {
++  k = var_opt_int_k["param_avoid_fma_max_bits"]
++  j = var_opt_int_j["param_avoid_fma_max_bits"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_builtin_expect_probability" in var_opt_int_k) {
++  k = var_opt_int_k["param_builtin_expect_probability"]
++  j = var_opt_int_j["param_builtin_expect_probability"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_builtin_string_cmp_inline_length" in var_opt_int_k) {
++  k = var_opt_int_k["param_builtin_string_cmp_inline_length"]
++  j = var_opt_int_j["param_builtin_string_cmp_inline_length"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_case_values_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_case_values_threshold"]
++  j = var_opt_int_j["param_case_values_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_comdat_sharing_probability" in var_opt_int_k) {
++  k = var_opt_int_k["param_comdat_sharing_probability"]
++  j = var_opt_int_j["param_comdat_sharing_probability"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_pointer_compression_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_pointer_compression_size"]
++  j = var_opt_int_j["param_pointer_compression_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_construct_interfere_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_construct_interfere_size"]
++  j = var_opt_int_j["param_construct_interfere_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_destruct_interfere_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_destruct_interfere_size"]
++  j = var_opt_int_j["param_destruct_interfere_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_dse_max_alias_queries_per_store" in var_opt_int_k) {
++  k = var_opt_int_k["param_dse_max_alias_queries_per_store"]
++  j = var_opt_int_j["param_dse_max_alias_queries_per_store"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_dse_max_object_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_dse_max_object_size"]
++  j = var_opt_int_j["param_dse_max_object_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_early_inlining_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_early_inlining_insns"]
++  j = var_opt_int_j["param_early_inlining_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_evrp_sparse_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_evrp_sparse_threshold"]
++  j = var_opt_int_j["param_evrp_sparse_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_evrp_switch_limit" in var_opt_int_k) {
++  k = var_opt_int_k["param_evrp_switch_limit"]
++  j = var_opt_int_j["param_evrp_switch_limit"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_fsm_scale_path_blocks" in var_opt_int_k) {
++  k = var_opt_int_k["param_fsm_scale_path_blocks"]
++  j = var_opt_int_j["param_fsm_scale_path_blocks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_fsm_scale_path_stmts" in var_opt_int_k) {
++  k = var_opt_int_k["param_fsm_scale_path_stmts"]
++  j = var_opt_int_j["param_fsm_scale_path_stmts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_gcse_after_reload_critical_fraction" in var_opt_int_k) {
++  k = var_opt_int_k["param_gcse_after_reload_critical_fraction"]
++  j = var_opt_int_j["param_gcse_after_reload_critical_fraction"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_gcse_after_reload_partial_fraction" in var_opt_int_k) {
++  k = var_opt_int_k["param_gcse_after_reload_partial_fraction"]
++  j = var_opt_int_j["param_gcse_after_reload_partial_fraction"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_gcse_cost_distance_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_gcse_cost_distance_ratio"]
++  j = var_opt_int_j["param_gcse_cost_distance_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_gcse_unrestricted_cost" in var_opt_int_k) {
++  k = var_opt_int_k["param_gcse_unrestricted_cost"]
++  j = var_opt_int_j["param_gcse_unrestricted_cost"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_graphite_max_arrays_per_scop" in var_opt_int_k) {
++  k = var_opt_int_k["param_graphite_max_arrays_per_scop"]
++  j = var_opt_int_j["param_graphite_max_arrays_per_scop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_graphite_max_nb_scop_params" in var_opt_int_k) {
++  k = var_opt_int_k["param_graphite_max_nb_scop_params"]
++  j = var_opt_int_j["param_graphite_max_nb_scop_params"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_hwasan_instrument_allocas" in var_opt_int_k) {
++  k = var_opt_int_k["param_hwasan_instrument_allocas"]
++  j = var_opt_int_j["param_hwasan_instrument_allocas"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_hwasan_instrument_mem_intrinsics" in var_opt_int_k) {
++  k = var_opt_int_k["param_hwasan_instrument_mem_intrinsics"]
++  j = var_opt_int_j["param_hwasan_instrument_mem_intrinsics"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_hwasan_instrument_reads" in var_opt_int_k) {
++  k = var_opt_int_k["param_hwasan_instrument_reads"]
++  j = var_opt_int_j["param_hwasan_instrument_reads"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_hwasan_instrument_stack" in var_opt_int_k) {
++  k = var_opt_int_k["param_hwasan_instrument_stack"]
++  j = var_opt_int_j["param_hwasan_instrument_stack"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_hwasan_instrument_writes" in var_opt_int_k) {
++  k = var_opt_int_k["param_hwasan_instrument_writes"]
++  j = var_opt_int_j["param_hwasan_instrument_writes"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_hwasan_random_frame_tag" in var_opt_int_k) {
++  k = var_opt_int_k["param_hwasan_random_frame_tag"]
++  j = var_opt_int_j["param_hwasan_random_frame_tag"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ifcvt_allow_register_renaming" in var_opt_int_k) {
++  k = var_opt_int_k["param_ifcvt_allow_register_renaming"]
++  j = var_opt_int_j["param_ifcvt_allow_register_renaming"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_inline_heuristics_hint_percent" in var_opt_int_k) {
++  k = var_opt_int_k["param_inline_heuristics_hint_percent"]
++  j = var_opt_int_j["param_inline_heuristics_hint_percent"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_inline_min_speedup" in var_opt_int_k) {
++  k = var_opt_int_k["param_inline_min_speedup"]
++  j = var_opt_int_j["param_inline_min_speedup"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_inline_unit_growth" in var_opt_int_k) {
++  k = var_opt_int_k["param_inline_unit_growth"]
++  j = var_opt_int_j["param_inline_unit_growth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_eval_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_eval_threshold"]
++  j = var_opt_int_j["param_ipa_cp_eval_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_large_unit_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_large_unit_insns"]
++  j = var_opt_int_j["param_ipa_cp_large_unit_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_loop_hint_bonus" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_loop_hint_bonus"]
++  j = var_opt_int_j["param_ipa_cp_loop_hint_bonus"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_max_recursive_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_max_recursive_depth"]
++  j = var_opt_int_j["param_ipa_cp_max_recursive_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_min_recursive_probability" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_min_recursive_probability"]
++  j = var_opt_int_j["param_ipa_cp_min_recursive_probability"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_profile_count_base" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_profile_count_base"]
++  j = var_opt_int_j["param_ipa_cp_profile_count_base"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_recursion_penalty" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_recursion_penalty"]
++  j = var_opt_int_j["param_ipa_cp_recursion_penalty"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_recursive_freq_factor" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_recursive_freq_factor"]
++  j = var_opt_int_j["param_ipa_cp_recursive_freq_factor"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_single_call_penalty" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_single_call_penalty"]
++  j = var_opt_int_j["param_ipa_cp_single_call_penalty"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_unit_growth" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_unit_growth"]
++  j = var_opt_int_j["param_ipa_cp_unit_growth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_cp_value_list_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_cp_value_list_size"]
++  j = var_opt_int_j["param_ipa_cp_value_list_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_jump_function_lookups" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_jump_function_lookups"]
++  j = var_opt_int_j["param_ipa_jump_function_lookups"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_max_aa_steps" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_max_aa_steps"]
++  j = var_opt_int_j["param_ipa_max_aa_steps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_max_agg_items" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_max_agg_items"]
++  j = var_opt_int_j["param_ipa_max_agg_items"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_max_loop_predicates" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_max_loop_predicates"]
++  j = var_opt_int_j["param_ipa_max_loop_predicates"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_max_param_expr_ops" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_max_param_expr_ops"]
++  j = var_opt_int_j["param_ipa_max_param_expr_ops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_max_switch_predicate_bounds" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_max_switch_predicate_bounds"]
++  j = var_opt_int_j["param_ipa_max_switch_predicate_bounds"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_prefetch_distance_factor" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_prefetch_distance_factor"]
++  j = var_opt_int_j["param_ipa_prefetch_distance_factor"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_prefetch_locality" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_prefetch_locality"]
++  j = var_opt_int_j["param_ipa_prefetch_locality"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_prefetch_pagesize" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_prefetch_pagesize"]
++  j = var_opt_int_j["param_ipa_prefetch_pagesize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_sra_max_replacements" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_sra_max_replacements"]
++  j = var_opt_int_j["param_ipa_sra_max_replacements"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ipa_sra_ptr_growth_factor" in var_opt_int_k) {
++  k = var_opt_int_k["param_ipa_sra_ptr_growth_factor"]
++  j = var_opt_int_j["param_ipa_sra_ptr_growth_factor"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ira_consider_dup_in_all_alts" in var_opt_int_k) {
++  k = var_opt_int_k["param_ira_consider_dup_in_all_alts"]
++  j = var_opt_int_j["param_ira_consider_dup_in_all_alts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[0] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ira_loop_reserved_regs" in var_opt_int_k) {
++  k = var_opt_int_k["param_ira_loop_reserved_regs"]
++  j = var_opt_int_j["param_ira_loop_reserved_regs"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ira_max_conflict_table_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_ira_max_conflict_table_size"]
++  j = var_opt_int_j["param_ira_max_conflict_table_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ira_max_loops_num" in var_opt_int_k) {
++  k = var_opt_int_k["param_ira_max_loops_num"]
++  j = var_opt_int_j["param_ira_max_loops_num"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_iv_always_prune_cand_set_bound" in var_opt_int_k) {
++  k = var_opt_int_k["param_iv_always_prune_cand_set_bound"]
++  j = var_opt_int_j["param_iv_always_prune_cand_set_bound"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_iv_consider_all_candidates_bound" in var_opt_int_k) {
++  k = var_opt_int_k["param_iv_consider_all_candidates_bound"]
++  j = var_opt_int_j["param_iv_consider_all_candidates_bound"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_iv_max_considered_uses" in var_opt_int_k) {
++  k = var_opt_int_k["param_iv_max_considered_uses"]
++  j = var_opt_int_j["param_iv_max_considered_uses"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_jump_table_max_growth_ratio_for_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_jump_table_max_growth_ratio_for_size"]
++  j = var_opt_int_j["param_jump_table_max_growth_ratio_for_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_jump_table_max_growth_ratio_for_speed" in var_opt_int_k) {
++  k = var_opt_int_k["param_jump_table_max_growth_ratio_for_speed"]
++  j = var_opt_int_j["param_jump_table_max_growth_ratio_for_speed"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_l1_cache_line_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_l1_cache_line_size"]
++  j = var_opt_int_j["param_l1_cache_line_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_l1_cache_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_l1_cache_size"]
++  j = var_opt_int_j["param_l1_cache_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_l2_cache_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_l2_cache_size"]
++  j = var_opt_int_j["param_l2_cache_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_large_function_growth" in var_opt_int_k) {
++  k = var_opt_int_k["param_large_function_growth"]
++  j = var_opt_int_j["param_large_function_growth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_large_function_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_large_function_insns"]
++  j = var_opt_int_j["param_large_function_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_stack_frame_growth" in var_opt_int_k) {
++  k = var_opt_int_k["param_stack_frame_growth"]
++  j = var_opt_int_j["param_stack_frame_growth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_large_stack_frame" in var_opt_int_k) {
++  k = var_opt_int_k["param_large_stack_frame"]
++  j = var_opt_int_j["param_large_stack_frame"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_large_unit_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_large_unit_insns"]
++  j = var_opt_int_j["param_large_unit_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_lim_expensive" in var_opt_int_k) {
++  k = var_opt_int_k["param_lim_expensive"]
++  j = var_opt_int_j["param_lim_expensive"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_block_tile_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_block_tile_size"]
++  j = var_opt_int_j["param_loop_block_tile_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_interchange_max_num_stmts" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_interchange_max_num_stmts"]
++  j = var_opt_int_j["param_loop_interchange_max_num_stmts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_interchange_stride_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_interchange_stride_ratio"]
++  j = var_opt_int_j["param_loop_interchange_stride_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_invariant_max_bbs_in_loop" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_invariant_max_bbs_in_loop"]
++  j = var_opt_int_j["param_loop_invariant_max_bbs_in_loop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_max_datarefs_for_datadeps" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_max_datarefs_for_datadeps"]
++  j = var_opt_int_j["param_loop_max_datarefs_for_datadeps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_versioning_max_inner_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_versioning_max_inner_insns"]
++  j = var_opt_int_j["param_loop_versioning_max_inner_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_loop_versioning_max_outer_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_loop_versioning_max_outer_insns"]
++  j = var_opt_int_j["param_loop_versioning_max_outer_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_lra_inheritance_ebb_probability_cutoff" in var_opt_int_k) {
++  k = var_opt_int_k["param_lra_inheritance_ebb_probability_cutoff"]
++  j = var_opt_int_j["param_lra_inheritance_ebb_probability_cutoff"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_lra_max_considered_reload_pseudos" in var_opt_int_k) {
++  k = var_opt_int_k["param_lra_max_considered_reload_pseudos"]
++  j = var_opt_int_j["param_lra_max_considered_reload_pseudos"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_average_unrolled_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_average_unrolled_insns"]
++  j = var_opt_int_j["param_max_average_unrolled_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_combine_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_combine_insns"]
++  j = var_opt_int_j["param_max_combine_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_unroll_iterations" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_unroll_iterations"]
++  j = var_opt_int_j["param_max_unroll_iterations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_completely_peel_times" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_completely_peel_times"]
++  j = var_opt_int_j["param_max_completely_peel_times"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_completely_peeled_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_completely_peeled_insns"]
++  j = var_opt_int_j["param_max_completely_peeled_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_crossjump_edges" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_crossjump_edges"]
++  j = var_opt_int_j["param_max_crossjump_edges"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_cse_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_cse_insns"]
++  j = var_opt_int_j["param_max_cse_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_cse_path_length" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_cse_path_length"]
++  j = var_opt_int_j["param_max_cse_path_length"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_cselib_memory_locations" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_cselib_memory_locations"]
++  j = var_opt_int_j["param_max_cselib_memory_locations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_debug_marker_count" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_debug_marker_count"]
++  j = var_opt_int_j["param_max_debug_marker_count"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_delay_slot_insn_search" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_delay_slot_insn_search"]
++  j = var_opt_int_j["param_max_delay_slot_insn_search"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_delay_slot_live_search" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_delay_slot_live_search"]
++  j = var_opt_int_j["param_max_delay_slot_live_search"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_dse_active_local_stores" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_dse_active_local_stores"]
++  j = var_opt_int_j["param_max_dse_active_local_stores"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_early_inliner_max_iterations" in var_opt_int_k) {
++  k = var_opt_int_k["param_early_inliner_max_iterations"]
++  j = var_opt_int_j["param_early_inliner_max_iterations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_find_base_term_values" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_find_base_term_values"]
++  j = var_opt_int_j["param_max_find_base_term_values"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_fsm_thread_length" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_fsm_thread_length"]
++  j = var_opt_int_j["param_max_fsm_thread_length"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_fsm_thread_path_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_fsm_thread_path_insns"]
++  j = var_opt_int_j["param_max_fsm_thread_path_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_gcse_insertion_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_gcse_insertion_ratio"]
++  j = var_opt_int_j["param_max_gcse_insertion_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_gcse_memory" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_gcse_memory"]
++  j = var_opt_int_j["param_max_gcse_memory"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_goto_duplication_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_goto_duplication_insns"]
++  j = var_opt_int_j["param_max_goto_duplication_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_grow_copy_bb_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_grow_copy_bb_insns"]
++  j = var_opt_int_j["param_max_grow_copy_bb_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_hoist_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_hoist_depth"]
++  j = var_opt_int_j["param_max_hoist_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_inline_functions_called_once_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_inline_functions_called_once_insns"]
++  j = var_opt_int_j["param_inline_functions_called_once_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_inline_functions_called_once_loop_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_inline_functions_called_once_loop_depth"]
++  j = var_opt_int_j["param_inline_functions_called_once_loop_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_insns_auto" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_insns_auto"]
++  j = var_opt_int_j["param_max_inline_insns_auto"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_insns_recursive_auto" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_insns_recursive_auto"]
++  j = var_opt_int_j["param_max_inline_insns_recursive_auto"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_insns_recursive" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_insns_recursive"]
++  j = var_opt_int_j["param_max_inline_insns_recursive"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_insns_single" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_insns_single"]
++  j = var_opt_int_j["param_max_inline_insns_single"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_insns_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_insns_size"]
++  j = var_opt_int_j["param_max_inline_insns_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_insns_small" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_insns_small"]
++  j = var_opt_int_j["param_max_inline_insns_small"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_recursive_depth_auto" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_recursive_depth_auto"]
++  j = var_opt_int_j["param_max_inline_recursive_depth_auto"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_inline_recursive_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_inline_recursive_depth"]
++  j = var_opt_int_j["param_max_inline_recursive_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_isl_operations" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_isl_operations"]
++  j = var_opt_int_j["param_max_isl_operations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_iterations_computation_cost" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_iterations_computation_cost"]
++  j = var_opt_int_j["param_max_iterations_computation_cost"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_iterations_to_track" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_iterations_to_track"]
++  j = var_opt_int_j["param_max_iterations_to_track"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_jump_thread_duplication_stmts" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_jump_thread_duplication_stmts"]
++  j = var_opt_int_j["param_max_jump_thread_duplication_stmts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_last_value_rtl" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_last_value_rtl"]
++  j = var_opt_int_j["param_max_last_value_rtl"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_loop_header_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_loop_header_insns"]
++  j = var_opt_int_j["param_max_loop_header_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[1] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_modulo_backtrack_attempts" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_modulo_backtrack_attempts"]
++  j = var_opt_int_j["param_max_modulo_backtrack_attempts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_partial_antic_length" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_partial_antic_length"]
++  j = var_opt_int_j["param_max_partial_antic_length"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_peel_branches" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_peel_branches"]
++  j = var_opt_int_j["param_max_peel_branches"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_peel_times" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_peel_times"]
++  j = var_opt_int_j["param_max_peel_times"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_peeled_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_peeled_insns"]
++  j = var_opt_int_j["param_max_peeled_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_pending_list_length" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_pending_list_length"]
++  j = var_opt_int_j["param_max_pending_list_length"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_pipeline_region_blocks" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_pipeline_region_blocks"]
++  j = var_opt_int_j["param_max_pipeline_region_blocks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_pipeline_region_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_pipeline_region_insns"]
++  j = var_opt_int_j["param_max_pipeline_region_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_pow_sqrt_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_pow_sqrt_depth"]
++  j = var_opt_int_j["param_max_pow_sqrt_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_predicted_iterations" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_predicted_iterations"]
++  j = var_opt_int_j["param_max_predicted_iterations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_reload_search_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_reload_search_insns"]
++  j = var_opt_int_j["param_max_reload_search_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_rtl_if_conversion_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_rtl_if_conversion_insns"]
++  j = var_opt_int_j["param_max_rtl_if_conversion_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_rtl_if_conversion_predictable_cost" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_rtl_if_conversion_predictable_cost"]
++  j = var_opt_int_j["param_max_rtl_if_conversion_predictable_cost"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_rtl_if_conversion_unpredictable_cost" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_rtl_if_conversion_unpredictable_cost"]
++  j = var_opt_int_j["param_max_rtl_if_conversion_unpredictable_cost"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_sched_extend_regions_iters" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_sched_extend_regions_iters"]
++  j = var_opt_int_j["param_max_sched_extend_regions_iters"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_sched_insn_conflict_delay" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_sched_insn_conflict_delay"]
++  j = var_opt_int_j["param_max_sched_insn_conflict_delay"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_sched_ready_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_sched_ready_insns"]
++  j = var_opt_int_j["param_max_sched_ready_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_sched_region_blocks" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_sched_region_blocks"]
++  j = var_opt_int_j["param_max_sched_region_blocks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_sched_region_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_sched_region_insns"]
++  j = var_opt_int_j["param_max_sched_region_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_slsr_candidate_scan" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_slsr_candidate_scan"]
++  j = var_opt_int_j["param_max_slsr_candidate_scan"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_speculative_devirt_maydefs" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_speculative_devirt_maydefs"]
++  j = var_opt_int_j["param_max_speculative_devirt_maydefs"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_stores_to_merge" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_stores_to_merge"]
++  j = var_opt_int_j["param_max_stores_to_merge"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_stores_to_sink" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_stores_to_sink"]
++  j = var_opt_int_j["param_max_stores_to_sink"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_tail_merge_comparisons" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_tail_merge_comparisons"]
++  j = var_opt_int_j["param_max_tail_merge_comparisons"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_tail_merge_iterations" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_tail_merge_iterations"]
++  j = var_opt_int_j["param_max_tail_merge_iterations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_tracked_strlens" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_tracked_strlens"]
++  j = var_opt_int_j["param_max_tracked_strlens"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_tree_if_conversion_phi_args" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_tree_if_conversion_phi_args"]
++  j = var_opt_int_j["param_max_tree_if_conversion_phi_args"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_unroll_times" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_unroll_times"]
++  j = var_opt_int_j["param_max_unroll_times"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_unrolled_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_unrolled_insns"]
++  j = var_opt_int_j["param_max_unrolled_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_unswitch_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_unswitch_insns"]
++  j = var_opt_int_j["param_max_unswitch_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_unswitch_level" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_unswitch_level"]
++  j = var_opt_int_j["param_max_unswitch_level"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_variable_expansions" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_variable_expansions"]
++  j = var_opt_int_j["param_max_variable_expansions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_vartrack_expr_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_vartrack_expr_depth"]
++  j = var_opt_int_j["param_max_vartrack_expr_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_vartrack_reverse_op_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_vartrack_reverse_op_size"]
++  j = var_opt_int_j["param_max_vartrack_reverse_op_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_vartrack_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_vartrack_size"]
++  j = var_opt_int_j["param_max_vartrack_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_max_vrp_switch_assertions" in var_opt_int_k) {
++  k = var_opt_int_k["param_max_vrp_switch_assertions"]
++  j = var_opt_int_j["param_max_vrp_switch_assertions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_crossjump_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_crossjump_insns"]
++  j = var_opt_int_j["param_min_crossjump_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_inline_recursive_probability" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_inline_recursive_probability"]
++  j = var_opt_int_j["param_min_inline_recursive_probability"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_insn_to_prefetch_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_insn_to_prefetch_ratio"]
++  j = var_opt_int_j["param_min_insn_to_prefetch_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_loop_cond_split_prob" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_loop_cond_split_prob"]
++  j = var_opt_int_j["param_min_loop_cond_split_prob"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_pagesize" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_pagesize"]
++  j = var_opt_int_j["param_min_pagesize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_size_for_stack_sharing" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_size_for_stack_sharing"]
++  j = var_opt_int_j["param_min_size_for_stack_sharing"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_spec_prob" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_spec_prob"]
++  j = var_opt_int_j["param_min_spec_prob"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_min_vect_loop_bound" in var_opt_int_k) {
++  k = var_opt_int_k["param_min_vect_loop_bound"]
++  j = var_opt_int_j["param_min_vect_loop_bound"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_accesses" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_accesses"]
++  j = var_opt_int_j["param_modref_max_accesses"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_adjustments" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_adjustments"]
++  j = var_opt_int_j["param_modref_max_adjustments"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_bases" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_bases"]
++  j = var_opt_int_j["param_modref_max_bases"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_depth"]
++  j = var_opt_int_j["param_modref_max_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_escape_points" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_escape_points"]
++  j = var_opt_int_j["param_modref_max_escape_points"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_refs" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_refs"]
++  j = var_opt_int_j["param_modref_max_refs"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_modref_max_tests" in var_opt_int_k) {
++  k = var_opt_int_k["param_modref_max_tests"]
++  j = var_opt_int_j["param_modref_max_tests"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ldp_dependency_search_range" in var_opt_int_k) {
++  k = var_opt_int_k["param_ldp_dependency_search_range"]
++  j = var_opt_int_j["param_ldp_dependency_search_range"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_parloops_chunk_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_parloops_chunk_size"]
++  j = var_opt_int_j["param_parloops_chunk_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_parloops_min_per_thread" in var_opt_int_k) {
++  k = var_opt_int_k["param_parloops_min_per_thread"]
++  j = var_opt_int_j["param_parloops_min_per_thread"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_parloops_schedule" in var_opt_int_k) {
++  k = var_opt_int_k["param_parloops_schedule"]
++  j = var_opt_int_j["param_parloops_schedule"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_partial_inlining_entry_probability" in var_opt_int_k) {
++  k = var_opt_int_k["param_partial_inlining_entry_probability"]
++  j = var_opt_int_j["param_partial_inlining_entry_probability"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_predictable_branch_outcome" in var_opt_int_k) {
++  k = var_opt_int_k["param_predictable_branch_outcome"]
++  j = var_opt_int_j["param_predictable_branch_outcome"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_prefetch_dynamic_strides" in var_opt_int_k) {
++  k = var_opt_int_k["param_prefetch_dynamic_strides"]
++  j = var_opt_int_j["param_prefetch_dynamic_strides"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_prefetch_latency" in var_opt_int_k) {
++  k = var_opt_int_k["param_prefetch_latency"]
++  j = var_opt_int_j["param_prefetch_latency"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_prefetch_min_insn_to_mem_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_prefetch_min_insn_to_mem_ratio"]
++  j = var_opt_int_j["param_prefetch_min_insn_to_mem_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_prefetch_minimum_stride" in var_opt_int_k) {
++  k = var_opt_int_k["param_prefetch_minimum_stride"]
++  j = var_opt_int_j["param_prefetch_minimum_stride"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ranger_logical_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_ranger_logical_depth"]
++  j = var_opt_int_j["param_ranger_logical_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_relation_block_limit" in var_opt_int_k) {
++  k = var_opt_int_k["param_relation_block_limit"]
++  j = var_opt_int_j["param_relation_block_limit"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_rpo_vn_max_loop_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_rpo_vn_max_loop_depth"]
++  j = var_opt_int_j["param_rpo_vn_max_loop_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[2] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sccvn_max_alias_queries_per_access" in var_opt_int_k) {
++  k = var_opt_int_k["param_sccvn_max_alias_queries_per_access"]
++  j = var_opt_int_j["param_sccvn_max_alias_queries_per_access"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_scev_max_expr_complexity" in var_opt_int_k) {
++  k = var_opt_int_k["param_scev_max_expr_complexity"]
++  j = var_opt_int_j["param_scev_max_expr_complexity"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_scev_max_expr_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_scev_max_expr_size"]
++  j = var_opt_int_j["param_scev_max_expr_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sched_autopref_queue_depth" in var_opt_int_k) {
++  k = var_opt_int_k["param_sched_autopref_queue_depth"]
++  j = var_opt_int_j["param_sched_autopref_queue_depth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sched_mem_true_dep_cost" in var_opt_int_k) {
++  k = var_opt_int_k["param_sched_mem_true_dep_cost"]
++  j = var_opt_int_j["param_sched_mem_true_dep_cost"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sched_pressure_algorithm" in var_opt_int_k) {
++  k = var_opt_int_k["param_sched_pressure_algorithm"]
++  j = var_opt_int_j["param_sched_pressure_algorithm"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sched_spec_prob_cutoff" in var_opt_int_k) {
++  k = var_opt_int_k["param_sched_spec_prob_cutoff"]
++  j = var_opt_int_j["param_sched_spec_prob_cutoff"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sched_state_edge_prob_cutoff" in var_opt_int_k) {
++  k = var_opt_int_k["param_sched_state_edge_prob_cutoff"]
++  j = var_opt_int_j["param_sched_state_edge_prob_cutoff"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_selsched_insns_to_rename" in var_opt_int_k) {
++  k = var_opt_int_k["param_selsched_insns_to_rename"]
++  j = var_opt_int_j["param_selsched_insns_to_rename"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_selsched_max_lookahead" in var_opt_int_k) {
++  k = var_opt_int_k["param_selsched_max_lookahead"]
++  j = var_opt_int_j["param_selsched_max_lookahead"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_selsched_max_sched_times" in var_opt_int_k) {
++  k = var_opt_int_k["param_selsched_max_sched_times"]
++  j = var_opt_int_j["param_selsched_max_sched_times"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("semi_relayout_level" in var_opt_int_k) {
++  k = var_opt_int_k["semi_relayout_level"]
++  j = var_opt_int_j["semi_relayout_level"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_simultaneous_prefetches" in var_opt_int_k) {
++  k = var_opt_int_k["param_simultaneous_prefetches"]
++  j = var_opt_int_j["param_simultaneous_prefetches"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sink_frequency_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_sink_frequency_threshold"]
++  j = var_opt_int_j["param_sink_frequency_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sms_dfa_history" in var_opt_int_k) {
++  k = var_opt_int_k["param_sms_dfa_history"]
++  j = var_opt_int_j["param_sms_dfa_history"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sms_loop_average_count_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_sms_loop_average_count_threshold"]
++  j = var_opt_int_j["param_sms_loop_average_count_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sms_max_ii_factor" in var_opt_int_k) {
++  k = var_opt_int_k["param_sms_max_ii_factor"]
++  j = var_opt_int_j["param_sms_max_ii_factor"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sms_min_sc" in var_opt_int_k) {
++  k = var_opt_int_k["param_sms_min_sc"]
++  j = var_opt_int_j["param_sms_min_sc"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sra_max_propagations" in var_opt_int_k) {
++  k = var_opt_int_k["param_sra_max_propagations"]
++  j = var_opt_int_j["param_sra_max_propagations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sra_max_scalarization_size_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_sra_max_scalarization_size_size"]
++  j = var_opt_int_j["param_sra_max_scalarization_size_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_sra_max_scalarization_size_speed" in var_opt_int_k) {
++  k = var_opt_int_k["param_sra_max_scalarization_size_speed"]
++  j = var_opt_int_j["param_sra_max_scalarization_size_speed"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ssa_name_def_chain_limit" in var_opt_int_k) {
++  k = var_opt_int_k["param_ssa_name_def_chain_limit"]
++  j = var_opt_int_j["param_ssa_name_def_chain_limit"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ssp_buffer_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_ssp_buffer_size"]
++  j = var_opt_int_j["param_ssp_buffer_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_stack_clash_protection_guard_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_stack_clash_protection_guard_size"]
++  j = var_opt_int_j["param_stack_clash_protection_guard_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_stack_clash_protection_probe_interval" in var_opt_int_k) {
++  k = var_opt_int_k["param_stack_clash_protection_probe_interval"]
++  j = var_opt_int_j["param_stack_clash_protection_probe_interval"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_store_merging_allow_unaligned" in var_opt_int_k) {
++  k = var_opt_int_k["param_store_merging_allow_unaligned"]
++  j = var_opt_int_j["param_store_merging_allow_unaligned"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_store_merging_max_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_store_merging_max_size"]
++  j = var_opt_int_j["param_store_merging_max_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_struct_reorg_cold_struct_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_struct_reorg_cold_struct_ratio"]
++  j = var_opt_int_j["param_struct_reorg_cold_struct_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_switch_conversion_branch_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_switch_conversion_branch_ratio"]
++  j = var_opt_int_j["param_switch_conversion_branch_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tm_max_aggregate_size" in var_opt_int_k) {
++  k = var_opt_int_k["param_tm_max_aggregate_size"]
++  j = var_opt_int_j["param_tm_max_aggregate_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tracer_dynamic_coverage_feedback" in var_opt_int_k) {
++  k = var_opt_int_k["param_tracer_dynamic_coverage_feedback"]
++  j = var_opt_int_j["param_tracer_dynamic_coverage_feedback"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tracer_dynamic_coverage" in var_opt_int_k) {
++  k = var_opt_int_k["param_tracer_dynamic_coverage"]
++  j = var_opt_int_j["param_tracer_dynamic_coverage"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tracer_max_code_growth" in var_opt_int_k) {
++  k = var_opt_int_k["param_tracer_max_code_growth"]
++  j = var_opt_int_j["param_tracer_max_code_growth"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tracer_min_branch_probability_feedback" in var_opt_int_k) {
++  k = var_opt_int_k["param_tracer_min_branch_probability_feedback"]
++  j = var_opt_int_j["param_tracer_min_branch_probability_feedback"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tracer_min_branch_probability" in var_opt_int_k) {
++  k = var_opt_int_k["param_tracer_min_branch_probability"]
++  j = var_opt_int_j["param_tracer_min_branch_probability"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tracer_min_branch_ratio" in var_opt_int_k) {
++  k = var_opt_int_k["param_tracer_min_branch_ratio"]
++  j = var_opt_int_j["param_tracer_min_branch_ratio"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_tree_reassoc_width" in var_opt_int_k) {
++  k = var_opt_int_k["param_tree_reassoc_width"]
++  j = var_opt_int_j["param_tree_reassoc_width"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_uninit_control_dep_attempts" in var_opt_int_k) {
++  k = var_opt_int_k["param_uninit_control_dep_attempts"]
++  j = var_opt_int_j["param_uninit_control_dep_attempts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_uninlined_function_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_uninlined_function_insns"]
++  j = var_opt_int_j["param_uninlined_function_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_uninlined_function_time" in var_opt_int_k) {
++  k = var_opt_int_k["param_uninlined_function_time"]
++  j = var_opt_int_j["param_uninlined_function_time"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_uninlined_function_thunk_insns" in var_opt_int_k) {
++  k = var_opt_int_k["param_uninlined_function_thunk_insns"]
++  j = var_opt_int_j["param_uninlined_function_thunk_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_uninlined_function_thunk_time" in var_opt_int_k) {
++  k = var_opt_int_k["param_uninlined_function_thunk_time"]
++  j = var_opt_int_j["param_uninlined_function_thunk_time"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_unlikely_bb_count_fraction" in var_opt_int_k) {
++  k = var_opt_int_k["param_unlikely_bb_count_fraction"]
++  j = var_opt_int_j["param_unlikely_bb_count_fraction"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_unroll_jam_max_unroll" in var_opt_int_k) {
++  k = var_opt_int_k["param_unroll_jam_max_unroll"]
++  j = var_opt_int_j["param_unroll_jam_max_unroll"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_unroll_jam_min_percent" in var_opt_int_k) {
++  k = var_opt_int_k["param_unroll_jam_min_percent"]
++  j = var_opt_int_j["param_unroll_jam_min_percent"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_use_after_scope_direct_emission_threshold" in var_opt_int_k) {
++  k = var_opt_int_k["param_use_after_scope_direct_emission_threshold"]
++  j = var_opt_int_j["param_use_after_scope_direct_emission_threshold"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_flexible_seg_len" in var_opt_int_k) {
++  k = var_opt_int_k["param_flexible_seg_len"]
++  j = var_opt_int_j["param_flexible_seg_len"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_epilogues_nomask" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_epilogues_nomask"]
++  j = var_opt_int_j["param_vect_epilogues_nomask"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_induction_float" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_induction_float"]
++  j = var_opt_int_j["param_vect_induction_float"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_inner_loop_cost_factor" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_inner_loop_cost_factor"]
++  j = var_opt_int_j["param_vect_inner_loop_cost_factor"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_max_peeling_for_alignment" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_max_peeling_for_alignment"]
++  j = var_opt_int_j["param_vect_max_peeling_for_alignment"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_max_version_for_alias_checks" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_max_version_for_alias_checks"]
++  j = var_opt_int_j["param_vect_max_version_for_alias_checks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_max_version_for_alignment_checks" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_max_version_for_alignment_checks"]
++  j = var_opt_int_j["param_vect_max_version_for_alignment_checks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vect_partial_vector_usage" in var_opt_int_k) {
++  k = var_opt_int_k["param_vect_partial_vector_usage"]
++  j = var_opt_int_j["param_vect_partial_vector_usage"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_stalled_insns" in var_opt_int_k) {
++  k = var_opt_int_k["flag_sched_stalled_insns"]
++  j = var_opt_int_j["flag_sched_stalled_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_stalled_insns_dep" in var_opt_int_k) {
++  k = var_opt_int_k["flag_sched_stalled_insns_dep"]
++  j = var_opt_int_j["flag_sched_stalled_insns_dep"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_parallelize_loops" in var_opt_int_k) {
++  k = var_opt_int_k["flag_tree_parallelize_loops"]
++  j = var_opt_int_j["flag_tree_parallelize_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_evrp_mode" in var_opt_enum_k) {
++  k = var_opt_enum_k["param_evrp_mode"]
++  j = var_opt_enum_j["param_evrp_mode"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_ranger_debug" in var_opt_enum_k) {
++  k = var_opt_enum_k["param_ranger_debug"]
++  j = var_opt_enum_j["param_ranger_debug"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_threader_debug" in var_opt_enum_k) {
++  k = var_opt_enum_k["param_threader_debug"]
++  j = var_opt_enum_j["param_threader_debug"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vrp1_mode" in var_opt_enum_k) {
++  k = var_opt_enum_k["param_vrp1_mode"]
++  j = var_opt_enum_j["param_vrp1_mode"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("param_vrp2_mode" in var_opt_enum_k) {
++  k = var_opt_enum_k["param_vrp2_mode"]
++  j = var_opt_enum_j["param_vrp2_mode"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_excess_precision" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_excess_precision"]
++  j = var_opt_enum_j["flag_excess_precision"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_fp_contract_mode" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_fp_contract_mode"]
++  j = var_opt_enum_j["flag_fp_contract_mode"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[3] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ira_algorithm" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_ira_algorithm"]
++  j = var_opt_enum_j["flag_ira_algorithm"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ira_region" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_ira_region"]
++  j = var_opt_enum_j["flag_ira_region"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_live_patching" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_live_patching"]
++  j = var_opt_enum_j["flag_live_patching"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_fp_model" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_fp_model"]
++  j = var_opt_enum_j["flag_fp_model"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_reorder_blocks_algorithm" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_reorder_blocks_algorithm"]
++  j = var_opt_enum_j["flag_reorder_blocks_algorithm"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_simd_cost_model" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_simd_cost_model"]
++  j = var_opt_enum_j["flag_simd_cost_model"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_stack_reuse" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_stack_reuse"]
++  j = var_opt_enum_j["flag_stack_reuse"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_auto_var_init" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_auto_var_init"]
++  j = var_opt_enum_j["flag_auto_var_init"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_vect_cost_model" in var_opt_enum_k) {
++  k = var_opt_enum_k["flag_vect_cost_model"]
++  j = var_opt_enum_j["flag_vect_cost_model"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("optimize" in var_opt_char_k) {
++  k = var_opt_char_k["optimize"]
++  j = var_opt_char_j["optimize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("optimize_size" in var_opt_char_k) {
++  k = var_opt_char_k["optimize_size"]
++  j = var_opt_char_j["optimize_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("optimize_debug" in var_opt_char_k) {
++  k = var_opt_char_k["optimize_debug"]
++  j = var_opt_char_j["optimize_debug"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("optimize_fast" in var_opt_char_k) {
++  k = var_opt_char_k["optimize_fast"]
++  j = var_opt_char_j["optimize_fast"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("warn_inline" in var_opt_char_k) {
++  k = var_opt_char_k["warn_inline"]
++  j = var_opt_char_j["warn_inline"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_aggressive_loop_optimizations" in var_opt_char_k) {
++  k = var_opt_char_k["flag_aggressive_loop_optimizations"]
++  j = var_opt_char_j["flag_aggressive_loop_optimizations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_align_functions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_align_functions"]
++  j = var_opt_char_j["flag_align_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_align_jumps" in var_opt_char_k) {
++  k = var_opt_char_k["flag_align_jumps"]
++  j = var_opt_char_j["flag_align_jumps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_align_labels" in var_opt_char_k) {
++  k = var_opt_char_k["flag_align_labels"]
++  j = var_opt_char_j["flag_align_labels"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_align_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_align_loops"]
++  j = var_opt_char_j["flag_align_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_allocation_dce" in var_opt_char_k) {
++  k = var_opt_char_k["flag_allocation_dce"]
++  j = var_opt_char_j["flag_allocation_dce"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_store_data_races" in var_opt_char_k) {
++  k = var_opt_char_k["flag_store_data_races"]
++  j = var_opt_char_j["flag_store_data_races"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_array_widen_compare" in var_opt_char_k) {
++  k = var_opt_char_k["flag_array_widen_compare"]
++  j = var_opt_char_j["flag_array_widen_compare"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_associative_math" in var_opt_char_k) {
++  k = var_opt_char_k["flag_associative_math"]
++  j = var_opt_char_j["flag_associative_math"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_asynchronous_unwind_tables" in var_opt_char_k) {
++  k = var_opt_char_k["flag_asynchronous_unwind_tables"]
++  j = var_opt_char_j["flag_asynchronous_unwind_tables"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_auto_inc_dec" in var_opt_char_k) {
++  k = var_opt_char_k["flag_auto_inc_dec"]
++  j = var_opt_char_j["flag_auto_inc_dec"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_bit_tests" in var_opt_char_k) {
++  k = var_opt_char_k["flag_bit_tests"]
++  j = var_opt_char_j["flag_bit_tests"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_branch_on_count_reg" in var_opt_char_k) {
++  k = var_opt_char_k["flag_branch_on_count_reg"]
++  j = var_opt_char_j["flag_branch_on_count_reg"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_branch_probabilities" in var_opt_char_k) {
++  k = var_opt_char_k["flag_branch_probabilities"]
++  j = var_opt_char_j["flag_branch_probabilities"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_caller_saves" in var_opt_char_k) {
++  k = var_opt_char_k["flag_caller_saves"]
++  j = var_opt_char_j["flag_caller_saves"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ccmp2" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ccmp2"]
++  j = var_opt_char_j["flag_ccmp2"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_code_hoisting" in var_opt_char_k) {
++  k = var_opt_char_k["flag_code_hoisting"]
++  j = var_opt_char_j["flag_code_hoisting"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_combine_stack_adjustments" in var_opt_char_k) {
++  k = var_opt_char_k["flag_combine_stack_adjustments"]
++  j = var_opt_char_j["flag_combine_stack_adjustments"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_compare_elim_after_reload" in var_opt_char_k) {
++  k = var_opt_char_k["flag_compare_elim_after_reload"]
++  j = var_opt_char_j["flag_compare_elim_after_reload"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_conserve_stack" in var_opt_char_k) {
++  k = var_opt_char_k["flag_conserve_stack"]
++  j = var_opt_char_j["flag_conserve_stack"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_convert_minmax" in var_opt_char_k) {
++  k = var_opt_char_k["flag_convert_minmax"]
++  j = var_opt_char_j["flag_convert_minmax"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_cprop_registers" in var_opt_char_k) {
++  k = var_opt_char_k["flag_cprop_registers"]
++  j = var_opt_char_j["flag_cprop_registers"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_crossjumping" in var_opt_char_k) {
++  k = var_opt_char_k["flag_crossjumping"]
++  j = var_opt_char_j["flag_crossjumping"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_crypto_accel_aes" in var_opt_char_k) {
++  k = var_opt_char_k["flag_crypto_accel_aes"]
++  j = var_opt_char_j["flag_crypto_accel_aes"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_cse_follow_jumps" in var_opt_char_k) {
++  k = var_opt_char_k["flag_cse_follow_jumps"]
++  j = var_opt_char_j["flag_cse_follow_jumps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_cx_fortran_rules" in var_opt_char_k) {
++  k = var_opt_char_k["flag_cx_fortran_rules"]
++  j = var_opt_char_j["flag_cx_fortran_rules"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_cx_limited_range" in var_opt_char_k) {
++  k = var_opt_char_k["flag_cx_limited_range"]
++  j = var_opt_char_j["flag_cx_limited_range"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_dce" in var_opt_char_k) {
++  k = var_opt_char_k["flag_dce"]
++  j = var_opt_char_j["flag_dce"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_defer_pop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_defer_pop"]
++  j = var_opt_char_j["flag_defer_pop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_delayed_branch" in var_opt_char_k) {
++  k = var_opt_char_k["flag_delayed_branch"]
++  j = var_opt_char_j["flag_delayed_branch"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_delete_dead_exceptions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_delete_dead_exceptions"]
++  j = var_opt_char_j["flag_delete_dead_exceptions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_delete_null_pointer_checks" in var_opt_char_k) {
++  k = var_opt_char_k["flag_delete_null_pointer_checks"]
++  j = var_opt_char_j["flag_delete_null_pointer_checks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_devirtualize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_devirtualize"]
++  j = var_opt_char_j["flag_devirtualize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_devirtualize_speculatively" in var_opt_char_k) {
++  k = var_opt_char_k["flag_devirtualize_speculatively"]
++  j = var_opt_char_j["flag_devirtualize_speculatively"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_dse" in var_opt_char_k) {
++  k = var_opt_char_k["flag_dse"]
++  j = var_opt_char_j["flag_dse"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_early_inlining" in var_opt_char_k) {
++  k = var_opt_char_k["flag_early_inlining"]
++  j = var_opt_char_j["flag_early_inlining"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_exceptions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_exceptions"]
++  j = var_opt_char_j["flag_exceptions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_expensive_optimizations" in var_opt_char_k) {
++  k = var_opt_char_k["flag_expensive_optimizations"]
++  j = var_opt_char_j["flag_expensive_optimizations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_finite_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_finite_loops"]
++  j = var_opt_char_j["flag_finite_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_finite_math_only" in var_opt_char_k) {
++  k = var_opt_char_k["flag_finite_math_only"]
++  j = var_opt_char_j["flag_finite_math_only"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_float_store" in var_opt_char_k) {
++  k = var_opt_char_k["flag_float_store"]
++  j = var_opt_char_j["flag_float_store"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_fold_simple_inlines" in var_opt_char_k) {
++  k = var_opt_char_k["flag_fold_simple_inlines"]
++  j = var_opt_char_j["flag_fold_simple_inlines"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_forward_propagate" in var_opt_char_k) {
++  k = var_opt_char_k["flag_forward_propagate"]
++  j = var_opt_char_j["flag_forward_propagate"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_fp_int_builtin_inexact" in var_opt_char_k) {
++  k = var_opt_char_k["flag_fp_int_builtin_inexact"]
++  j = var_opt_char_j["flag_fp_int_builtin_inexact"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ftz" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ftz"]
++  j = var_opt_char_j["flag_ftz"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_no_function_cse" in var_opt_char_k) {
++  k = var_opt_char_k["flag_no_function_cse"]
++  j = var_opt_char_j["flag_no_function_cse"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_gcse" in var_opt_char_k) {
++  k = var_opt_char_k["flag_gcse"]
++  j = var_opt_char_j["flag_gcse"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_gcse_after_reload" in var_opt_char_k) {
++  k = var_opt_char_k["flag_gcse_after_reload"]
++  j = var_opt_char_j["flag_gcse_after_reload"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_gcse_las" in var_opt_char_k) {
++  k = var_opt_char_k["flag_gcse_las"]
++  j = var_opt_char_j["flag_gcse_las"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_gcse_lm" in var_opt_char_k) {
++  k = var_opt_char_k["flag_gcse_lm"]
++  j = var_opt_char_j["flag_gcse_lm"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[4] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_gcse_sm" in var_opt_char_k) {
++  k = var_opt_char_k["flag_gcse_sm"]
++  j = var_opt_char_j["flag_gcse_sm"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_graphite" in var_opt_char_k) {
++  k = var_opt_char_k["flag_graphite"]
++  j = var_opt_char_j["flag_graphite"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_graphite_identity" in var_opt_char_k) {
++  k = var_opt_char_k["flag_graphite_identity"]
++  j = var_opt_char_j["flag_graphite_identity"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_guess_branch_prob" in var_opt_char_k) {
++  k = var_opt_char_k["flag_guess_branch_prob"]
++  j = var_opt_char_j["flag_guess_branch_prob"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_harden_compares" in var_opt_char_k) {
++  k = var_opt_char_k["flag_harden_compares"]
++  j = var_opt_char_j["flag_harden_compares"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_harden_conditional_branches" in var_opt_char_k) {
++  k = var_opt_char_k["flag_harden_conditional_branches"]
++  j = var_opt_char_j["flag_harden_conditional_branches"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_hoist_adjacent_loads" in var_opt_char_k) {
++  k = var_opt_char_k["flag_hoist_adjacent_loads"]
++  j = var_opt_char_j["flag_hoist_adjacent_loads"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_icp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_icp"]
++  j = var_opt_char_j["flag_icp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_icp_speculatively" in var_opt_char_k) {
++  k = var_opt_char_k["flag_icp_speculatively"]
++  j = var_opt_char_j["flag_icp_speculatively"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_if_conversion" in var_opt_char_k) {
++  k = var_opt_char_k["flag_if_conversion"]
++  j = var_opt_char_j["flag_if_conversion"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_if_conversion_gimple" in var_opt_char_k) {
++  k = var_opt_char_k["flag_if_conversion_gimple"]
++  j = var_opt_char_j["flag_if_conversion_gimple"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_if_conversion2" in var_opt_char_k) {
++  k = var_opt_char_k["flag_if_conversion2"]
++  j = var_opt_char_j["flag_if_conversion2"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ifcvt_allow_complicated_cmps" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ifcvt_allow_complicated_cmps"]
++  j = var_opt_char_j["flag_ifcvt_allow_complicated_cmps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_indirect_inlining" in var_opt_char_k) {
++  k = var_opt_char_k["flag_indirect_inlining"]
++  j = var_opt_char_j["flag_indirect_inlining"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_no_inline" in var_opt_char_k) {
++  k = var_opt_char_k["flag_no_inline"]
++  j = var_opt_char_j["flag_no_inline"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_inline_atomics" in var_opt_char_k) {
++  k = var_opt_char_k["flag_inline_atomics"]
++  j = var_opt_char_j["flag_inline_atomics"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_inline_functions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_inline_functions"]
++  j = var_opt_char_j["flag_inline_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_inline_functions_called_once" in var_opt_char_k) {
++  k = var_opt_char_k["flag_inline_functions_called_once"]
++  j = var_opt_char_j["flag_inline_functions_called_once"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_inline_small_functions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_inline_small_functions"]
++  j = var_opt_char_j["flag_inline_small_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_bit_cp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_bit_cp"]
++  j = var_opt_char_j["flag_ipa_bit_cp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_cp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_cp"]
++  j = var_opt_char_j["flag_ipa_cp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_cp_clone" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_cp_clone"]
++  j = var_opt_char_j["flag_ipa_cp_clone"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_ic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_ic"]
++  j = var_opt_char_j["flag_ipa_ic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_icf" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_icf"]
++  j = var_opt_char_j["flag_ipa_icf"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_icf_functions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_icf_functions"]
++  j = var_opt_char_j["flag_ipa_icf_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_icf_variables" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_icf_variables"]
++  j = var_opt_char_j["flag_ipa_icf_variables"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_modref" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_modref"]
++  j = var_opt_char_j["flag_ipa_modref"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_prefetch" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_prefetch"]
++  j = var_opt_char_j["flag_ipa_prefetch"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_profile" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_profile"]
++  j = var_opt_char_j["flag_ipa_profile"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_pta" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_pta"]
++  j = var_opt_char_j["flag_ipa_pta"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_pure_const" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_pure_const"]
++  j = var_opt_char_j["flag_ipa_pure_const"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_ra" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_ra"]
++  j = var_opt_char_j["flag_ipa_ra"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_reference" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_reference"]
++  j = var_opt_char_j["flag_ipa_reference"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_reference_addressable" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_reference_addressable"]
++  j = var_opt_char_j["flag_ipa_reference_addressable"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_reorder_fields" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_reorder_fields"]
++  j = var_opt_char_j["flag_ipa_reorder_fields"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_sra" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_sra"]
++  j = var_opt_char_j["flag_ipa_sra"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_stack_alignment" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_stack_alignment"]
++  j = var_opt_char_j["flag_ipa_stack_alignment"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_strict_aliasing" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_strict_aliasing"]
++  j = var_opt_char_j["flag_ipa_strict_aliasing"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_struct_reorg" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_struct_reorg"]
++  j = var_opt_char_j["flag_ipa_struct_reorg"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ipa_vrp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ipa_vrp"]
++  j = var_opt_char_j["flag_ipa_vrp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ira_hoist_pressure" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ira_hoist_pressure"]
++  j = var_opt_char_j["flag_ira_hoist_pressure"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ira_loop_pressure" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ira_loop_pressure"]
++  j = var_opt_char_j["flag_ira_loop_pressure"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ira_share_save_slots" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ira_share_save_slots"]
++  j = var_opt_char_j["flag_ira_share_save_slots"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ira_share_spill_slots" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ira_share_spill_slots"]
++  j = var_opt_char_j["flag_ira_share_spill_slots"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_isolate_erroneous_paths_attribute" in var_opt_char_k) {
++  k = var_opt_char_k["flag_isolate_erroneous_paths_attribute"]
++  j = var_opt_char_j["flag_isolate_erroneous_paths_attribute"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_isolate_erroneous_paths_dereference" in var_opt_char_k) {
++  k = var_opt_char_k["flag_isolate_erroneous_paths_dereference"]
++  j = var_opt_char_j["flag_isolate_erroneous_paths_dereference"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ivopts" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ivopts"]
++  j = var_opt_char_j["flag_ivopts"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_jump_tables" in var_opt_char_k) {
++  k = var_opt_char_k["flag_jump_tables"]
++  j = var_opt_char_j["flag_jump_tables"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_keep_gc_roots_live" in var_opt_char_k) {
++  k = var_opt_char_k["flag_keep_gc_roots_live"]
++  j = var_opt_char_j["flag_keep_gc_roots_live"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_kernel_pgo" in var_opt_char_k) {
++  k = var_opt_char_k["flag_kernel_pgo"]
++  j = var_opt_char_j["flag_kernel_pgo"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_lifetime_dse" in var_opt_char_k) {
++  k = var_opt_char_k["flag_lifetime_dse"]
++  j = var_opt_char_j["flag_lifetime_dse"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_limit_function_alignment" in var_opt_char_k) {
++  k = var_opt_char_k["flag_limit_function_alignment"]
++  j = var_opt_char_j["flag_limit_function_alignment"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_live_range_shrinkage" in var_opt_char_k) {
++  k = var_opt_char_k["flag_live_range_shrinkage"]
++  j = var_opt_char_j["flag_live_range_shrinkage"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_loop_crc" in var_opt_char_k) {
++  k = var_opt_char_k["flag_loop_crc"]
++  j = var_opt_char_j["flag_loop_crc"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_loop_elim" in var_opt_char_k) {
++  k = var_opt_char_k["flag_loop_elim"]
++  j = var_opt_char_j["flag_loop_elim"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_loop_interchange" in var_opt_char_k) {
++  k = var_opt_char_k["flag_loop_interchange"]
++  j = var_opt_char_j["flag_loop_interchange"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_loop_nest_optimize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_loop_nest_optimize"]
++  j = var_opt_char_j["flag_loop_nest_optimize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_loop_parallelize_all" in var_opt_char_k) {
++  k = var_opt_char_k["flag_loop_parallelize_all"]
++  j = var_opt_char_j["flag_loop_parallelize_all"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unroll_jam" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unroll_jam"]
++  j = var_opt_char_j["flag_unroll_jam"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_lra_remat" in var_opt_char_k) {
++  k = var_opt_char_k["flag_lra_remat"]
++  j = var_opt_char_j["flag_lra_remat"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_errno_math" in var_opt_char_k) {
++  k = var_opt_char_k["flag_errno_math"]
++  j = var_opt_char_j["flag_errno_math"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_merge_mull" in var_opt_char_k) {
++  k = var_opt_char_k["flag_merge_mull"]
++  j = var_opt_char_j["flag_merge_mull"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_modulo_sched" in var_opt_char_k) {
++  k = var_opt_char_k["flag_modulo_sched"]
++  j = var_opt_char_j["flag_modulo_sched"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_modulo_sched_allow_regmoves" in var_opt_char_k) {
++  k = var_opt_char_k["flag_modulo_sched_allow_regmoves"]
++  j = var_opt_char_j["flag_modulo_sched_allow_regmoves"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[5] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_move_loop_invariants" in var_opt_char_k) {
++  k = var_opt_char_k["flag_move_loop_invariants"]
++  j = var_opt_char_j["flag_move_loop_invariants"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_move_loop_stores" in var_opt_char_k) {
++  k = var_opt_char_k["flag_move_loop_stores"]
++  j = var_opt_char_j["flag_move_loop_stores"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_non_call_exceptions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_non_call_exceptions"]
++  j = var_opt_char_j["flag_non_call_exceptions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_nothrow_opt" in var_opt_char_k) {
++  k = var_opt_char_k["flag_nothrow_opt"]
++  j = var_opt_char_j["flag_nothrow_opt"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_omit_frame_pointer" in var_opt_char_k) {
++  k = var_opt_char_k["flag_omit_frame_pointer"]
++  j = var_opt_char_j["flag_omit_frame_pointer"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_opt_info" in var_opt_char_k) {
++  k = var_opt_char_k["flag_opt_info"]
++  j = var_opt_char_j["flag_opt_info"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_optimize_sibling_calls" in var_opt_char_k) {
++  k = var_opt_char_k["flag_optimize_sibling_calls"]
++  j = var_opt_char_j["flag_optimize_sibling_calls"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_optimize_strlen" in var_opt_char_k) {
++  k = var_opt_char_k["flag_optimize_strlen"]
++  j = var_opt_char_j["flag_optimize_strlen"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_pack_struct" in var_opt_char_k) {
++  k = var_opt_char_k["flag_pack_struct"]
++  j = var_opt_char_j["flag_pack_struct"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_partial_inlining" in var_opt_char_k) {
++  k = var_opt_char_k["flag_partial_inlining"]
++  j = var_opt_char_j["flag_partial_inlining"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_peel_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_peel_loops"]
++  j = var_opt_char_j["flag_peel_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_no_peephole" in var_opt_char_k) {
++  k = var_opt_char_k["flag_no_peephole"]
++  j = var_opt_char_j["flag_no_peephole"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_peephole2" in var_opt_char_k) {
++  k = var_opt_char_k["flag_peephole2"]
++  j = var_opt_char_j["flag_peephole2"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_plt" in var_opt_char_k) {
++  k = var_opt_char_k["flag_plt"]
++  j = var_opt_char_j["flag_plt"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_predictive_commoning" in var_opt_char_k) {
++  k = var_opt_char_k["flag_predictive_commoning"]
++  j = var_opt_char_j["flag_predictive_commoning"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_prefetch_loop_arrays" in var_opt_char_k) {
++  k = var_opt_char_k["flag_prefetch_loop_arrays"]
++  j = var_opt_char_j["flag_prefetch_loop_arrays"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_printf_return_value" in var_opt_char_k) {
++  k = var_opt_char_k["flag_printf_return_value"]
++  j = var_opt_char_j["flag_printf_return_value"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_profile_partial_training" in var_opt_char_k) {
++  k = var_opt_char_k["flag_profile_partial_training"]
++  j = var_opt_char_j["flag_profile_partial_training"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_profile_reorder_functions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_profile_reorder_functions"]
++  j = var_opt_char_j["flag_profile_reorder_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_reciprocal_math" in var_opt_char_k) {
++  k = var_opt_char_k["flag_reciprocal_math"]
++  j = var_opt_char_j["flag_reciprocal_math"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ree" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ree"]
++  j = var_opt_char_j["flag_ree"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_pcc_struct_return" in var_opt_char_k) {
++  k = var_opt_char_k["flag_pcc_struct_return"]
++  j = var_opt_char_j["flag_pcc_struct_return"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_rename_registers" in var_opt_char_k) {
++  k = var_opt_char_k["flag_rename_registers"]
++  j = var_opt_char_j["flag_rename_registers"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_reorder_blocks" in var_opt_char_k) {
++  k = var_opt_char_k["flag_reorder_blocks"]
++  j = var_opt_char_j["flag_reorder_blocks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_reorder_blocks_and_partition" in var_opt_char_k) {
++  k = var_opt_char_k["flag_reorder_blocks_and_partition"]
++  j = var_opt_char_j["flag_reorder_blocks_and_partition"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_reorder_functions" in var_opt_char_k) {
++  k = var_opt_char_k["flag_reorder_functions"]
++  j = var_opt_char_j["flag_reorder_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_rerun_cse_after_loop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_rerun_cse_after_loop"]
++  j = var_opt_char_j["flag_rerun_cse_after_loop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_resched_modulo_sched" in var_opt_char_k) {
++  k = var_opt_char_k["flag_resched_modulo_sched"]
++  j = var_opt_char_j["flag_resched_modulo_sched"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_rounding_math" in var_opt_char_k) {
++  k = var_opt_char_k["flag_rounding_math"]
++  j = var_opt_char_j["flag_rounding_math"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_rtti" in var_opt_char_k) {
++  k = var_opt_char_k["flag_rtti"]
++  j = var_opt_char_j["flag_rtti"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_save_optimization_record" in var_opt_char_k) {
++  k = var_opt_char_k["flag_save_optimization_record"]
++  j = var_opt_char_j["flag_save_optimization_record"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_critical_path_heuristic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_critical_path_heuristic"]
++  j = var_opt_char_j["flag_sched_critical_path_heuristic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_dep_count_heuristic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_dep_count_heuristic"]
++  j = var_opt_char_j["flag_sched_dep_count_heuristic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_group_heuristic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_group_heuristic"]
++  j = var_opt_char_j["flag_sched_group_heuristic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_interblock" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_interblock"]
++  j = var_opt_char_j["flag_schedule_interblock"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_last_insn_heuristic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_last_insn_heuristic"]
++  j = var_opt_char_j["flag_sched_last_insn_heuristic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_pressure" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_pressure"]
++  j = var_opt_char_j["flag_sched_pressure"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_rank_heuristic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_rank_heuristic"]
++  j = var_opt_char_j["flag_sched_rank_heuristic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_speculative" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_speculative"]
++  j = var_opt_char_j["flag_schedule_speculative"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched_spec_insn_heuristic" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched_spec_insn_heuristic"]
++  j = var_opt_char_j["flag_sched_spec_insn_heuristic"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_speculative_load" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_speculative_load"]
++  j = var_opt_char_j["flag_schedule_speculative_load"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_speculative_load_dangerous" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_speculative_load_dangerous"]
++  j = var_opt_char_j["flag_schedule_speculative_load_dangerous"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sched2_use_superblocks" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sched2_use_superblocks"]
++  j = var_opt_char_j["flag_sched2_use_superblocks"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_fusion" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_fusion"]
++  j = var_opt_char_j["flag_schedule_fusion"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_insns" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_insns"]
++  j = var_opt_char_j["flag_schedule_insns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_schedule_insns_after_reload" in var_opt_char_k) {
++  k = var_opt_char_k["flag_schedule_insns_after_reload"]
++  j = var_opt_char_j["flag_schedule_insns_after_reload"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_section_anchors" in var_opt_char_k) {
++  k = var_opt_char_k["flag_section_anchors"]
++  j = var_opt_char_j["flag_section_anchors"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sel_sched_pipelining" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sel_sched_pipelining"]
++  j = var_opt_char_j["flag_sel_sched_pipelining"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sel_sched_pipelining_outer_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sel_sched_pipelining_outer_loops"]
++  j = var_opt_char_j["flag_sel_sched_pipelining_outer_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_sel_sched_reschedule_pipelined" in var_opt_char_k) {
++  k = var_opt_char_k["flag_sel_sched_reschedule_pipelined"]
++  j = var_opt_char_j["flag_sel_sched_reschedule_pipelined"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_selective_scheduling" in var_opt_char_k) {
++  k = var_opt_char_k["flag_selective_scheduling"]
++  j = var_opt_char_j["flag_selective_scheduling"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_selective_scheduling2" in var_opt_char_k) {
++  k = var_opt_char_k["flag_selective_scheduling2"]
++  j = var_opt_char_j["flag_selective_scheduling2"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_semantic_interposition" in var_opt_char_k) {
++  k = var_opt_char_k["flag_semantic_interposition"]
++  j = var_opt_char_j["flag_semantic_interposition"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_short_enums" in var_opt_char_k) {
++  k = var_opt_char_k["flag_short_enums"]
++  j = var_opt_char_j["flag_short_enums"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_short_wchar" in var_opt_char_k) {
++  k = var_opt_char_k["flag_short_wchar"]
++  j = var_opt_char_j["flag_short_wchar"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_shrink_wrap" in var_opt_char_k) {
++  k = var_opt_char_k["flag_shrink_wrap"]
++  j = var_opt_char_j["flag_shrink_wrap"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_shrink_wrap_separate" in var_opt_char_k) {
++  k = var_opt_char_k["flag_shrink_wrap_separate"]
++  j = var_opt_char_j["flag_shrink_wrap_separate"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_signaling_nans" in var_opt_char_k) {
++  k = var_opt_char_k["flag_signaling_nans"]
++  j = var_opt_char_j["flag_signaling_nans"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_signed_zeros" in var_opt_char_k) {
++  k = var_opt_char_k["flag_signed_zeros"]
++  j = var_opt_char_j["flag_signed_zeros"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_simdmath" in var_opt_char_k) {
++  k = var_opt_char_k["flag_simdmath"]
++  j = var_opt_char_j["flag_simdmath"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_single_precision_constant" in var_opt_char_k) {
++  k = var_opt_char_k["flag_single_precision_constant"]
++  j = var_opt_char_j["flag_single_precision_constant"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_split_ivs_in_unroller" in var_opt_char_k) {
++  k = var_opt_char_k["flag_split_ivs_in_unroller"]
++  j = var_opt_char_j["flag_split_ivs_in_unroller"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_split_ldp_stp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_split_ldp_stp"]
++  j = var_opt_char_j["flag_split_ldp_stp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_split_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_split_loops"]
++  j = var_opt_char_j["flag_split_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[6] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_split_paths" in var_opt_char_k) {
++  k = var_opt_char_k["flag_split_paths"]
++  j = var_opt_char_j["flag_split_paths"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_split_wide_types" in var_opt_char_k) {
++  k = var_opt_char_k["flag_split_wide_types"]
++  j = var_opt_char_j["flag_split_wide_types"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_split_wide_types_early" in var_opt_char_k) {
++  k = var_opt_char_k["flag_split_wide_types_early"]
++  j = var_opt_char_j["flag_split_wide_types_early"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ssa_backprop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ssa_backprop"]
++  j = var_opt_char_j["flag_ssa_backprop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_ssa_phiopt" in var_opt_char_k) {
++  k = var_opt_char_k["flag_ssa_phiopt"]
++  j = var_opt_char_j["flag_ssa_phiopt"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_stack_clash_protection" in var_opt_char_k) {
++  k = var_opt_char_k["flag_stack_clash_protection"]
++  j = var_opt_char_j["flag_stack_clash_protection"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_stack_protect" in var_opt_char_k) {
++  k = var_opt_char_k["flag_stack_protect"]
++  j = var_opt_char_j["flag_stack_protect"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_stdarg_opt" in var_opt_char_k) {
++  k = var_opt_char_k["flag_stdarg_opt"]
++  j = var_opt_char_j["flag_stdarg_opt"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_store_merging" in var_opt_char_k) {
++  k = var_opt_char_k["flag_store_merging"]
++  j = var_opt_char_j["flag_store_merging"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_strict_aliasing" in var_opt_char_k) {
++  k = var_opt_char_k["flag_strict_aliasing"]
++  j = var_opt_char_j["flag_strict_aliasing"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_strict_enums" in var_opt_char_k) {
++  k = var_opt_char_k["flag_strict_enums"]
++  j = var_opt_char_j["flag_strict_enums"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_strict_volatile_bitfields" in var_opt_char_k) {
++  k = var_opt_char_k["flag_strict_volatile_bitfields"]
++  j = var_opt_char_j["flag_strict_volatile_bitfields"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_thread_jumps" in var_opt_char_k) {
++  k = var_opt_char_k["flag_thread_jumps"]
++  j = var_opt_char_j["flag_thread_jumps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_threadsafe_statics" in var_opt_char_k) {
++  k = var_opt_char_k["flag_threadsafe_statics"]
++  j = var_opt_char_j["flag_threadsafe_statics"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_toplevel_reorder" in var_opt_char_k) {
++  k = var_opt_char_k["flag_toplevel_reorder"]
++  j = var_opt_char_j["flag_toplevel_reorder"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tracer" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tracer"]
++  j = var_opt_char_j["flag_tracer"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_trapping_math" in var_opt_char_k) {
++  k = var_opt_char_k["flag_trapping_math"]
++  j = var_opt_char_j["flag_trapping_math"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_trapv" in var_opt_char_k) {
++  k = var_opt_char_k["flag_trapv"]
++  j = var_opt_char_j["flag_trapv"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_bit_ccp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_bit_ccp"]
++  j = var_opt_char_j["flag_tree_bit_ccp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 18) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_builtin_call_dce" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_builtin_call_dce"]
++  j = var_opt_char_j["flag_tree_builtin_call_dce"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 19) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_ccp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_ccp"]
++  j = var_opt_char_j["flag_tree_ccp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 20) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_ch" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_ch"]
++  j = var_opt_char_j["flag_tree_ch"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 21) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_coalesce_vars" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_coalesce_vars"]
++  j = var_opt_char_j["flag_tree_coalesce_vars"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 22) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_copy_prop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_copy_prop"]
++  j = var_opt_char_j["flag_tree_copy_prop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 23) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_cselim" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_cselim"]
++  j = var_opt_char_j["flag_tree_cselim"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 24) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_dce" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_dce"]
++  j = var_opt_char_j["flag_tree_dce"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 25) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_dom" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_dom"]
++  j = var_opt_char_j["flag_tree_dom"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 26) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_dse" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_dse"]
++  j = var_opt_char_j["flag_tree_dse"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 27) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_forwprop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_forwprop"]
++  j = var_opt_char_j["flag_tree_forwprop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 28) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_fre" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_fre"]
++  j = var_opt_char_j["flag_tree_fre"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 29) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_distribute_patterns" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_distribute_patterns"]
++  j = var_opt_char_j["flag_tree_loop_distribute_patterns"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 30) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_distribution" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_distribution"]
++  j = var_opt_char_j["flag_tree_loop_distribution"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 31) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_if_convert" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_if_convert"]
++  j = var_opt_char_j["flag_tree_loop_if_convert"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 32) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_im" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_im"]
++  j = var_opt_char_j["flag_tree_loop_im"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 33) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_ivcanon" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_ivcanon"]
++  j = var_opt_char_j["flag_tree_loop_ivcanon"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 34) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_optimize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_optimize"]
++  j = var_opt_char_j["flag_tree_loop_optimize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 35) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_loop_vectorize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_loop_vectorize"]
++  j = var_opt_char_j["flag_tree_loop_vectorize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 36) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_live_range_split" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_live_range_split"]
++  j = var_opt_char_j["flag_tree_live_range_split"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 37) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_partial_pre" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_partial_pre"]
++  j = var_opt_char_j["flag_tree_partial_pre"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 38) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_phiprop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_phiprop"]
++  j = var_opt_char_j["flag_tree_phiprop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 39) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_pre" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_pre"]
++  j = var_opt_char_j["flag_tree_pre"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 40) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_pta" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_pta"]
++  j = var_opt_char_j["flag_tree_pta"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 41) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_reassoc" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_reassoc"]
++  j = var_opt_char_j["flag_tree_reassoc"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 42) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_scev_cprop" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_scev_cprop"]
++  j = var_opt_char_j["flag_tree_scev_cprop"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 43) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_sink" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_sink"]
++  j = var_opt_char_j["flag_tree_sink"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 44) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_slp_transpose_vectorize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_slp_transpose_vectorize"]
++  j = var_opt_char_j["flag_tree_slp_transpose_vectorize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 45) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_slp_vectorize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_slp_vectorize"]
++  j = var_opt_char_j["flag_tree_slp_vectorize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 46) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_slsr" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_slsr"]
++  j = var_opt_char_j["flag_tree_slsr"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 47) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_sra" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_sra"]
++  j = var_opt_char_j["flag_tree_sra"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 48) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_switch_conversion" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_switch_conversion"]
++  j = var_opt_char_j["flag_tree_switch_conversion"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 49) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_tail_merge" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_tail_merge"]
++  j = var_opt_char_j["flag_tree_tail_merge"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 50) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_ter" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_ter"]
++  j = var_opt_char_j["flag_tree_ter"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 51) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_vectorize" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_vectorize"]
++  j = var_opt_char_j["flag_tree_vectorize"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 52) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_tree_vrp" in var_opt_char_k) {
++  k = var_opt_char_k["flag_tree_vrp"]
++  j = var_opt_char_j["flag_tree_vrp"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 53) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unconstrained_commons" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unconstrained_commons"]
++  j = var_opt_char_j["flag_unconstrained_commons"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 54) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unroll_all_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unroll_all_loops"]
++  j = var_opt_char_j["flag_unroll_all_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 55) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_cunroll_grow_size" in var_opt_char_k) {
++  k = var_opt_char_k["flag_cunroll_grow_size"]
++  j = var_opt_char_j["flag_cunroll_grow_size"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 56) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unroll_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unroll_loops"]
++  j = var_opt_char_j["flag_unroll_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 57) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unsafe_math_optimizations" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unsafe_math_optimizations"]
++  j = var_opt_char_j["flag_unsafe_math_optimizations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 58) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unswitch_loops" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unswitch_loops"]
++  j = var_opt_char_j["flag_unswitch_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 59) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_unwind_tables" in var_opt_char_k) {
++  k = var_opt_char_k["flag_unwind_tables"]
++  j = var_opt_char_j["flag_unwind_tables"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 60) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_var_tracking" in var_opt_char_k) {
++  k = var_opt_char_k["flag_var_tracking"]
++  j = var_opt_char_j["flag_var_tracking"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 61) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_var_tracking_assignments" in var_opt_char_k) {
++  k = var_opt_char_k["flag_var_tracking_assignments"]
++  j = var_opt_char_j["flag_var_tracking_assignments"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 62) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_var_tracking_assignments_toggle" in var_opt_char_k) {
++  k = var_opt_char_k["flag_var_tracking_assignments_toggle"]
++  j = var_opt_char_j["flag_var_tracking_assignments_toggle"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[7] >> 63) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_var_tracking_uninit" in var_opt_char_k) {
++  k = var_opt_char_k["flag_var_tracking_uninit"]
++  j = var_opt_char_j["flag_var_tracking_uninit"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 0) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_variable_expansion_in_unroller" in var_opt_char_k) {
++  k = var_opt_char_k["flag_variable_expansion_in_unroller"]
++  j = var_opt_char_j["flag_variable_expansion_in_unroller"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 1) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_version_loops_for_strides" in var_opt_char_k) {
++  k = var_opt_char_k["flag_version_loops_for_strides"]
++  j = var_opt_char_j["flag_version_loops_for_strides"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 2) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_value_profile_transformations" in var_opt_char_k) {
++  k = var_opt_char_k["flag_value_profile_transformations"]
++  j = var_opt_char_j["flag_value_profile_transformations"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 3) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_web" in var_opt_char_k) {
++  k = var_opt_char_k["flag_web"]
++  j = var_opt_char_j["flag_web"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 4) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_wrapv" in var_opt_char_k) {
++  k = var_opt_char_k["flag_wrapv"]
++  j = var_opt_char_j["flag_wrapv"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 5) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_wrapv_pointer" in var_opt_char_k) {
++  k = var_opt_char_k["flag_wrapv_pointer"]
++  j = var_opt_char_j["flag_wrapv_pointer"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 6) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("debug_nonbind_markers_p" in var_opt_char_k) {
++  k = var_opt_char_k["debug_nonbind_markers_p"]
++  j = var_opt_char_j["debug_nonbind_markers_p"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 7) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_cmlt_arith" in var_opt_char_k) {
++  k = var_opt_char_k["flag_cmlt_arith"]
++  j = var_opt_char_j["flag_cmlt_arith"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 8) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_mlow_precision_div" in var_opt_char_k) {
++  k = var_opt_char_k["flag_mlow_precision_div"]
++  j = var_opt_char_j["flag_mlow_precision_div"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 9) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_mrecip_low_precision_sqrt" in var_opt_char_k) {
++  k = var_opt_char_k["flag_mrecip_low_precision_sqrt"]
++  j = var_opt_char_j["flag_mrecip_low_precision_sqrt"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 10) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_mlow_precision_sqrt" in var_opt_char_k) {
++  k = var_opt_char_k["flag_mlow_precision_sqrt"]
++  j = var_opt_char_j["flag_mlow_precision_sqrt"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 11) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_simdmath_64" in var_opt_char_k) {
++  k = var_opt_char_k["flag_simdmath_64"]
++  j = var_opt_char_j["flag_simdmath_64"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 12) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("str_align_functions" in var_opt_string_k) {
++  k = var_opt_string_k["str_align_functions"]
++  j = var_opt_string_j["str_align_functions"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 13) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("str_align_jumps" in var_opt_string_k) {
++  k = var_opt_string_k["str_align_jumps"]
++  j = var_opt_string_j["str_align_jumps"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 14) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("str_align_labels" in var_opt_string_k) {
++  k = var_opt_string_k["str_align_labels"]
++  j = var_opt_string_j["str_align_labels"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 15) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("str_align_loops" in var_opt_string_k) {
++  k = var_opt_string_k["str_align_loops"]
++  j = var_opt_string_j["str_align_loops"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 16) & HOST_WIDE_INT_1U) << "j";"
++}
++if ("flag_patchable_function_entry" in var_opt_string_k) {
++  k = var_opt_string_k["flag_patchable_function_entry"]
++  j = var_opt_string_j["flag_patchable_function_entry"]
++  print "  ptr->explicit_mask[" k "] |= ((explicit_mask_prev[8] >> 17) & HOST_WIDE_INT_1U) << "j";"
++}
++print "}";
++print "";
++
+ print "/* Free heap memory used by optimization options  */";
+ print "void";
+ print "cl_optimization_option_free (struct cl_optimization *ptr ATTRIBUTE_UNUSED)";
+-- 
+2.25.1
+
diff --git a/0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch b/0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch
new file mode 100644
index 0000000..cdd28b1
--- /dev/null
+++ b/0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch
@@ -0,0 +1,963 @@
+From f81a5b294711e3a420fe66702f0d9221332271c4 Mon Sep 17 00:00:00 2001
+From: h00564365 
+Date: Wed, 13 Nov 2024 17:18:01 +0800
+Subject: [PATCH 2/2] Add multi-version lto symbol parse, cross lto units
+ ipa-inline extension, and lto compression algorithm specified.
+
+---
+ gcc/common.opt                               |  20 +++
+ gcc/config/aarch64/aarch64.cc                |  41 ++++++
+ gcc/doc/tm.texi                              |   6 +
+ gcc/doc/tm.texi.in                           |   2 +
+ gcc/ipa-inline.cc                            | 141 ++++++++++++++++++-
+ gcc/lto-compress.cc                          |   6 +-
+ gcc/lto-section-in.cc                        |   5 +
+ gcc/lto-streamer-out.cc                      |   7 +-
+ gcc/lto-wrapper.cc                           |   4 +
+ gcc/optc-save-gen.awk                        |  57 ++++++++
+ gcc/opth-gen.awk                             |   3 +
+ gcc/opts.cc                                  |  46 ++++++
+ gcc/target.def                               |  10 ++
+ gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c |  15 ++
+ gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c |   6 +
+ gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c |  15 ++
+ gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c |   5 +
+ gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c |  15 ++
+ gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c |  10 ++
+ gcc/tree-streamer-in.cc                      |  58 +++++++-
+ lto-plugin/lto-plugin.c                      |  83 +++++++++++
+ 21 files changed, 547 insertions(+), 8 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c
+ create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c
+ create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c
+ create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c
+ create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c
+ create mode 100644 gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index be5fcc681..78cfc333a 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1928,6 +1928,21 @@ finline-atomics
+ Common Var(flag_inline_atomics) Init(1) Optimization
+ Inline __atomic operations when a lock free instruction sequence is available.
+ 
++fmulti-version-lib=
++Common Joined Var(multi_version_lib_string)
++Use specify LTO stream in mode for specified target (object or lib). If there
++are multiple target files, use commas (,) to separate them and without spaces.
++
++finline-force
++Common Var(flag_inline_force) Init(0) Optimization
++Force perform ipa inline when march options are incompatible between functions.
++
++finline-force=
++Common Joined Var(force_inline_targets_string)
++Force perform ipa inline specified target(object or lib) when march options are
++incompatible between functions.  If there are multiple target files, use commas
++(,) to separate them and without spaces.
++
+ fcf-protection
+ Common RejectNegative Alias(fcf-protection=,full)
+ 
+@@ -2168,6 +2183,11 @@ flto-partition=
+ Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_BALANCED)
+ Specify the algorithm to partition symbols and vars at linktime.
+ 
++flto-compression-algorithm=
++Common Joined Var(lto_compression_algorithm)
++-flto-compression-algorithm= Generate lto compression in zlib/zstd
++format .
++
+ ; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
+ flto-compression-level=
+ Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 19)
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 025a3c478..f095f17aa 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -20829,6 +20829,44 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
+ 	   arch->name, extension.c_str ());
+ }
+ 
++/* Implement TARGET_OPTION_PRINT_DIFF.  */
++
++static void
++aarch64_option_print_diff (FILE *file, int indent,
++			   struct cl_target_option *ptr1,
++			   struct cl_target_option *ptr2)
++{
++  const char *const cpu1
++    = aarch64_get_tune_cpu (ptr1->x_selected_tune)->name;
++  const struct processor *arch1 = aarch64_get_arch (ptr1->x_selected_arch);
++  std::string extension1
++    = aarch64_get_extension_string_for_isa_flags (ptr1->x_aarch64_isa_flags,
++						  arch1->flags);
++
++  const char *const cpu2
++    = aarch64_get_tune_cpu (ptr2->x_selected_tune)->name;
++  const struct processor *arch2 = aarch64_get_arch (ptr2->x_selected_arch);
++  std::string extension2
++    = aarch64_get_extension_string_for_isa_flags (ptr2->x_aarch64_isa_flags,
++						  arch2->flags);
++
++  if (cpu1 != cpu2 && (!cpu1 || !cpu2 || strcmp (cpu1, cpu2)))
++    fprintf (file, "%*s%s (%s/%s)\n", indent, "",
++	     "cpu", cpu1 ? cpu1 : "(null)", cpu2 ? cpu2 : "(null)");
++
++  if (arch1->name != arch2->name
++      && (!arch1->name || !arch2->name || strcmp (arch1->name, arch2->name)))
++    fprintf (file, "%*s%s (%s/%s)\n", indent, "",
++	     "arch", arch1->name ? arch1->name : "(null)",
++	     arch2->name ? arch2->name : "(null)");
++
++  if (extension1 != extension2)
++    fprintf (file, "%*s%s (%s/%s)\n", indent, "",
++	     "extension",
++	     extension1.empty () ? "(null)" : extension1.c_str (),
++	     extension2.empty () ? "(null)" : extension2.c_str ());
++}
++
+ static GTY(()) tree aarch64_previous_fndecl;
+ 
+ void
+@@ -31161,6 +31199,9 @@ aarch64_libgcc_floating_mode_supported_p
+ #undef TARGET_OPTION_PRINT
+ #define TARGET_OPTION_PRINT aarch64_option_print
+ 
++#undef TARGET_OPTION_PRINT_DIFF
++#define TARGET_OPTION_PRINT_DIFF aarch64_option_print_diff
++
+ #undef TARGET_OPTION_VALID_ATTRIBUTE_P
+ #define TARGET_OPTION_VALID_ATTRIBUTE_P aarch64_option_valid_attribute_p
+ 
+diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
+index 1e96521e6..50bbbbc42 100644
+--- a/gcc/doc/tm.texi
++++ b/gcc/doc/tm.texi
+@@ -10589,6 +10589,12 @@ information in the @code{struct cl_target_option} structure for
+ function-specific options.
+ @end deftypefn
+ 
++@deftypefn {Target Hook} void TARGET_OPTION_PRINT_DIFF (FILE *@var{file}, int @var{indent}, struct cl_target_option *@var{ptr1}, struct cl_target_option *@var{ptr2})
++This hook is called to print diff additional target-specific
++information in the ptr1 and ptr2 @code{struct cl_target_option} structure for
++function-specific options.
++@end deftypefn
++
+ @deftypefn {Target Hook} bool TARGET_OPTION_PRAGMA_PARSE (tree @var{args}, tree @var{pop_target})
+ This target hook parses the options for @code{#pragma GCC target}, which
+ sets the target-specific options for functions that occur later in the
+diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
+index 2dd515659..cfda60304 100644
+--- a/gcc/doc/tm.texi.in
++++ b/gcc/doc/tm.texi.in
+@@ -6985,6 +6985,8 @@ on this implementation detail.
+ 
+ @hook TARGET_OPTION_PRINT
+ 
++@hook TARGET_OPTION_PRINT_DIFF
++
+ @hook TARGET_OPTION_PRAGMA_PARSE
+ 
+ @hook TARGET_OPTION_OVERRIDE
+diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc
+index f8bb072c4..8d5cc9a84 100644
+--- a/gcc/ipa-inline.cc
++++ b/gcc/ipa-inline.cc
+@@ -90,6 +90,8 @@ along with GCC; see the file COPYING3.  If not see
+ 	 the need for offline copy of the function.  */
+ 
+ #include "config.h"
++#define INCLUDE_SET
++#define INCLUDE_STRING
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -127,6 +129,7 @@ typedef fibonacci_node  edge_heap_node_t;
+ static int overall_size;
+ static profile_count max_count;
+ static profile_count spec_rem;
++static std::set force_inline_targets;
+ 
+ /* Return false when inlining edge E would lead to violating
+    limits on function unit growth or stack usage growth.  
+@@ -222,6 +225,38 @@ caller_growth_limits (struct cgraph_edge *e)
+   return true;
+ }
+ 
++/* Warn and prompt the user, and output only once for the file pair where
++   the function is located.  */
++
++static void
++prompt_inline_failed_target_option_reason (struct cgraph_edge *e)
++{
++  static std::set> address_pair_set;
++  if (e->inline_failed == CIF_TARGET_OPTION_MISMATCH
++      && !cl_target_option_eq_major (target_opts_for_fn (e->caller->decl),
++	   target_opts_for_fn (e->callee->ultimate_alias_target ()->decl))
++      && e->caller->lto_file_data
++      && e->callee->ultimate_alias_target ()->lto_file_data)
++    {
++      std::pair addr_pair
++	= std::make_pair (&e->caller->lto_file_data,
++			  &e->callee->ultimate_alias_target ()->lto_file_data);
++      if (address_pair_set.find (addr_pair) != address_pair_set.end ())
++	return;
++
++      address_pair_set.insert (addr_pair);
++      warning (0, "LTO objects caller in: %s, callee in: %s, not inlinable: %s."
++	       " Try to use -finline-force=callee_object_or_lib_name to force "
++	       "inline", e->caller->lto_file_data->file_name,
++	       e->callee->ultimate_alias_target ()->lto_file_data->file_name,
++	       cgraph_inline_failed_string (CIF_TARGET_OPTION_MISMATCH));
++
++      cl_target_option_print_diff
++	(stderr, 2, target_opts_for_fn (e->caller->decl),
++	target_opts_for_fn (e->callee->ultimate_alias_target ()->decl));
++    }
++}
++
+ /* Dump info about why inlining has failed.  */
+ 
+ static void
+@@ -254,6 +289,8 @@ report_inline_failed_reason (struct cgraph_edge *e)
+ 	    (dump_file, 2, opts_for_fn (e->caller->decl),
+ 	     opts_for_fn (e->callee->ultimate_alias_target ()->decl));
+     }
++
++  prompt_inline_failed_target_option_reason (e);
+ }
+ 
+  /* Decide whether sanitizer-related attributes allow inlining. */
+@@ -310,6 +347,77 @@ sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee)
+       (opts_for_fn (caller->decl)->x_##flag		\
+        != opts_for_fn (callee->decl)->x_##flag)
+ 
++/* find related node that has lto_file_data.  */
++
++static cgraph_node *
++find_related_node_lto_file_data (cgraph_node *node)
++{
++  cgraph_node *cur = node;
++
++  while (cur->clone_of)
++    {
++      /* Switch to original node, for example xxx.constprop.x function.  */
++      cur = cur->clone_of;
++      if (cur->lto_file_data)
++	return cur;
++
++      /* Find the lto_file_data information of referring.  */
++      struct ipa_ref *ref = NULL;
++      for (int i = 0; cur->iterate_referring (i, ref); i++)
++	{
++	  struct cgraph_node *cnode = dyn_cast  (ref->referring);
++	  if (cnode && cnode->lto_file_data)
++	    return cnode;
++	}
++    }
++
++  return NULL;
++}
++
++/* Determines whether to force inline or force inline only the specified
++   object.  Use for 3 inline extensions:
++   1) CIF_TARGET_OPTION_MISMATCH: cancel the restriction that the target options
++      of different compilation units are different.
++   2) CIF_OVERWRITABLE: indicates that the function is available, which is
++      similar to the "inline" keyword indication.
++   3) CIF_OPTIMIZATION_MISMATCH: cancel the check in the case of fp_expressions,
++      which is similar to the "always_inline" attribute.
++   */
++
++static bool
++can_force_inline_p (cgraph_node *callee)
++{
++  if (!in_lto_p)
++    return false;
++  if (flag_inline_force)
++    return true;
++  if (force_inline_targets_string)
++    {
++      cgraph_node * node = callee;
++      std::string name = "";
++      if (callee->ultimate_alias_target () == NULL
++	  || callee->ultimate_alias_target ()->lto_file_data == NULL)
++	{
++	  node = find_related_node_lto_file_data (callee);
++	  if (node && node->lto_file_data)
++	    name = node->lto_file_data->file_name;
++	}
++      else
++	name = node->ultimate_alias_target ()->lto_file_data->file_name;
++      while (!name.empty () && name.back () == '/')
++	name.erase (name.length () - 1);
++      if (name.empty ())
++	return false;
++      size_t last_slash_pos = name.find_last_of ('/');
++      if (last_slash_pos != std::string::npos
++	  && last_slash_pos != name.length () - 1)
++	name = name.substr (last_slash_pos + 1);
++      if (force_inline_targets.find (name) != force_inline_targets.end ())
++	return true;
++    }
++  return false;
++}
++
+ /* Decide if we can inline the edge and possibly update
+    inline_failed reason.  
+    We check whether inlining is possible at all and whether
+@@ -352,7 +460,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
+       e->inline_failed = CIF_USES_COMDAT_LOCAL;
+       inlinable = false;
+     }
+-  else if (avail <= AVAIL_INTERPOSABLE)
++  else if (avail <= AVAIL_INTERPOSABLE && !can_force_inline_p (callee))
+     {
+       e->inline_failed = CIF_OVERWRITABLE;
+       inlinable = false;
+@@ -378,8 +486,8 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
+       inlinable = false;
+     }
+   /* Check compatibility of target optimization options.  */
+-  else if (!targetm.target_option.can_inline_p (caller->decl,
+-						callee->decl))
++  else if (!can_force_inline_p (callee)
++	   && !targetm.target_option.can_inline_p (caller->decl, callee->decl))
+     {
+       e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
+       inlinable = false;
+@@ -495,7 +603,8 @@ can_inline_edge_by_limits_p (struct cgraph_edge *e, bool report,
+       bool always_inline =
+ 	     (DECL_DISREGARD_INLINE_LIMITS (callee->decl)
+ 	      && lookup_attribute ("always_inline",
+-				   DECL_ATTRIBUTES (callee->decl)));
++				   DECL_ATTRIBUTES (callee->decl)))
++	     || can_force_inline_p (callee);
+       ipa_fn_summary *caller_info = ipa_fn_summaries->get (caller);
+       ipa_fn_summary *callee_info = ipa_fn_summaries->get (callee);
+ 
+@@ -2652,6 +2761,27 @@ flatten_remove_node_hook (struct cgraph_node *node, void *data)
+   removed->add (node);
+ }
+ 
++/* Parse string that specify forced inlining, separated by commas.  */
++
++static void
++parse_force_inline_targets_string (const char* s)
++{
++  std::string target_string (s);
++  std::string delim = ",";
++  size_t start = 0;
++  size_t end = target_string.find (delim);
++  if (target_string.substr (start, end - start) == "")
++    return;
++
++  while (end != std::string::npos)
++    {
++      force_inline_targets.insert (target_string.substr (start, end - start));
++      start = end + delim.size ();
++      end = target_string.find (delim, start);
++    }
++  force_inline_targets.insert (target_string.substr (start, end - start));
++}
++
+ /* Decide on the inlining.  We do so in the topological order to avoid
+    expenses on updating data structures.  */
+ 
+@@ -2665,6 +2795,9 @@ ipa_inline (void)
+   int cold;
+   bool remove_functions = false;
+ 
++  if (force_inline_targets_string)
++    parse_force_inline_targets_string (force_inline_targets_string);
++
+   order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
+ 
+   if (dump_file)
+diff --git a/gcc/lto-compress.cc b/gcc/lto-compress.cc
+index 27f0992a8..f9d0722a9 100644
+--- a/gcc/lto-compress.cc
++++ b/gcc/lto-compress.cc
+@@ -305,7 +305,11 @@ void
+ lto_end_compression (struct lto_compression_stream *stream)
+ {
+ #ifdef HAVE_ZSTD_H
+-  lto_compression_zstd (stream);
++  if (lto_compression_algorithm
++      && strcmp (lto_compression_algorithm, "zstd") == 0)
++    lto_compression_zstd (stream);
++  else
++    lto_compression_zlib (stream);
+ #else
+   lto_compression_zlib (stream);
+ #endif
+diff --git a/gcc/lto-section-in.cc b/gcc/lto-section-in.cc
+index ba87c7276..947f8eb15 100644
+--- a/gcc/lto-section-in.cc
++++ b/gcc/lto-section-in.cc
+@@ -448,6 +448,11 @@ lto_free_function_in_decl_state_for_node (symtab_node *node)
+       lto_free_function_in_decl_state (*slot);
+       node->lto_file_data->function_decl_states->clear_slot (slot);
+     }
++
++  /* In force inline case, keep lto file path information.  */
++  if (in_lto_p && (flag_inline_force || force_inline_targets_string))
++    return;
++
+   node->lto_file_data = NULL;
+ }
+ 
+diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc
+index 471f35c31..a574f0f1e 100644
+--- a/gcc/lto-streamer-out.cc
++++ b/gcc/lto-streamer-out.cc
+@@ -2666,7 +2666,12 @@ produce_lto_section ()
+   free (section_name);
+ 
+ #ifdef HAVE_ZSTD_H
+-  lto_compression compression = ZSTD;
++  lto_compression compression = ZLIB;
++  if (lto_compression_algorithm
++      && strcmp (lto_compression_algorithm, "zstd") == 0)
++    compression = ZSTD;
++  else
++    compression = ZLIB;
+ #else
+   lto_compression compression = ZLIB;
+ #endif
+diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
+index 155ccce57..2b1994652 100644
+--- a/gcc/lto-wrapper.cc
++++ b/gcc/lto-wrapper.cc
+@@ -491,6 +491,8 @@ merge_and_complain (vec &decoded_options,
+ 	|| decoded_options[j].opt_index == OPT_fpic)
+       {
+ 	/* -fno-pic in one unit implies -fno-pic everywhere.  */
++	/* The -fno-pic adjustment here should provide some information hints,
++	   but may affect the use case test of deja.  */
+ 	if (decoded_options[j].value == 0)
+ 	  j++;
+ 	/* If we have no pic option or merge in -fno-pic, we still may turn
+@@ -534,6 +536,8 @@ merge_and_complain (vec &decoded_options,
+ 	    || decoded_options[j].opt_index == OPT_fpie)
+       {
+ 	/* -fno-pie in one unit implies -fno-pie everywhere.  */
++	/* The -fno-pie adjustment here should provide some information hints,
++	   but may affect the use case test of deja.  */
+ 	if (decoded_options[j].value == 0)
+ 	  j++;
+ 	/* If we have no pie option or merge in -fno-pie, we still preserve
+diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
+index 7c012dd4e..94b85b331 100644
+--- a/gcc/optc-save-gen.awk
++++ b/gcc/optc-save-gen.awk
+@@ -1043,6 +1043,10 @@ for (i = 0; i < n_target_string; i++) {
+ 	print "";
+ }
+ 
++print "";
++print "  if (targetm.target_option.print_diff)";
++print "    targetm.target_option.print_diff (file, indent, ptr1, ptr2);";
++
+ print "}";
+ 
+ print "";
+@@ -1160,6 +1164,59 @@ print "  return true;";
+ 
+ print "}";
+ 
++print "";
++print "/* Compare two target major options.  */";
++print "bool";
++print "cl_target_option_eq_major (struct cl_target_option const *ptr1 ATTRIBUTE_UNUSED,";
++print "                     struct cl_target_option const *ptr2 ATTRIBUTE_UNUSED)";
++print "{";
++n_target_val_major = 0;
++
++for (i = 0; i < n_target_save; i++) {
++	var = target_save_decl[i];
++	sub (" *=.*", "", var);
++	name = var;
++	type = var;
++	sub("^.*[ *]", "", name)
++	sub(" *" name "$", "", type)
++        if (target_save_decl[i] ~ "^const char \\*+[_" alnum "]+$")
++		continue;
++        if (target_save_decl[i] ~ " .*\\[.+\\]+$")
++                continue;
++
++        var_target_val_major[n_target_val_major++] = name;
++}
++if (have_save) {
++	for (i = 0; i < n_opts; i++) {
++		if (flag_set_p("Save", flags[i])) {
++			name = var_name(flags[i])
++			if(name == "")
++				name = "target_flags";
++
++			if(name in var_list_seen)
++				continue;
++
++			var_list_seen[name]++;
++			otype = var_type_struct(flags[i])
++			if (otype ~ "^const char \\**$")
++				continue;
++			var_target_val_major[n_target_val_major++] = "x_" name;
++		}
++	}
++} else {
++	var_target_val_major[n_target_val_major++] = "x_target_flags";
++}
++
++for (i = 0; i < n_target_val_major; i++) {
++	name = var_target_val_major[i]
++	print "  if (ptr1->" name" != ptr2->" name ")";
++	print "    return false;";
++}
++
++print "  return true;";
++
++print "}";
++
+ print "";
+ print "/* Hash target options  */";
+ print "hashval_t";
+diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk
+index 8bba8ec45..cb016e85d 100644
+--- a/gcc/opth-gen.awk
++++ b/gcc/opth-gen.awk
+@@ -330,6 +330,9 @@ print "";
+ print "/* Compare two target option variables from a structure.  */";
+ print "extern bool cl_target_option_eq (const struct cl_target_option *, const struct cl_target_option *);";
+ print "";
++print "/* Compare two target major option variables from a structure.  */";
++print "extern bool cl_target_option_eq_major (const struct cl_target_option *, const struct cl_target_option *);";
++print "";
+ print "/* Free heap memory used by target option variables.  */";
+ print "extern void cl_target_option_free (struct cl_target_option *);";
+ print "";
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index d97f6079f..d9de8747c 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -2611,6 +2611,32 @@ print_help (struct gcc_options *opts, unsigned int lang_mask,
+ 			 lang_mask);
+ }
+ 
++/* Checks whether the input forced inline string complies with the
++   restriction.  */
++
++void
++check_force_inline_targets_string (const char *arg, location_t loc)
++{
++  const int MAX_FORCE_INLINE_TARGET_LEN = 10000;
++  const int MAX_NUM_TARGET = 100;
++  __SIZE_TYPE__ length = strlen (arg);
++  int target_num = 1;
++  if (length > MAX_FORCE_INLINE_TARGET_LEN)
++    error_at (loc,
++	      "input string exceeds %d characters to %<-finline_force=%> "
++	      "option: %qs", MAX_FORCE_INLINE_TARGET_LEN, arg);
++  for (__SIZE_TYPE__ i = 0; i < length; i++)
++    {
++      if (arg[i] == ',')
++	{
++	  target_num++;
++	  if (target_num > MAX_NUM_TARGET)
++	    error_at (loc, "input target exceeds %d to %<-finline_force=%> "
++		      "option: %qs", MAX_NUM_TARGET, arg);
++	}
++    }
++}
++
+ /* Handle target- and language-independent options.  Return zero to
+    generate an "unknown option" message.  Only options that need
+    extra handling need to be listed here; if you simply want
+@@ -2952,6 +2978,14 @@ common_handle_option (struct gcc_options *opts,
+ 			   value / 2);
+       break;
+ 
++    case OPT_finline_force:
++      opts->x_force_inline_targets_string = value ? "" : NULL;
++      break;
++
++    case OPT_finline_force_:
++      check_force_inline_targets_string (arg, loc);
++      break;
++
+     case OPT_finstrument_functions_exclude_function_list_:
+       add_comma_separated_to_vector
+ 	(&opts->x_flag_instrument_functions_exclude_functions, arg);
+@@ -3226,6 +3260,18 @@ common_handle_option (struct gcc_options *opts,
+ 		  "unrecognized argument to %<-flto=%> option: %qs", arg);
+       break;
+ 
++    case OPT_flto_compression_algorithm_:
++      if (atoi (arg) == 0
++	  && strcmp (arg, "zlib") != 0
++#ifdef HAVE_ZSTD_H
++	  && strcmp (arg, "zstd") != 0
++#endif
++	)
++	error_at (loc,
++		  "unrecognized argument to %<-flto-compression-algorithm=%> "
++		  "option: %qs", arg);
++      break;
++
+     case OPT_w:
+       dc->dc_inhibit_warnings = true;
+       break;
+diff --git a/gcc/target.def b/gcc/target.def
+index 7183f363d..142858fa3 100644
+--- a/gcc/target.def
++++ b/gcc/target.def
+@@ -6644,6 +6644,16 @@ information in the @code{struct cl_target_option} structure for\n\
+ function-specific options.",
+  void, (FILE *file, int indent, struct cl_target_option *ptr), NULL)
+ 
++/* Function to print any extra target state from the target options
++   structure.  */
++DEFHOOK
++(print_diff,
++ "This hook is called to print diff additional target-specific\n\
++information in the ptr1 and ptr2 @code{struct cl_target_option} structure for\n\
++function-specific options.",
++ void, (FILE *file, int indent, struct cl_target_option *ptr1,
++ struct cl_target_option *ptr2), NULL)
++
+ /* Function to parse arguments to be validated for #pragma target, and to
+    change the state if the options are valid.  If the first argument is
+    NULL, the second argument specifies the default options to use.  Return
+diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c b/gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c
+new file mode 100644
+index 000000000..0b5cd5953
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/lto/binary-inline-1_0.c
+@@ -0,0 +1,15 @@
++/* { dg-lto-do link }  */
++/* { dg-require-effective-target shared } */
++/* { dg-extra-ld-options {-shared -finline-force=c_lto_binary-inline-1_1.o} } */
++/* { dg-lto-options {{-O3 -flto -march=armv8.2-a -fdump-ipa-inline-details}} }  */ 
++
++extern double multi_op(float x);
++
++double func_a (float x)
++{
++  double res = 0;
++  res = multi_op (x);
++  return res;
++}
++
++/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls"  "inline"  } } */
+diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c b/gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c
+new file mode 100644
+index 000000000..8181384b7
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/lto/binary-inline-1_1.c
+@@ -0,0 +1,6 @@
++/* { dg-options "-march=armv8.3-a+sve+f64mm+crc+crypto+fp16+i8mm+simd" } */
++
++double multi_op (float x)
++{
++    return x * 2 + 10;
++}
+diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c b/gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c
+new file mode 100644
+index 000000000..e873937d3
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/lto/binary-inline-2_0.c
+@@ -0,0 +1,15 @@
++/* { dg-lto-do link }  */
++/* { dg-require-effective-target shared } */
++/* { dg-extra-ld-options {-shared -finline-force=c_lto_binary-inline-2_1.o} } */
++/* { dg-lto-options {{-O3 -flto -fPIC -fdump-ipa-inline-details}} }  */ 
++
++extern double multi_op(float x);
++
++double func_a (float x)
++{
++  double res = 0;
++  res = multi_op (x);
++  return res;
++}
++
++/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls"  "inline"  } } */
+diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c b/gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c
+new file mode 100644
+index 000000000..dc7c4fd9f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/lto/binary-inline-2_1.c
+@@ -0,0 +1,5 @@
++
++double multi_op (float x)
++{
++    return x * 2 + 10;
++}
+diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c b/gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c
+new file mode 100644
+index 000000000..c78ba066d
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/lto/binary-inline-3_0.c
+@@ -0,0 +1,15 @@
++/* { dg-lto-do link }  */
++/* { dg-require-effective-target shared } */
++/* { dg-extra-ld-options {-shared -finline-force=c_lto_binary-inline-3_1.o} } */
++/* { dg-lto-options {{-O3 -flto -fdump-ipa-inline-details}} }  */ 
++
++extern double multi_op(double x);
++
++double func_a (double x)
++{
++  double res = 0;
++  res = multi_op (x);
++  return res;
++}
++
++/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls"  "inline"  } } */
+diff --git a/gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c b/gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c
+new file mode 100644
+index 000000000..8b505fa0c
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/lto/binary-inline-3_1.c
+@@ -0,0 +1,10 @@
++/* { dg-options "-O2 -fno-math-errno" }  */
++
++#include 
++
++double multi_op (double x)
++{
++    double a = 0;
++    a = sqrt (x);
++    return a * 2 + 10;
++}
+diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc
+index a35a810f4..79f819ad8 100644
+--- a/gcc/tree-streamer-in.cc
++++ b/gcc/tree-streamer-in.cc
+@@ -20,6 +20,9 @@ along with GCC; see the file COPYING3.  If not see
+ .  */
+ 
+ #include "config.h"
++#include 
++#define INCLUDE_SET
++#define INCLUDE_STRING
+ #include "system.h"
+ #include "coretypes.h"
+ #include "backend.h"
+@@ -36,6 +39,47 @@ along with GCC; see the file COPYING3.  If not see
+ #include "asan.h"
+ #include "opts.h"
+ 
++/* Parse string that specify forced inlining, separated by commas.  */
++static std::set multi_version_libs;
++static void
++parse_multi_version_lib_string (const char* s)
++{
++  std::string target_string (s);
++  std::string delim = ",";
++  size_t start = 0;
++  size_t end = target_string.find (delim);
++  if (target_string.substr (start, end - start) == "")
++    return;
++
++  while (end != std::string::npos)
++    {
++      multi_version_libs.insert (target_string.substr (start, end - start));
++      start = end + delim.size ();
++      end = target_string.find (delim, start);
++    }
++  multi_version_libs.insert (target_string.substr (start, end - start));
++}
++
++static bool
++target_lib_p (std::string name)
++{
++  if (multi_version_libs.empty () && multi_version_lib_string)
++    parse_multi_version_lib_string (multi_version_lib_string);
++  if (multi_version_lib_string)
++    {
++      while (!name.empty () && name.back () == '/')
++	name.erase (name.length () - 1);
++      if (name.empty ())
++	return false;
++      size_t last_slash_pos = name.find_last_of ('/');
++      if (last_slash_pos != std::string::npos
++	  && last_slash_pos != name.length () - 1)
++	name = name.substr (last_slash_pos + 1);
++      if (multi_version_libs.find (name) != multi_version_libs.end ())
++	return true;
++    }
++  return false;
++}
+ 
+ /* Read a STRING_CST from the string table in DATA_IN using input
+    block IB.  */
+@@ -555,7 +599,12 @@ streamer_read_tree_bitfields (class lto_input_block *ib,
+     unpack_ts_translation_unit_decl_value_fields (data_in, &bp, expr);
+ 
+   if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
+-    cl_optimization_stream_in (data_in, &bp, TREE_OPTIMIZATION (expr));
++  {
++    if (target_lib_p (data_in->file_data->file_name))
++      cl_optimization_stream_in_prev (data_in, &bp, TREE_OPTIMIZATION (expr));
++    else
++      cl_optimization_stream_in (data_in, &bp, TREE_OPTIMIZATION (expr));
++  }
+ 
+   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
+     {
+@@ -569,7 +618,12 @@ streamer_read_tree_bitfields (class lto_input_block *ib,
+ #ifndef ACCEL_COMPILER
+   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION))
+     {
+-      cl_target_option_stream_in (data_in, &bp, TREE_TARGET_OPTION (expr));
++      if (target_lib_p (data_in->file_data->file_name))
++	cl_target_option_stream_in_prev (
++		data_in, &bp, TREE_TARGET_OPTION (expr));
++      else
++	cl_target_option_stream_in (data_in, &bp, TREE_TARGET_OPTION (expr));
++
+       if (targetm.target_option.post_stream_in)
+ 	targetm.target_option.post_stream_in (TREE_TARGET_OPTION (expr));
+     }
+diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
+index 33d49571d..b3301a8a4 100644
+--- a/lto-plugin/lto-plugin.c
++++ b/lto-plugin/lto-plugin.c
+@@ -89,6 +89,10 @@ along with this program; see the file COPYING3.  If not see
+ 
+ #define LTO_SEGMENT_NAME "__GNU_LTO"
+ 
++#define GCC_major_version 12
++#define LTO_major_version GCC_major_version
++#define LTO_minor_version 0
++
+ /* Return true if STR string starts with PREFIX.  */
+ 
+ static inline bool
+@@ -118,6 +122,18 @@ struct plugin_symtab
+   unsigned long long id;
+ };
+ 
++/* Structure that represents LTO ELF section with information
++   about the format.  */
++
++struct lto_section
++{
++  int16_t major_version;
++  int16_t minor_version;
++  unsigned char slim_object;
++  unsigned char _padding;
++  uint16_t flags;
++};
++
+ /* Encapsulates object file data during symbol scan.  */
+ struct plugin_objfile
+ {
+@@ -126,6 +142,7 @@ struct plugin_objfile
+   simple_object_read *objfile;
+   struct plugin_symtab *out;
+   const struct ld_plugin_input_file *file;
++  struct lto_section version;
+ };
+ 
+ /* All that we have to remember about a file. */
+@@ -216,6 +233,8 @@ static int gold_version = -1;
+    (in fact, only first letter of style arg is checked.)  */
+ static enum symbol_style sym_style = ss_none;
+ 
++static bool multi_version_lto_parse = false;
++
+ static void
+ check_1 (int gate, enum ld_plugin_level level, const char *text)
+ {
+@@ -1078,6 +1097,59 @@ err:
+   return 0;
+ }
+ 
++/* Process version section of an object file.  */
++
++static int
++process_lto_version (void *data, const char *name, off_t offset, off_t length)
++{
++  struct plugin_objfile *obj = (struct plugin_objfile *)data;
++  char *s;
++  char *secdatastart, *secdata;
++
++  if (!startswith (name, ".gnu.lto_.lto"))
++    return 1;
++
++  s = strrchr (name, '.');
++  if (s)
++    sscanf (s, ".%" PRI_LL "x", &obj->out->id);
++  secdata = secdatastart = xmalloc (length);
++  offset += obj->file->offset;
++  if (offset != lseek (obj->file->fd, offset, SEEK_SET))
++    goto err;
++
++  do
++    {
++      ssize_t got = read (obj->file->fd, secdata, length);
++      if (got == 0)
++	break;
++      else if (got > 0)
++	{
++	  secdata += got;
++	  length -= got;
++	}
++      else if (errno != EINTR)
++	goto err;
++    }
++  while (length > 0);
++  if (length > 0)
++    goto err;
++
++  struct lto_section *lto_info = (struct lto_section *)secdatastart;
++  obj->version = *lto_info;
++
++  obj->found++;
++  free (secdatastart);
++  return 1;
++
++err:
++  if (message)
++    message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
++  /* Force claim_file_handler to abandon this file.  */
++  obj->found = 0;
++  free (secdatastart);
++  return 0;
++}
++
+ /* Process one section of an object file.  */
+ 
+ static int
+@@ -1223,6 +1295,15 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
+   if (obj.found == 0 && obj.offload == 0)
+     goto err;
+ 
++  if (multi_version_lto_parse)
++    {
++      simple_object_find_sections (obj.objfile, process_lto_version, &obj,
++	      &err);
++      if (obj.version.major_version != LTO_major_version
++	  || obj.version.minor_version != LTO_minor_version)
++	goto err;
++    }
++
+   if (obj.found > 1)
+     resolve_conflicts (<o_file.symtab, <o_file.conflicts);
+ 
+@@ -1366,6 +1447,8 @@ process_option (const char *option)
+     }
+   else if (startswith (option, "-ltrans-objects="))
+     ltrans_objects = xstrdup (option + strlen ("-ltrans-objects="));
++  else if (strcmp (option, "-multi-version-lto-parse") == 0)
++    multi_version_lto_parse = true;
+   else
+     {
+       int size;
+-- 
+2.25.1
+
diff --git a/0305-Backport-varasm-Handle-private-COMDAT-function-symbo.patch b/0305-Backport-varasm-Handle-private-COMDAT-function-symbo.patch
new file mode 100644
index 0000000..e3bf4dc
--- /dev/null
+++ b/0305-Backport-varasm-Handle-private-COMDAT-function-symbo.patch
@@ -0,0 +1,296 @@
+From bbb4954294d010977fcfb96931384101cf015a44 Mon Sep 17 00:00:00 2001
+From: Jakub Jelinek 
+Date: Mon, 26 Feb 2024 17:55:07 +0100
+Subject: [PATCH] [Backport]varasm: Handle private COMDAT function symbol
+ reference in readonly data section [PR113617]
+
+If default_elf_select_rtx_section is called to put a reference to some
+local symbol defined in a comdat section into memory, which happens more often
+since the r14-4944 RA change, linking might fail.
+default_elf_select_rtx_section puts such constants into .data.rel.ro.local
+etc. sections and if linker chooses comdat sections from some other TU
+and discards the one to which a relocation in .data.rel.ro.local remains,
+linker diagnoses error.  References to private comdat symbols can only appear
+from functions or data objects in the same comdat group, so the following
+patch arranges using .data.rel.ro.local.pool. and similar sections.
+
+2024-02-26  Jakub Jelinek  
+	    H.J. Lu  
+
+	PR rtl-optimization/113617
+	* varasm.cc (default_elf_select_rtx_section): For
+	references to private symbols in comdat sections
+	use .data.relro.local.pool., .data.relro.pool.
+	or .rodata. comdat sections.
+
+	* g++.dg/other/pr113617.C: New test.
+	* g++.dg/other/pr113617.h: New test.
+	* g++.dg/other/pr113617-aux.cc: New test.
+---
+ gcc/testsuite/g++.dg/other/pr113617-aux.cc |   9 ++
+ gcc/testsuite/g++.dg/other/pr113617.C      |  27 +++++
+ gcc/testsuite/g++.dg/other/pr113617.h      | 132 +++++++++++++++++++++
+ gcc/varasm.cc                              |  48 +++++++-
+ 4 files changed, 215 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/g++.dg/other/pr113617-aux.cc
+ create mode 100644 gcc/testsuite/g++.dg/other/pr113617.C
+ create mode 100644 gcc/testsuite/g++.dg/other/pr113617.h
+
+diff --git a/gcc/testsuite/g++.dg/other/pr113617-aux.cc b/gcc/testsuite/g++.dg/other/pr113617-aux.cc
+new file mode 100644
+index 000000000..e6900e05a
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/other/pr113617-aux.cc
+@@ -0,0 +1,9 @@
++// PR rtl-optimization/113617
++// { dg-do link { target { c++17 && c++14_down } } }
++
++#include "pr113617.h"
++
++void qux() {
++  A a;
++  a.foo(0, 0);
++}
+diff --git a/gcc/testsuite/g++.dg/other/pr113617.C b/gcc/testsuite/g++.dg/other/pr113617.C
+new file mode 100644
+index 000000000..a02dda142
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/other/pr113617.C
+@@ -0,0 +1,27 @@
++// PR rtl-optimization/113617
++// { dg-do link { target c++11 } }
++// { dg-options "-O2" }
++// { dg-additional-options "-fPIC" { target fpic } } */
++// { dg-additional-options "-shared" { target shared } } */
++// { dg-additional-sources pr113617-aux.cc }
++
++#include "pr113617.h"
++
++int z;
++long xx1;
++void corge() {
++  A a;
++  a.foo(xx1, 0);
++}
++
++typedef unsigned long int VV __attribute__((vector_size (2 * sizeof (long))));
++VV vv;
++__attribute__((noipa)) static void fn1 (void) {}
++__attribute__((noipa)) static void fn2 (void) {}
++
++void
++fn3 ()
++{
++  VV a = { (unsigned long) &fn1, (unsigned long) &fn2 };
++  vv = a;
++}
+diff --git a/gcc/testsuite/g++.dg/other/pr113617.h b/gcc/testsuite/g++.dg/other/pr113617.h
+new file mode 100644
+index 000000000..4d30eddbc
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/other/pr113617.h
+@@ -0,0 +1,132 @@
++namespace {
++template  struct J { static constexpr int value = V; };
++template  using K = J;
++using M = K;
++template  struct L { template  using type = _Tp; };
++template  using N = typename L<_Cond>::type<_If, _Else>;
++M k;
++template  struct O { using type = _Tp; };
++template 
++struct P : N, _Up> {};
++template  struct Q { using type = typename P<_Tp>::type; };
++}
++namespace R {
++struct H;
++enum G {};
++template  class S;
++struct T { using U = bool (*) (H &, const H &, G); U F; };
++template  class B;
++template 
++struct B<_R(_A...), _F> {
++  static bool F(H &, const H &, G) { return false; }
++  __attribute__((noipa)) static _R bar(const H &) {}
++};
++template 
++struct S<_R(_A...)> : T {
++  template  using AH = B<_R(), _F>;
++  template  S(_F) {
++    using AG = AH<_F>;
++    barr = AG::bar;
++    F = AG::F;
++  }
++  using AF = _R (*)(const H &);
++  AF barr;
++};
++template  class I;
++template 
++struct I<_F(_B...)> {};
++template  using W = decltype(k);
++template  struct V {
++  typedef I::type(typename Q<_B>::type...)> type;
++};
++template 
++__attribute__((noipa)) typename V::value, _F, _B...>::type
++baz(_F, _B...) { return typename V::value, _F, _B...>::type (); }
++template  struct AJ {
++  template  struct _Ptr { using type = _Up *; };
++  using AI = typename _Ptr<_Tp>::type;
++};
++template  struct Y {
++  using AI = typename AJ<_Tp>::AI;
++  AI operator->();
++};
++}
++extern int z;
++namespace N1 {
++namespace N2 {
++namespace N3 {
++enum Z { Z1, Z2 };
++template  struct X {
++  template 
++  __attribute__((noipa)) void boo(long long, long long, long long, _F &) {}
++};
++struct AC {
++  AC(int);
++  void m1(R::S);
++};
++template 
++__attribute__((noipa)) void garply(void *, long long, long long, long long) {}
++template <>
++template 
++void X::boo(long long, long long x, long long y, _F &fi) {
++  AC pool(z);
++  for (;;) {
++    auto job = R::baz(garply<_F>, &fi, y, y, x);
++    pool.m1(job);
++  }
++}
++struct AB {
++  static AB &bleh();
++  template 
++  void boo(long first, long x, long y, _F fi) {
++    switch (ab1) {
++    case Z1:
++      ab2->boo(first, x, y, fi);
++    case Z2:
++      ab3->boo(first, x, y, fi);
++    }
++  }
++  Z ab1;
++  R::Y> ab2;
++  R::Y> ab3;
++};
++template  struct C;
++template  struct C<_F, false> {
++  __attribute__((noipa)) C(_F) {}
++  void boo(long first, long x, long y) {
++    auto u = AB::bleh();
++    u.boo(first, x, y, *this);
++  }
++};
++template  struct AA { typedef C<_F, 0> type; };
++}
++}
++}
++struct AD {
++  template 
++  static void boo(long first, long x, long y, _F f) {
++    typename N1::N2::N3::AA<_F>::type fi(f);
++    fi.boo(first, x, y);
++  }
++  template 
++  static void boo(long first, long x, _F f) {
++    boo(first, x, 0, f);
++  }
++};
++template  struct A {
++  void foo(long long, long long);
++  int *c;
++};
++namespace {
++template  struct D { __attribute__((noipa)) D(int *) {} };
++}
++template 
++void A::foo(long long x, long long y)
++{
++  int e;
++  D d(&e);
++  AD::boo(0, y, d);
++  long p;
++  for (p = 0; p < x; p++)
++    c[p] = c[p - 1];
++}
+diff --git a/gcc/varasm.cc b/gcc/varasm.cc
+index bae935694..d122730b5 100644
+--- a/gcc/varasm.cc
++++ b/gcc/varasm.cc
+@@ -7317,17 +7317,63 @@ default_elf_select_rtx_section (machine_mode mode, rtx x,
+ 				unsigned HOST_WIDE_INT align)
+ {
+   int reloc = compute_reloc_for_rtx (x);
++  tree decl = nullptr;
++  const char *prefix = nullptr;
++  int flags = 0;
++
++  /* If it is a private COMDAT function symbol reference, call
++     function_rodata_section for the read-only or relocated read-only
++     data section associated with function DECL so that the COMDAT
++     section will be used for the private COMDAT function symbol.  */
++  if (HAVE_COMDAT_GROUP)
++    {
++      if (GET_CODE (x) == CONST
++	 && GET_CODE (XEXP (x, 0)) == PLUS
++	 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
++       x = XEXP (XEXP (x, 0), 0);
++
++      if (GET_CODE (x) == SYMBOL_REF)
++       {
++	 decl = SYMBOL_REF_DECL (x);
++	 if (decl
++	     && (TREE_CODE (decl) != FUNCTION_DECL
++		 || !DECL_COMDAT_GROUP (decl)
++		 || TREE_PUBLIC (decl)))
++	   decl = nullptr;
++       }
++    }
+ 
+   /* ??? Handle small data here somehow.  */
+ 
+   if (reloc & targetm.asm_out.reloc_rw_mask ())
+     {
+-      if (reloc == 1)
++      if (decl)
++	{
++	  prefix = reloc == 1 ? ".data.rel.ro.local" : ".data.rel.ro";
++	  flags = SECTION_WRITE | SECTION_RELRO;
++	}
++      else if (reloc == 1)
+ 	return get_named_section (NULL, ".data.rel.ro.local", 1);
+       else
+ 	return get_named_section (NULL, ".data.rel.ro", 3);
+     }
+ 
++  if (decl)
++    {
++      const char *comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl));
++      if (!prefix)
++	prefix = ".rodata";
++      size_t prefix_len = strlen (prefix);
++      size_t comdat_len = strlen (comdat);
++      size_t len = prefix_len + sizeof (".pool.") + comdat_len;
++      char *name = XALLOCAVEC (char, len);
++      memcpy (name, prefix, prefix_len);
++      memcpy (name + prefix_len, ".pool.", sizeof (".pool.") - 1);
++      memcpy (name + prefix_len + sizeof (".pool.") - 1, comdat,
++	      comdat_len + 1);
++      return get_section (name, flags | SECTION_LINKONCE, decl);
++    }
++
+   return mergeable_constant_section (mode, align, 0);
+ }
+ 
+-- 
+2.33.0
+
diff --git a/0306-RISC-V-Install-libstdc-libcc1-etc-to-lib64-instead-o.patch b/0306-RISC-V-Install-libstdc-libcc1-etc-to-lib64-instead-o.patch
new file mode 100644
index 0000000..3c0c15a
--- /dev/null
+++ b/0306-RISC-V-Install-libstdc-libcc1-etc-to-lib64-instead-o.patch
@@ -0,0 +1,65 @@
+From 84edbc6544ed872aedb3cb6f6d0feb8647ff1d8b Mon Sep 17 00:00:00 2001
+From: YunQiang Su 
+Date: Mon, 14 Oct 2024 10:09:46 +0800
+Subject: [PATCH] RISC-V: Install libstdc++/libcc1 etc to /lib64 instead of lib
+
+The problem is that if we are configured with `--disable-multilib`,
+  gcc -print-multi-os-directory
+outputs
+  .
+Thus the dest to install libraries is set to
+  /usr/lib/.
+While other platforms (x86-64, arm64) it will be
+  /usr/lib/../lib64
+Let's sync riscv64 with them
+
+Another problem is that
+  gcc -print-file-name=libzstd.so.1
+will output
+  /usr/lib64/lp64d/../lib64/libzstd.so.1
+which is also need to patched.
+---
+ gcc/config.gcc               | 3 +++
+ gcc/config/riscv/linux.h     | 2 ++
+ gcc/config/riscv/t-openEuler | 2 ++
+ 3 files changed, 7 insertions(+)
+ create mode 100644 gcc/config/riscv/t-openEuler
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 19b21a280..23c5bee2b 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -2453,6 +2453,9 @@ riscv*-*-linux*)
+ 	xyes) tmake_file="${tmake_file} riscv/t-linux-multilib" ;;
+ 	*) echo "Unknown value for enable_multilib"; exit 1
+ 	esac
++	case "x${target_vendor}" in
++	xopenEuler) tmake_file="${tmake_file} riscv/t-openEuler"
++	esac
+ 	tmake_file="${tmake_file} riscv/t-riscv riscv/t-linux"
+ 	gnu_ld=yes
+ 	gas=yes
+diff --git a/gcc/config/riscv/linux.h b/gcc/config/riscv/linux.h
+index b5c6c5027..a8d65f4e0 100644
+--- a/gcc/config/riscv/linux.h
++++ b/gcc/config/riscv/linux.h
+@@ -62,6 +62,8 @@ along with GCC; see the file COPYING3.  If not see
+ #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+ 
+ #define STARTFILE_PREFIX_SPEC 			\
++   "/lib" XLEN_SPEC "/ " 			\
++   "/usr/lib" XLEN_SPEC "/ " 			\
+    "/lib" XLEN_SPEC "/" ABI_SPEC "/ "		\
+    "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ "	\
+    "/lib/ "					\
+diff --git a/gcc/config/riscv/t-openEuler b/gcc/config/riscv/t-openEuler
+new file mode 100644
+index 000000000..26541dd08
+--- /dev/null
++++ b/gcc/config/riscv/t-openEuler
+@@ -0,0 +1,2 @@
++MULTILIB_OPTIONS = mabi=lp64d
++MULTILIB_DIRNAMES = ../lib64
+-- 
+2.39.5 (Apple Git-154)
+
diff --git a/0307-Set-fallback-value-for-print-multi-os-directory.patch b/0307-Set-fallback-value-for-print-multi-os-directory.patch
new file mode 100644
index 0000000..2032f6b
--- /dev/null
+++ b/0307-Set-fallback-value-for-print-multi-os-directory.patch
@@ -0,0 +1,105 @@
+From 0d157b14f361f8319f4694c54c6e01ac8f59d278 Mon Sep 17 00:00:00 2001
+From: YunQiang Su 
+Date: Tue, 8 Oct 2024 17:56:23 +0800
+Subject: [PATCH 1/2] Set fallback value for -print-multi-os-directory
+
+Clang doesn't support -print-multi-os-directory option.
+So let's set the fallback value (../lib64) if it is empty.
+
+This is only needed for the projects built by hostcc:
+  gcc, libcc1, libiberty
+
+The projects for targets only, will always built by gcc itself.
+---
+ gcc/configure         | 3 +++
+ libcc1/configure      | 6 ++++++
+ libcc1/configure.ac   | 3 +++
+ libiberty/Makefile.in | 5 ++++-
+ libtool.m4            | 3 +++
+ 5 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/configure b/gcc/configure
+index 7e64599b0..ef0449edd 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -18598,6 +18598,9 @@ if test "$GCC" = yes; then
+   # and add multilib dir if necessary.
+   lt_tmp_lt_search_path_spec=
+   lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
++  if [ -z "$lt_multi_os_dir" ];then
++    lt_multi_os_dir=../lib64
++  fi
+   for lt_sys_path in $lt_search_path_spec; do
+     if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+diff --git a/libcc1/configure b/libcc1/configure
+index 01cfb2806..3c437d690 100755
+--- a/libcc1/configure
++++ b/libcc1/configure
+@@ -9701,6 +9701,9 @@ if test "$GCC" = yes; then
+   # and add multilib dir if necessary.
+   lt_tmp_lt_search_path_spec=
+   lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
++  if [ -z "$lt_multi_os_dir" ];then
++    lt_multi_os_dir=../lib64
++  fi
+   for lt_sys_path in $lt_search_path_spec; do
+     if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+@@ -14865,6 +14868,9 @@ libsuffix=
+ if test "$GXX" = yes; then
+   libsuffix=`$CXX -print-multi-os-directory`
+ fi
++if [ -z "$libsuffix" ];then
++  libsuffix=../lib64
++fi
+ 
+ 
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket libraries" >&5
+diff --git a/libcc1/configure.ac b/libcc1/configure.ac
+index 36f5a7e09..acd7c4c04 100644
+--- a/libcc1/configure.ac
++++ b/libcc1/configure.ac
+@@ -72,6 +72,9 @@ libsuffix=
+ if test "$GXX" = yes; then
+   libsuffix=`$CXX -print-multi-os-directory`
+ fi
++if [ -z "$libsuffix" ];then
++  libsuffix=../lib64
++fi
+ AC_SUBST(libsuffix)
+ 
+ dnl Test for -lsocket and -lnsl.  Copied from libgo/configure.ac.
+diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
+index 1b17c2e3a..2bfa00de5 100644
+--- a/libiberty/Makefile.in
++++ b/libiberty/Makefile.in
+@@ -385,7 +385,10 @@ install-strip: install
+ # multilib-specific flags, it's overridden by FLAGS_TO_PASS from the
+ # default multilib, so we have to take CFLAGS into account as well,
+ # since it will be passed the multilib flags.
+-MULTIOSDIR = `$(CC) $(CFLAGS) -print-multi-os-directory`
++MULTIOSDIR = `$(CC) $(CFLAGS) -print-multi-os-directory 2>/dev/null`
++ifeq ($(MULTIOSDIR),)
++ MULTIOSDIR = ../lib64
++endif
+ install_to_libdir: all
+ 	if test -n "${target_header_dir}"; then \
+ 		${mkinstalldirs} $(DESTDIR)$(libdir)/$(MULTIOSDIR); \
+diff --git a/libtool.m4 b/libtool.m4
+index 17f8e5f30..86fc1e705 100644
+--- a/libtool.m4
++++ b/libtool.m4
+@@ -2059,6 +2059,9 @@ if test "$GCC" = yes; then
+   # and add multilib dir if necessary.
+   lt_tmp_lt_search_path_spec=
+   lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
++  if [ -z "$lt_multi_os_dir" ];then
++    lt_multi_os_dir=../lib64
++  fi
+   for lt_sys_path in $lt_search_path_spec; do
+     if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+-- 
+2.47.0
+
diff --git a/0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch b/0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch
new file mode 100644
index 0000000..a16e937
--- /dev/null
+++ b/0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch
@@ -0,0 +1,108 @@
+From 1624bdceb341e0034c22ce46bc2e422726f76cce Mon Sep 17 00:00:00 2001
+From: YunQiang Su 
+Date: Tue, 8 Oct 2024 17:59:56 +0800
+Subject: [PATCH 2/2] Fix enum { INPUT, MIDDLE, FINAL } aes_stage
+
+The FINAL is defined in ansidecl.h.
+Let's rename the elements to
+   aesINPUT, aseMIDDLE, aseFINAL
+to avoid conflits.
+
+I find this problem when trying to build gcc with clang.
+In fact FINAL is defined to empty for clang, and `final` for gcc.
+So it coincidentally worked for gcc.
+---
+ gcc/crypto-accel.cc | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/gcc/crypto-accel.cc b/gcc/crypto-accel.cc
+index e7766a585..716c4a38b 100644
+--- a/gcc/crypto-accel.cc
++++ b/gcc/crypto-accel.cc
+@@ -1251,7 +1251,7 @@ public:
+ 
+ /* AES stage description.  Required for some specializations
+    for curtain rounds.  */
+-typedef enum { INPUT, MIDDLE, FINAL } aes_stage;
++typedef enum { aesINPUT, aesMIDDLE, aesFINAL } aes_stage;
+ 
+ /* AES entity description.  It can be both round or state inside round.
+    It provides interface for unified analysis between blocks of 4 parts:
+@@ -1356,7 +1356,7 @@ struct state_input
+ 
+ /* Input round state uses special input.  */
+ template<>
+-struct state_input
++struct state_input
+ {
+   typedef std::pair type;
+ 
+@@ -1389,7 +1389,7 @@ struct state_output
+ 
+ /* Final round state generates special output.  */
+ template<>
+-struct state_output
++struct state_output
+ {
+   typedef std::pair type;
+ 
+@@ -1409,7 +1409,7 @@ struct round_input
+ 
+ /* Input round uses special input just as its state.  */
+ template<>
+-struct round_input
++struct round_input
+ {
+   typedef std::pair type;
+ };
+@@ -1437,7 +1437,7 @@ struct round_output
+    AES encryption.  */
+ template<>
+ template<>
+-void round_output::reorder (type &out)
++void round_output::reorder (type &out)
+ {
+   gcc_assert (out.size () == 4);
+   std::swap (out[1], out[3]);
+@@ -1445,14 +1445,14 @@ void round_output::reorder (type &out)
+ 
+ template<>
+ template<>
+-void round_output::reorder (type &out)
++void round_output::reorder (type &out)
+ {
+-  round_output::reorder (out);
++  round_output::reorder (out);
+ }
+ 
+ /* Final round generates special output.  */
+ template<>
+-struct round_output : state_output
++struct round_output : state_output
+ {
+   template
+   static void finalize (type &out, const T &v)
+@@ -1644,14 +1644,14 @@ public:
+   typedef std::map > table_ref_map;
+ 
+   /* AES states typedefs.  */
+-  typedef aes_state aes_input_state;
+-  typedef aes_state, MIDDLE, T> aes_body_state;
+-  typedef aes_state, FINAL, T> aes_final_state;
++  typedef aes_state aes_input_state;
++  typedef aes_state, aesMIDDLE, T> aes_body_state;
++  typedef aes_state, aesFINAL, T> aes_final_state;
+ 
+   /* AES rounds typedefs.  */
+-  typedef aes_round aes_input_round;
+-  typedef aes_round, MIDDLE, T> aes_body_round;
+-  typedef aes_round, FINAL, T> aes_final_round;
++  typedef aes_round aes_input_round;
++  typedef aes_round, aesMIDDLE, T> aes_body_round;
++  typedef aes_round, aesFINAL, T> aes_final_round;
+ 
+   bool run ();
+ 
+-- 
+2.47.0
+
diff --git a/0309-CSPGO-Add-context-sensitive-PGO.patch b/0309-CSPGO-Add-context-sensitive-PGO.patch
new file mode 100644
index 0000000..04174af
--- /dev/null
+++ b/0309-CSPGO-Add-context-sensitive-PGO.patch
@@ -0,0 +1,1337 @@
+From 45a424e51c4c5de46062f2d7f355da8a99604d71 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Tue, 19 Nov 2024 22:06:48 +0800
+Subject: [PATCH] [CSPGO] Add context sensitive PGO
+
+Same as LLVM, GCC PGO profile counts are not context sensitive. Therefore,
+CSPGO is added to collect the profile again after PGO to obtain accurate
+execution information after inline for better performance.
+---
+ gcc/auto-profile.cc |   2 +-
+ gcc/cgraph.cc       |  47 ++++++++++
+ gcc/cgraph.h        |   8 +-
+ gcc/cgraphunit.cc   |  63 ++++++++++++-
+ gcc/common.opt      |  20 ++++
+ gcc/coverage.cc     | 162 +++++++++++++++++++++++---------
+ gcc/coverage.h      |   5 +-
+ gcc/gcc.cc          |   5 +-
+ gcc/ipa-profile.cc  |   4 +-
+ gcc/lto-cgraph.cc   |   7 ++
+ gcc/opts.cc         |  18 ++++
+ gcc/passes.cc       |  71 ++++++++++++++
+ gcc/passes.def      |   1 +
+ gcc/profile.cc      |  27 +++---
+ gcc/profile.h       |   2 +-
+ gcc/timevar.def     |   1 +
+ gcc/tree-pass.h     |   2 +
+ gcc/tree-profile.cc | 223 +++++++++++++++++++++++++++++++++++++++++++-
+ gcc/value-prof.cc   |   9 +-
+ gcc/value-prof.h    |   4 +-
+ 20 files changed, 611 insertions(+), 70 deletions(-)
+
+diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
+index f45f0ec66..5e85381ce 100644
+--- a/gcc/auto-profile.cc
++++ b/gcc/auto-profile.cc
+@@ -1775,7 +1775,7 @@ auto_profile (void)
+   if (symtab->state == FINISHED)
+     return 0;
+ 
+-  init_node_map (true);
++  init_node_map (true, false);
+   profile_info = autofdo::afdo_profile_info;
+ 
+   FOR_EACH_FUNCTION (node)
+diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
+index 7d738b891..95619aefa 100644
+--- a/gcc/cgraph.cc
++++ b/gcc/cgraph.cc
+@@ -4076,6 +4076,53 @@ cgraph_node::get_body (void)
+   return updated;
+ }
+ 
++/* Prepare function body.  When doing LTO, read cgraph_node's body from disk
++   if it is not already present.  When some IPA transformations are scheduled,
++   apply them.
++   Flag is used to control only skipping or enabling cspgo.  */
++
++bool
++cgraph_node::ipa_transform_for_cspgo (bool is_cspgo)
++{
++  bool updated;
++
++  bitmap_obstack_initialize (NULL);
++  updated = get_untransformed_body ();
++
++  /* Getting transformed body makes no sense for inline clones;
++     we should never use this on real clones because they are materialized
++     early.
++     TODO: Materializing clones here will likely lead to smaller LTRANS
++     footprint.  */
++  gcc_assert (!inlined_to && !clone_of);
++  if (ipa_transforms_to_apply.exists ())
++    {
++      opt_pass *saved_current_pass = current_pass;
++      FILE *saved_dump_file = dump_file;
++      const char *saved_dump_file_name = dump_file_name;
++      dump_flags_t saved_dump_flags = dump_flags;
++      dump_file_name = NULL;
++      set_dump_file (NULL);
++
++      push_cfun (DECL_STRUCT_FUNCTION (decl));
++
++      update_ssa (TODO_update_ssa_only_virtuals);
++      execute_all_ipa_transforms_for_cspgo (is_cspgo);
++      cgraph_edge::rebuild_edges ();
++      free_dominance_info (CDI_DOMINATORS);
++      free_dominance_info (CDI_POST_DOMINATORS);
++      pop_cfun ();
++      updated = true;
++
++      current_pass = saved_current_pass;
++      set_dump_file (saved_dump_file);
++      dump_file_name = saved_dump_file_name;
++      dump_flags = saved_dump_flags;
++    }
++  bitmap_obstack_release (NULL);
++  return updated;
++}
++
+ /* Return the DECL_STRUCT_FUNCTION of the function.  */
+ 
+ struct function *
+diff --git a/gcc/cgraph.h b/gcc/cgraph.h
+index 2332539e5..3fdf36769 100644
+--- a/gcc/cgraph.h
++++ b/gcc/cgraph.h
+@@ -1097,11 +1097,17 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
+      present.  */
+   bool get_untransformed_body ();
+ 
+-  /* Prepare function body.  When doing LTO, read cgraph_node's body from disk 
++  /* Prepare function body.  When doing LTO, read cgraph_node's body from disk
+      if it is not already present.  When some IPA transformations are scheduled,
+      apply them.  */
+   bool get_body ();
+ 
++  /* Prepare function body.  When doing LTO, read cgraph_node's body from disk
++     if it is not already present.  When some IPA transformations are scheduled,
++     apply them.
++     Flag is used to control only skipping or enabling cspgo.  */
++  bool ipa_transform_for_cspgo (bool);
++
+   void materialize_clone (void);
+ 
+   /* Release memory used to represent body of function.
+diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
+index 5aa7b57c9..37cc83eab 100644
+--- a/gcc/cgraphunit.cc
++++ b/gcc/cgraphunit.cc
+@@ -208,6 +208,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "ipa-inline.h"
+ #include "omp-offload.h"
+ #include "symtab-thunks.h"
++#include "profile.h" // for del_node_map
+ 
+ /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
+    secondary queue used during optimization to accommodate passes that
+@@ -1928,6 +1929,29 @@ tp_first_run_node_cmp (const void *pa, const void *pb)
+   return tp_first_run_a - tp_first_run_b;
+ }
+ 
++static bool
++expand_node_with_cspgo (cgraph_node *node, bool is_cspgo)
++{
++  gcc_assert (node);
++  /* Nodes in other partition, inline to, and clone of are not
++     interesting in cspgo.  */
++  if (!node->has_gimple_body_p ()
++      || node->in_other_partition
++      || node->inlined_to
++      || node->clone_of)
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] node %s will not do"
++			    " transform\n", node->dump_name ());
++      return false;
++    }
++
++  if (node->process)
++    node->ipa_transform_for_cspgo (is_cspgo);
++  return true;
++}
++
++
+ /* Expand all functions that must be output.
+ 
+    Attempt to topologically sort the nodes so function is output when
+@@ -1968,6 +1992,39 @@ expand_all_functions (void)
+   /* First output functions with time profile in specified order.  */
+   qsort (tp_first_run_order, tp_first_run_order_pos,
+ 	 sizeof (cgraph_node *), tp_first_run_node_cmp);
++
++  if (flag_csprofile_generate || flag_csprofile_use)
++    {
++      bool is_cspgo = false;
++
++      /* We need to execute loop twice.  The first performs all transforms
++	 except cspgo, and the second performs cspgo transform.  */
++      for (int idx = 0; idx < 2; idx++)
++	{
++	  for (i = 0; i < tp_first_run_order_pos; i++)
++	    {
++	      node = tp_first_run_order[i];
++	      if (!expand_node_with_cspgo (node, is_cspgo))
++		continue;
++	    }
++
++	  for (i = new_order_pos - 1; i >= 0; i--)
++	    {
++	      node = order[i];
++	      if (!expand_node_with_cspgo (node, is_cspgo))
++		continue;
++	    }
++
++	  is_cspgo = true;
++	}
++
++      if (flag_csprofile_use)
++	handle_missing_profiles ();
++
++      if (coverage_node_map_initialized_p ())
++	del_node_map ();
++    }
++
+   for (i = 0; i < tp_first_run_order_pos; i++)
+     {
+       node = tp_first_run_order[i];
+@@ -2009,6 +2066,10 @@ expand_all_functions (void)
+     fprintf (symtab->dump_file, "Expanded functions with time profile:%u/%u\n",
+              profiled_func_count, expanded_func_count);
+ 
++  /* Generate coverage variables and constructor for cspgo.  */
++  if (flag_csprofile_generate)
++    coverage_finish (true);
++
+   symtab->process_new_functions ();
+   free_gimplify_stack ();
+   delete ipa_saved_clone_sources;
+@@ -2176,7 +2237,7 @@ ipa_passes (void)
+   if (!in_lto_p)
+     {
+       /* Generate coverage variables and constructors.  */
+-      coverage_finish ();
++      coverage_finish (false);
+ 
+       /* Process new functions added.  */
+       set_cfun (NULL);
+diff --git a/gcc/common.opt b/gcc/common.opt
+index be5fcc681..fc2920cee 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2397,6 +2397,10 @@ Common Joined RejectNegative Var(profile_data_prefix)
+ Set the top-level directory for storing the profile data.
+ The default is 'pwd'.
+ 
++fcfgo-csprofile-dir=
++Common Joined RejectNegative Var(csprofile_data_prefix)
++Set the top-level directory for storing the cs profile data.
++
+ fprofile-note=
+ Common Joined RejectNegative Var(profile_note_location)
+ Select the name for storing the profile note file.
+@@ -2461,6 +2465,14 @@ fprofile-generate=
+ Common Joined RejectNegative
+ Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=.
+ 
++fcfgo-csprofile-generate
++Common Var(flag_csprofile_generate)
++Enable common options for generating context sensitive profile info for profile feedback directed optimizations.
++
++fcfgo-csprofile-generate=
++Common Joined RejectNegative
++Enable common options for generating context sensitive profile info for profile feedback directed optimizations, and set -fcfgo-csprofile-dir=.
++
+ fkernel-pgo
+ Common Var(flag_kernel_pgo) Optimization Init(0)
+ Disable TLS setting of instrumentation variables to support PGO kernel compilation in -fprofile-generate, as kernel does not support TLS.
+@@ -2485,6 +2497,14 @@ fprofile-use=
+ Common Joined RejectNegative
+ Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
+ 
++fcfgo-csprofile-use
++Common Var(flag_csprofile_use)
++Enable common options for performing context sensitive profile feedback directed optimizations.
++
++fcfgo-csprofile-use=
++Common Joined RejectNegative
++Enable common options for performing context sensitive profile feedback directed optimizations, and set -fcfgo-csprofile-dir=.
++
+ fprofile-values
+ Common Var(flag_profile_values)
+ Insert code to profile values of expressions.
+diff --git a/gcc/coverage.cc b/gcc/coverage.cc
+index 8ece5db68..1a7fcb5df 100644
+--- a/gcc/coverage.cc
++++ b/gcc/coverage.cc
+@@ -86,7 +86,6 @@ struct counts_entry : pointer_hash 
+ 
+ static GTY(()) struct coverage_data *functions_head = 0;
+ static struct coverage_data **functions_tail = &functions_head;
+-static unsigned no_coverage = 0;
+ 
+ /* Cumulative counter information for whole program.  */
+ static unsigned prg_ctr_mask; /* Mask of counter types generated.  */
+@@ -114,6 +113,9 @@ static unsigned bbg_file_stamp;
+ /* Name of the count data (gcda) file.  */
+ static char *da_file_name;
+ 
++/* Name of the cs count data (gcda) file.  */
++static char *cs_da_file_name;
++
+ /* The names of merge functions for counters.  */
+ #define STR(str) #str
+ #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) STR(__gcov_merge ## FN_TYPE),
+@@ -173,23 +175,28 @@ counts_entry::remove (counts_entry *entry)
+ /* Hash table of count data.  */
+ static hash_table *counts_hash;
+ 
++/* Hash table of cs count data.  */
++static hash_table *cs_counts_hash;
++
+ /* Read in the counts file, if available.  */
+ 
+ static void
+-read_counts_file (void)
++read_counts_file (bool is_cspgo)
+ {
+   gcov_unsigned_t fn_ident = 0;
+   gcov_unsigned_t tag;
+   int is_error = 0;
+   unsigned lineno_checksum = 0;
+   unsigned cfg_checksum = 0;
++  char *gcda_file_name = (is_cspgo ? cs_da_file_name : da_file_name);
+ 
+-  if (!gcov_open (da_file_name, 1))
++  if (!gcov_open (gcda_file_name, 1))
+     return;
+ 
+   if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
+     {
+-      warning (0, "%qs is not a gcov data file", da_file_name);
++      warning (0, "%qs is not a %s data file", gcda_file_name,
++	       (is_cspgo ? "cs gcov" : "gcov"));
+       gcov_close ();
+       return;
+     }
+@@ -201,7 +208,7 @@ read_counts_file (void)
+       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
+ 
+       warning (0, "%qs is version %q.*s, expected version %q.*s",
+- 	       da_file_name, 4, v, 4, e);
++	       gcda_file_name, 4, v, 4, e);
+       gcov_close ();
+       return;
+     }
+@@ -213,7 +220,7 @@ read_counts_file (void)
+   /* Read checksum.  */
+   gcov_read_unsigned ();
+ 
+-  counts_hash = new hash_table (10);
++  (is_cspgo ? cs_counts_hash : counts_hash) = new hash_table (10);
+   while ((tag = gcov_read_unsigned ()))
+     {
+       gcov_unsigned_t length;
+@@ -234,9 +241,18 @@ read_counts_file (void)
+ 	}
+       else if (tag == GCOV_TAG_OBJECT_SUMMARY)
+ 	{
+-	  profile_info = XCNEW (gcov_summary);
+-	  profile_info->runs = gcov_read_unsigned ();
+-	  profile_info->sum_max = gcov_read_unsigned ();
++	  if (is_cspgo)
++	    {
++	      /* TODO: runs and sum_max need better handling for cspgo.  */
++	      gcov_unsigned_t runs = gcov_read_unsigned ();
++	      gcov_unsigned_t sum_max = gcov_read_unsigned ();
++	    }
++	  else
++	    {
++	      profile_info = XCNEW (gcov_summary);
++	      profile_info->runs = gcov_read_unsigned ();
++	      profile_info->sum_max = gcov_read_unsigned ();
++	    }
+ 	}
+       else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
+ 	{
+@@ -249,7 +265,9 @@ read_counts_file (void)
+ 	  elt.ident = fn_ident;
+ 	  elt.ctr = GCOV_COUNTER_FOR_TAG (tag);
+ 
+-	  slot = counts_hash->find_slot (&elt, INSERT);
++	  slot = (is_cspgo ? cs_counts_hash->find_slot (&elt, INSERT) :
++			     counts_hash->find_slot (&elt, INSERT));
++
+ 	  entry = *slot;
+ 	  if (!entry)
+ 	    {
+@@ -264,12 +282,21 @@ read_counts_file (void)
+ 	  else if (entry->lineno_checksum != lineno_checksum
+ 		   || entry->cfg_checksum != cfg_checksum)
+ 	    {
+-	      error ("profile data for function %u is corrupted", fn_ident);
++	      error ("%s data for function %u is corrupted",
++		     (is_cspgo ? "cs profile" : "profile"), fn_ident);
+ 	      error ("checksum is (%x,%x) instead of (%x,%x)",
+ 		     entry->lineno_checksum, entry->cfg_checksum,
+ 		     lineno_checksum, cfg_checksum);
+-	      delete counts_hash;
+-	      counts_hash = NULL;
++	      if (is_cspgo)
++		{
++		  delete cs_counts_hash;
++		  cs_counts_hash = NULL;
++		}
++	      else
++		{
++		  delete counts_hash;
++		  counts_hash = NULL;
++		}
+ 	      break;
+ 	    }
+ 	  if (read_length > 0)
+@@ -282,9 +309,17 @@ read_counts_file (void)
+ 	  error (is_error < 0
+ 		 ? G_("%qs has overflowed")
+ 		 : G_("%qs is corrupted"),
+-		 da_file_name);
+-	  delete counts_hash;
+-	  counts_hash = NULL;
++		 gcda_file_name);
++	  if (is_cspgo)
++	    {
++	      delete cs_counts_hash;
++	      cs_counts_hash = NULL;
++	    }
++	  else
++	    {
++	      delete counts_hash;
++	      counts_hash = NULL;
++	    }
+ 	  break;
+ 	}
+     }
+@@ -296,26 +331,30 @@ read_counts_file (void)
+ 
+ gcov_type *
+ get_coverage_counts (unsigned counter, unsigned cfg_checksum,
+-		     unsigned lineno_checksum, unsigned int n_counts)
++		     unsigned lineno_checksum, unsigned int n_counts,
++		     bool is_cspgo)
+ {
+   counts_entry *entry, elt;
++  char *gcda_file_name = (is_cspgo ? cs_da_file_name : da_file_name);
+ 
+   /* No hash table, no counts.  */
+-  if (!counts_hash)
++  if ((is_cspgo ? (!cs_counts_hash) : (!counts_hash)))
+     {
+       static int warned = 0;
+ 
+       if (!warned++)
+ 	{
+ 	  warning (OPT_Wmissing_profile,
+-		   "%qs profile count data file not found",
+-		   da_file_name);
++		   "%qs %s count data file not found",
++		   gcda_file_name, (is_cspgo ? "cs profile" : "profile"));
+ 	  if (dump_enabled_p ())
+ 	    {
+ 	      dump_user_location_t loc
+ 		= dump_user_location_t::from_location_t (input_location);
+ 	      dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+-			       "file %s not found, %s\n", da_file_name,
++			       "%s file %s not found, %s\n",
++			       (is_cspgo ? "cs profile" : "profile"),
++			       gcda_file_name,
+ 			       (flag_guess_branch_prob
+ 				? "execution counts estimated"
+ 				: "execution counts assumed to be zero"));
+@@ -331,13 +370,14 @@ get_coverage_counts (unsigned counter, unsigned cfg_checksum,
+       elt.ident = cgraph_node::get (current_function_decl)->profile_id;
+     }
+   elt.ctr = counter;
+-  entry = counts_hash->find (&elt);
++  entry = (is_cspgo ? cs_counts_hash->find (&elt) : counts_hash->find (&elt));
+   if (!entry)
+     {
+       if (counter == GCOV_COUNTER_ARCS)
+ 	warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+ 		    OPT_Wmissing_profile,
+-		    "profile for function %qD not found in profile data",
++		    "%s for function %qD not found in profile data",
++		    (is_cspgo ? "cs profile" : "profile"),
+ 		    current_function_decl);
+       /* The function was not emitted, or is weak and not chosen in the
+ 	 final executable.  Silently fail, because there's nothing we
+@@ -357,9 +397,10 @@ get_coverage_counts (unsigned counter, unsigned cfg_checksum,
+ 	warning_printed =
+ 	  warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+ 		      OPT_Wcoverage_mismatch,
+-		      "number of counters in profile data for function %qD "
++		      "number of counters in %s data for function %qD "
+ 		      "does not match "
+ 		      "its profile data (counter %qs, expected %i and have %i)",
++		      (is_cspgo ? "cs profile" : "profile"),
+ 		      current_function_decl,
+ 		      ctr_names[counter], entry->n_counts, n_counts);
+       else
+@@ -367,7 +408,8 @@ get_coverage_counts (unsigned counter, unsigned cfg_checksum,
+ 	  warning_at (DECL_SOURCE_LOCATION (current_function_decl),
+ 		      OPT_Wcoverage_mismatch,
+ 		      "the control flow of function %qD does not match "
+-		      "its profile data (counter %qs)", current_function_decl,
++		      "its %s data (counter %qs)", current_function_decl,
++		      (is_cspgo ? "cs profile" : "profile"),
+ 		      ctr_names[counter]);
+       if (warning_printed && dump_enabled_p ())
+ 	{
+@@ -413,9 +455,6 @@ get_coverage_counts (unsigned counter, unsigned cfg_checksum,
+ int
+ coverage_counter_alloc (unsigned counter, unsigned num)
+ {
+-  if (no_coverage)
+-    return 0;
+-
+   if (!num)
+     return 1;
+ 
+@@ -623,7 +662,7 @@ coverage_begin_function (unsigned lineno_checksum, unsigned cfg_checksum)
+ {
+   /* We don't need to output .gcno file unless we're under -ftest-coverage
+      (e.g. -fprofile-arcs/generate/use don't need .gcno to work). */
+-  if (no_coverage || !bbg_file_name)
++  if (!bbg_file_name)
+     return 0;
+ 
+   expanded_location startloc
+@@ -981,7 +1020,8 @@ build_info_type (tree type, tree fn_info_ptr_type)
+    function info objects.  */
+ 
+ static tree
+-build_info (tree info_type, tree fn_ary, unsigned object_checksum)
++build_info (tree info_type, tree fn_ary, unsigned object_checksum,
++	    bool is_cspgo)
+ {
+   tree info_fields = TYPE_FIELDS (info_type);
+   tree merge_fn_type, n_funcs;
+@@ -1014,8 +1054,16 @@ build_info (tree info_type, tree fn_ary, unsigned 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);
++  if (is_cspgo)
++    {
++      da_file_name_len = strlen (cs_da_file_name);
++      filename_string = build_string (da_file_name_len + 1, cs_da_file_name);
++    }
++  else
++    {
++      da_file_name_len = strlen (da_file_name);
++      filename_string = build_string (da_file_name_len + 1, da_file_name);
++    }
+   TREE_TYPE (filename_string) = build_array_type
+     (char_type_node, build_index_type (size_int (da_file_name_len)));
+   CONSTRUCTOR_APPEND_ELT (v1, info_fields,
+@@ -1142,7 +1190,7 @@ build_gcov_info_var_registration (tree gcov_info_type)
+    for the object.  Returns TRUE if coverage data is being emitted.  */
+ 
+ static bool
+-coverage_obj_init (void)
++coverage_obj_init (bool is_cspgo)
+ {
+   tree gcov_info_type;
+   unsigned n_counters = 0;
+@@ -1151,8 +1199,6 @@ coverage_obj_init (void)
+   struct coverage_data **fn_prev;
+   char name_buf[32];
+ 
+-  no_coverage = 1; /* Disable any further coverage.  */
+-
+   if (!prg_ctr_mask)
+     return false;
+ 
+@@ -1161,7 +1207,9 @@ coverage_obj_init (void)
+ 
+   /* Prune functions.  */
+   for (fn_prev = &functions_head; (fn = *fn_prev);)
+-    if (DECL_STRUCT_FUNCTION (fn->fn_decl))
++    /* In cspgo, the DECL_STRUCT_FUNCTION attribute has been checked in
++       csprofile_transform.  */
++    if (is_cspgo || DECL_STRUCT_FUNCTION (fn->fn_decl))
+       fn_prev = &fn->next;
+     else
+       /* The function is not being emitted, remove from list.  */
+@@ -1225,7 +1273,7 @@ coverage_obj_fn (vec *ctor, tree fn,
+ 
+ static void
+ coverage_obj_finish (vec *ctor,
+-		     unsigned object_checksum)
++		     unsigned object_checksum, bool is_cspgo)
+ {
+   unsigned n_functions = vec_safe_length (ctor);
+   tree fn_info_ary_type = build_array_type
+@@ -1242,7 +1290,8 @@ coverage_obj_finish (vec *ctor,
+   varpool_node::finalize_decl (fn_info_ary);
+   
+   DECL_INITIAL (gcov_info_var)
+-    = build_info (TREE_TYPE (gcov_info_var), fn_info_ary, object_checksum);
++    = build_info (TREE_TYPE (gcov_info_var), fn_info_ary, object_checksum,
++		  is_cspgo);
+   varpool_node::finalize_decl (gcov_info_var);
+ }
+ 
+@@ -1310,11 +1359,32 @@ coverage_init (const char *filename)
+   memcpy (da_file_name + prefix_len, filename, len);
+   strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
+ 
++  /* Name of cspgo da file.  */
++  if (flag_csprofile_generate || flag_csprofile_use)
++    {
++      if (csprofile_data_prefix)
++	prefix_len = strlen (csprofile_data_prefix);
++
++      cs_da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX)
++				 + prefix_len + 2);
++
++      if (csprofile_data_prefix)
++	{
++	  memcpy (cs_da_file_name, csprofile_data_prefix, prefix_len);
++	  cs_da_file_name[prefix_len++] = *separator;
++	}
++      memcpy (cs_da_file_name + prefix_len, filename, len);
++      strcpy (cs_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)
+-    read_counts_file ();
++    read_counts_file (false);
++
++  if (flag_csprofile_use)
++    read_counts_file (true);
+ 
+   /* Name of bbg file.  */
+   if (flag_test_coverage && !flag_compare_debug)
+@@ -1354,7 +1424,7 @@ coverage_init (const char *filename)
+    variables and constructor.  */
+ 
+ void
+-coverage_finish (void)
++coverage_finish (bool is_cspgo)
+ {
+   if (bbg_file_name && gcov_close ())
+     unlink (bbg_file_name);
+@@ -1368,7 +1438,7 @@ coverage_finish (void)
+   /* Global GCDA checksum that aggregates all functions.  */
+   unsigned object_checksum = 0;
+ 
+-  if (coverage_obj_init ())
++  if (coverage_obj_init (is_cspgo))
+     {
+       vec *fn_ctor = NULL;
+       struct coverage_data *fn;
+@@ -1382,11 +1452,17 @@ coverage_finish (void)
+ 					    fn->lineno_checksum);
+ 	  object_checksum = crc32_unsigned (object_checksum, fn->cfg_checksum);
+ 	}
+-      coverage_obj_finish (fn_ctor, object_checksum);
++      coverage_obj_finish (fn_ctor, object_checksum, is_cspgo);
+     }
+ 
+-  XDELETEVEC (da_file_name);
++  if (da_file_name)
++    XDELETEVEC (da_file_name);
+   da_file_name = NULL;
++  if (is_cspgo)
++    {
++      XDELETEVEC (cs_da_file_name);
++      cs_da_file_name = NULL;
++    }
+ }
+ 
+ #include "gt-coverage.h"
+diff --git a/gcc/coverage.h b/gcc/coverage.h
+index 0ac046c88..a4e90e8bd 100644
+--- a/gcc/coverage.h
++++ b/gcc/coverage.h
+@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "gcov-io.h"
+ 
+ extern void coverage_init (const char *);
+-extern void coverage_finish (void);
++extern void coverage_finish (bool);
+ extern void coverage_remove_note_file (void);
+ 
+ /* Start outputting coverage information for the current
+@@ -53,7 +53,8 @@ extern tree tree_coverage_counter_addr (unsigned /*counter*/, unsigned/*num*/);
+ extern gcov_type *get_coverage_counts (unsigned /*counter*/,
+ 				       unsigned /*cfg_checksum*/,
+ 				       unsigned /*lineno_checksum*/,
+-				       unsigned /*n_counts*/);
++				       unsigned /*n_counts*/,
++				       bool /*is_cspgo*/);
+ 
+ extern tree get_gcov_type (void);
+ extern bool coverage_node_map_initialized_p (void);
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index 32e45adc2..b37b50be2 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -1147,7 +1147,8 @@ proper position among the other output files.  */
+ 	%:include(libgomp.spec)%(link_gomp)}\
+     %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
+     %(mflib) " STACK_SPLIT_SPEC "\
+-    %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \
++    %{fprofile-arcs|fprofile-generate*|fcfgo-csprofile-generate*|coverage:-lgcov} \
++    " SANITIZER_SPEC " \
+     %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}\
+     %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*}  \n%(post_link) }}}}}}"
+ #endif
+@@ -1265,7 +1266,7 @@ static const char *cc1_options =
+  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}}\
+  %{fsyntax-only:-o %j} %{-param*}\
+  %{coverage:-fprofile-arcs -ftest-coverage}\
+- %{fprofile-arcs|fprofile-generate*|coverage:\
++ %{fprofile-arcs|fprofile-generate*|fcfgo-csprofile-generate*|coverage:\
+    %{!fprofile-update=single:\
+      %{pthread:-fprofile-update=prefer-atomic}}}";
+ 
+diff --git a/gcc/ipa-profile.cc b/gcc/ipa-profile.cc
+index ffdcb4476..27554e507 100644
+--- a/gcc/ipa-profile.cc
++++ b/gcc/ipa-profile.cc
+@@ -827,7 +827,7 @@ ipa_profile (void)
+   if (dump_file)
+     {
+       if (!node_map_initialized)
+-	init_node_map (false);
++	init_node_map (false, false);
+       node_map_initialized = true;
+ 
+       ipa_profile_dump_all_summaries (dump_file);
+@@ -850,7 +850,7 @@ ipa_profile (void)
+ 	  if (spec_count)
+ 	    {
+ 	      if (!node_map_initialized)
+-		init_node_map (false);
++		init_node_map (false, false);
+ 	      node_map_initialized = true;
+ 	      ncommon++;
+ 
+diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
+index 237743ef0..fd41941d1 100644
+--- a/gcc/lto-cgraph.cc
++++ b/gcc/lto-cgraph.cc
+@@ -1677,6 +1677,13 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
+   if (flag_ltrans)
+     return;
+ 
++  /* TODO: The different max_run values obtained during the cspgo GEN and USE
++     stages with unknown bug resulted in different scaling results, which led
++     different optimization decisions and finally led to coverage mismatch.
++     Therefore, skip the following processing steps when doing cspgo.  */
++  if (flag_csprofile_generate || flag_csprofile_use)
++    return;
++
+   /* Now compute count_materialization_scale of each node.
+      During LTRANS we already have values of count_materialization_scale
+      computed, so just update them.  */
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index d97f6079f..7900a658f 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -3016,6 +3016,15 @@ common_handle_option (struct gcc_options *opts,
+ 			     false);
+       break;
+ 
++    case OPT_fcfgo_csprofile_use_:
++      opts->x_csprofile_data_prefix = xstrdup (arg);
++      value = true;
++      /* No break here - do -fcfgo-csprofile-use processing.  */
++      /* FALLTHRU */
++    case OPT_fcfgo_csprofile_use:
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_csprofile_use, value);
++      break;
++
+     case OPT_fauto_profile_:
+       opts->x_auto_profile_file = xstrdup (arg);
+       opts->x_flag_auto_profile = true;
+@@ -3059,6 +3068,15 @@ common_handle_option (struct gcc_options *opts,
+       SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
+       break;
+ 
++    case OPT_fcfgo_csprofile_generate_:
++      opts->x_csprofile_data_prefix = xstrdup (arg);
++      value = true;
++      /* No break here - do -fcfgo-csprofile-generate processing.  */
++      /* FALLTHRU */
++    case OPT_fcfgo_csprofile_generate:
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_csprofile_generate, value);
++      break;
++
+     case OPT_fprofile_info_section:
+       opts->x_profile_info_section = ".gcov_info";
+       break;
+diff --git a/gcc/passes.cc b/gcc/passes.cc
+index 36e5b4ac4..154690d02 100644
+--- a/gcc/passes.cc
++++ b/gcc/passes.cc
+@@ -2410,6 +2410,77 @@ execute_all_ipa_transforms (bool do_not_collect)
+   node->ipa_transforms_to_apply.release ();
+ }
+ 
++/* When is_cspgo is true, execute all passes except cspgo and save the pointer
++   for the next execution.  */
++
++void
++execute_all_ipa_transforms_for_cspgo (bool is_cspgo)
++{
++  struct cgraph_node *node;
++  ipa_opt_pass_d *cspgo_pass = NULL;
++  node = cgraph_node::get (current_function_decl);
++
++  cgraph_node *next_clone;
++  for (cgraph_node *n = node->clones; n; n = next_clone)
++    {
++      next_clone = n->next_sibling_clone;
++      if (n->decl != node->decl)
++	n->materialize_clone ();
++    }
++
++  int j = 0;
++  gcc::pass_manager *passes = g->get_passes ();
++  bool report = profile_report && (cfun->curr_properties & PROP_gimple) != 0;
++
++  if (report)
++    push_cfun (DECL_STRUCT_FUNCTION (node->decl));
++
++  for (auto p : node->ipa_transforms_to_apply)
++    {
++      /* Execute all passes except cspgo, and save the pointer of cspgo pass
++	 for the next execution.  */
++      if (!is_cspgo && strstr (p->name, "csprofile") != NULL)
++	{
++	  cspgo_pass = p;
++	  continue;
++	}
++      /* To get consistent statistics, we need to account each functio
++	 to each IPA pass.  */
++      if (report)
++	{
++	  for (;j < p->static_pass_number; j++)
++	    if (passes->get_pass_for_id (j)
++		&& passes->get_pass_for_id (j)->type == IPA_PASS
++		&& ((ipa_opt_pass_d *)passes->get_pass_for_id (j))
++		   ->function_transform)
++	      {
++		check_profile_consistency (j, true);
++		account_profile (j, true);
++	      }
++	  gcc_checking_assert (passes->get_pass_for_id (j) == p);
++	}
++      execute_one_ipa_transform_pass (node, p, true);
++    }
++  /* Account remaining IPA passes.  */
++  if (report)
++    {
++      for (;!passes->get_pass_for_id (j)
++	    || passes->get_pass_for_id (j)->type != RTL_PASS; j++)
++	if (passes->get_pass_for_id (j)
++	    && passes->get_pass_for_id (j)->type == IPA_PASS
++	    && ((ipa_opt_pass_d *)passes->get_pass_for_id (j))
++	       ->function_transform)
++	  {
++	    check_profile_consistency (j, true);
++	    account_profile (j, true);
++	  }
++      pop_cfun ();
++    }
++  node->ipa_transforms_to_apply.release ();
++  if (!is_cspgo)
++    node->ipa_transforms_to_apply.safe_push (cspgo_pass);
++}
++
+ /* Check if PASS is explicitly disabled or enabled and return
+    the gate status.  FUNC is the function to be processed, and
+    GATE_STATUS is the gate status determined by pass manager by
+diff --git a/gcc/passes.def b/gcc/passes.def
+index e945af96a..862ef0d8f 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -164,6 +164,7 @@ along with GCC; see the file COPYING3.  If not see
+   NEXT_PASS (pass_ipa_cdtor_merge);
+   NEXT_PASS (pass_ipa_fn_summary);
+   NEXT_PASS (pass_ipa_inline);
++  NEXT_PASS (pass_ipa_csprofile);
+   NEXT_PASS (pass_ipa_pure_const);
+   NEXT_PASS (pass_ipa_modref);
+   NEXT_PASS (pass_ipa_free_fn_summary, false /* small_p */);
+diff --git a/gcc/profile.cc b/gcc/profile.cc
+index 40e105258..0ffc1ba4f 100644
+--- a/gcc/profile.cc
++++ b/gcc/profile.cc
+@@ -201,7 +201,7 @@ instrument_values (histogram_values values)
+    CFG_CHECKSUM is the precomputed checksum for the CFG.  */
+ 
+ static gcov_type *
+-get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum)
++get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum, bool is_cspgo)
+ {
+   unsigned num_edges = 0;
+   basic_block bb;
+@@ -219,7 +219,7 @@ get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum)
+     }
+ 
+   counts = get_coverage_counts (GCOV_COUNTER_ARCS, cfg_checksum,
+-				lineno_checksum, num_edges);
++				lineno_checksum, num_edges, is_cspgo);
+   if (!counts)
+     return NULL;
+ 
+@@ -418,7 +418,8 @@ cmp_stats (const void *ptr1, const void *ptr2)
+    CFG_CHECKSUM is the precomputed checksum for the CFG.  */
+ 
+ static void
+-compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
++compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum,
++			      bool is_cspgo)
+ {
+   basic_block bb;
+   int i;
+@@ -427,7 +428,8 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
+   int passes;
+   int hist_br_prob[20];
+   int num_branches;
+-  gcov_type *exec_counts = get_exec_counts (cfg_checksum, lineno_checksum);
++  gcov_type *exec_counts = get_exec_counts (cfg_checksum, lineno_checksum,
++					    is_cspgo);
+   int inconsistent = 0;
+ 
+   /* Very simple sanity checks so we catch bugs in our profiling code.  */
+@@ -868,7 +870,7 @@ sort_hist_values (histogram_value hist)
+ 
+ static void
+ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
+-                          unsigned lineno_checksum)
++			  unsigned lineno_checksum, bool is_cspgo)
+ {
+   unsigned i, j, t, any;
+   unsigned n_histogram_counters[GCOV_N_VALUE_COUNTERS];
+@@ -898,7 +900,8 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
+       histogram_counts[t] = get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
+ 						 cfg_checksum,
+ 						 lineno_checksum,
+-						 n_histogram_counters[t]);
++						 n_histogram_counters[t],
++						 is_cspgo);
+       if (histogram_counts[t])
+ 	any = 1;
+       act_count[t] = histogram_counts[t];
+@@ -1128,11 +1131,12 @@ compare_freqs (const void *p1, const void *p2)
+ /* Only read execution count for thunks.  */
+ 
+ void
+-read_thunk_profile (struct cgraph_node *node)
++read_thunk_profile (struct cgraph_node *node, bool is_cspgo)
+ {
+   tree old = current_function_decl;
+   current_function_decl = node->decl;
+-  gcov_type *counts = get_coverage_counts (GCOV_COUNTER_ARCS, 0, 0, 1);
++  gcov_type *counts = get_coverage_counts (GCOV_COUNTER_ARCS, 0, 0, 1,
++					   is_cspgo);
+   if (counts)
+     {
+       node->callees->count = node->count
+@@ -1164,7 +1168,7 @@ read_thunk_profile (struct cgraph_node *node)
+    Main entry point of this file.  */
+ 
+ void
+-branch_prob (bool thunk)
++branch_prob (bool thunk, bool is_cspgo)
+ {
+   basic_block bb;
+   unsigned i;
+@@ -1507,9 +1511,10 @@ branch_prob (bool thunk)
+ 
+   if (flag_branch_probabilities)
+     {
+-      compute_branch_probabilities (cfg_checksum, lineno_checksum);
++      compute_branch_probabilities (cfg_checksum, lineno_checksum, is_cspgo);
+       if (flag_profile_values)
+-	compute_value_histograms (values, cfg_checksum, lineno_checksum);
++	compute_value_histograms (values, cfg_checksum, lineno_checksum,
++				  is_cspgo);
+     }
+ 
+   remove_fake_edges ();
+diff --git a/gcc/profile.h b/gcc/profile.h
+index c5b6f4889..e92d6154c 100644
+--- a/gcc/profile.h
++++ b/gcc/profile.h
+@@ -68,7 +68,7 @@ extern void mcf_smooth_cfg (void);
+ 
+ extern gcov_type sum_edge_counts (vec *edges);
+ 
+-extern void init_node_map (bool);
++extern void init_node_map (bool, bool);
+ extern void del_node_map (void);
+ 
+ extern void get_working_sets (void);
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index fc2b1e1e7..6fdb2c767 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -104,6 +104,7 @@ DEFTIMEVAR (TV_WHOPR_PARTITIONING    , "whopr partitioning")
+ DEFTIMEVAR (TV_WHOPR_LTRANS          , "whopr ltrans")
+ DEFTIMEVAR (TV_IPA_REFERENCE         , "ipa reference")
+ DEFTIMEVAR (TV_IPA_PROFILE           , "ipa profile")
++DEFTIMEVAR (TV_IPA_CSPROFILE         , "ipa csprofile")
+ DEFTIMEVAR (TV_IPA_AUTOFDO           , "auto profile")
+ DEFTIMEVAR (TV_IPA_PURE_CONST        , "ipa pure const")
+ DEFTIMEVAR (TV_IPA_ICF		     , "ipa icf")
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 18b0f8022..f9c2eed8b 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -519,6 +519,7 @@ extern simple_ipa_opt_pass *make_pass_ipa_increase_alignment (gcc::context
+ 							      *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_fn_summary (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_inline (gcc::context *ctxt);
++extern ipa_opt_pass_d *make_pass_ipa_csprofile (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_free_lang_data (gcc::context *ctxt);
+ extern simple_ipa_opt_pass *make_pass_ipa_free_fn_summary (gcc::context *ctxt);
+ extern ipa_opt_pass_d *make_pass_ipa_cp (gcc::context *ctxt);
+@@ -667,6 +668,7 @@ extern void execute_pass_list (function *, opt_pass *);
+ extern void execute_ipa_pass_list (opt_pass *);
+ extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
+ extern void execute_all_ipa_transforms (bool);
++extern void execute_all_ipa_transforms_for_cspgo (bool);
+ extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple **);
+ extern bool pass_init_dump_file (opt_pass *);
+ extern void pass_fini_dump_file (opt_pass *);
+diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
+index e7646f1a1..aa3a2b3a9 100644
+--- a/gcc/tree-profile.cc
++++ b/gcc/tree-profile.cc
+@@ -725,7 +725,7 @@ tree_profiling (void)
+      cgraphunit.cc:ipa_passes().  */
+   gcc_assert (symtab->state == IPA_SSA);
+ 
+-  init_node_map (true);
++  init_node_map (true, false);
+   parse_profile_file_filtering ();
+ 
+   FOR_EACH_DEFINED_FUNCTION (node)
+@@ -766,7 +766,7 @@ tree_profiling (void)
+ 	     time.  */
+ 	  else
+ 	    {
+-	      read_thunk_profile (node);
++	      read_thunk_profile (node, false);
+ 	      continue;
+ 	    }
+ 	}
+@@ -781,7 +781,7 @@ tree_profiling (void)
+ 	  && (execute_fixup_cfg () & TODO_cleanup_cfg))
+ 	cleanup_tree_cfg ();
+ 
+-      branch_prob (thunk);
++      branch_prob (thunk, false);
+ 
+       if (! flag_branch_probabilities
+ 	  && flag_profile_values)
+@@ -863,6 +863,170 @@ tree_profiling (void)
+   return 0;
+ }
+ 
++/* Profile all functions in the callgraph with cs profile.  */
++
++static unsigned int
++csprofile_transform (struct cgraph_node *node)
++{
++  basic_block bb;
++  bool thunk = false;
++
++  parse_profile_file_filtering ();
++
++  if (dump_file)
++    {
++      fprintf (dump_file, "[cspgo] trying cspgo on function:\n");
++      dump_function_header (dump_file, cfun->decl, dump_flags);
++    }
++
++  if (!DECL_STRUCT_FUNCTION (current_function_decl))
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s without function decl, skip.\n",
++		 node->dump_name ());
++      return 0;
++    }
++
++  if (!gimple_has_body_p (node->decl) && !node->thunk)
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s without gimple body, skip.\n",
++		 node->dump_name ());
++      return 0;
++    }
++
++  /* Don't profile functions produced for builtin stuff.  */
++  if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION)
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s with BUILTINS_LOCATION, skip.\n",
++		 node->dump_name ());
++      return 0;
++    }
++
++  const char *file = LOCATION_FILE (DECL_SOURCE_LOCATION (node->decl));
++  if (!file || !include_source_file_for_profile (file))
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s is sub func or in filter-files, "
++			    "skip.\n", node->dump_name ());
++      return 0;
++    }
++
++  if (lookup_attribute ("no_profile_instrument_function",
++			DECL_ATTRIBUTES (node->decl)))
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s is no_profile_instrument_function,"
++		 " skip.\n", node->dump_name ());
++      return 0;
++    }
++
++  /* Do not instrument extern inline functions.  */
++  if (DECL_EXTERNAL (node->decl))
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s is DECL_EXTERNAL, skip.\n",
++			     node->dump_name ());
++      return 0;
++    }
++
++  if (!coverage_node_map_initialized_p ())
++    init_node_map (true, true);
++
++  /* Node without profile id should skip.  */
++  if (!node->profile_id)
++    {
++      if (dump_file)
++	fprintf (dump_file, "[cspgo] %s does not has profile_id, skip.\n",
++			     node->dump_name ());
++      return 0;
++    }
++
++  if (flag_csprofile_generate)
++    {
++      profile_arc_flag = 1;
++      flag_branch_probabilities = 0;
++    }
++
++  /* Process thunk function.  */
++  if (node->thunk)
++    {
++      /* We cannot expand variadic thunks to Gimple.  */
++      if (stdarg_p (TREE_TYPE (node->decl)))
++	{
++	  if (dump_file)
++	    fprintf (dump_file, "[cspgo] %s is DECL_EXTERNAL, skip.\n",
++			     node->dump_name ());
++	  return 0;
++	}
++      thunk = true;
++      /* When generate profile, expand thunk to gimple so it can be
++	 instrumented same way as other functions.  */
++      if (profile_arc_flag)
++	expand_thunk (node, false, true);
++      /* Read cgraph profile but keep function as thunk at profile-use
++	 time.  */
++      else
++	{
++	  read_thunk_profile (node, true);
++	  return 0;
++	}
++    }
++
++  /* Local pure-const may imply need to fixup the cfg.  */
++  if (gimple_has_body_p (node->decl)
++	&& (execute_fixup_cfg () & TODO_cleanup_cfg))
++    cleanup_tree_cfg ();
++
++  branch_prob (thunk, true);
++
++  if (! flag_branch_probabilities
++	&& flag_profile_values)
++    gimple_gen_ic_func_profiler ();
++
++  if (flag_branch_probabilities
++      && !thunk
++      && flag_profile_values
++      && flag_value_profile_transformations
++      && profile_status_for_fn (cfun) == PROFILE_READ)
++    gimple_value_profile_transformations ();
++
++  /* The above could hose dominator info.  Currently there is
++     none coming in, this is a safety valve.  It should be
++     easy to adjust it, if and when there is some.  */
++  free_dominance_info (CDI_DOMINATORS);
++  free_dominance_info (CDI_POST_DOMINATORS);
++
++  release_profile_file_filtering ();
++
++  if (flag_csprofile_generate)
++    {
++      profile_arc_flag = 0;
++      flag_branch_probabilities = 1;
++    }
++
++  /* Update call statements and rebuild the cgraph.  */
++  FOR_EACH_BB_FN (bb, cfun)
++    {
++      gimple_stmt_iterator gsi;
++      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
++	{
++	  gimple *stmt = gsi_stmt (gsi);
++	  if (is_gimple_call (stmt))
++	    update_stmt (stmt);
++	}
++    }
++
++  /* re-merge split blocks.  */
++  cleanup_tree_cfg ();
++  update_ssa (TODO_update_ssa);
++
++  cgraph_edge::rebuild_edges ();
++
++  return 0;
++}
++
+ namespace {
+ 
+ const pass_data pass_data_ipa_tree_profile =
+@@ -910,4 +1074,57 @@ make_pass_ipa_tree_profile (gcc::context *ctxt)
+   return new pass_ipa_tree_profile (ctxt);
+ }
+ 
++namespace {
++
++const pass_data pass_data_ipa_csprofile =
++{
++  IPA_PASS, /* type */
++  "csprofile", /* name */
++  OPTGROUP_NONE, /* optinfo_flags */
++  TV_IPA_CSPROFILE, /* tv_id */
++  0, /* properties_required */
++  0, /* properties_provided */
++  0, /* properties_destroyed */
++  0, /* todo_flags_start */
++  0, /* todo_flags_finish */
++};
++
++class pass_ipa_csprofile : public ipa_opt_pass_d
++{
++public:
++  pass_ipa_csprofile (gcc::context *ctxt)
++    : ipa_opt_pass_d (pass_data_ipa_csprofile, ctxt,
++		      NULL, /* generate_summary */
++		      NULL, /* write_summary */
++		      NULL, /* read_summary */
++		      NULL, /* write_optimization_summary */
++		      NULL, /* read_optimization_summary */
++		      NULL, /* stmt_fixup */
++		      0, /* function_transform_todo_flags_start */
++		      csprofile_transform, /* function_transform */
++		      NULL) /* variable_transform */
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *)
++    {
++      return (flag_csprofile_generate || flag_csprofile_use);
++    }
++  /* The main process of cspgo is in csprofile_transform, execute does not need
++     to do anything.  */
++  virtual unsigned int execute (function *)
++    {
++      return 0;
++    }
++
++}; // class pass_ipa_csprofile
++
++} // anon namespace
++
++ipa_opt_pass_d *
++make_pass_ipa_csprofile (gcc::context *ctxt)
++{
++  return new pass_ipa_csprofile (ctxt);
++}
++
+ #include "gt-tree-profile.h"
+diff --git a/gcc/value-prof.cc b/gcc/value-prof.cc
+index c240a1863..9c7191287 100644
+--- a/gcc/value-prof.cc
++++ b/gcc/value-prof.cc
+@@ -1234,7 +1234,7 @@ coverage_node_map_initialized_p (void)
+    that the PROFILE_IDs was already assigned.  */
+ 
+ void
+-init_node_map (bool local)
++init_node_map (bool local, bool is_cspgo)
+ {
+   struct cgraph_node *n;
+   cgraph_node_map = new hash_map;
+@@ -1245,6 +1245,12 @@ init_node_map (bool local)
+ 	cgraph_node **val;
+ 	dump_user_location_t loc
+ 	  = dump_user_location_t::from_function_decl (n->decl);
++
++	/* In cspgo, inline and clone functions will not be expand,
++	   so skipped.  */
++	if (is_cspgo && (n->inlined_to || n->clone_of))
++	  continue;
++
+ 	if (local)
+ 	  {
+ 	    n->profile_id = coverage_compute_profile_id (n);
+@@ -1290,6 +1296,7 @@ void
+ del_node_map (void)
+ {
+   delete cgraph_node_map;
++  cgraph_node_map = 0;
+ }
+ 
+ /* Return cgraph node for function with pid */
+diff --git a/gcc/value-prof.h b/gcc/value-prof.h
+index d852c41f3..0fe3821c3 100644
+--- a/gcc/value-prof.h
++++ b/gcc/value-prof.h
+@@ -112,8 +112,8 @@ extern struct cgraph_node* find_func_by_profile_id (int func_id);
+ 
+ /* In profile.cc.  */
+ extern void init_branch_prob (void);
+-extern void branch_prob (bool);
+-extern void read_thunk_profile (struct cgraph_node *);
++extern void branch_prob (bool, bool);
++extern void read_thunk_profile (struct cgraph_node *, bool);
+ extern void end_branch_prob (void);
+ 
+ #endif	/* GCC_VALUE_PROF_H */
+-- 
+2.25.1
+
diff --git a/0310-CFGO-Add-cfgo-pgo-optimization.patch b/0310-CFGO-Add-cfgo-pgo-optimization.patch
new file mode 100644
index 0000000..4a930ab
--- /dev/null
+++ b/0310-CFGO-Add-cfgo-pgo-optimization.patch
@@ -0,0 +1,168 @@
+From 84635dc65ebe285457d0c16bbb5caf995f803436 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 27 Nov 2024 18:36:27 +0800
+Subject: [PATCH] [CFGO] Add cfgo-pgo optimization
+
+Add a cfgo-pgo to better optimize with AI4C
+---
+ gcc/common.opt    | 16 +++++++++++++
+ gcc/gcc.cc        |  4 ++--
+ gcc/lto-cgraph.cc |  3 ++-
+ gcc/opts.cc       | 57 +++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 77 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index c9baa12be..a45fbfe1b 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2485,6 +2485,14 @@ fprofile-generate=
+ Common Joined RejectNegative
+ Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=.
+ 
++fcfgo-profile-generate
++Common Var(flag_cfgo_profile_generate)
++Enable common options for generating cfgo profile info for profile feedback directed optimizations.
++
++fcfgo-profile-generate=
++Common Joined RejectNegative
++Enable common options for generating cfgo profile info for profile feedback directed optimizations, and set -fprofile-dir=.
++
+ fcfgo-csprofile-generate
+ Common Var(flag_csprofile_generate)
+ Enable common options for generating context sensitive profile info for profile feedback directed optimizations.
+@@ -2517,6 +2525,14 @@ fprofile-use=
+ Common Joined RejectNegative
+ Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
+ 
++fcfgo-profile-use
++Common Var(flag_cfgo_profile_use)
++Enable common options for performing profile feedback directed optimizations.
++
++fcfgo-profile-use=
++Common Joined RejectNegative
++Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
++
+ fcfgo-csprofile-use
+ Common Var(flag_csprofile_use)
+ Enable common options for performing context sensitive profile feedback directed optimizations.
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index b37b50be2..e5c43dd90 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -1147,7 +1147,7 @@ proper position among the other output files.  */
+ 	%:include(libgomp.spec)%(link_gomp)}\
+     %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
+     %(mflib) " STACK_SPLIT_SPEC "\
+-    %{fprofile-arcs|fprofile-generate*|fcfgo-csprofile-generate*|coverage:-lgcov} \
++    %{fprofile-arcs|fprofile-generate*|fcfgo-profile-generate*|fcfgo-csprofile-generate*|coverage:-lgcov} \
+     " SANITIZER_SPEC " \
+     %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}\
+     %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*}  \n%(post_link) }}}}}}"
+@@ -1266,7 +1266,7 @@ static const char *cc1_options =
+  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}}\
+  %{fsyntax-only:-o %j} %{-param*}\
+  %{coverage:-fprofile-arcs -ftest-coverage}\
+- %{fprofile-arcs|fprofile-generate*|fcfgo-csprofile-generate*|coverage:\
++ %{fprofile-arcs|fprofile-generate*|fcfgo-profile-generate*|fcfgo-csprofile-generate*|coverage:\
+    %{!fprofile-update=single:\
+      %{pthread:-fprofile-update=prefer-atomic}}}";
+ 
+diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
+index fd41941d1..9a30f1190 100644
+--- a/gcc/lto-cgraph.cc
++++ b/gcc/lto-cgraph.cc
+@@ -1681,7 +1681,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
+      stages with unknown bug resulted in different scaling results, which led
+      different optimization decisions and finally led to coverage mismatch.
+      Therefore, skip the following processing steps when doing cspgo.  */
+-  if (flag_csprofile_generate || flag_csprofile_use)
++  if (flag_csprofile_generate || flag_csprofile_use
++      || flag_cfgo_profile_generate || flag_cfgo_profile_use)
+     return;
+ 
+   /* Now compute count_materialization_scale of each node.
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 89d03e834..84dd8925a 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -2087,6 +2087,38 @@ enable_fdo_optimizations (struct gcc_options *opts,
+   SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribution, value);
+ }
+ 
++/* Enable cfgo-related flags.  */
++
++static void
++enable_cfgo_optimizations (struct gcc_options *opts,
++			   struct gcc_options *opts_set,
++			   int value)
++{
++  SET_OPTION_IF_UNSET (opts, opts_set, flag_modulo_sched, value);
++  SET_OPTION_IF_UNSET (opts, opts_set, flag_selective_scheduling, value);
++  SET_OPTION_IF_UNSET (opts, opts_set, flag_rename_registers, value);
++
++  SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_auto, 185);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_inline_unit_growth, 66);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_recursive_depth_auto,
++		       31);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_large_function_insns, 7286);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_large_function_growth, 89);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_large_unit_insns, 11783);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_eval_threshold, 864);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_loop_hint_bonus, 440);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_max_recursive_depth, 29);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_min_recursive_probability,
++		       4);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_recursive_freq_factor, 18);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_recursion_penalty, 64);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_single_call_penalty, 43);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_unit_growth, 96);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_large_unit_insns, 47631);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_value_list_size, 12);
++  SET_OPTION_IF_UNSET (opts, opts_set, param_ipa_cp_profile_count_base, 54);
++}
++
+ /* -f{,no-}sanitize{,-recover}= suboptions.  */
+ const struct sanitizer_opts_s sanitizer_opts[] =
+ {
+@@ -3033,6 +3065,18 @@ common_handle_option (struct gcc_options *opts,
+       /* Deferred.  */
+       break;
+ 
++    case OPT_fcfgo_profile_use_:
++      /* No break here - do -fcfgo-profile-use processing.  */
++      /* FALLTHRU */
++    case OPT_fcfgo_profile_use:
++      value = true;
++      if (value)
++	{
++	  enable_cfgo_optimizations (opts, opts_set, value);
++	  SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_use, value);
++	}
++      /* No break here - do -fprofile-use processing.  */
++      /* FALLTHRU */
+     case OPT_fprofile_use_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+       opts->x_flag_profile_use = true;
+@@ -3090,6 +3134,19 @@ common_handle_option (struct gcc_options *opts,
+       SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_struct_reorg, value);
+       break;
+ 
++    case OPT_fcfgo_profile_generate_:
++      /* No break here - do -fcfgo-profile-generate processing.  */
++      /* FALLTHRU */
++    case OPT_fcfgo_profile_generate:
++      value = true;
++      if (value)
++	{
++	  enable_cfgo_optimizations (opts, opts_set, value);
++	  SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_generate,
++			       value);
++	}
++      /* No break here - do -fcfgo-profile-generate processing.  */
++      /* FALLTHRU */
+     case OPT_fprofile_generate_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+       value = true;
+-- 
+2.25.1
+
diff --git a/0311-PATCH-Add-if-split-optimization-pass.patch b/0311-PATCH-Add-if-split-optimization-pass.patch
new file mode 100644
index 0000000..5e3b75e
--- /dev/null
+++ b/0311-PATCH-Add-if-split-optimization-pass.patch
@@ -0,0 +1,1203 @@
+From 899db9bca3c2ef3cd346814be761eed8b85f5e1e Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 27 Nov 2024 19:26:13 +0800
+Subject: [PATCH] [PATCH] Add if-split optimization pass
+
+This pass splits conditions like
+if (cond1  or  cond2)
+to the sequense of separate conditions.
+
+This happens only if there is a function call under condition
+Which  depends on the condition variable.
+---
+ gcc/Makefile.in                             |   1 +
+ gcc/common.opt                              |   4 +
+ gcc/gimple-if-split.cc                      | 567 ++++++++++++++++++++
+ gcc/opts.cc                                 |   2 +-
+ gcc/passes.def                              |   1 +
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c  |  24 +
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c |  45 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c  |  36 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c  |  36 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c  |  42 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c  |  42 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c  |  45 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c  |  45 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c  |  42 ++
+ gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c  |  44 ++
+ gcc/timevar.def                             |   1 +
+ gcc/tree-cfg.h                              |   2 +
+ gcc/tree-pass.h                             |   1 +
+ gcc/tree-ssa-ifcombine.cc                   |   6 +-
+ 19 files changed, 981 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/gimple-if-split.cc
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c
+ create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index bb6197a8e..683b28896 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1393,6 +1393,7 @@ OBJS = \
+ 	gimple-builder.o \
+ 	gimple-expr.o \
+ 	gimple-if-to-switch.o \
++	gimple-if-split.o \
+ 	gimple-iterator.o \
+ 	gimple-fold.o \
+ 	gimple-harden-conditionals.o \
+diff --git a/gcc/common.opt b/gcc/common.opt
+index a45fbfe1b..a52fa9814 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1981,6 +1981,10 @@ finstrument-functions-exclude-file-list=
+ Common RejectNegative Joined
+ -finstrument-functions-exclude-file-list=filename,...	Do not instrument functions listed in files.
+ 
++fif-split
++Common Var(flag_if_split) Init(0) Optimization
++Perform splitting if complex conditions on separate ones with clonning their bodies (gimple version).
++
+ fipa-cp
+ Common Var(flag_ipa_cp) Optimization
+ Perform interprocedural constant propagation.
+diff --git a/gcc/gimple-if-split.cc b/gcc/gimple-if-split.cc
+new file mode 100644
+index 000000000..3446204ea
+--- /dev/null
++++ b/gcc/gimple-if-split.cc
+@@ -0,0 +1,567 @@
++/* If-split.
++   Copyright (C) 2024 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
++.  */
++
++#include "config.h"
++#define INCLUDE_FUNCTIONAL
++#include "system.h"
++#include "coretypes.h"
++#include "tree.h"
++#include "tree-ssa.h"
++#include "tree-pass.h"
++#include "diagnostic-core.h"
++#include "function.h"
++#include "basic-block.h"
++#include "gimple.h"
++#include "gimple-pretty-print.h"
++#include "gimple-iterator.h"
++#include "cfg.h"
++#include "cfghooks.h"
++#include "ssa.h"
++#include "fold-const.h"
++#include "tree-into-ssa.h"
++#include "tree-cfg.h"
++#include "bitmap.h"
++#include "cfganal.h"
++
++/* Perform splitting if-then-else patterns, whose complex OR condition in
++cond-bb contains comparison of some variable with constant and then-bb got
++function call, whose arg list contains this var (or this variable is a
++scalar of an aggregate which is an arg of this call). We split condition on
++two separate ones and duplicate then-bb for each one, thus help ipa const
++prop to propagate corresponding constant in function calls.
++Example:
++	Before:
++		if (n == const || some_cond)
++			func (n);
++	After:
++		if (n == const)
++			func (n);
++		else if (some_cond)
++			func (n);  */
++
++//-------------------------------------------------------------------------
++// Auxiliary functions
++//-------------------------------------------------------------------------
++/* Check if arg list of call got n.  */
++bool
++got_in_args_p (gimple* call, tree n)
++{
++  unsigned num_args = gimple_call_num_args (call);
++
++  for (int i = 0; i < num_args; i++)
++    {
++      if (n == gimple_call_arg (call, i))
++  return true;
++    }
++
++  return false;
++}
++
++#define SCALAR_NESTING 2
++/* Check if call is "necessary" for n.  Call is called "necessary"
++ * for n, if n is one of call args, or n is scalar of some aggregate,
++ * which is one of this call args.  Nesting param determines how many
++ * levels of aggregate-scalar nesting we want to check.  For example,
++ * if nesting == 2, we allow only 2 levels of nesting, like
++ * outer_aggr->inner_aggr->scalar.  */
++static bool
++necessary_call_p (gimple *call, tree n, unsigned nesting)
++{
++  if (!call)
++    return false;
++
++  if (got_in_args_p (call, n))
++    return true;
++
++  /* Else we need to check if n could be a scalar of some aggregate which
++   * is one of call args.  */
++  tree scalar = n;
++  tree aggregate = NULL_TREE;
++
++  for (int i = 0; i < nesting; i++)
++    {
++      if (!scalar || TREE_CODE (scalar) != SSA_NAME)
++	return false;
++
++      gimple *scalar_def = SSA_NAME_DEF_STMT (scalar);
++
++      if (!is_gimple_assign (scalar_def)
++	  || gimple_assign_rhs_code (scalar_def) != COMPONENT_REF)
++	return false;
++
++      tree scalar_def_rhs = gimple_assign_rhs1 (scalar_def);
++      tree aggregate = TREE_OPERAND (scalar_def_rhs, 0);
++
++      if (TREE_CODE (aggregate) == MEM_REF)
++	aggregate = TREE_OPERAND (aggregate, 0);
++
++      if (aggregate && got_in_args_p (call, aggregate))
++	return true;
++
++      scalar = aggregate;
++    }
++
++  return false;
++}
++
++/* Check if bb got a "necessary" call statement.  */
++static bool
++bb_got_necessary_call_p (basic_block bb, tree n, unsigned nesting)
++{
++  gimple *stmt = NULL;
++
++  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) && necessary_call_p (stmt, n, nesting))
++	return true;
++    }
++
++  return false;
++}
++
++//-------------------------------------------------------------------------
++// Complex conditions
++//-------------------------------------------------------------------------
++/* Auxiliary struct which contains var and its constant of comaprison
++ * of expr: n == cst.  */
++struct var_const
++{
++  tree n = NULL_TREE;
++  tree cst = NULL_TREE;
++};
++
++/* Check if var_def stmt got this pattern:
++ *    var = (n == const);
++ * If it does, we need to set var_cst struct.  */
++static bool
++comp_with_const_p (gimple *var_def, var_const *var_cst)
++{
++  if (gimple_expr_code (var_def) != EQ_EXPR)
++    return false;
++
++  tree var_def_rhs2 = gimple_assign_rhs2 (var_def);
++
++  if (TREE_CODE (var_def_rhs2) != INTEGER_CST)
++    return false;
++
++  var_cst->n = gimple_assign_rhs1 (var_def);
++  var_cst->cst = var_def_rhs2;
++
++  return true;
++}
++
++/* Auxiliary struct which contains defenition of each part of
++ * complex condition, like:
++ *    a = ... <- a_def
++ *    b = ... <- b_def
++ *    c = a | b  <- complex_cond.  */
++struct cond_parts_defs
++{
++  gimple *a_def = NULL;
++  gimple *b_def = NULL;
++};
++
++/* Check if cond got this pattern:
++ *    a = ...; <- a_def
++ *    b = ...; <- b_def
++ *    c = a | b;
++ *    if (c != 0)
++ * and a_def or b_def is comparison with constant.  If it does,
++ * we need to set a with a_def and b with b_def.  */
++static bool
++necessary_complex_cond_p (const gimple *cond, basic_block then_bb,
++			  cond_parts_defs *defs)
++{
++  tree lhs = gimple_cond_lhs (cond);
++  tree rhs = gimple_cond_rhs (cond);
++
++  /* As we look for: if (c != 0).  */
++  if (gimple_cond_code (cond) != NE_EXPR || TREE_CODE (lhs) != SSA_NAME
++      || !integer_zerop (rhs))
++    return false;
++
++  gimple *c_def = SSA_NAME_DEF_STMT (lhs);
++
++  /* As we look for: c = a | b.  */
++  if (!c_def || !is_gimple_assign (c_def) || gimple_num_ops (c_def) != 3
++      || gimple_expr_code (c_def) != BIT_IOR_EXPR)
++    return false;
++
++  tree a_var = gimple_assign_rhs1 (c_def);
++  tree b_var = gimple_assign_rhs2 (c_def);
++  gimple *a_def = SSA_NAME_DEF_STMT (a_var);
++  gimple *b_def = SSA_NAME_DEF_STMT (b_var);
++
++  if (!a_def || !is_gimple_assign (a_def) || !b_def
++      || !is_gimple_assign (b_def))
++    return false;
++
++  var_const var_cst;
++
++  if (!(comp_with_const_p (a_def, &var_cst)
++	&& bb_got_necessary_call_p (then_bb, var_cst.n, SCALAR_NESTING))
++      && !(comp_with_const_p (b_def, &var_cst)
++	   && bb_got_necessary_call_p (then_bb, var_cst.n, SCALAR_NESTING)))
++    return false;
++
++  defs->a_def = a_def;
++  defs->b_def = b_def;
++
++  return true;
++}
++
++/* Check if our complex condition seems to be "necessary"
++ * and if it does split it on two separate ones.  Like:
++ *    a = (n == const); <- a_def
++ *    b = smth; <- b_def
++ *    c = a | b
++ *    if (c != 0)
++ *       call func (n, ...)
++ * Transform this to:
++ *    if (n == const)
++ *	 goto then
++ *    else if (b != 0)
++ *	 goto then
++ *     then:
++ *	 call func (n, ...).
++ * A complex condition is called "necessary", if it is OR of two
++ * conditions, one of them is comparison with constant and then_bb
++ * of this cond got "necessary" function_call.  To know, what
++ * "necessary" function call means look at necessary_call_p ().  */
++static void
++process_complex_cond (basic_block cond_bb, basic_block then_bb,
++		      basic_block else_bb)
++{
++  gimple *cond = last_stmt (cond_bb);
++  cond_parts_defs defs;
++
++  if (!can_duplicate_block_p (then_bb)
++      || !necessary_complex_cond_p (cond, then_bb, &defs))
++    return;
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file,
++	       "Recognized necessary complex condition: ", cond_bb->index);
++      print_gimple_stmt (dump_file, cond, 0, TDF_NONE);
++    }
++
++  var_const var_cst;
++
++  /* Setting cond.  */
++  if (comp_with_const_p (defs.a_def, &var_cst))
++      /* Setting cond as: if (n == const).  */
++      gimple_cond_set_condition (as_a (cond), EQ_EXPR, var_cst.n,
++					var_cst.cst);
++  else
++    {
++      /* Setting cond as: if (a != 0).  */
++      tree cond_lhs = gimple_assign_lhs (defs.a_def);
++      gimple_cond_set_condition (as_a (cond), NE_EXPR, cond_lhs,
++      					build_zero_cst (TREE_TYPE (cond_lhs)));
++    }
++  update_stmt (cond);
++
++  /* Creating inner_cond_bb.  */
++  edge then_e = find_edge (cond_bb, then_bb);
++  edge else_e = find_edge (cond_bb, else_bb);
++  basic_block inner_cond_bb = split_edge (else_e);
++
++  /* Setting inner_cond.  */
++  gcond *inner_cond = NULL;
++  if (comp_with_const_p (defs.b_def, &var_cst))
++    {
++      /* Setting inner cond as: if (b == const).  */
++      inner_cond = gimple_build_cond (EQ_EXPR, var_cst.n, var_cst.cst,
++				      NULL_TREE, NULL_TREE);
++    }
++  else
++    {
++      /* Setting inner cond as: if (b != 0).  */
++      tree inner_cond_lhs = gimple_assign_lhs (defs.b_def);
++      inner_cond = gimple_build_cond (
++	  NE_EXPR, inner_cond_lhs, build_zero_cst (TREE_TYPE (inner_cond_lhs)),
++	  NULL_TREE, NULL_TREE);
++    }
++  gimple_stmt_iterator gsi = gsi_last_bb (inner_cond_bb);
++  gsi_insert_after (&gsi, inner_cond, GSI_NEW_STMT);
++
++  /* Configuring edges.  */
++  edge inner_cond_then_e = make_edge (inner_cond_bb, then_bb, EDGE_TRUE_VALUE);
++  edge inner_cond_else_e = find_edge (inner_cond_bb, else_bb);
++  inner_cond_else_e->flags = EDGE_FALSE_VALUE;
++
++  /* Setting phinode args in then_bb coming from inner_cond_bb the same as
++   * ones coming from cond_bb.  */
++  for (gphi_iterator psi = gsi_start_phis (then_bb); !gsi_end_p (psi);
++       gsi_next (&psi))
++    {
++      gphi *phi = psi.phi ();
++      add_phi_arg (phi, PHI_ARG_DEF_FROM_EDGE (phi, then_e), inner_cond_then_e,
++		   UNKNOWN_LOCATION);
++    }
++
++  /* Updating dominators.  */
++  set_immediate_dominator (CDI_DOMINATORS, inner_cond_bb, cond_bb);
++  basic_block cond_bb_postdominator
++      = get_immediate_dominator (CDI_POST_DOMINATORS, cond_bb);
++  set_immediate_dominator (CDI_POST_DOMINATORS, inner_cond_bb,
++			   cond_bb_postdominator);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Successfully transformed:\n (o_cond) ",
++	       cond_bb->index);
++      print_gimple_stmt (dump_file, cond, 0, TDF_NONE);
++      fprintf (dump_file, " (i_cond) ", inner_cond_bb->index);
++      print_gimple_stmt (dump_file, inner_cond, 0, TDF_NONE);
++    }
++}
++
++//-------------------------------------------------------------------------
++// Condition pairs
++//-------------------------------------------------------------------------
++/* Transforming cfg if we recognized patern in process_condition_pair (). */
++static basic_block
++make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
++			 basic_block then_bb)
++{
++  if (!can_duplicate_block_p (then_bb) || EDGE_COUNT (then_bb->succs) != 1)
++    return NULL;
++
++  edge outer_then_e = find_edge (outer_cond_bb, then_bb);
++
++  /* Making duplication of then_bb.  */
++  basic_block then_bb_dom = get_immediate_dominator (CDI_DOMINATORS, then_bb);
++  basic_block merge_bb = split_edge (single_succ_edge (then_bb));
++  basic_block then_bb1 = duplicate_block (then_bb, outer_then_e, outer_cond_bb);
++  edge outer_then1_e = find_edge (outer_cond_bb, then_bb1);
++
++  /* Setting phinode args in then_bb1 coming from outer_cond_bb by previously
++   * collected args_from_outer_cond_bb.  */
++  flush_pending_stmts (outer_then1_e);
++
++  /* Updating dominators.  */
++  if (then_bb_dom == outer_cond_bb)
++    set_immediate_dominator (CDI_DOMINATORS, then_bb, inner_cond_bb);
++
++  set_immediate_dominator (CDI_DOMINATORS, merge_bb, then_bb_dom);
++  set_immediate_dominator (CDI_DOMINATORS, then_bb1, outer_cond_bb);
++
++  set_immediate_dominator (CDI_POST_DOMINATORS, then_bb, merge_bb);
++  set_immediate_dominator (CDI_POST_DOMINATORS, then_bb1, merge_bb);
++  set_immediate_dominator (CDI_POST_DOMINATORS, merge_bb,
++			   single_succ (merge_bb));
++
++  return then_bb1;
++}
++
++/* Here we check if cond of bb got this pattern:
++ *    if (n == const)
++ * And if it does we need to set n.  */
++static bool
++got_necessary_cond_p (basic_block bb, tree *n)
++{
++  gimple *stmt = last_stmt (bb);
++  if (!stmt || gimple_code (stmt) != GIMPLE_COND)
++    return false;
++
++  gcond *cond = as_a (stmt);
++
++  if (gimple_cond_code (cond) != EQ_EXPR
++      || TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
++      || TREE_CODE (gimple_cond_rhs (cond)) != INTEGER_CST)
++    return false;
++
++  *n = gimple_cond_lhs (cond);
++
++  return true;
++}
++
++/* Recognize pattern:
++ *    if (n == const)
++ *	 goto then
++ *    else if (some_cond)
++ *	 goto then
++ *    then:
++ *	 call func (n, ...)
++ * Transform this to:
++ *    if (n == const)
++ *	 call func (n, ...)
++ *    else if (some_cond)
++ *	 call func (n, ...).  */
++static void
++process_cond_pair (basic_block outer_cond_bb, basic_block inner_cond_bb,
++		   basic_block then_bb)
++{
++  tree n = NULL_TREE;
++
++  if (inner_cond_bb == then_bb
++      || !recognize_if_then_else (outer_cond_bb, &then_bb, &inner_cond_bb)
++      || !same_phi_args_p (outer_cond_bb, inner_cond_bb, then_bb)
++      || (!got_necessary_cond_p (outer_cond_bb, &n)
++	  && !got_necessary_cond_p (inner_cond_bb, &n))
++      || !bb_got_necessary_call_p (then_bb, n, SCALAR_NESTING))
++    return;
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      fprintf (dump_file, "Recognized necessary condition pair: (o_cond) ");
++      print_gimple_stmt (dump_file, last_stmt (outer_cond_bb), 0, TDF_NONE);
++      fprintf (dump_file, " (i_cond) ");
++      print_gimple_stmt (dump_file, last_stmt (inner_cond_bb), 0, TDF_NONE);
++    }
++
++  basic_block then_bb1
++      = make_two_separate_calls (outer_cond_bb, inner_cond_bb, then_bb);
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    {
++      if (then_bb1)
++	fprintf (dump_file,
++		 "Successfully transformed: bb<%d> is a copy of bb<%d> \n",
++		 then_bb1->index, then_bb->index);
++      else
++	fprintf (dump_file, "No transformation: bb<%d> cannot be duplicated \n",
++		 then_bb->index);
++    }
++}
++
++//-------------------------------------------------------------------------
++// Main logic
++//-------------------------------------------------------------------------
++/* If cond_bb suits if-then-else pattern and got single pred, execute func
++ * over it and its then, else basic blocks.  */
++template 
++static void
++process_bb (basic_block cond_bb, F func)
++{
++  basic_block then_bb = NULL, else_bb = NULL;
++
++  if (!recognize_if_then_else (cond_bb, &then_bb, &else_bb))
++    return;
++
++  func (cond_bb, then_bb, else_bb);
++}
++
++/* For each block, if it has condition, execute function over it.  We walk
++ * the blocks in order that guarantees that a block with a single predecessor
++ * is processed after the predecessor.  */
++template 
++static void
++execute_function_over_conditional_bbs (F func)
++{
++  basic_block *bbs = single_pred_before_succ_order ();
++  for (int i = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
++    {
++      gimple *stmt = last_stmt (bbs[i]);
++
++      if (stmt && gimple_code (stmt) == GIMPLE_COND)
++	{
++	  process_bb (bbs[i], func);
++	}
++    }
++  update_ssa (TODO_update_ssa);
++  free (bbs);
++}
++
++static void
++process_if_split_cfun ()
++{
++  /* First pass.  Split complex conditions, so process_condition_pair_bb ()
++   * will be able to recognize more necessary patterns.  */
++  execute_function_over_conditional_bbs (process_complex_cond);
++
++  /* Second pass.  Search each basic block for condition pair we may be
++   * able to optimize.  */
++  execute_function_over_conditional_bbs (
++      [] (basic_block cond_bb, basic_block then_bb, basic_block else_bb)
++      {
++	if (!single_pred_p (cond_bb))
++	  return;
++	process_cond_pair (single_pred (cond_bb), cond_bb, then_bb);
++      });
++}
++
++namespace
++{
++
++const pass_data pass_data_if_split = {
++  GIMPLE_PASS,	    /* type.  */
++  "if-split",	    /* name.  */
++  OPTGROUP_NONE,    /* optinfo_flags.  */
++  TV_TREE_IF_SPLIT, /* tv_id.  */
++  0,		    /* properties_required.  */
++  0,		    /* properties_provided.  */
++  0,		    /* properties_destroyed.  */
++  0,		    /* todo_flags_start.  */
++  0		    /* todo_flags_finish.  */
++};
++
++class pass_if_split : public gimple_opt_pass
++{
++public:
++  pass_if_split (gcc::context *ctxt)
++      : gimple_opt_pass (pass_data_if_split, ctxt)
++  {
++  }
++
++  /* opt_pass methods: */
++  virtual bool
++  gate (function *)
++  {
++    /* Don't bother doing anything if the program has errors.  */
++    return (optimize >= 3 && flag_if_split && !seen_error ());
++  }
++
++  virtual unsigned int execute (function *);
++
++}; // class pass_if_split
++
++unsigned int
++pass_if_split::execute (function *fun)
++{
++  calculate_dominance_info (CDI_DOMINATORS);
++  calculate_dominance_info (CDI_POST_DOMINATORS);
++  initialize_original_copy_tables ();
++
++  process_if_split_cfun ();
++
++  checking_verify_ssa (true, true);
++  checking_verify_flow_info ();
++  checking_verify_dominators (CDI_DOMINATORS);
++  checking_verify_dominators (CDI_POST_DOMINATORS);
++
++  free_original_copy_tables ();
++  free_dominance_info (CDI_POST_DOMINATORS);
++  free_dominance_info (CDI_DOMINATORS);
++
++  return 0;
++}
++
++} // anon namespace
++
++gimple_opt_pass *
++make_pass_if_split (gcc::context *ctxt)
++{
++  return new pass_if_split (ctxt);
++}
+\ No newline at end of file
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 84dd8925a..4f3eb4bd4 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -3145,7 +3145,7 @@ common_handle_option (struct gcc_options *opts,
+ 	  SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_generate,
+ 			       value);
+ 	}
+-      /* No break here - do -fcfgo-profile-generate processing.  */
++      /* No break here - do -fprofile-generate processing.  */
+       /* FALLTHRU */
+     case OPT_fprofile_generate_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+diff --git a/gcc/passes.def b/gcc/passes.def
+index 862ef0d8f..fbe828439 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -100,6 +100,7 @@ along with GCC; see the file COPYING3.  If not see
+ 	  NEXT_PASS (pass_if_to_switch);
+ 	  NEXT_PASS (pass_convert_switch);
+ 	  NEXT_PASS (pass_cleanup_eh);
++	  NEXT_PASS (pass_if_split);
+ 	  NEXT_PASS (pass_profile);
+ 	  NEXT_PASS (pass_local_pure_const);
+ 	  NEXT_PASS (pass_modref);
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c
+new file mode 100644
+index 000000000..5909dac41
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-1.c
+@@ -0,0 +1,24 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int main(int argc, char** argv){
++    int b = argc;
++    int res = 0;
++
++    if (b == 5 || b == 52)
++        res = foo (b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c
+new file mode 100644
+index 000000000..20a45116b
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-10.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++    int foo2_res = foo2();
++
++    if (data.y.b == 5 || data.y.b == 52 || foo2_res == 25)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 2 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c
+new file mode 100644
+index 000000000..1370f9474
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-2.c
+@@ -0,0 +1,36 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct X
++{
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_a (X* x, int val)
++{
++    x->a = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int main(int argc, char** argv){
++    X data;
++    set_a (&data, argc);
++    int res = 0;
++
++    if (data.a == 5 || data.a == 52)
++        res = foo (data.a);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c
+new file mode 100644
+index 000000000..93a6eb6dd
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-3.c
+@@ -0,0 +1,36 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct X
++{
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_a (X* x, int val)
++{
++    x->a = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int main(int argc, char** argv){
++    X data;
++    set_a (&data, argc);
++    int res = 0;
++
++    if (data.a == 5 || data.a == 52 || data.a == 25)
++        res = foo (data.a);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 2 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c
+new file mode 100644
+index 000000000..36f2a15b3
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-4.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++
++    if (data.y.b == 5 || data.y.b == 52)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c
+new file mode 100644
+index 000000000..fbc3b0c19
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-5.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++
++    if (data.y.b == 5 || data.y.b == 52 || data.y.b == 25)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 2 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c
+new file mode 100644
+index 000000000..185127c79
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-6.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++    int foo2_res = foo2();
++
++    if (data.y.b == 5 || foo2_res == 52)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c
+new file mode 100644
+index 000000000..23f1a8f04
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-7.c
+@@ -0,0 +1,45 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++
++    if (data.y.b == 5 || foo2() == 52)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary complex condition:" 0 "if-split" } } */
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 0 "if-split" } } */
++/* { dg-final { scan-tree-dump-times "Successfully transformed:" 0 "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c
+new file mode 100644
+index 000000000..028b6dc40
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-8.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++
++    if (data.y.b == 5 || data.a == 52)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c b/gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c
+new file mode 100644
+index 000000000..3ff7e2efc
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tree-ssa/if-split-9.c
+@@ -0,0 +1,44 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -fif-split -fdump-tree-if-split-details" } */
++
++typedef struct Y
++{
++    int b;
++} Y;
++
++typedef struct X
++{
++    Y y;
++    int a;
++} X;
++
++
++void  __attribute__ ((noinline)) set_b (Y* y, int val)
++{
++    y->b = val;
++}
++
++static __attribute__ ((noinline)) int foo (int b)
++{
++    int res = 1;
++    for (int i = 0; i < b; i++) {
++        res*=3;
++    }
++    return res;
++}
++
++int foo2 ();
++
++int main(int argc, char** argv){
++    X data;
++    set_b (&data.y, argc);
++    int res = 0;
++
++    if (data.y.b == 5 || data.y.b == 52 || foo2() == 25)
++        res = foo (data.y.b);
++
++    return res;
++}
++
++/* { dg-final { scan-tree-dump-times "Recognized necessary condition pair:" 1 "if-split" } } */
++/* { dg-final { scan-tree-dump "Successfully transformed:" "if-split" } } */
+\ No newline at end of file
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index 6fdb2c767..b0d3d1188 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -306,6 +306,7 @@ DEFTIMEVAR (TV_VAR_TRACKING_DATAFLOW , "var-tracking dataflow")
+ DEFTIMEVAR (TV_VAR_TRACKING_EMIT     , "var-tracking emit")
+ DEFTIMEVAR (TV_TREE_IFCOMBINE        , "tree if-combine")
+ DEFTIMEVAR (TV_TREE_IF_TO_SWITCH     , "if to switch conversion")
++DEFTIMEVAR (TV_TREE_IF_SPLIT         , "gimple if splitting")
+ DEFTIMEVAR (TV_TREE_UNINIT           , "uninit var analysis")
+ DEFTIMEVAR (TV_PLUGIN_INIT           , "plugin initialization")
+ DEFTIMEVAR (TV_PLUGIN_RUN            , "plugin execution")
+diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
+index cb67cdf87..bfe44c073 100644
+--- a/gcc/tree-cfg.h
++++ b/gcc/tree-cfg.h
+@@ -112,6 +112,8 @@ extern basic_block gimple_switch_default_bb (function *, gswitch *);
+ extern edge gimple_switch_edge (function *, gswitch *, unsigned);
+ extern edge gimple_switch_default_edge (function *, gswitch *);
+ extern bool cond_only_block_p (basic_block);
++extern bool recognize_if_then_else (basic_block, basic_block *, basic_block *);
++extern bool same_phi_args_p (basic_block, basic_block, basic_block);
+ 
+ /* Return true if the LHS of a call should be removed.  */
+ 
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index f9c2eed8b..fb17b189c 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -383,6 +383,7 @@ extern gimple_opt_pass *make_pass_graphite (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_graphite_transforms (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_if_conversion (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_if_to_switch (gcc::context *ctxt);
++extern gimple_opt_pass *make_pass_if_split (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_loop_distribution (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_vectorize (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_simduid_cleanup (gcc::context *ctxt);
+diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
+index 264a8bcae..3b50fc114 100644
+--- a/gcc/tree-ssa-ifcombine.cc
++++ b/gcc/tree-ssa-ifcombine.cc
+@@ -76,8 +76,7 @@ along with GCC; see the file COPYING3.  If not see
+    match the then and else basic-blocks to make the pattern match.
+    Returns true if the pattern matched, false otherwise.  */
+ 
+-static bool
+-recognize_if_then_else (basic_block cond_bb,
++bool recognize_if_then_else (basic_block cond_bb,
+ 			basic_block *then_bb, basic_block *else_bb)
+ {
+   edge t, e;
+@@ -168,8 +167,7 @@ forwarder_block_to (basic_block bb, basic_block to_bb)
+    BB2 to DEST are the same.  This makes the CFG merge point
+    free from side-effects.  Return true in this case, else false.  */
+ 
+-static bool
+-same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest)
++bool same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest)
+ {
+   edge e1 = find_edge (bb1, dest);
+   edge e2 = find_edge (bb2, dest);
+-- 
+2.25.1
+
diff --git a/0312-Add-late-slp-vectorization-pass-with-additional-chec.patch b/0312-Add-late-slp-vectorization-pass-with-additional-chec.patch
new file mode 100644
index 0000000..19e519f
--- /dev/null
+++ b/0312-Add-late-slp-vectorization-pass-with-additional-chec.patch
@@ -0,0 +1,320 @@
+From 9df4a0bd76299734ae47f2f4e236b10f6c156994 Mon Sep 17 00:00:00 2001
+From: d84370931 
+Date: Thu, 14 Nov 2024 17:08:40 +0800
+Subject: [PATCH 3/8] Add late slp vectorization pass with additional checks.
+
+Add expansion of data reference offset using affine trees to check
+if data references may alias.
+
+Add check if a group of interleaving data references is smaller than
+max vector register size.
+
+Add operands swap for commutative operations.
+Swapping operands is necessary for better vector constructing.
+For example for operations
+  _1 = a * b;
+  _2 = b * c;
+Construction vectors (a, c) * (b, b) is more profitable
+than (a, b) * (b, c).
+
+Add tests and special param flags for each check:
+  --param=vect-addr-expand-for-alias-check={0,1}
+  --param=vect-swap-operands={0,1}
+  --param=vect-register-size-check={0,1}
+
+Add enabling flag for late slp pass:
+  -ftree-slp-late
+---
+ gcc/common.opt                                |  4 ++
+ gcc/params.opt                                | 12 ++++++
+ gcc/passes.def                                |  4 ++
+ gcc/testsuite/gcc.dg/vect/vect-alias-expand.c | 12 ++++++
+ gcc/testsuite/gcc.dg/vect/vect-op-swap.c      | 10 +++++
+ gcc/testsuite/gcc.dg/vect/vect-regsize.c      | 18 +++++++++
+ gcc/timevar.def                               |  1 +
+ gcc/tree-data-ref.cc                          | 12 ++++++
+ gcc/tree-pass.h                               |  1 +
+ gcc/tree-vect-data-refs.cc                    | 15 +++++++
+ gcc/tree-vect-slp.cc                          | 28 +++++++++++++
+ gcc/tree-vectorizer.cc                        | 39 +++++++++++++++++++
+ 12 files changed, 156 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-alias-expand.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-op-swap.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-regsize.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 78cfc333a..c3c64ceaf 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -3268,6 +3268,10 @@ ftree-slp-transpose-vectorize
+ Common Var(flag_tree_slp_transpose_vectorize) Optimization Init(0)
+ Enable basic block vectorization (SLP) for transposed stores and loads on trees.
+ 
++ftree-slp-late
++Common Var(flag_slp_late) Init(0) Optimization
++Enable additional SLP vectorization pass after reassociation.
++
+ fvect-cost-model=
+ Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Optimization
+ -fvect-cost-model=[unlimited|dynamic|cheap|very-cheap]	Specifies the cost model for vectorization.
+diff --git a/gcc/params.opt b/gcc/params.opt
+index 3ddfaf5b2..bb4dc1825 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1213,6 +1213,18 @@ The maximum factor which the loop vectorizer applies to the cost of statements i
+ Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRange(0, 1) Param Optimization
+ Enable loop vectorization of floating point inductions.
+ 
++-param=vect-swap-operands=
++Common Joined UInteger Var(param_vect_swap_operands) Init(0) IntegerRange(0, 1) Param Optimization
++Enable swapping operands for commutative operations in vectorization analysis.
++
++-param=addr-expand-for-alias-check=
++Common Joined UInteger Var(param_addr_expand_for_alias_check) Init(0) IntegerRange(0, 1) Param Optimization
++Enable data reference address expansion for alias check.
++
++-param=vect-register-size-check=
++Common Joined UInteger Var(param_vect_register_size_check) Init(0) IntegerRange(0, 1) Param Optimization
++Enable checking if a group of interleaving data references may not fit in vector register.
++
+ -param=vrp1-mode=
+ Common Joined Var(param_vrp1_mode) Enum(vrp_mode) Init(VRP_MODE_VRP) Param Optimization
+ --param=vrp1-mode=[vrp|ranger] Specifies the mode VRP1 should operate in.
+diff --git a/gcc/passes.def b/gcc/passes.def
+index e945af96a..529cc5093 100644
+--- a/gcc/passes.def
++++ b/gcc/passes.def
+@@ -337,6 +337,10 @@ along with GCC; see the file COPYING3.  If not see
+       NEXT_PASS (pass_lower_switch);
+       NEXT_PASS (pass_cse_reciprocals);
+       NEXT_PASS (pass_reassoc, false /* early_p */);
++      NEXT_PASS (pass_slp_vectorize_late);
++      PUSH_INSERT_PASSES_WITHIN (pass_slp_vectorize_late)
++	  NEXT_PASS (pass_slp_vectorize);
++      POP_INSERT_PASSES ()
+       NEXT_PASS (pass_strength_reduction);
+       NEXT_PASS (pass_split_paths);
+       NEXT_PASS (pass_tracer);
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-alias-expand.c b/gcc/testsuite/gcc.dg/vect/vect-alias-expand.c
+new file mode 100644
+index 000000000..a68f4baf8
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-alias-expand.c
+@@ -0,0 +1,12 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -ftree-vectorize --param=addr-expand-for-alias-check=1 -fdump-tree-slp-details" } */
++
++extern float arr[2][2];
++
++void foo (int i, int j, float a, float b)
++{
++  arr[i][j] *= a;
++  arr[i][j+1] *= b;
++}
++
++/* { dg-final { scan-tree-dump "Basic block will be vectorized using SLP" "slp2" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-op-swap.c b/gcc/testsuite/gcc.dg/vect/vect-op-swap.c
+new file mode 100644
+index 000000000..4872dc414
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-op-swap.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -ftree-vectorize --param=vect-swap-operands=1 -fdump-tree-slp-details" } */
++
++void foo (float *res, float a, float b, float c)
++{
++  res[0] = a * b;
++  res[1] = b * c;
++}
++
++/* { dg-final { scan-tree-dump "Swapped operands for" "slp2" } } */
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-regsize.c b/gcc/testsuite/gcc.dg/vect/vect-regsize.c
+new file mode 100644
+index 000000000..bcd81e6df
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-regsize.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -ftree-vectorize --param=vect-register-size-check=1 -fdump-tree-slp-details" } */
++
++extern float arr[256][256][1024];
++
++void foo (int i, int j, float a, float b)
++{
++  arr[i][j][0] += a;
++  arr[i][j][1] += b;
++  arr[i][j+1][0] += a;
++  arr[i][j+1][1] += b;
++  arr[i+1][j][0] += a;
++  arr[i+1][j][1] += b;
++  arr[i+1][j+1][0] += a;
++  arr[i+1][j+1][1] += b;
++}
++
++/* { dg-final { scan-tree-dump "Basic block will be vectorized using SLP" "slp2" } } */
+diff --git a/gcc/timevar.def b/gcc/timevar.def
+index fc2b1e1e7..7560e930a 100644
+--- a/gcc/timevar.def
++++ b/gcc/timevar.def
+@@ -205,6 +205,7 @@ DEFTIMEVAR (TV_SCALAR_CLEANUP        , "scalar cleanup")
+ DEFTIMEVAR (TV_TREE_PARALLELIZE_LOOPS, "tree parallelize loops")
+ DEFTIMEVAR (TV_TREE_VECTORIZATION    , "tree vectorization")
+ DEFTIMEVAR (TV_TREE_SLP_VECTORIZATION, "tree slp vectorization")
++DEFTIMEVAR (TV_TREE_LATE_SLP         , "late slp vectorization")
+ DEFTIMEVAR (TV_GRAPHITE              , "Graphite")
+ DEFTIMEVAR (TV_GRAPHITE_TRANSFORMS   , "Graphite loop transforms")
+ DEFTIMEVAR (TV_GRAPHITE_DATA_DEPS    , "Graphite data dep analysis")
+diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
+index a05073c51..5eb4ac102 100644
+--- a/gcc/tree-data-ref.cc
++++ b/gcc/tree-data-ref.cc
+@@ -3021,6 +3021,18 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b,
+       get_inner_reference_aff (DR_REF (b), &off2, &size2);
+       aff_combination_scale (&off1, -1);
+       aff_combination_add (&off2, &off1);
++
++      if (param_addr_expand_for_alias_check)
++	{
++	  using tree_expand_map_t = hash_map;
++	  /* Cache used by aff_combination_expand.  */
++	  tree_expand_map_t *cache = NULL;
++
++	  if (off2.n)
++	    aff_combination_expand (&off2, &cache);
++	  free_affine_expand_cache (&cache);
++	}
++
+       if (aff_comb_cannot_overlap_p (&off2, size1, size2))
+ 	return false;
+     }
+diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
+index 18b0f8022..2ed79f353 100644
+--- a/gcc/tree-pass.h
++++ b/gcc/tree-pass.h
+@@ -390,6 +390,7 @@ extern gimple_opt_pass *make_pass_slp_vectorize (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_complete_unroll (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_complete_unrolli (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt);
++extern gimple_opt_pass *make_pass_slp_vectorize_late (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_parallelize_loops (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_loop_prefetch (gcc::context *ctxt);
+ extern gimple_opt_pass *make_pass_iv_optimize (gcc::context *ctxt);
+diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
+index aae7f62f3..ee58c8f6c 100644
+--- a/gcc/tree-vect-data-refs.cc
++++ b/gcc/tree-vect-data-refs.cc
+@@ -3234,6 +3234,21 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
+ 		      != type_size_a))
+ 		break;
+ 
++	      if (param_vect_register_size_check)
++		{
++		  tree scalar_type = TREE_TYPE (DR_REF (dra));
++		  tree vec_type = get_related_vectype_for_scalar_type (
++		      vinfo->vector_mode, scalar_type);
++		  poly_uint64 vec_size = TYPE_VECTOR_SUBPARTS (vec_type);
++
++		  /* If we have a large interleaving group (especially a group
++		     of loads with gaps) that does not fit in vector register,
++		     we should split this group to chunks we support.  */
++		  if (maybe_ge (((unsigned HOST_WIDE_INT)init_b - init_prev)
++				/ type_size_a, vec_size))
++		    break;
++		}
++
+ 	      /* If the step (if not zero or non-constant) is smaller than the
+ 		 difference between data-refs' inits this splits groups into
+ 		 suitable sizes.  */
+diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
+index fbd638333..79026fb5b 100644
+--- a/gcc/tree-vect-slp.cc
++++ b/gcc/tree-vect-slp.cc
+@@ -687,6 +687,34 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
+   if (first)
+     return 0;
+ 
++  /* If different statements in the group of commutative operations
++     have the same arguments but in different places, swap them to
++     group the same operands in one vector.
++
++     Check if swapping is enabled, operation is commutative and has
++     two operands of the same type.
++     If one of the operands in current statement match the operand
++     on another place of the first statement in the group we
++     swap operands in current statement.  */
++  if (param_vect_swap_operands && commutative_op == 0 && !first
++      && is_a  (vinfo) && number_of_oprnds == 2
++      && vect_def_types_match (dts[0], dts[1]))
++    {
++      slp_oprnd_info oprnd_info0 = (*oprnds_info)[0];
++      slp_oprnd_info oprnd_info1 = (*oprnds_info)[1];
++      if (oprnd_info1->ops[stmt_num] == oprnd_info0->ops[0]
++	  || oprnd_info0->ops[stmt_num] == oprnd_info1->ops[0])
++      {
++	std::swap (oprnd_info0->def_stmts[stmt_num],
++		   oprnd_info1->def_stmts[stmt_num]);
++	std::swap (oprnd_info0->ops[stmt_num],
++		   oprnd_info1->ops[stmt_num]);
++	if (dump_enabled_p ())
++	  dump_printf_loc (MSG_NOTE, vect_location,
++			   "Swapped operands for %G", stmt_info->stmt);
++      }
++    }
++
+   /* Now match the operand definition types to that of the first stmt.  */
+   for (i = 0; i < number_of_oprnds;)
+     {
+diff --git a/gcc/tree-vectorizer.cc b/gcc/tree-vectorizer.cc
+index a63fa3912..c363ce490 100644
+--- a/gcc/tree-vectorizer.cc
++++ b/gcc/tree-vectorizer.cc
+@@ -1524,6 +1524,45 @@ make_pass_slp_vectorize (gcc::context *ctxt)
+   return new pass_slp_vectorize (ctxt);
+ }
+ 
++/*  The late SLP vectorization pass.  */
++
++namespace {
++
++const pass_data pass_data_slp_vectorize_late =
++{
++  GIMPLE_PASS, /* type.  */
++  "slp_late", /* name.  */
++  OPTGROUP_NONE, /* optinfo_flags.  */
++  TV_TREE_LATE_SLP, /* tv_id.  */
++  PROP_cfg, /* properties_required.  */
++  0, /* properties_provided.  */
++  0, /* properties_destroyed.  */
++  0, /* todo_flags_start.  */
++  0, /* todo_flags_finish.  */
++};
++
++class pass_slp_vectorize_late : public gimple_opt_pass
++{
++public:
++  pass_slp_vectorize_late (gcc::context *ctxt)
++    : gimple_opt_pass (pass_data_slp_vectorize_late, ctxt)
++  {}
++
++  /* opt_pass methods: */
++  virtual bool gate (function *)
++  {
++    return flag_slp_late != 0;
++  }
++
++}; // class pass_slp_vectorize_late
++
++} // anon namespace
++
++gimple_opt_pass *
++make_pass_slp_vectorize_late (gcc::context *ctxt)
++{
++  return new pass_slp_vectorize_late (ctxt);
++}
+ 
+ /* Increase alignment of global arrays to improve vectorization potential.
+    TODO:
+-- 
+2.33.0
+
diff --git a/0313-Add-tracer-transformation-for-static-probabilities.patch b/0313-Add-tracer-transformation-for-static-probabilities.patch
new file mode 100644
index 0000000..53d2337
--- /dev/null
+++ b/0313-Add-tracer-transformation-for-static-probabilities.patch
@@ -0,0 +1,130 @@
+From ed300a0b07e608efb756b623263f014c2cebdf08 Mon Sep 17 00:00:00 2001
+From: Egorov Ivan WX1280859 
+Date: Tue, 26 Nov 2024 14:53:59 +0300
+Subject: [PATCH 6/8] Add tracer transformation for static probabilities
+
+---
+ gcc/common.opt                         |  4 ++++
+ gcc/opts.cc                            |  4 ++++
+ gcc/params.opt                         |  8 ++++++++
+ gcc/testsuite/gcc.dg/tracer-static-1.c | 28 ++++++++++++++++++++++++++
+ gcc/tracer.cc                          | 11 ++++++++++
+ 5 files changed, 55 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/tracer-static-1.c
+
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 96888cf1b..db35391c3 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -2990,6 +2990,10 @@ ftracer
+ Common Var(flag_tracer) Optimization
+ Perform superblock formation via tail duplication.
+ 
++ftracer-static
++Common Var(flag_tracer_static) Init(0) Optimization
++Perform superblock formation via tail duplication for a given bb size.
++
+ ftrampolines
+ Common Var(flag_trampolines) Init(0)
+ For targets that normally need trampolines for nested functions, always
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 84dd8925a..34b84db8f 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -3180,6 +3180,10 @@ common_handle_option (struct gcc_options *opts,
+       }
+       break;
+ 
++    case OPT_ftracer_static:
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_tracer, true);
++      break;
++
+     case OPT_ftree_vectorize:
+       /* Automatically sets -ftree-loop-vectorize and
+ 	 -ftree-slp-vectorize.  Nothing more to do here.  */
+diff --git a/gcc/params.opt b/gcc/params.opt
+index bb4dc1825..e5472dfc8 100644
+--- a/gcc/params.opt
++++ b/gcc/params.opt
+@@ -1116,6 +1116,10 @@ The percentage of function, weighted by execution frequency, that must be covere
+ Common Joined UInteger Var(param_tracer_max_code_growth) Init(100) Param Optimization
+ Maximal code growth caused by tail duplication (in percent).
+ 
++-param=tracer-max-not-covered-insns-num=
++Common Joined UInteger Var(param_tracer_max_not_covered_insns_num) Init(12) Param Optimization
++Maximal number of instructions in the block, that must not be covered by trace formation.
++
+ -param=tracer-min-branch-probability=
+ Common Joined UInteger Var(param_tracer_min_branch_probability) Init(50) IntegerRange(0, 100) Param Optimization
+ Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is not available.
+@@ -1128,6 +1132,10 @@ Stop forward growth if the probability of best edge is less than this threshold
+ Common Joined UInteger Var(param_tracer_min_branch_ratio) Init(10) IntegerRange(0, 100) Param Optimization
+ Stop reverse growth if the reverse probability of best edge is less than this threshold (in percent).
+ 
++-param=tracer-min-not-covered-insns-num=
++Common Joined UInteger Var(param_tracer_min_not_covered_insns_num) Init(1) Param Optimization
++Minimal number of instructions in the block, that must not be covered by trace formation.
++
+ -param=tree-reassoc-width=
+ Common Joined UInteger Var(param_tree_reassoc_width) Param Optimization
+ Set the maximum number of instructions executed in parallel in reassociated tree.  If 0, use the target dependent heuristic.
+diff --git a/gcc/testsuite/gcc.dg/tracer-static-1.c b/gcc/testsuite/gcc.dg/tracer-static-1.c
+new file mode 100644
+index 000000000..76c863b48
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/tracer-static-1.c
+@@ -0,0 +1,28 @@
++/* { dg-do compile } */
++/* { dg-options "-O3 -ftracer-static -fdump-tree-tracer" } */
++
++static __attribute__ ((noinline)) int fib (int n)
++{
++  if (n < 3)
++    return 0;
++
++  long long fib1 = 0, fib2 = 1;
++  long long currentFib = 0;
++
++  for (int i = 3; i <= n; ++i)
++    {
++      currentFib = fib1 + fib2;
++      fib1 = fib2;
++      fib2 = currentFib;
++    }
++
++  return currentFib;
++}
++
++int main (int argc, char** argv)
++{
++  int n = argc;
++  return fib (n);
++}
++
++/* { dg-final { scan-tree-dump-times "BB\\d+ with n = \\d+ will not be covered by tracer formation" 4 "tracer" } } */
+\ No newline at end of file
+diff --git a/gcc/tracer.cc b/gcc/tracer.cc
+index 4d054fe8f..9b1578cd4 100644
+--- a/gcc/tracer.cc
++++ b/gcc/tracer.cc
+@@ -304,6 +304,17 @@ tail_duplicate (void)
+     {
+       int n;
+       analyze_bb (bb, &n);
++
++    if (flag_tracer_static && n >= param_tracer_min_not_covered_insns_num
++	&& n <= param_tracer_max_not_covered_insns_num)
++      {
++	if (dump_file)
++	  fprintf (dump_file,
++		   "BB%d with n = %d will not be covered by tracer formation\n",
++		   bb->index, n);
++	continue;
++      }
++
+       if (!ignore_bb_p (bb))
+ 	blocks[bb->index] = heap.insert (-bb->count.to_frequency (cfun), bb);
+ 
+-- 
+2.33.0
+
diff --git a/0314-bugfix-Modify-the-hip09-tune-flags.patch b/0314-bugfix-Modify-the-hip09-tune-flags.patch
new file mode 100644
index 0000000..1809731
--- /dev/null
+++ b/0314-bugfix-Modify-the-hip09-tune-flags.patch
@@ -0,0 +1,56 @@
+From e94bf3e1ad12211ec037c9e04a1698e1ed16c87a Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Tue, 3 Dec 2024 21:02:39 +0800
+Subject: [PATCH 8/8] [bugfix] Modify the hip09 tune flags.
+
+---
+ gcc/config/aarch64/aarch64-tuning-flags.def |  3 +++
+ gcc/config/aarch64/aarch64.cc               | 11 +++++++++--
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def
+index b4a8f99a6..293f6fb7e 100644
+--- a/gcc/config/aarch64/aarch64-tuning-flags.def
++++ b/gcc/config/aarch64/aarch64-tuning-flags.def
+@@ -49,6 +49,9 @@ AARCH64_EXTRA_TUNING_OPTION ("no_ldp_combine", NO_LDP_COMBINE)
+ 
+ AARCH64_EXTRA_TUNING_OPTION ("rename_load_regs", RENAME_LOAD_REGS)
+ 
++/* Prefer Advanced SIMD over SVE for auto-vectorization.  */
++AARCH64_EXTRA_TUNING_OPTION ("prefer_advsimd_autovec", PREFER_ADVSIMD_AUTOVEC)
++
+ AARCH64_EXTRA_TUNING_OPTION ("cse_sve_vl_constants", CSE_SVE_VL_CONSTANTS)
+ 
+ AARCH64_EXTRA_TUNING_OPTION ("use_new_vector_costs", USE_NEW_VECTOR_COSTS)
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 1d479f270..829e0da8f 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -1934,8 +1934,7 @@ static const struct tune_params hip09_tunings =
+   2,    /* min_div_recip_mul_df.  */
+   0,    /* max_case_values.  */
+   tune_params::AUTOPREFETCHER_WEAK,     /* autoprefetcher_model.  */
+-  (AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS
+-   | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT),     /* tune_flags.  */
++  (AARCH64_EXTRA_TUNE_PREFER_ADVSIMD_AUTOVEC),     /* tune_flags.  */
+   &hip09_prefetch_tune
+ };
+ 
+@@ -20250,6 +20249,14 @@ aarch64_override_options_internal (struct gcc_options *opts)
+   SET_OPTION_IF_UNSET (opts, &global_options_set,
+ 		       param_sched_autopref_queue_depth, queue_depth);
+ 
++  /* If the core wants only AdvancedSIMD autovectorization, do this through
++     aarch64_autovec_preference.  If the user set it explicitly, they should
++     know what they want.  */
++  if (aarch64_tune_params.extra_tuning_flags
++      & AARCH64_EXTRA_TUNE_PREFER_ADVSIMD_AUTOVEC)
++    SET_OPTION_IF_UNSET (opts, &global_options_set,
++			 aarch64_autovec_preference, 1);
++
+   /* If using Advanced SIMD only for autovectorization disable SVE vector costs
+      comparison.  */
+   if (aarch64_autovec_preference == 1)
+-- 
+2.33.0
+
diff --git a/0315-Bugfix-Add-no-var-recored-check-for-ssa_name-in-stru.patch b/0315-Bugfix-Add-no-var-recored-check-for-ssa_name-in-stru.patch
new file mode 100644
index 0000000..befe1f6
--- /dev/null
+++ b/0315-Bugfix-Add-no-var-recored-check-for-ssa_name-in-stru.patch
@@ -0,0 +1,234 @@
+From 05bece3d79daa886a469b066061f0606ca6ebed8 Mon Sep 17 00:00:00 2001
+From: huang-xioaquan 
+Date: Mon, 2 Dec 2024 17:39:11 +0800
+Subject: [PATCH 2/5] [Bugfix] Add no var recored check for ssa_name in struct
+ reorg
+
+---
+ gcc/ipa-struct-reorg/escapes.def              |   1 +
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc      |  44 ++++++
+ .../gcc.dg/struct/rf_void_ptr_ssa_name.c      | 125 ++++++++++++++++++
+ 3 files changed, 170 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/rf_void_ptr_ssa_name.c
+
+diff --git a/gcc/ipa-struct-reorg/escapes.def b/gcc/ipa-struct-reorg/escapes.def
+index 996a09bac..4ba9cc2d0 100644
+--- a/gcc/ipa-struct-reorg/escapes.def
++++ b/gcc/ipa-struct-reorg/escapes.def
+@@ -61,5 +61,6 @@ DEF_ESCAPE (escape_unhandled_rewrite, "Type escapes via a unhandled rewrite stmt
+ DEF_ESCAPE (escape_via_orig_escape, "Type escapes via a original escape type")
+ DEF_ESCAPE (escape_instance_field, "Type escapes via a field of instance")
+ DEF_ESCAPE (escape_via_empty_no_orig, "Type escapes via empty and no original")
++DEF_ESCAPE (escape_no_record_var, "Type escapes via no record var")
+ 
+ #undef DEF_ESCAPE
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index 1a169c635..b93b8a5b5 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -1433,6 +1433,7 @@ public:
+   void propagate_escape_via_original (void);
+   void propagate_escape_via_empty_with_no_original (void);
+   void propagate_escape_via_ext_func_types (void);
++  void propagate_escape_via_no_record_var (void);
+   void analyze_types (void);
+   void clear_visited (void);
+   bool create_new_types (void);
+@@ -4467,6 +4468,13 @@ ipa_struct_reorg::check_type_and_push (tree newdecl, srdecl *decl,
+ 	}
+       /* At this point there should only be unkown void* ssa names.  */
+       gcc_assert (TREE_CODE (newdecl) == SSA_NAME);
++      tree inner = SSA_NAME_VAR (newdecl);
++      if (current_layout_opt_level >= STRUCT_REORDER_FIELDS && 
++	  inner && find_decl (inner) == NULL)
++	{
++	  type->mark_escape (escape_no_record_var, stmt);
++	  return;
++	}
+       if (dump_file && (dump_flags & TDF_DETAILS))
+ 	{
+ 	  fprintf (dump_file, "\nrecording unkown decl: ");
+@@ -5512,6 +5520,41 @@ ipa_struct_reorg::propagate_escape_via_ext_func_types (void)
+     }
+ }
+ 
++/* Escape propagation is performed on ssa_name decl that no record var in
++   decls.  */
++
++void
++ipa_struct_reorg::propagate_escape_via_no_record_var (void)
++{
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\n propagate_escape_via_no_record_var: \n\n");
++
++  for (unsigned i = 0; i < functions.length (); i++)
++    {
++      if (functions[i]->node)
++	set_cfun (DECL_STRUCT_FUNCTION (functions[i]->node->decl));
++
++      for (unsigned j = 0; j < functions[i]->decls.length (); j++)
++	{
++	  srdecl *decl = functions[i]->decls[j];
++	  srtype *type = decl->type;
++
++	  if (TREE_CODE (decl->decl) == SSA_NAME)
++	    {
++	      tree inner = SSA_NAME_VAR (decl->decl);
++
++	      if (inner && functions[i]->find_decl (inner) == NULL)
++		type->mark_escape (escape_no_record_var, NULL);
++	    }
++	}
++
++      set_cfun (NULL);
++    }
++
++  if (dump_file && (dump_flags & TDF_DETAILS))
++    fprintf (dump_file, "\n end propagate_escape_via_no_record_var \n\n");
++}
++
+ /* Prune the escaped types and their decls from what was recorded.  */
+ 
+ void
+@@ -5530,6 +5573,7 @@ ipa_struct_reorg::prune_escaped_types (void)
+       propagate_escape_via_original ();
+       propagate_escape_via_empty_with_no_original ();
+       propagate_escape_via_ext_func_types ();
++      propagate_escape_via_no_record_var ();
+     }
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+diff --git a/gcc/testsuite/gcc.dg/struct/rf_void_ptr_ssa_name.c b/gcc/testsuite/gcc.dg/struct/rf_void_ptr_ssa_name.c
+new file mode 100644
+index 000000000..0f624b6b9
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/rf_void_ptr_ssa_name.c
+@@ -0,0 +1,125 @@
++// Add a void* ssa_name check and escape.
++/* { dg-do compile } */
++
++// includes
++#include "stdio.h"
++#include "stdlib.h"
++#include "time.h"
++#include "string.h"
++#include "limits.h"
++#include "float.h"
++
++#define JOTAI_NUM_RANDS_ 25
++
++const unsigned rand_primes[JOTAI_NUM_RANDS_] = {179, 103, 479, 647, 229, 37,
++271, 557, 263, 607, 18743, 50359, 21929, 48757, 98179, 12907, 52937, 64579,
++49957, 52567, 507163, 149939, 412157, 680861, 757751};
++
++int next_i ()
++{
++  int counter = 0;
++  return rand_primes[(++counter)%JOTAI_NUM_RANDS_];
++}
++
++float next_f ()
++{
++  int counter = 0;
++  return rand_primes[(++counter)%JOTAI_NUM_RANDS_] / 757751.0F;
++}
++
++// Usage menu
++void usage()
++{
++    printf("%s", "Usage:\n\
++    prog [ARGS]\n\
++\nARGS:\n\
++       0	    big-arr\n\
++       1	    big-arr-10x\n\
++       2	    empty\n\
++\n\
++");
++}
++
++// ------------------------------------------------------------------------- //
++
++typedef unsigned long size_t;  // Customize by platform.
++typedef long intptr_t;
++typedef unsigned long uintptr_t;
++typedef long scalar_t__;  // Either arithmetic or pointer type.
++/* By default, we understand bool (as a convenience). */
++typedef int bool;
++#define false 0
++#define true 1
++
++/* Forward declarations */
++
++/* Type definitions */
++typedef  size_t u32 ;
++struct octeon_device {int octeon_id; } ;
++
++/* Variables and functions */
++ size_t MAX_OCTEON_DEVICES ; 
++ struct octeon_device** octeon_device ; 
++
++int lio_get_device_id(void *dev)
++{
++  struct octeon_device *octeon_dev = (struct octeon_device *)dev;
++  u32 i;
++
++  for (i = 0; i < MAX_OCTEON_DEVICES; i++)
++    {
++      if (octeon_device[i] == octeon_dev)
++	return octeon_dev->octeon_id;
++    }
++  return -1;
++}
++
++// ------------------------------------------------------------------------- //
++
++int main(int argc, char *argv[])
++{
++  if (argc != 2)
++    {
++      usage();
++      return 1;
++    }
++
++  int opt = atoi(argv[1]);
++  switch(opt)
++    {
++      // big-arr
++      case 0:
++	{
++	  void * dev;
++	  int benchRet = lio_get_device_id(dev);
++	  printf("%d\n", benchRet); 
++	  break;
++	}
++
++      // big-arr-10x
++      case 1:
++	{
++	  void * dev;
++	  int benchRet = lio_get_device_id(dev);
++	  printf("%d\n", benchRet); 
++	  break;
++	}
++
++      // empty
++      case 2:
++	{
++	  void * dev;
++	  int benchRet = lio_get_device_id(dev);
++	  printf("%d\n", benchRet); 
++	  break;
++	}
++
++      default:
++	usage();
++	break;
++    }
++
++  return 0;
++}
++
++/* { dg-final { scan-ipa-dump "No structures to transform" "struct_reorg" } } */
+-- 
+2.33.0
+
diff --git a/0316-Use-ai-ability-to-guide-optimization.patch b/0316-Use-ai-ability-to-guide-optimization.patch
new file mode 100644
index 0000000..40b9786
--- /dev/null
+++ b/0316-Use-ai-ability-to-guide-optimization.patch
@@ -0,0 +1,741 @@
+From 0b85ab4639e2d25314175962a6e41a841649b028 Mon Sep 17 00:00:00 2001
+From: zhenyu zhao 
+Date: Sun, 24 Nov 2024 17:29:13 +0800
+Subject: [PATCH 3/5] Use ai ability to guide optimization.
+
+---
+ gcc/Makefile.in               |   8 +-
+ gcc/ai4c-infer.cc             | 457 ++++++++++++++++++++++++++++++++++
+ gcc/ai4c-infer.h              |  29 +++
+ gcc/config/aarch64/aarch64.cc |  14 +-
+ gcc/gcc.cc                    |  32 +++
+ gcc/gcc.h                     |   1 +
+ gcc/ipa-hardware-detection.cc |   6 +-
+ gcc/onnx.fdata                |   1 +
+ gcc/opts-global.cc            |  10 +
+ 9 files changed, 550 insertions(+), 8 deletions(-)
+ create mode 100644 gcc/ai4c-infer.cc
+ create mode 100644 gcc/ai4c-infer.h
+ create mode 100644 gcc/onnx.fdata
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index bb6197a8e..6315462aa 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1734,13 +1734,13 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+ 	pretty-print.o intl.o \
+ 	sbitmap.o \
+ 	vec.o input.o hash-table.o ggc-none.o memory-block.o \
+-	selftest.o selftest-diagnostic.o sort.o
++	ai4c-infer.o selftest.o selftest-diagnostic.o sort.o
+ 
+ # Objects in libcommon-target.a, used by drivers and by the core
+ # compiler and containing target-dependent code.
+ OBJS-libcommon-target = $(common_out_object_file) prefix.o \
+ 	opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \
+-	hash-table.o file-find.o spellcheck.o selftest.o opt-suggestions.o
++	hash-table.o file-find.o spellcheck.o ai4c-infer.o selftest.o opt-suggestions.o
+ 
+ # This lists all host objects for the front ends.
+ ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
+@@ -2256,7 +2256,7 @@ gcc-nm.cc: gcc-ar.cc
+ 	cp $^ $@
+ 
+ COLLECT2_OBJS = collect2.o collect2-aix.o vec.o ggc-none.o \
+-  collect-utils.o file-find.o hash-table.o selftest.o
++  collect-utils.o file-find.o hash-table.o ai4c-infer.o selftest.o
+ COLLECT2_LIBS = @COLLECT2_LIBS@
+ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
+ # Don't try modifying collect2 (aka ld) in place--it might be linking this.
+@@ -3720,6 +3720,8 @@ install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype
+ 
+ # Install the compiler executables built during cross compilation.
+ install-common: native lang.install-common installdirs
++	rm -f $(DESTDIR)$(libexecdir)/onnx.fdata
++	cp $(srcdir)/onnx.fdata $(DESTDIR)$(libexecsubdir)/onnx.fdata
+ 	for file in $(COMPILERS); do \
+ 	  if [ -f $$file ] ; then \
+ 	    rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
+diff --git a/gcc/ai4c-infer.cc b/gcc/ai4c-infer.cc
+new file mode 100644
+index 000000000..99f7a6b45
+--- /dev/null
++++ b/gcc/ai4c-infer.cc
+@@ -0,0 +1,457 @@
++/* Lightweight AI Inference Framework.
++   Copyright (C) 2024-2024 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
++.  */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "ai4c-infer.h"
++#include "config.h"
++#include "system.h"
++
++#define M_MODE_SIZE  6
++#define NATIVE_TUNE_SIZE 128
++#define CATS_STRINGS_ROW  12
++#define CATS_STRINGS_COL  65
++#define OFFSET_ROW  6
++#define SCALE_ROW  6
++#define UNITY_ROW 1
++#define COEFFICIENT_ROW  18
++#define COEFFICIENT_COL  100
++#define COEFFICIENT1_ROW  100
++#define COEFFICIENT1_COL  1
++#define INTERCEPTS_ROW  100
++#define INTERCEPTS1_ROW  1
++
++/* Model info.  */
++static int64_t argv_hw1[M_MODE_SIZE];
++static char native_tune[NATIVE_TUNE_SIZE];
++
++/* Intermediate computation results from the ONNX model.  */
++static char cats_strings[CATS_STRINGS_ROW][CATS_STRINGS_COL];
++static float offset[OFFSET_ROW];
++static float scale[SCALE_ROW];
++static float unity[UNITY_ROW];
++static float coefficient[COEFFICIENT_ROW][COEFFICIENT_COL];
++static float coefficient1[COEFFICIENT1_ROW][COEFFICIENT1_COL];
++static float intercepts[INTERCEPTS_ROW];
++static float intercepts1[INTERCEPTS1_ROW];
++
++/* Model result.  */
++static int64_t initialized;
++static int64_t optimize_result;
++
++void
++prepare_native_tune_str (const char *info)
++{
++  gcc_assert (strlen (info) < NATIVE_TUNE_SIZE);
++  if (info)
++    strcpy (native_tune, info);
++  return;
++}
++
++void
++set_cache_info (int prefetches, int l1_cache_size,
++		int l1_cache_line_size, int l2_cache_size,
++		int prefetch_latency, int prefetch_distance_factor)
++{
++  gcc_assert (5 < M_MODE_SIZE);
++  argv_hw1[0] = prefetches;
++  argv_hw1[1] = l1_cache_size;
++  argv_hw1[2] = l1_cache_line_size;
++  argv_hw1[3] = l2_cache_size;
++  argv_hw1[4] = prefetch_latency;
++  argv_hw1[5] = prefetch_distance_factor;
++}
++
++/* Read float from onnx.fdata.  */
++
++float static
++read_float_from_file (FILE* file)
++{
++  char hex_float[8];
++  float result;
++
++  if (!file)
++    {
++      perror ("Can not open file.");
++      return result;
++    }
++    
++  if (fscanf (file, "%8s", hex_float) != 1)
++    {
++      perror ("Can not read hex from onnx.fdata.");
++      return result;
++    }
++
++  unsigned char bytes[4];
++  for (int i = 0; i < 4; i++)
++    {
++      sscanf(hex_float + 2 * i, "%2hhx", &bytes[i]);
++    }
++
++  memcpy(&result, bytes, sizeof(float));
++  return result;
++}
++
++/* To read model parameter information from onnx.fdata and store it into the
++   appropriate arrays.  */
++
++static void
++fill_node (const char *file_name)
++{
++  FILE *file = fopen (file_name, "rb");
++
++  if (!file)
++    {
++      perror ("Can not open file.");
++      return;
++    }
++
++   /* Read cats_strings from onnx.fdata.  */
++  char hex_string[2];
++  for (int i = 0; i < CATS_STRINGS_ROW; i++)
++    {
++      for (int j = 0; j < CATS_STRINGS_COL - 1; j++)
++	{
++	  if (fscanf(file, "%2s", hex_string) != 1)
++	    {
++	      perror ("Can not read cats_strings from onnx.fdata.");
++	      return;
++	    }
++	  cats_strings[i][j] = (unsigned char)strtol(hex_string, NULL, 16);
++	}
++	cats_strings[i][CATS_STRINGS_COL - 1] = '\0';
++    }
++  
++  /* Read offset from onnx.fdata.  */
++  for (int i = 0; i < OFFSET_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      offset[i] = result;
++    }
++  
++  /* Read scale from onnx.fdata.  */
++  for (int i = 0; i < SCALE_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      scale[i] = result;
++    }
++
++  /* Read coefficient from onnx.fdata.  */
++  for (int i = 0; i < COEFFICIENT_ROW; i++)
++    for (int j = 0; j < COEFFICIENT_COL; j++)
++      {
++	float result = read_float_from_file (file);
++	coefficient[i][j] = result;
++      }
++
++  /* Read coefficient1 from onnx.fdata.  */
++  for (int i = 0; i < COEFFICIENT1_ROW; i++)
++    for (int j = 0; j < COEFFICIENT1_COL; j++)
++      {
++	float result = read_float_from_file (file);
++	coefficient1[i][j] = result;
++      }
++
++  /* Read intercepts from onnx.fdata.  */
++  for (int i = 0; i < INTERCEPTS_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      intercepts[i] = result;
++    }
++
++  /* Read intercepts1 from onnx.fdata.  */
++  for (int i = 0; i < INTERCEPTS1_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      intercepts1[i] = result;
++    }
++
++  /* Read unity from onnx.fdata.  */
++  for (int i = 0; i < UNITY_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      unity[i] = result;
++    }
++
++  fclose (file);
++  return;
++}
++
++static void
++matmul (const float *lhs, const float *rhs, int m, int k, int n, float *out)
++{
++  for (int i = 0; i < m; i++)
++    {
++      for (int j = 0; j < n; j++)
++	{
++	  out[i * n + j] = 0.0f;
++	  for (int p = 0; p < k; p++)
++	    {
++	      out[i * n + j] += lhs[i * k + p] * rhs[p * n + j];
++	    }
++	}
++    }
++}
++
++static void
++add (const float *lhs, const float *rhs, int length, float *out)
++{
++  for (int i = 0; i < length; i++)
++    {
++      out[i] = lhs[i] + rhs[i];
++    }
++}
++
++static void
++sub (const float *lhs, const float *rhs, int length, float *out)
++{
++  for (int i = 0; i < length; i++)
++    {
++      out[i] = lhs[i] - rhs[i];
++    }
++}
++
++static void
++sigmoid (const float *in, int length, float *out)
++{
++  for (int i = 0; i < length; i++)
++    {
++      out[i] = 1.0f / (1.0f + expf (-in[i]));
++    }
++}
++
++static void
++relu (const float *data, int length, float *out)
++{
++  for (int i = 0; i < length; i++)
++    {
++      if (data[i] < 0)
++	{
++	  out[i] = 0;
++	}
++      else
++	{
++	  out[i] = data[i];
++	}
++    }
++}
++
++static void
++line_concat (const float *in, int in_size, float *out, int out_size)
++{
++  for (int i = 0; i < in_size; i++)
++    out[out_size + i] = in[i];
++}
++
++static void
++one_hot_encoder (const char *in, const char (*cats)[65], float *out,
++		 int out_size)
++{
++  for (int i = 0; i < out_size; i++)
++    {
++      if (i < out_size && strcmp (cats[i], in) == 0)
++	{
++	  out[i] = 1.0f;
++	}
++      else
++	{
++	  out[i] = 0.0f;
++	}
++    }
++}
++
++static void
++imputer (const int64_t *in, int size, float *out)
++{
++  for (int i = 0; i < size; i++)
++    out[i] = in[i] * 1.0f;
++}
++
++static void
++scaler (const float *in, const float *offset, const float *scale, int size,
++	float *out)
++{
++  for (int i = 0; i < size; i++)
++    out[i] = (in[i] - offset[i]) * scale[i];
++}
++
++static int
++argmax (const float *in, int in_size)
++{
++  int out_idx = 0;
++  for (int i = 0; i < in_size; i++)
++    {
++      if (in[i] > in[out_idx])
++	out_idx = i;
++    }
++  return out_idx;
++}
++
++static void
++preprocess (int argc, int64_t *argv, int64_t *in_modes)
++{
++  int default_int_val= 0;
++  for (int i = 0; i < argc && i < M_MODE_SIZE; i++)
++    {
++      if (i < argc)
++	{
++	  in_modes[i] = argv[i];
++	}
++      else
++	{
++	  in_modes[i] = default_int_val;
++	}
++    }
++}
++
++/* The process of model inference.  */
++static int
++graph_infer (int argc, const char *argv, int argc2, int64_t *argv2)
++{
++  const char *file_name = getenv ("GCC_AI4C_ONNX_FDATA");
++
++  if (access (file_name, F_OK) == 0)
++    {
++      fill_node (file_name);
++    }
++  else
++    {
++      return 0;
++    }
++
++  int64_t in_modes[M_MODE_SIZE];
++
++  preprocess (argc2, argv2, in_modes);
++  
++  /* concat_result and encoder_out are intermediate computation results from
++     the ONNX model. concat_result is a 1 × 18 matrix, and encoder_out is a
++     1 × 12 matrix.  */
++
++  const int concat_out_size = 18;
++  float concat_result[concat_out_size];
++  const int encoder_out_size = 12;
++  float encoder_out[encoder_out_size];
++
++  one_hot_encoder (argv, cats_strings, encoder_out, encoder_out_size);
++
++  line_concat (encoder_out, encoder_out_size, concat_result, 0);
++
++  float variable[M_MODE_SIZE];
++  imputer (in_modes, M_MODE_SIZE, variable);
++
++  float variable1[M_MODE_SIZE];
++  scaler (variable, offset, scale, M_MODE_SIZE, variable1);
++  float transformed_column[concat_out_size + M_MODE_SIZE];
++  line_concat (variable1, M_MODE_SIZE, transformed_column, 0);
++  line_concat (concat_result, concat_out_size, transformed_column, 6);
++
++  /* This requires performing matrix multiplication between a 1 × 18 matrix
++     and an 18 × 100 matrix  */
++
++  const int m = 1, k = 18, n = 100;
++  float mul_result[n];
++  matmul (transformed_column, coefficient[0], m, k, n, mul_result);
++
++  float add_result[n];
++  add (mul_result, intercepts, n, add_result);
++
++  float next_activations[n];
++  relu (add_result, n, next_activations);
++
++  /* This requires performing matrix multiplication between a 1 × 100 matrix
++     and an 100 × 1 matrix  */
++
++  const int m2 = 1, k2 = 100, n2 = 1;
++  float mul_result1[n2];
++  matmul (next_activations, coefficient1[0], m2, k2, n2, mul_result1);
++
++  float add_result1[n2];
++  add (mul_result1, intercepts1, n2, add_result1);
++
++  float out_activations_result[n2];
++  sigmoid (add_result1, n2, out_activations_result);
++
++  float negative_class_proba[n2];
++  sub (unity, out_activations_result, n2, negative_class_proba);
++  const int prob_size = n2 + n2;
++  float probabilities[prob_size];
++  line_concat (negative_class_proba, n2, probabilities, 0);
++  line_concat (out_activations_result, n2, probabilities, n2);
++
++  int argmax_output = argmax (probabilities, prob_size);
++  return argmax_output;
++}
++
++void execute_sha256 (const char *input, char *output, size_t output_size)
++{
++    char command[256];
++    snprintf (command, sizeof (command), "echo -n \"%s\" | sha256sum", input);
++
++    FILE *pipe = popen (command, "r");
++    if (pipe == NULL)
++      {
++	perror ("Failed to run command.");
++	return;
++      }
++
++    fgets (output, output_size, pipe);
++    pclose (pipe);
++}
++
++int
++get_optimize_decision_from_ai4c ()
++{
++  if (initialized== 1)
++    {
++      return optimize_result;
++    }
++  if (native_tune && (strchr (native_tune, '+') != NULL))
++    {
++      char hash[65];
++      char input[64];
++      const char prefix = '=';
++      const char *start = strchr (native_tune, prefix);
++      if (start)
++	{
++	  start += 1;
++	  const char *end = strchr (start, '+');
++	  if (!end)
++	    {
++	      end = native_tune + strlen (native_tune);
++	    }
++	  size_t len = end - start;
++	  if (len >= sizeof (input))
++	    len = sizeof (input) - 1;
++	  strncpy (input, start, len);
++	  input[len] = '\0';
++	}
++      else
++	input[0] = '\0';
++
++      execute_sha256 (input, hash, sizeof (hash));
++      optimize_result = graph_infer (1, hash, M_MODE_SIZE, argv_hw1);
++      initialized = 1;
++      if (optimize_result == 1)
++	setenv ("AI_GUIDED", "1", 1);
++    }
++  return optimize_result;
++}
+diff --git a/gcc/ai4c-infer.h b/gcc/ai4c-infer.h
+new file mode 100644
+index 000000000..7fb75900b
+--- /dev/null
++++ b/gcc/ai4c-infer.h
+@@ -0,0 +1,29 @@
++/* Lightweight AI Inference Framework.
++
++   Copyright (C) 2024-2024 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
++   .  */
++
++#ifndef AI4C_INFER_H
++#define AI4C_INFER_H
++
++extern int get_optimize_decision_from_ai4c ();
++extern void set_cache_info (int prefetches, int l1_cache_size, 
++			    int l1_cache_line_size, int l2_cache_size,
++			    int prefetch_latency, int prefetch_distance_factor);
++extern void prepare_native_tune_str (const char *info);
++#endif /* AI4C_INFER_H */
+\ No newline at end of file
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 08a43541e..1d479f270 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -18764,12 +18764,14 @@ override_C_optimize_options (struct gcc_options *opts)
+   opts->x_flag_ipa_struct_reorg = 6;
+   opts->x_struct_layout_optimize_level = 6;
+   opts->x_flag_gnu89_inline = 1;
+-  opts->x_flag_ccmp2 = 1;
+-  opts->x_flag_array_widen_compare = 1;
+   opts->x_flag_convert_minmax = 1;
+   opts->x_flag_tree_slp_transpose_vectorize = 1;
+   opts->x_param_max_inline_insns_auto = 64;
+   opts->x_param_inline_unit_growth = 96;
++  opts->x_param_pointer_compression_size = 16;
++  opts->x_semi_relayout_level = 14;
++  opts->x_flag_ipa_prefetch = 1;
++  opts->x_flag_ipa_ic = 1;
+ }
+ 
+ /* Check whether in CPP language or LTO with only CPP language.  */
+@@ -18826,6 +18828,8 @@ override_optimize_options_1 (struct gcc_options *opts)
+   opts->x_param_ifcvt_allow_register_renaming = 2;
+   opts->x_param_max_rtl_if_conversion_unpredictable_cost = 48;
+   opts->x_param_max_rtl_if_conversion_predictable_cost = 48;
++  opts->x_flag_ccmp2 = 1;
++  opts->x_flag_array_widen_compare = 1;
+ }
+ 
+ static void
+@@ -18848,6 +18852,8 @@ override_Fortran_optimize_options (struct gcc_options *opts)
+   opts->x_flag_reorder_blocks = 1;
+   opts->x_flag_crypto_accel_aes = 1;
+   opts->x_param_flexible_seg_len = 1;
++  opts->x_flag_alias_analysis_expand_ssa = 1;
++  opts->x_flag_chrec_mul_fold_strict_overflow = 1;
+ }
+ 
+ /* Reset the optimize option.
+@@ -18857,7 +18863,9 @@ static void
+ reset_machine_option (struct gcc_options *opts)
+ {
+   if (!(opts->x_optimize_maximum)
+-      || strstr (opts->x_aarch64_tune_string, "hip09") == NULL)
++      || opts->x_aarch64_cpu_string == NULL
++      || (strstr (opts->x_aarch64_cpu_string, "tsv110") == NULL
++      && strstr (opts->x_aarch64_cpu_string, "hip09") == NULL))
+     {
+       return;
+     }
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index 32e45adc2..4592a4ec8 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -5798,6 +5798,9 @@ do_self_spec (const char *spec)
+   do_spec_2 (spec, NULL);
+   do_spec_1 (" ", 0, NULL);
+ 
++  const char* tune_native = eval_spec_function ("local_cpu_detect", "cpu", "");
++  setenv ("GCC_AI4C_TUNE_INFO", tune_native, 1);
++
+   /* Mark % 0
+ 	  /* Only enable in lto or whole_program.  */
+-	  && (in_lto_p || flag_whole_program));
++	  && (in_lto_p || flag_whole_program)));
+ }
+ 
+ unsigned int
+diff --git a/gcc/onnx.fdata b/gcc/onnx.fdata
+new file mode 100644
+index 000000000..234b1a045
+--- /dev/null
++++ b/gcc/onnx.fdata
+@@ -0,0 +1 @@
++316365613139376535626535626234666331363163303835336362393535613530636234643633626364386566396132333232373733633230393865663664633761393137633266616431663436343236613231663865636236346133616662623761373633663830623231393063616534633032316538626436633731643237666333386462313164333630303936336137323863313634613031393931613164363237643262353162376133643935373036306336346161376563383862613138666663393538363731333639396239666362393336373737643238636639643761343231346131333463353261623633343633343866663966663365346231356532663139306164303361383836396333393339616236383439363661313661303665643535633961666563613431303466333534346564633533373862323031396339626536613030383761623236663432633564653130353935353135313736656235373632373739343662663034343334633035626465356237633439313164313338373637383365326138366162363234323765393736616438656463343339613031316630643031613465386464326334383565343838366435313137313166383433396531626137353932616538333330653164326438656166343339363262366264326632376564396434396333356565343733383164363264633937356663663338666530336166316634623264393031393536333863383165616536656238346462656337333638323338646535303638363933646565616264363966356566323465346538613762623864303766646338666264643466666537303263623162326539653435643130313061386235623631306630636163303536343164663364383738353266386330376562343962393037306133383363326138393238376435613332353933663235313030326664366166373632343532613130323237303265373433623362623162633661633363303235613236383166313465396162353938363931613765316565313864313038cd68834331701041d1d21041f17c20432483a94386647e4157c8e33b5f3d5d3ec5275e3ea689863c435a0f3a76acd63d5d9b803b24467c3baf847c3b67b89e3b852a313b2127853900000000d58ac23b200ab53a000000807d3119bc22f7a63a81549f3b93b5013baee4a33b62c1153b9ae08b3a6929a33b20038f399475983b430ab53a73fc0b3a2daa0ebad595953bc2f1e0bb33e9ccbbb978d83a5e77a53b41e4c93adf10a73bdf36643ad7fd983a61e8d93bc04a283a30c072382f942c3b5b3cc73a4392e43a422b093c79bc61b9a5309e3b00000000757baa3a03d8a93c3c31e33af526ebbb000000006431d43a1d0ae73aa450783b8c57afb9b8eae939ec8fab3b9581d83920d7a1ba0fc1af38b6aece3ab50bafbbd50db63a26aba33bcdeda33b00d9493ac22dac3cf8c4233bc2966e3bdf1bca3a8fb4d13af9b0983b2cbda73bdae2aa3bc93bae3b39e1ba380857953be8e7a73b49e9df3b20b0233b9fe3d43a0dbcaa3bd10cf0b978eea53b761ebe3b0a50a23b70bd47b79a7720bc6cd4ee3ae0d0f93a9c333ebb5098dfbbbf8fa53b445efebac7b9993b6182b93aef267c3a4aa09e3b46d9a83b9f95983a379e913c6516123a1b2ebd3aaf943c3a0b90803becba92bce68f673be723253c5d7f813ad779613800000080af3c65ba6999743900000080957a003d82f2fe39baab4d3b7f348c39b8d3323b3c1e253ace952dbbc9d364bc3aafaf373d0a633be8fdee3968b0fa39eb70a83a7cba4e3bdf2407bc40f50f3d94f4c3b9a828573b3f2bc3b99a5763bcccb838bb24f011bae3400dbdc3074fba30a829bb3dde6e3ad7c2caba2b2aa7b8d479a7bbebe2603a7025583b00000000017414ba680386bc9b365e3aaacb03bc000000006afd90b9a64e263980eb223c80a48ebcca9703392310573b1fd419bbf7368abc17a2083a3ceafab95eb11cbcf29995b9a64264bc8bae403bc1dc6139631c88bc12e3373c07cf0c3cdc93a6b97edbc0b917754d3b5cdc143c61ef393b40a809baf3861dbbafce623be550513b828382bc359d513afa4a25ba31394c3bb013da3a9835553bf3d9553bec2b65bcee09bab9f6343e3c03a59f39fb11053a078e7cbc5bd006bcfe23363b08d12cbb3cfb533bb98a8fbadcb99139cbd1573b24725e3b01014fb6dcbc45ba6ee024bb318db1baf39ce9b952d625bc41afddb91d7dffbbc0ba163b0387b93b2594623b00000000f60cf9ba483c983b0000008015e6c6bcbd45983b77d62ebcfbb69f3b7b5752bcc334ab3b4f9806bc9d89063cc0675a3b807426bca81a9f3b7ef56f3b6a96a13a045937bcd4a2f33cb92173bc40af783b26ac40bc5fef6b3beba6fe3b8c7207bc5e25443bfd99a33be7e7403b4c2508bc0c87bb3bb95dcd3abe228b3bac03deb91a2ab03add753bbc000000002e04703be98f1fbccef2af3b17ebe93c0000000020e37a3b46ba913b1fd7003b1f3f133df85d423bacc843bc5fada7bbc8680d3d8423503b2afc6c3b4e43033dcfcc7c3bcece053cdbb44ebc4151823ba14426bc6e942c3b3bdc4d3a34967f3b7687783bd0cd3ebcfc75053ade324ebcd10c32bc9ff9fbbb0b7430bcf60e4abcd6b6e03b295db43b25c75d3b88334fbc8d95883ac9c73ebcddf941bc2b18083c43044c3b405414bd7617963b9910a03bd5e70c3d9356f23c3a2750bc472107bce47d47bc0125243b3c41953b0f6134bc8c403bbc8fb3873ba5e218bcae5d06bc2dfe103b758a493b43cef63cd7438d3c2bf1eb3b2d4a833cf13a43bc5d14c4bd000000002932a7bc3191e4bb00000080224e753dea87dfbb41e28a3cbeb44b3d731d8f3c1312d2bb54e44dbc232b84bc74f9d9bd033bcb3cdda410bbeeeb47bdd7e44e3b3c3e21bb435712bdb3e6413c82e770393f20a53cc6642dbc325484bc410c4e3dcb49823dc262bd3c204a563d032393bb0887753c0cad943d3946abbbcb77b3bc9151c6ba860dc0bd00000080e5880d3a2f960ebd1bba99bcce3910bd0000008037acde3be98a983bd60b7c3c66ee27bd2431aab98b2b95bded06813bc17429bdf5a9e9bc4ff297bafad924bdc14d53bc901784bcad96073cd34989bc84580fbd1e276b3ca48e513c189796bbe15f8cbb39fa473cce9c693cbdd0843a4f07443dbf40c03c38a1893c3790ab3cb48c58bcc5e9863b684448bcb5c32abc0726a6ba1def9ebb57ce273d772b84bc1925c63d2e26d8bc24460cbcb0f807bc8dd0a5bc9ba312bd6ed5393c32e1f43cf3c58bbc8a5334bc8e0c53bbf78cb13c7805793c8d5800bbc4a5c2bcfc2c85bba79d3c3df00f493db55cb73cce71c43dc030f03cc953823c79c1f13d614db73d0000000074e98f3ca415183c000000801104803d9afea83ddf9ff93d835f9bbce8d8623cd67e093c453d143d7d8c90bc1434e23d24580b3e00711d3c729b903d81a0253c82e9b53cba65123ca564a23d7a53003c2c82ec3de139f93c58f58ebce101813ba5782d3d4e198e3dbaa40fbb58e2bc3bbf92943c98421e3df32c0c3cbc235ebcc2fe443c2789033e00000080b94ca73be81815bd1758e53c5df7053b00000080f9f63f3cc7a9893cb846823c65d2143c9bb50e3cced60c3e92fb983b583593bbbbfe263e390bdf3b696887bbd13e823c207890bc1cf0c23cd688163dd14e16bdd3cb813c95a6593c70d7083cd6c6e43b6d4d9b3c9455683c876e1f3e599ff83c4b377f3c2afd953cbeedd43ccbdb163d2d78fd3bcc84363c5c7fa63c22fedf3c3318e83d0ecdba3d0ea690bc462e9a3d0b11013cf19f503da4f8813db249c0bba7300f3c2d6c223dd1d7663b56b4c43d56e5f93c4799e43b0702a73d4e15ae3de8040e3cdfad72bc0ab6593d1fb7c9bb6f90b43dbfcab83b4cd802bbbd3c993be1a91c3c8f677cbaa83420bb0000008084bf263b6336adba00000000373bd13b521cffba733ac83bee8c9bba1306f73bbf5471ba8651773bc863ac3a6ed119bb926fc43b9368e5ba34f319bba9c8ebbaa74acb3b39169ebc812d573b4764beba5815ea3b5211caba956ec23a9e107d3b64dbc4ba674ac73be88107bb5354493b688c5cbaaf4571bab3d6b3bae566603b11b0b0ba6bd1d03b000000005b6cc1ba0720833c5210c7ba85cd97bc000000003c1fc4bab35dbbba30b6fe3b389ea2bc97eb8eba37bae43b697a293b87969abc5c9e04bb83acc2ba5f8fadbcf872c5bab03daf3ad509fe3b2f81f9ba4317863cd808bb3b0177f03b02dabdbab2efbdba3b03d83bc09f223c6030ec3b0137c13b29f5663bf195ce3bc10eff3b18cda93b35486cba7dd7c8ba0d51003c34dc93ba891be33bb785ea3bbb75a73ae04f2abba21d8f3b9065c3ba8892bbbac37d96bc6a0c9dbc596cef3bce5a063bd64cec3be62fb0baaa5cbbba1acbd03b5cdfe13b0f37e9ba48bb653cc513733bc352a0bacba0ffba469ababdf17dae3c939271bd7af718be283c113ed15fbb3d00000080920e90badfa4d63d00000080df70d63c18f5c03dbbb677bde981e83d5a78d2bd0985093e663cffbd9a12803d3fc0b33d65b388bd50a0dd3d011acc3d2df0203ed04095bd5c9a8abd7294323dd404b33dabc5bdbd8042a33d93cb6f3d3b81f7bd4e2e823dfdba273d83ea863d7d0f3cbeaff2133e565a3d3d0d66ca3d035bea398af8073ec3b79abd00000000d078ad3dbe475c3c9267013e1db874bd000000809e1db03d23f9cb3d902b14be16ea52bdc41ac33db52abbbdf07981bed9442ebd4d94a83de0f7a93d745d41bd4cebb33d01f57c3da16adbbd8ae0b63d2d6c763cc1f40ebe098cbebddc59b83d256bb13d359fa9bdf886e5bd0dfcbbbdd68d0dbd726807be83579fbd05c9dcbdd8e8983ccd620d3edcf69f3dc980e8bdcb6c923e1cdcb3bdcc6ec1bde600823d030d993d9b3a1d3d420bcd3d754dde3df8132cbdfabb85bdce89c3bdefd054beafc6c8bd931e7c3d30fed83dbef795bd7fb1b3bd6d9eb73de344993cceb603bebd216b3de45c803d70a1953e1dfb62bea91d2a3ed284113f544008bfc50498be00000000d460e13b0d05b2be0000000066f28ebe9adb9ebe4ee6323efd01c7be63c7ac3e888dfabe44e5e23ec6f631bed07890beb0fe4a3e6217babee93daabecf501abfd1b9573e7bd53a3f805fe2be10a48cbecac09a3e52c67bbef48823be9a9dd83eb74340be75deeabd3fbf42be9d1c3c3f74e10abf923b05beaec4a4be66229fbbb35ff6be8a146c3e00000080638d84be04cb14be4dcfe7be53ec253f00000000208c89be7039a8bef1170c3f70ac0d3fdcd59bbe68f4973e6b1f903f16a3eb3e6d0a86be361a81be4cba023f82c88cbe01132ebea3feb73e79f391beeb6826be5130063fc4d9953e4a6690becd328abe13b7803efa6fc23e9823993efea5b83d60e0f43eff276c3ed453ba3e374b63bdd41502bf17e36dbe5034c53ea2ac9dbfff04903e64879e3e4c9d35bede8b6cbe435ed2be4e73abbe3020bfbef8c6e83e8630343ff9de9e3e78d65c3f3659a63eee6f35bed729b4be3954623ef8778f3ef4758fbe75fd4ebed9e3ed3e770a23be6b403ebed7e596bd656a093d6e463cbddfa103be2213f73d8a4c973d0000000050dc0bbb9d64b03d00000080d5e9283d3e429c3d1d0b3ebd35e5c03d101cacbd51b0e83dd890d5bd1378483dcc6a903d431d54bda0cab63d6376a63df1ab0a3e1a586bbd6bcfdbbd5cfb8d3db01a903dced598bdc300823d43fc3a3db75ccebdfea14a3d8f27fe3cf98c533de7d924bef762fc3df248103dde32a53d8d067e3a17bee53d5b6573bd00000080285b8b3d5cd0283d3447d93dd249c3bd00000000317f8d3db47da63df06ffebd933ca7bd3da29e3d0f9496bd7f1c6dbe2feb8abdd761863d8d3f883dc33d9abdecee903dd3ed453dc93cb4bd785f933d08c8393d5eb3f4bdef249bbd4ffb943d98be8e3d7b5487bd365bbebd103397bd19bdd2bcbc53e4bd9eb77cbd7d6fb5bdcc15713c4f00f03d54fc7e3d1c98c0bd05dd853e0dea8fbd5a2d9cbd35aa4b3d879a713df19b783d214da73d821bb73dc52889bdb707d4bdfd3d9ebdb6e53cbe1ee9a2bdc740443d3594b23de3046bbd4acb8fbdbf54943d23de5e3dbd36ddbddae5363d5155473de961aa3ed3a432be5d8e583e1d9a173f318110bfbc47aabe00000000a572363c9755c8be00000000c5235abe14fbb1be3f59573e57f8dbbe0adcc13e40d705bf1517f43eb1d467be07b3a2be40216f3eb6d9cfbe84b1bbbeba571cbf5c30843e96700c3f700eb6beee52a3bedcd6ab3eb39b93be9fd159be7524eb3efdd668beee2a1abe9dd171be0acf3d3f227e12bfbb312dbe3966bbbee3f99bbcec2f01bf2790883e0000008047ae9dbe59a438be26a4f9bedaf7f93e000000004b62a0bea849bdbe00ac123fa905d63e3e96b2bed43da93eef558d3f0c73b23e65bf96be67359abe8cc9c53e372ba4be184265becf66cb3edd11a7bed6d249be506f0d3f7429af3e0ba1a8bed2aca1becacc973e154ad73e9df5a93e53dd003e4cbd023fedc88d3e01e5cc3eff3eb3bd194d0abfa27090beb4a9d93ed0bf9dbf7c95a13e7bb5af3eb12a6bbeace488beb5419fbe86c8bebedea8d1beb735b03e6889073fb9f1b13e34835e3f7d7bb73ef8e961be08c5cabe6ff4833e956fa13e33e0a7befd926ebe6009fe3e8bc653be843b65be6a18a0bdd534f93c01fc52bd6b6f09be77e3fd3dc1c59f3d00000000e97d92bbf664b83d00000000972f193da896a43d65e754bd5e81c83d269cb4bd1d84ef3d1f11ddbd55385e3d020b993d4fdf69bd12a5be3ddd95ae3d62cb0d3e7ff87fbd7418c7bdf8ca803d1ed5983d13dea1bd480c8b3df3be503d2202d6bd540d5e3dc93e133d530d673d1b012bbe8f7c013eb79d243d9072ad3d772a273acfa6ec3d0ce383bd00000000fd56943de9119e3c0f64e03dd0cdb0bd00000080274f963deba6ae3d1c0a05be683297bd1f18a73d49b19fbdc64270be58657bbd263a8f3d374f913d63948bbda1b0993ddab55b3d7485bcbd00fc9b3df3edb03c892c00be9350a6bd25af9d3d968b973d79fe90bdeca4c9bdba46a0bddb1004bdbc84ebbde25788bd3ab0bdbda690963ccab6f63d60cc883d918ec8bd51ba873e9a3e99bdd01da5bde567613d50fd813d6981613d7163af3ddbdcbe3d473578bd8c07c0bd6924a7bd21c53fbe8ca6abbdaaf9573d158dba3d86c37fbd572399bd2a109d3d6994dc3c1e95e4bd4e1d4b3d7eca5a3d032771bdc8f5403d4b1a09bde53ceabdbfd4db3de573753d000000004909b9ba32b88f3d00000000c1c16c3d8b42803d994910bd8ba8a03dac6f8bbd482cca3db803b7bd3e900f3dbd44693d09b223bd2e39963db96c893d58fbf83dd2092ebd01b411be3149c43d891f633dd5b879bd93444b3d60e4033dfcc3aebd6c231b3de078bd3c57241d3dc16d17bed815e03d92dad63cc208853d82c1823a3acdc63d6d833ebd00000000ad06563de91bf63ca912bb3d854001be00000000941b5e3d5cd1873d744ce1bd91fce3bd57a17b3d804275bd64d465be11f8bdbdae6a583d0b73503dfc7bd1bd7155633d3e6a0c3db57194bd8eae6b3d6798093d58a9d7bdc3db71bdbd2b693d602c5f3d20c14fbd73e59cbdd53e77bdf28694bc1c71c5bd7f773ebd704a96bdd115383cf8ebd13df406403d27019fbde07f823eef7668bd4fcf7fbd6184123d9a113f3ddd37ad3dfe6a8a3dda459a3d3a30bbbdafb00cbe663c80bd0e3832be203886bdf262123d1972913df4a036bd978267bd99a5673d02f7283d6ae8bfbdd981033d3e82193df70172bdf1b33b3d2c8309bdf837ebbd4944dc3d875a763d000000001630b3baef2e903d000000008d6c663da8b4803d58ca10bd9221a13d74e08bbd7fa6ca3d338bb7bd700e103d71236a3dc13924bd00b2963d3de8893d2c6cf93d4ab12ebd894d11be9e58c13d81f0633dae8e7abd69054c3d5b51043d5d42afbdc1b21b3db199bd3cdab61d3d61aa17be7e84e03d2c57d73c907b853d18e27a3ac747c73d073e3fbd0000000013d0563d4ba4ec3cf98ebb3db3d400be0000000068ea5e3df445883d2b22e2bded78e2bd97817c3d232376bdb02f66becefebbbd053d593d6b38513d5d50cfbdab27643d1ce40c3d1ce994bdc0866c3dc167043d7161d8bd9abb72bd8c016a3ddcfa5f3d6e8650bdf66e9dbda51c78bd8b6494bc14dcc5bd07203fbd87b396bd8478363cab61d23dd8be403d137e9fbda19d833edb4969bdf35780bd9506133d4ac83f3d4157a93d2be18a3d44c19a3db553b9bd422c0cbe29ae80bd8b1f32be2ab086bd7fe6123d5ce9913d1b4c37bd253c68bdf37a683dda1d253d1866c0bd1fef033d630f1a3d55a78ebd9363e43c877813bdf06300be01e5f03d82788b3d00000000c3734fba035aa53d00000000e511873d7b68913d4e6e1cbd7718b73d813fa9bdcc68e13d5460cdbdbca5213daa5f843dade935bd383bac3d31919b3d2bf8073e69c848bd95ef2cbe5d65d83dba17833d49ee93bddd1f693de61c123dab7ac5bdd1dd2d3d5cf9643c6e50333d290923bebe38f63d2111e33cba73993d0a4b1c3aff26de3de00c5abd0000008092d2793d9b92fc3c1457d13de3451bbe00000080993e803dcd659b3d9082f7bd691808bef0f6913d51b390bdbab66cbe5acce9bda06e743dd62e733d250efbbd92ab833d46cc1d3d0c53b4bdea20873d8341113dbc72edbda26d8cbd369a873d164c813d395d75bdbe4ab3bd341392bd2d3f81bc05cadcbd939c5ebdc34eb6bd0175de3b5116e93d1b04603d00c2c2bda59a863e93b488bd09f997bda483253d75f4573dfd1ad83d23ed9c3d4bbfad3dc5f9e5bdf05c27be036399bd72e93bbe8204a0bd71d8243d7988a73d352350bdb95188bdcbd0863df73d3e3d0cbed5bd59aa133d40402b3d52f370bd85b63b3d0fd708bd723aeabdcdb1db3d87df743d000000806cedb3bad56b8f3d00000000d46d663d35e87f3d67e50fbd8859a03da22e8bbd43f6c93d37deb6bd811c0f3daeb1683d765223bdb9ef953d1c24893da7e7f83d15a22dbdd3ac11bee609c13d9f83623d703979bd21b74a3d7b7b033def92aebd70b81a3d730bbd3c5cbd1c3d0ecd17bef7f0df3d8140d63cd8b9843d1d757e3ac997c63d11023ebd00000000937d553d0e57ef3c0edaba3dc82f01be000000807c885d3ded82873d247ae1bd3436e3bd170e7b3d5ab774bd32eb68bef817bdbd6edc573ddbec4f3d4721d1bde3c1623d5ffa0b3df23994bd8a176b3d63e0053deec1d7bd7a5971bd5899683d57945e3d72434fbd92a59cbd4c9e76bde50b94bcc364c5bdab1a3ebd841a96bd88b5363cb8bbd13d548a3f3dd1e69ebd72ce833edbe867bd6f517fbda50d123dc88a3e3d8f2ba93dd51b8a3d83fc993d10a3babddc870cbe05e47fbdc04732be17f885bdfdfe113d7b27913dd82436bd100667bddb16673d808c263dbfbcbfbdfa2c033d6118193dc7b077bde7d4433ddcae0dbdc3a7efbd20dfe03dbb5f7c3d00000000603dbdbab68b933d00000080e852703d98cf833d651615bd4fbfa43dce3a8fbdd0edce3d2297bbbdfe4c143dbdf46f3de7d728bd892b9a3d092a8d3d635efe3dce9033bdcff113be186ac83d49a3693d124780bd8e56513d255a083d402eb3bde733203df262c43c6343223d04aa1abe2d29e53d0392de3cb1a9883d8ea7833ab384cb3d0e5744bd00000000d2555c3d8ed7f63caaa1bf3d462903be000000801f8e643d88808b3d81a9e6bd24a3e8bd4854813dee347cbdeafb6bbe1474c1bd62c75e3d92a6563d5559d5bda6e2693dbb14113dd06d98bd8065723d3e040a3d071cddbdc1d478bd83d76f3d8d9e653d47f855bde307a1bdaf257ebdce119abce91fcabd9f3a44bdee319abd37ff3e3ccecad63d6be6453d101fa3bd177f853e88256fbdab7483bd6e52173d12e6443da4ecaf3d32268e3d324b9e3d0603bfbd44ea0ebe44cb83bdad6235be57ee89bd933e173da14e953dd84a3cbd7c026ebd384d6e3d9d5f2b3de293c4bd3104083dbe891e3d97b16fbd8d903a3dc1e207bd7219eabdc854db3df7f4733d00000000e850b1ba61f98e3d000000005023653d9b007f3dc20d0fbd7beb9f3dfab88abdd293c93d1e74b6bdb4490e3d3bc7673d755122bd3e7e953d89af883dc493f83d8dbc2cbdcd0711be5457c03d389b613d165078bd9bcf493d41ae023d0226aebd2ddc193d9366bb3c94df1b3d008d17be2995df3d3dbcd43c3446843d9367763ad233c63da91b3dbd000000805b93543d7659ea3c8b72ba3d3a4100be00000080009f5c3dc40f873d922ce1bd32cce0bdcc237a3df4cb73bd988d68bef1ddbabdc7f2563d12034f3d497ccebd01d8613dde280b3d17c693bdf72d6a3dd434033d60b6d7bdb06b70bddbae673d96ab5d3d24584ebdc2339cbdb0b675bd189c92bc81e0c4bd3e2b3dbdbd8e95bd1ac1343c405bd13dbca23e3d396f9ebda2b7833e68ff66bd3d687ebd9a39113d03a53d3df37fa83d74a9893df58c993d4e6db8bdf6030cbedcfa7ebd142532be818285bd7426113d02b5903d4d4035bd28f265bdd02b663da385233d2056bfbd115b023db03c183db67f6bbd2238373dd9f904bd22b7e6bd6a08d83dee556f3d00000000ade0acba75698c3d00000000f81e613d4b3c7a3de7e50bbd952b9d3da23788bdd76dc63d2d7cb3bd59220b3d7e4f633d7cf91ebde1db923d2333863dd90ef53dfb1b29bd309d0fbe4f9dbd3d9c365d3d57a273bd67be453d2576ff3c0b43abbde685163d9d25b73c9e81183dc2bb15be5940dc3dd0c4cf3cd1d5813da770743ad315c33df03939bd00000080845d503d6a53e83ccd6fb73da62cfebd00000080394c583db596843d6201debd1f8fdfbd2971753d652e6fbd538966be80adb9bdc0b3523dd9e04a3ddf6dcdbdbf735d3d780f083d5d2a91bd6ead653d6e14023d8e3fd4bd8fda6bbd9f37633dc054593d64394abd3a8099bd5d0f71bd21308fbccde4c1bdbb5139bd100693bdb242303c8a24ce3d22bc3a3dc7bb9bbdb39e823e728962bd89a779bd5f050e3d61c0393db4f7a53d2828873d21de963dd6f4b6bd38820abe1b387abd071b30be521083bd6bf50d3d5f208e3d217c31bd92a961bd07ba613dbd25223d3f48bcbd38d9fe3c41ed143dd523d63e2f30a6be5ce7723ed5b3503f886143bf5a97d9be00000000c1361f3cccf6febe00000000c6a7ccbe1e6ae3be53717f3e548d0ebf056cf73e199933bf669a223feb077ebe93bfcebea700913e864805bf36c6f3be43625dbfe4309a3e1cd6843f05862bbfa03fc9be5676dd3e6810b4be955869be71381b3f575a89be84a727be4f278bbe140b873fb12947bf300e3ebed7eaebbe6f18e1bb9c9930bf87c0a83e00000080a1a9bdbe755354be942526bf6d1c6c3f0000008047d1c4be18e0f0be20e6483f35e1493fbe1adfbe1a73d93e563bcf3fc2fb273f6dc3bfbe63b5b8bec4753a3f2078c9be5a7578bef4c2033f06e3d0beea966dbe5368403f7778d63e0baccebe57bfc5be121fb83eee420b3f4424db3e763c033e51892f3ffbd8a83e686e053fdedaa1bd5d843abfda1faabe45450d3f5488eabf600cce3e4ce3e23ed6a181be523aa9be643b16bf1a7ff5be76e208bf7cdd253f4b25803f6a67e33e789a9e3fe61fee3e8b9781bea90601bfbac0a13ead42cd3e5d54cdbe8fe093be127f2a3fccd368be1ee887be106a0c3eeee1893e82029f3d5725303e5642663f3d48ee3e04d172bdd485bc3d3547ff3ebf8421bebc6bdd3e023dcb3e23feb53e08b1363fd7ad833e92133b3f3091903e0fafc13f51adf03e4b2e0c3e6612e43e92e1dd3e0d091e3fb063833e89ea713e2698003ff850313fb951543ede510b3feed7bd3ff97d843ee29fd73e0161653eeff1ad3e7755773e09023e3ffd34bd3ebdd90e3f0fa2503eee46033feb2b833eef03febd8727d83e8ae5a83f665d0a3f17b35d3ed825d5bba70bf43e5126033f1900253e8a569a3e88b7ba3e7c70703eb6557e3ec9ba7d3e7c13ae3e5830d03ecc7b683e5adeee3ec9c7b83f2190693e9937bc3e9a92b03f24c51b3e101df53d7e77e33eff50233fd3666b3edf57163eee32983e5416253eee1e513e11fe1f3ecdef4e3ef340053e45e4273f99bccd3eb76e623e886d9e3f8fbd5a3eb44f543e27dbc33fd1e4d63eea1a123f46521a3f75a2083fdbf8533e77cf6c3e0bdb8a3eec4fc83e2d98653ec5310c3f5ec9ea3e3bf2513e3fb13f3e7277c13edbe3bf3ea6c69e3ea869d03eee4ba73eb83d76be0000803f
+\ No newline at end of file
+diff --git a/gcc/opts-global.cc b/gcc/opts-global.cc
+index a18c76940..e684bc5e3 100644
+--- a/gcc/opts-global.cc
++++ b/gcc/opts-global.cc
+@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "attribs.h"
+ #include "asan.h"
+ #include "file-prefix-map.h" /* add_*_prefix_map()  */
++#include "ai4c-infer.h"
+ 
+ typedef const char *const_char_p; /* For DEF_VEC_P.  */
+ 
+@@ -304,6 +305,15 @@ decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
+ 		location_t loc, diagnostic_context *dc,
+ 		void (*target_option_override_hook) (void))
+ {
++  set_cache_info (global_options.x_param_simultaneous_prefetches,
++		  global_options.x_param_l1_cache_size,
++		  global_options.x_param_l1_cache_line_size,
++		  global_options.x_param_l2_cache_size,
++		  global_options.x_param_prefetch_latency,
++		  global_options.x_param_ipa_prefetch_distance_factor);
++  const char *tune_native = getenv ("GCC_AI4C_TUNE_INFO");
++  prepare_native_tune_str (tune_native);
++
+   struct cl_option_handlers handlers;
+ 
+   unsigned int lang_mask;
+-- 
+2.33.0
+
diff --git a/0317-Bugfix-set-default-value-when-tune_native-is-NULL.patch b/0317-Bugfix-set-default-value-when-tune_native-is-NULL.patch
new file mode 100644
index 0000000..92f10c2
--- /dev/null
+++ b/0317-Bugfix-set-default-value-when-tune_native-is-NULL.patch
@@ -0,0 +1,27 @@
+From bc468838ffa1991e50cb4b82b45154d44302417b Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Tue, 3 Dec 2024 22:39:36 +0800
+Subject: [PATCH 5/5] Bugfix: set default value when tune_native is NULL.
+
+---
+ gcc/gcc.cc | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index 0032735db..90f6dfe85 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -5800,6 +5800,10 @@ do_self_spec (const char *spec)
+   do_spec_1 (" ", 0, NULL);
+ 
+   const char* tune_native = eval_spec_function ("local_cpu_detect", "cpu", "");
++  if (tune_native == NULL)
++    {
++      tune_native = "native";
++    }
+   setenv ("GCC_AI4C_TUNE_INFO", tune_native, 1);
+ 
+   /* Mark %
+Date: Wed, 11 Sep 2024 17:27:19 +0800
+Subject: [PATCH 4/5] add flag -flto-try enable LTO and automatically skip in
+ inapplicable situation.
+
+---
+ gcc/collect2.cc    | 51 ++++++++++++++++++++++++++++++++++++++++++-
+ gcc/common.opt     |  8 +++++++
+ gcc/opts-common.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++-
+ gcc/opts.cc        | 20 +++++++++++++++++
+ 4 files changed, 131 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/collect2.cc b/gcc/collect2.cc
+index 9715e8eee..690363880 100644
+--- a/gcc/collect2.cc
++++ b/gcc/collect2.cc
+@@ -200,6 +200,7 @@ static enum lto_mode_d lto_mode = LTO_MODE_WHOPR;
+ #else
+ static enum lto_mode_d lto_mode = LTO_MODE_NONE;
+ #endif
++static bool maybe_relink_without_lto = false;
+ 
+ bool helpflag;			/* true if --help */
+ 
+@@ -751,7 +752,53 @@ do_link (char **ld_argv, const char *atsuffix)
+ 			 PEX_LAST | PEX_SEARCH,
+ 			 HAVE_GNU_LD && at_file_supplied, atsuffix);
+   int ret = collect_wait (prog, pex);
+-  if (ret)
++  if (ret && maybe_relink_without_lto)
++    {
++      bool link_with_lto_plugin_before = false;
++      for (int i = 0, j = -1; ld_argv[i]; ++i)
++	{
++	  if (endswith (ld_argv[i], "liblto_plugin.so"))
++	    {
++	      link_with_lto_plugin_before = true;
++	      for (j = i + 1; ld_argv[j]; ++j)
++		{
++		  if (!startswith (ld_argv[j], "-plugin-opt="))
++		    break;
++		}
++	      for (i = i - 1; ; ++i, ++j)
++		{
++		  ld_argv[i] = ld_argv[j];
++		  if (ld_argv[j] == NULL)
++		    break;
++		}
++	      break;
++	    }
++	}
++      int ret2 = 0;
++      if (link_with_lto_plugin_before)
++	{
++	  fprintf (stderr, "lto link fail, relinking without lto");
++	  lto_mode = LTO_MODE_NONE;
++	  pex = collect_execute (prog, ld_argv, NULL, NULL,
++				 PEX_LAST | PEX_SEARCH,
++				 HAVE_GNU_LD && at_file_supplied, atsuffix);
++	  ret2 = collect_wait (prog, pex);
++	}
++      else
++	  ret2 = ret;
++      if (ret2)
++	{
++	  error ("ld returned %d exit status", ret);
++	  exit (ret);
++	}
++      else
++	{
++	  /* We have just successfully produced an output file, so assume that
++	   we may unlink it if need be for now on.  */
++	  may_unlink_output_file = true;
++	}
++    }
++  else if (ret)
+     {
+       error ("ld returned %d exit status", ret);
+       exit (ret);
+@@ -1009,6 +1056,8 @@ main (int argc, char **argv)
+ 	  num_c_args++;
+ 	if (startswith (q, "-flto-partition=none"))
+ 	  no_partition = true;
++	else if (startswith (q, "-flto-try"))
++	  maybe_relink_without_lto = true;
+ 	else if (startswith (q, "-fno-lto"))
+ 	  lto_mode = LTO_MODE_NONE;
+ 	else if (startswith (q, "-save-temps"))
+diff --git a/gcc/common.opt b/gcc/common.opt
+index 96888cf1b..0895c6114 100644
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -70,6 +70,10 @@ bool flag_warn_unused_result = false
+ Variable
+ int flag_generate_lto
+ 
++; Nonzero if we should write GIMPLE bytecode for link-time optimization.
++Variable
++int flag_relink_whthout_lto = 0
++
+ ; Nonzero if we should write GIMPLE bytecode for offload compilation.
+ Variable
+ int flag_generate_offload = 0
+@@ -2161,6 +2165,10 @@ flto
+ Common
+ Enable link-time optimization.
+ 
++flto-try
++Common Var(flag_lto_try) Init(0)
++Do link-time optimization as much as possible.
++
+ flto=
+ Common RejectNegative Joined Var(flag_lto)
+ Link-time optimization with number of parallel jobs or jobserver.
+diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
+index 33c696f3d..176041bfe 100644
+--- a/gcc/opts-common.cc
++++ b/gcc/opts-common.cc
+@@ -1162,7 +1162,50 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv,
+   struct cl_decoded_option *opt_array;
+   unsigned int num_decoded_options;
+ 
+-  int opt_array_len = argc;
++  enum LTO_SKIP_STAT
++    {
++      NO_NEED_TO_SKIP,
++      NEED_TO_SKIP,
++      ALREADY_SKIP,
++    };
++  LTO_SKIP_STAT lto_skip_stat = NO_NEED_TO_SKIP;
++  bool try_use_lto = false;
++  const char* lto_option_conflict = NULL;
++  const char* wrap_option = "-Wl,--wrap=";
++  const char* start_lib_option = "-Wl,--start-lib";
++  for (i = 1; i < argc; i += 1)
++    {
++      if (startswith (argv[i], "-flto-try"))
++	{
++	  try_use_lto = true;
++	}
++
++      if (startswith (argv[i], wrap_option)
++      	  && (lto_skip_stat == NO_NEED_TO_SKIP))
++	{
++	  lto_option_conflict = wrap_option;
++	  lto_skip_stat = NEED_TO_SKIP;
++	}
++      else if (startswith (argv[i], start_lib_option)
++	       && (lto_skip_stat == NO_NEED_TO_SKIP))
++	{
++	  lto_option_conflict = start_lib_option;
++	  lto_skip_stat = NEED_TO_SKIP;
++	}
++      else if (startswith (argv[i], "-fno-lto"))
++	{
++	  lto_option_conflict = NULL;
++	  lto_skip_stat = ALREADY_SKIP;
++	  break;
++	}
++    }
++  if (!try_use_lto)
++    {
++      lto_skip_stat = NO_NEED_TO_SKIP;
++      lto_option_conflict = NULL;
++    }
++
++  int opt_array_len = lto_skip_stat == NEED_TO_SKIP ? argc + 1 : argc;
+   opt_array = XNEWVEC (struct cl_decoded_option, opt_array_len);
+ 
+   opt_array[0].opt_index = OPT_SPECIAL_program_name;
+@@ -1244,6 +1287,15 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv,
+   num_decoded_options += handle_machine_option (lang_mask, num_decoded_options,
+ 						argc, argv, opt_array);
+ 
++  if (lto_skip_stat == NEED_TO_SKIP)
++    {
++      const char * nolto = "-fno-lto";
++      fprintf (stderr, "skip lto for %s\n", lto_option_conflict);
++      decode_cmdline_option (&nolto, lang_mask,
++      			     &opt_array[num_decoded_options]);
++      num_decoded_options++;
++    }
++
+   *decoded_options = opt_array;
+   *decoded_options_count = num_decoded_options;
+   prune_options (decoded_options, decoded_options_count, lang_mask);
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 84dd8925a..9ccc22510 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -1143,6 +1143,26 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
+       SET_OPTION_IF_UNSET (opts, opts_set, param_stack_frame_growth, 40);
+     }
+ 
++  if (opts->x_flag_lto_try)
++    {
++#ifdef ENABLE_LTO
++      if (opts_set->x_flag_lto && opts->x_flag_lto)
++	{
++	  inform (loc, "%<-flto-try%> don't guarantee that lto "
++	  	  "will be enabled.");
++	}
++      opts->x_flag_lto = "";
++      if (opts_set->x_flag_fat_lto_objects && !opts->x_flag_fat_lto_objects)
++	{
++	  error_at (loc, "%<-flto-try%> are not supported with "
++	  	    "-fno-fat-lto-objects");
++	}
++      opts->x_flag_fat_lto_objects = 1;
++#else
++      error_at (loc, "LTO support has not been enabled in this configuration");
++#endif
++    }
++
+   if (opts->x_flag_lto)
+     {
+ #ifdef ENABLE_LTO
+-- 
+2.33.0
+
diff --git a/0319-CSPGO-fix-bugs-when-using-cspgo.patch b/0319-CSPGO-fix-bugs-when-using-cspgo.patch
new file mode 100644
index 0000000..bd86bb8
--- /dev/null
+++ b/0319-CSPGO-fix-bugs-when-using-cspgo.patch
@@ -0,0 +1,140 @@
+From 610470b1892213afd4ddcf83862667c758724872 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Wed, 4 Dec 2024 16:25:01 +0800
+Subject: [PATCH] [CSPGO] fix bugs when using cspgo
+
+---
+ gcc/opts.cc         | 36 ++++++++++++++++++++++++++----------
+ gcc/tree-profile.cc | 20 ++++++++++++++++++++
+ 2 files changed, 46 insertions(+), 10 deletions(-)
+
+diff --git a/gcc/opts.cc b/gcc/opts.cc
+index 6ca9dde7e..2433ace06 100644
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "diagnostic-color.h"
+ #include "version.h"
+ #include "selftest.h"
++#include "ai4c-infer.h"
+ 
+ /* In this file all option sets are explicit.  */
+ #undef OPTION_SET_P
+@@ -3086,17 +3087,28 @@ common_handle_option (struct gcc_options *opts,
+       break;
+ 
+     case OPT_fcfgo_profile_use_:
++      opts->x_profile_data_prefix = xstrdup (arg);
++      opts->x_flag_profile_use = true;
++      value = true;
+       /* No break here - do -fcfgo-profile-use processing.  */
+       /* FALLTHRU */
+     case OPT_fcfgo_profile_use:
+-      value = true;
+-      if (value)
++      if (get_optimize_decision_from_ai4c ())
+ 	{
++	  value = true;
+ 	  enable_cfgo_optimizations (opts, opts_set, value);
+ 	  SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_use, value);
++	  /* Enable orig fdo optimizations.  */
++	  enable_fdo_optimizations (opts, opts_set, value);
++	  SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_reorder_functions,
++			       value);
++	  /* Indirect call profiling should do all useful transformations
++	     speculative devirtualization does.  */
++	  if (opts->x_flag_value_profile_transformations)
++	    SET_OPTION_IF_UNSET (opts, opts_set, flag_devirtualize_speculatively,
++				 false);
+ 	}
+-      /* No break here - do -fprofile-use processing.  */
+-      /* FALLTHRU */
++      break;
+     case OPT_fprofile_use_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+       opts->x_flag_profile_use = true;
+@@ -3116,10 +3128,10 @@ common_handle_option (struct gcc_options *opts,
+ 
+     case OPT_fcfgo_csprofile_use_:
+       opts->x_csprofile_data_prefix = xstrdup (arg);
+-      value = true;
+       /* No break here - do -fcfgo-csprofile-use processing.  */
+       /* FALLTHRU */
+     case OPT_fcfgo_csprofile_use:
++      value = get_optimize_decision_from_ai4c ();
+       SET_OPTION_IF_UNSET (opts, opts_set, flag_csprofile_use, value);
+       break;
+ 
+@@ -3155,18 +3167,22 @@ common_handle_option (struct gcc_options *opts,
+       break;
+ 
+     case OPT_fcfgo_profile_generate_:
++      opts->x_profile_data_prefix = xstrdup (arg);
++      value = true;
+       /* No break here - do -fcfgo-profile-generate processing.  */
+       /* FALLTHRU */
+     case OPT_fcfgo_profile_generate:
+-      value = true;
+-      if (value)
++      if (get_optimize_decision_from_ai4c ())
+ 	{
+ 	  enable_cfgo_optimizations (opts, opts_set, value);
+ 	  SET_OPTION_IF_UNSET (opts, opts_set, flag_cfgo_profile_generate,
+ 			       value);
+ 	}
+-      /* No break here - do -fprofile-generate processing.  */
+-      /* FALLTHRU */
++      SET_OPTION_IF_UNSET (opts, opts_set, profile_arc_flag, value);
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value);
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value);
++      SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
++      break;
+     case OPT_fprofile_generate_:
+       opts->x_profile_data_prefix = xstrdup (arg);
+       value = true;
+@@ -3181,10 +3197,10 @@ common_handle_option (struct gcc_options *opts,
+ 
+     case OPT_fcfgo_csprofile_generate_:
+       opts->x_csprofile_data_prefix = xstrdup (arg);
+-      value = true;
+       /* No break here - do -fcfgo-csprofile-generate processing.  */
+       /* FALLTHRU */
+     case OPT_fcfgo_csprofile_generate:
++      value = get_optimize_decision_from_ai4c ();
+       SET_OPTION_IF_UNSET (opts, opts_set, flag_csprofile_generate, value);
+       break;
+ 
+diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
+index aa3a2b3a9..ace1fe31c 100644
+--- a/gcc/tree-profile.cc
++++ b/gcc/tree-profile.cc
+@@ -1114,6 +1114,26 @@ public:
+      to do anything.  */
+   virtual unsigned int execute (function *)
+     {
++      if (!profile_data_prefix)
++	error ("profile_data_prefix must set when using cspgo.");
++
++      if (!csprofile_data_prefix)
++	error ("csprofile_data_prefix must set when using cspgo.");
++
++      if (!flag_cfgo_profile_use)
++	error ("cspgo must used with cfgo-pgo.");
++
++      /* Just compare canonical pathnames.  */
++      char* cfgo_pgo_path = lrealpath (profile_data_prefix);
++      char* cfgo_cspgo_path = lrealpath (csprofile_data_prefix);
++      bool files_differ = filename_cmp (cfgo_pgo_path, cfgo_cspgo_path);
++      if (!files_differ)
++	{
++	  error ("pgo and cspgo path must different between %s and %s",
++		 cfgo_pgo_path, cfgo_cspgo_path);
++	}
++      free (cfgo_pgo_path);
++      free (cfgo_cspgo_path);
+       return 0;
+     }
+ 
+-- 
+2.25.1
+
diff --git a/0320-if-split-fix-bugs.patch b/0320-if-split-fix-bugs.patch
new file mode 100644
index 0000000..c8b97eb
--- /dev/null
+++ b/0320-if-split-fix-bugs.patch
@@ -0,0 +1,105 @@
+From 7636e8782aa0dac322c22631c4cd0b60c0eb1842 Mon Sep 17 00:00:00 2001
+From: Zinin Ivan WX1305386 
+Date: Tue, 3 Dec 2024 16:02:15 +0300
+Subject: [PATCH] Fix bugs
+
+Added check if then_bb got single succ in process_complex_cond()
+
+Made processing of cases when then_bb is pred of EXIT and got
+return statement inside. Splitting of edge from EXIT pred to
+EXIT deletes return statement, and duplication of then_bb will
+got no return statement too. So in such cases we need to build
+return statement in merge_bb by ourselves.
+---
+ gcc/gimple-if-split.cc | 35 +++++++++++++++++++++++++++++++++--
+ 1 file changed, 33 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/gimple-if-split.cc b/gcc/gimple-if-split.cc
+index 3446204ea..351515435 100644
+--- a/gcc/gimple-if-split.cc
++++ b/gcc/gimple-if-split.cc
+@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "tree-cfg.h"
+ #include "bitmap.h"
+ #include "cfganal.h"
++#include "cfgloop.h"
+ 
+ /* Perform splitting if-then-else patterns, whose complex OR condition in
+ cond-bb contains comparison of some variable with constant and then-bb got
+@@ -255,6 +256,7 @@ process_complex_cond (basic_block cond_bb, basic_block then_bb,
+   cond_parts_defs defs;
+ 
+   if (!can_duplicate_block_p (then_bb)
++      || !single_succ_p (then_bb)
+       || !necessary_complex_cond_p (cond, then_bb, &defs))
+     return;
+ 
+@@ -345,14 +347,39 @@ static basic_block
+ make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
+ 			 basic_block then_bb)
+ {
+-  if (!can_duplicate_block_p (then_bb) || EDGE_COUNT (then_bb->succs) != 1)
++  if (!can_duplicate_block_p (then_bb) || !single_succ_p (then_bb))
+     return NULL;
+ 
+   edge outer_then_e = find_edge (outer_cond_bb, then_bb);
+ 
+   /* Making duplication of then_bb.  */
+   basic_block then_bb_dom = get_immediate_dominator (CDI_DOMINATORS, then_bb);
++
++  /* Saving ret_value and then_bb succ edge flags, if then_bb is pred of
++   * EXIT_BLOCK and has return statement inside.  */
++  tree ret_val;
++  int then_bb_succ_edge_flags;
++  if (single_succ (then_bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
++    {
++      gcc_assert (gimple_code (last_stmt (then_bb)) == GIMPLE_RETURN);
++      ret_val = gimple_return_retval (as_a(last_stmt (then_bb)));
++
++      then_bb_succ_edge_flags = single_succ_edge (then_bb)->flags;
++    }
++
+   basic_block merge_bb = split_edge (single_succ_edge (then_bb));
++
++  /* Building return statement in merge_bb and setting merge_bb succ edge flags,
++   * if now merge_bb is pred of EXIT_BLOCK.  */
++  if (single_succ (merge_bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
++    {
++      gimple* ret = gimple_build_return (ret_val);
++      gimple_stmt_iterator gsi = gsi_last_bb (merge_bb);
++      gsi_insert_after (&gsi, ret, GSI_NEW_STMT);
++
++      single_succ_edge (merge_bb)->flags = then_bb_succ_edge_flags;
++    }
++
+   basic_block then_bb1 = duplicate_block (then_bb, outer_then_e, outer_cond_bb);
+   edge outer_then1_e = find_edge (outer_cond_bb, then_bb1);
+ 
+@@ -372,6 +399,9 @@ make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
+   set_immediate_dominator (CDI_POST_DOMINATORS, merge_bb,
+ 			   single_succ (merge_bb));
+ 
++  if (get_immediate_dominator (CDI_POST_DOMINATORS, outer_cond_bb) == then_bb)
++     set_immediate_dominator (CDI_POST_DOMINATORS, outer_cond_bb, merge_bb);
++
+   return then_bb1;
+ }
+ 
+@@ -548,6 +578,7 @@ pass_if_split::execute (function *fun)
+ 
+   checking_verify_ssa (true, true);
+   checking_verify_flow_info ();
++  checking_verify_loop_structure ();
+   checking_verify_dominators (CDI_DOMINATORS);
+   checking_verify_dominators (CDI_POST_DOMINATORS);
+ 
+@@ -564,4 +595,4 @@ gimple_opt_pass *
+ make_pass_if_split (gcc::context *ctxt)
+ {
+   return new pass_if_split (ctxt);
+-}
+\ No newline at end of file
++}
+-- 
+2.33.0
+
diff --git a/0321-Struct-reorg-Avoid-doing-struct-split-and-reorder_fi.patch b/0321-Struct-reorg-Avoid-doing-struct-split-and-reorder_fi.patch
new file mode 100644
index 0000000..8f94975
--- /dev/null
+++ b/0321-Struct-reorg-Avoid-doing-struct-split-and-reorder_fi.patch
@@ -0,0 +1,192 @@
+From a96315832872aae9af8ff3f81100b21e82c94072 Mon Sep 17 00:00:00 2001
+From: liyancheng <412998149@qq.com>
+Date: Sat, 7 Dec 2024 16:27:28 +0800
+Subject: [PATCH 1/2] [Struct-reorg] Avoid doing struct split and
+ reorder_fields together
+
+Rewrite between struct_split and reorder_fields is
+incompatible, so avoid doing them together.
+---
+ gcc/ipa-struct-reorg/ipa-struct-reorg.cc      |   7 +-
+ .../struct/rf_rewrite_problem_with_split.c    | 134 ++++++++++++++++++
+ gcc/testsuite/gcc.dg/struct/struct-reorg.exp  |   4 +
+ 3 files changed, 143 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/struct/rf_rewrite_problem_with_split.c
+
+diff --git a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+index b93b8a5b5..af91f15c5 100644
+--- a/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
++++ b/gcc/ipa-struct-reorg/ipa-struct-reorg.cc
+@@ -8646,8 +8646,11 @@ public:
+ 
+     if (level >= COMPLETE_STRUCT_RELAYOUT)
+       {
+-	/* Preserved for backward compatibility.  */
+-	ret_reorg = ipa_struct_reorg ().execute (STRUCT_SPLIT);
++	/* Preserved for backward compatibility.
++	   Rewrite between STRUCT_REORDER_FIELDS and STRUCT_SPLIT has unfixed
++	   problem, so avoid using them together.  */
++	if (!ret)
++	  ret_reorg = ipa_struct_reorg ().execute (STRUCT_SPLIT);
+ 	if (!ret_reorg)
+ 	  ret_reorg = ipa_struct_reorg ().execute (COMPLETE_STRUCT_RELAYOUT);
+       }
+diff --git a/gcc/testsuite/gcc.dg/struct/rf_rewrite_problem_with_split.c b/gcc/testsuite/gcc.dg/struct/rf_rewrite_problem_with_split.c
+new file mode 100644
+index 000000000..da357ec18
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/struct/rf_rewrite_problem_with_split.c
+@@ -0,0 +1,134 @@
++/* { dg-do run } */
++#include "stdio.h"
++#include "stdlib.h"
++#include "time.h"
++#include "string.h"
++#include "limits.h"
++#include "float.h"
++#define JOTAI_NUM_RANDS_ 25
++const unsigned rand_primes[JOTAI_NUM_RANDS_] = {179, 103, 479, 647, 229, 37,
++271, 557, 263, 607, 18743, 50359, 21929, 48757, 98179, 12907, 52937, 64579,
++49957, 52567, 507163, 149939, 412157, 680861, 757751};
++int next_i() {
++  int counter = 0;
++  return rand_primes[(++counter)%JOTAI_NUM_RANDS_];
++}
++typedef unsigned long size_t;  // Customize by platform.
++typedef long intptr_t; typedef unsigned long uintptr_t;
++typedef long scalar_t__;  // Either arithmetic or pointer type.
++typedef int bool;
++#define false 0
++#define true 1
++typedef  struct TYPE_2__   TYPE_1__;
++struct pci_dev {int devfn; TYPE_1__* sriov; int /*<<< orphan*/  is_physfn; };
++struct TYPE_2__ {int offset; int stride; } ;
++int EINVAL ;
++int pci_iov_virtfn_devfn(struct pci_dev *dev, int vf_id)
++{
++  if (!dev->is_physfn)
++    return -EINVAL;
++  return (dev->devfn + dev->sriov->offset +
++    dev->sriov->stride * vf_id) & 0xff;
++}
++int main(int argc, char *argv[]) {
++  int opt = 1;
++  switch(opt) {
++  case 0:
++  {
++    int vf_id = 100;
++    int _len_dev0 = 1;
++    struct pci_dev * dev =
++      (struct pci_dev *) malloc(_len_dev0*sizeof(struct pci_dev));
++    for(int _i0 = 0; _i0 < _len_dev0; _i0++) {
++      dev[_i0].devfn = ((-2 * (next_i()%2)) + 1) * next_i();
++      int _len_dev__i0__sriov0 = 1;
++      dev[_i0].sriov =
++      (struct TYPE_2__ *) malloc(_len_dev__i0__sriov0*sizeof(struct TYPE_2__));
++      for(int _j0 = 0; _j0 < _len_dev__i0__sriov0; _j0++) {
++	dev[_i0].sriov->offset = ((-2 * (next_i()%2)) + 1) * next_i();
++	dev[_i0].sriov->stride = ((-2 * (next_i()%2)) + 1) * next_i();
++      }
++      dev[_i0].is_physfn = ((-2 * (next_i()%2)) + 1) * next_i();
++    }
++    int benchRet = pci_iov_virtfn_devfn(dev,vf_id);
++    printf("%d\n", benchRet); 
++    for(int _aux = 0; _aux < _len_dev0; _aux++) {
++      free(dev[_aux].sriov);
++    }
++    free(dev);
++    break;
++  }
++  case 1:
++  {
++    int vf_id = 255;
++    int _len_dev0 = 65025;
++    struct pci_dev * dev = (struct pci_dev *) malloc(_len_dev0*sizeof(struct pci_dev));
++    for(int _i0 = 0; _i0 < _len_dev0; _i0++) {
++      dev[_i0].devfn = ((-2 * (next_i()%2)) + 1) * next_i();
++      int _len_dev__i0__sriov0 = 1;
++      dev[_i0].sriov = (struct TYPE_2__ *) malloc(_len_dev__i0__sriov0*sizeof(struct TYPE_2__));
++      for(int _j0 = 0; _j0 < _len_dev__i0__sriov0; _j0++) {
++	dev[_i0].sriov->offset = ((-2 * (next_i()%2)) + 1) * next_i();
++      dev[_i0].sriov->stride = ((-2 * (next_i()%2)) + 1) * next_i();
++      }
++      dev[_i0].is_physfn = ((-2 * (next_i()%2)) + 1) * next_i();
++    }
++    int benchRet = pci_iov_virtfn_devfn(dev,vf_id);
++    printf("%d\n", benchRet); 
++    for(int _aux = 0; _aux < _len_dev0; _aux++) {
++      free(dev[_aux].sriov);
++    }
++    free(dev);
++    break;
++  }
++  case 2:
++  {
++    int vf_id = 10;
++    int _len_dev0 = 100;
++    struct pci_dev * dev = (struct pci_dev *) malloc(_len_dev0*sizeof(struct pci_dev));
++    for(int _i0 = 0; _i0 < _len_dev0; _i0++) {
++      dev[_i0].devfn = ((-2 * (next_i()%2)) + 1) * next_i();
++      int _len_dev__i0__sriov0 = 1;
++      dev[_i0].sriov = (struct TYPE_2__ *) malloc(_len_dev__i0__sriov0*sizeof(struct TYPE_2__));
++      for(int _j0 = 0; _j0 < _len_dev__i0__sriov0; _j0++) {
++	dev[_i0].sriov->offset = ((-2 * (next_i()%2)) + 1) * next_i();
++	dev[_i0].sriov->stride = ((-2 * (next_i()%2)) + 1) * next_i();
++      }
++      dev[_i0].is_physfn = ((-2 * (next_i()%2)) + 1) * next_i();
++    }
++    int benchRet = pci_iov_virtfn_devfn(dev,vf_id);
++    printf("%d\n", benchRet); 
++    for(int _aux = 0; _aux < _len_dev0; _aux++) {
++      free(dev[_aux].sriov);
++    }
++    free(dev);
++    break;
++  }
++  case 3:
++  {
++    int vf_id = ((-2 * (next_i()%2)) + 1) * next_i();
++    int _len_dev0 = 1;
++    struct pci_dev * dev = (struct pci_dev *) malloc(_len_dev0*sizeof(struct pci_dev));
++    for(int _i0 = 0; _i0 < _len_dev0; _i0++) {
++      dev[_i0].devfn = ((-2 * (next_i()%2)) + 1) * next_i();
++      int _len_dev__i0__sriov0 = 1;
++      dev[_i0].sriov = (struct TYPE_2__ *) malloc(_len_dev__i0__sriov0*sizeof(struct TYPE_2__));
++      for(int _j0 = 0; _j0 < _len_dev__i0__sriov0; _j0++) {
++	dev[_i0].sriov->offset = ((-2 * (next_i()%2)) + 1) * next_i();
++	dev[_i0].sriov->stride = ((-2 * (next_i()%2)) + 1) * next_i();
++      }
++      dev[_i0].is_physfn = ((-2 * (next_i()%2)) + 1) * next_i();
++    }
++    int benchRet = pci_iov_virtfn_devfn(dev,vf_id);
++    printf("%d\n", benchRet); 
++    for(int _aux = 0; _aux < _len_dev0; _aux++) {
++      free(dev[_aux].sriov);
++    }
++    free(dev);
++    break;
++  }
++  default:
++    break;
++  }
++  return 0;
++}
+\ No newline at end of file
+diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+index 687f6609f..1ef26229a 100644
+--- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
++++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp
+@@ -43,6 +43,10 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/csr_*.c]] \
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/rf_*.c]] \
+ 	"" "-fipa-reorder-fields -fdump-ipa-all -flto-partition=one -fwhole-program"
+ 
++# -fipa-struct-reorg=2
++gcc-dg-runtest $srcdir/$subdir/rf_rewrite_problem_with_split.c \
++	"" "-fipa-struct-reorg=2 -fdump-ipa-all -flto-partition=one -fwhole-program"
++
+ # -fipa-struct-reorg=3
+ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/dfe*.c]] \
+ 	"" "-fipa-struct-reorg=3 -fdump-ipa-all -flto-partition=one -fwhole-program"
+-- 
+2.25.1
+
diff --git a/0322-Bugfix-Create-POINTER_PLUS_EXPR-for-REFERENCE_TYPE.patch b/0322-Bugfix-Create-POINTER_PLUS_EXPR-for-REFERENCE_TYPE.patch
new file mode 100644
index 0000000..b832c90
--- /dev/null
+++ b/0322-Bugfix-Create-POINTER_PLUS_EXPR-for-REFERENCE_TYPE.patch
@@ -0,0 +1,26 @@
+From 2c98e0ecaf06bd1ab4b77c85fea6098bfa0b201b Mon Sep 17 00:00:00 2001
+From: Generalov Vasilii WX1339879 
+Date: Wed, 4 Dec 2024 14:41:24 +0300
+Subject: [PATCH 2/2] [Bugfix] Create POINTER_PLUS_EXPR for REFERENCE_TYPE
+
+---
+ gcc/ipa-prefetch.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/ipa-prefetch.cc b/gcc/ipa-prefetch.cc
+index 685f9c267..220287d66 100644
+--- a/gcc/ipa-prefetch.cc
++++ b/gcc/ipa-prefetch.cc
+@@ -2171,7 +2171,8 @@ optimize_function (cgraph_node *n, function *fn)
+     }
+   tree var_type = TREE_TYPE (inc_var);
+   enum tree_code inc_code;
+-  if (TREE_CODE (var_type) == POINTER_TYPE)
++  enum tree_code var_code = TREE_CODE (var_type);
++  if (var_code == POINTER_TYPE || var_code == REFERENCE_TYPE)
+     inc_code = POINTER_PLUS_EXPR;
+   else
+     inc_code = PLUS_EXPR;
+-- 
+2.25.1
+
diff --git a/0323-Bugfix-replace-tmp-pattern-split.patch b/0323-Bugfix-replace-tmp-pattern-split.patch
new file mode 100644
index 0000000..2a6d10e
--- /dev/null
+++ b/0323-Bugfix-replace-tmp-pattern-split.patch
@@ -0,0 +1,50 @@
+From d10807504a7f4e58a7dd1fa245d0ccf16227d222 Mon Sep 17 00:00:00 2001
+From: Chernonog Viacheslav 
+Date: Wed, 4 Dec 2024 20:07:23 +0800
+Subject: [PATCH] [Bugfix] replace tmp pattern split
+
+move split before reload
+change split tmp pattern to 3 instructions
+---
+ gcc/config/aarch64/aarch64-simd.md | 19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
+index 04592fc90..fb5e355d0 100644
+--- a/gcc/config/aarch64/aarch64-simd.md
++++ b/gcc/config/aarch64/aarch64-simd.md
+@@ -6566,18 +6566,25 @@
+ 	    (match_operand:VDQHSD 1 "register_operand" "w")
+ 	    (match_operand:VDQHSD 2 "half_size_minus_one_operand"))
+ 	  (match_operand:VDQHSD 3 "cmlt_arith_mask_operand")))]
+-  "TARGET_SIMD && flag_cmlt_arith"
++  "TARGET_SIMD && !reload_completed && flag_cmlt_arith"
+   "#"
+-  "&& reload_completed"
+-  [(set (match_operand: 0 "register_operand")
++  "&& true"
++  [(set (match_operand: 0 "register_operand" "=w")
+ 	(lshiftrt:
+ 	  (match_operand:VDQHSD 1 "register_operand")
+ 	  (match_operand:VDQHSD 2 "half_size_minus_one_operand")))
++   (set (match_operand: 4 "register_operand" "w")
++	  (match_operand:VDQHSD 3 "cmlt_arith_mask_operand"))
+    (set (match_dup 0)
+ 	(and:
+-	  (match_dup 0)
+-	  (match_operand:VDQHSD 3 "cmlt_arith_mask_operand")))]
+-  ""
++	  (match_dup 4)
++	  (match_dup 0)))]
++  {
++    if (can_create_pseudo_p ())
++      operands[4] = gen_reg_rtx (mode);
++    else
++      FAIL;
++  }
+   [(set_attr "type" "neon_compare_zero")]
+ )
+ 
+-- 
+2.33.0
+
diff --git a/0324-bugfix-fix-vector-costs-for-hip09.patch b/0324-bugfix-fix-vector-costs-for-hip09.patch
new file mode 100644
index 0000000..9483a58
--- /dev/null
+++ b/0324-bugfix-fix-vector-costs-for-hip09.patch
@@ -0,0 +1,52 @@
+From 8f5c12954adb237685c837cb37c98b7594e9fa61 Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Tue, 10 Dec 2024 15:50:16 +0800
+Subject: [PATCH] [bugfix] fix vector costs for hip09.
+
+---
+ gcc/config/aarch64/aarch64-cost-tables.h | 6 +++++-
+ gcc/config/aarch64/aarch64.cc            | 4 +++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-cost-tables.h b/gcc/config/aarch64/aarch64-cost-tables.h
+index dc51d9c2c..06da1b271 100644
+--- a/gcc/config/aarch64/aarch64-cost-tables.h
++++ b/gcc/config/aarch64/aarch64-cost-tables.h
+@@ -872,7 +872,11 @@ const struct cpu_cost_table hip09_extra_costs =
+   },
+   /* Vector */
+   {
+-    COSTS_N_INSNS (1)  /* alu.  */
++    COSTS_N_INSNS (1),  /* alu.  */
++    COSTS_N_INSNS (4),  /* mult.  */
++    COSTS_N_INSNS (1),  /* movi.  */
++    COSTS_N_INSNS (2),  /* dup.  */
++    COSTS_N_INSNS (2)   /* extract.  */
+   }
+ };
+ 
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 829e0da8f..f2444a039 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -499,6 +499,8 @@ static const struct cpu_addrcost_table hip09_addrcost_table =
+     },
+   0, /* pre_modify  */
+   0, /* post_modify  */
++  0, /* post_modify_ld3_st3  */
++  0, /* post_modify_ld4_st4  */
+   0, /* register_offset  */
+   1, /* register_sextend  */
+   1, /* register_zextend  */
+@@ -1910,7 +1912,7 @@ static const struct tune_params hip09_tunings =
+   &hip09_extra_costs,
+   &hip09_addrcost_table,
+   &hip09_regmove_cost,
+-  &hip09_vector_cost,
++  &generic_vector_cost,
+   &generic_branch_cost,
+   &generic_approx_modes,
+   SVE_256, /* sve_width  */
+-- 
+2.33.0
+
diff --git a/0325-gcc-opts-common.cc-Fix-build-with-clang.patch b/0325-gcc-opts-common.cc-Fix-build-with-clang.patch
new file mode 100644
index 0000000..b862bf6
--- /dev/null
+++ b/0325-gcc-opts-common.cc-Fix-build-with-clang.patch
@@ -0,0 +1,54 @@
+From 14457b169e1e4cb372d165de3bbdde391e8b817f Mon Sep 17 00:00:00 2001
+From: YunQiang Su 
+Date: Tue, 8 Oct 2024 18:04:01 +0800
+Subject: [PATCH] gcc/opts-common.cc: Fix build with clang
+
+1. For putenv ("AI_INFER_LEVEL=1"), clang complains that C++11 deprecates
+convert string literal to char *, while putenv expcets "char *".
+Let's use setenv, which expects "const char *".
+
+2. Ditto for char *lan in handle_lto_option.
+
+3. In `handle_machine_option`, there is a variable length array,
+     int64_t argv_hw[argc_hw]
+   clang complains about it, and in fact, argc_hw can be an const var.
+---
+ gcc/opts-common.cc | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
+index 12c3f7299..33c696f3d 100644
+--- a/gcc/opts-common.cc
++++ b/gcc/opts-common.cc
+@@ -1053,7 +1053,7 @@ ai_infer_optimization (int argc, const char **argv,
+     dlclose (onnxruntime_lib_handle);
+ 
+   if (model_pred == 1)
+-    putenv ("AI_INFER_LEVEL=1");
++    setenv ("AI_INFER_LEVEL", "1", 1);
+   return model_pred;
+ }
+ 
+@@ -1065,9 +1065,8 @@ handle_lto_option (unsigned int lang_mask,
+ 		   struct cl_decoded_option *&opt_array)
+ {
+   int ret = 0;
+-  char *lan = "";
+   char *compiler = xstrdup (argv[0]);
+-  lan = strrchr (compiler, '/');
++  char *lan = strrchr (compiler, '/');
+   if (lan != NULL)
+     lan ++;
+   else
+@@ -1125,7 +1124,7 @@ handle_machine_option (unsigned int lang_mask,
+     {
+       return ret;
+     }
+-  int argc_hw = 6;
++  const int argc_hw = 6;
+   int64_t argv_hw[argc_hw] = {
+     global_options.x_param_simultaneous_prefetches,
+     global_options.x_param_l1_cache_size,
+-- 
+2.33.0
+
diff --git a/0326-BUGFIX-Fix-build-error-on-risv_64.patch b/0326-BUGFIX-Fix-build-error-on-risv_64.patch
new file mode 100644
index 0000000..6d91eaa
--- /dev/null
+++ b/0326-BUGFIX-Fix-build-error-on-risv_64.patch
@@ -0,0 +1,1005 @@
+From 19a1074e87577f9b511f382569ac081871e84147 Mon Sep 17 00:00:00 2001
+From: zhenyu--zhao_admin 
+Date: Sat, 7 Dec 2024 16:05:59 +0800
+Subject: [PATCH] [BUGFIX] Fix build error on risv_64.
+
+---
+ gcc/Makefile.in                 |  10 +-
+ gcc/ai-optimizer.cc             | 395 ++++++++++++++++++++++++++++++++
+ gcc/ai4c-infer.cc               |  46 ++--
+ gcc/ai4c-infer.h                |  26 ++-
+ gcc/c-family/c-common.h         |   2 +
+ gcc/c-family/c-opts.cc          |  21 ++
+ gcc/config/aarch64/aarch64-c.cc |  16 ++
+ gcc/config/aarch64/aarch64.cc   |  15 +-
+ gcc/gcc.cc                      |  39 +---
+ gcc/gcc.h                       |   1 -
+ gcc/optimizer.fdata             |   1 +
+ gcc/opts-common.cc              |  74 +-----
+ gcc/opts-global.cc              |   5 +-
+ 13 files changed, 521 insertions(+), 130 deletions(-)
+ create mode 100644 gcc/ai-optimizer.cc
+ create mode 100644 gcc/optimizer.fdata
+
+diff --git a/gcc/Makefile.in b/gcc/Makefile.in
+index 5610854e6..65f683bbd 100644
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -1735,13 +1735,13 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+ 	pretty-print.o intl.o \
+ 	sbitmap.o \
+ 	vec.o input.o hash-table.o ggc-none.o memory-block.o \
+-	ai4c-infer.o selftest.o selftest-diagnostic.o sort.o
++	ai4c-infer.o ai-optimizer.o selftest.o selftest-diagnostic.o sort.o
+ 
+ # Objects in libcommon-target.a, used by drivers and by the core
+ # compiler and containing target-dependent code.
+ OBJS-libcommon-target = $(common_out_object_file) prefix.o \
+ 	opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \
+-	hash-table.o file-find.o spellcheck.o ai4c-infer.o selftest.o opt-suggestions.o
++	hash-table.o file-find.o spellcheck.o ai4c-infer.o ai-optimizer.o selftest.o opt-suggestions.o
+ 
+ # This lists all host objects for the front ends.
+ ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
+@@ -2257,7 +2257,7 @@ gcc-nm.cc: gcc-ar.cc
+ 	cp $^ $@
+ 
+ COLLECT2_OBJS = collect2.o collect2-aix.o vec.o ggc-none.o \
+-  collect-utils.o file-find.o hash-table.o ai4c-infer.o selftest.o
++  collect-utils.o file-find.o hash-table.o ai4c-infer.o ai-optimizer.o selftest.o
+ COLLECT2_LIBS = @COLLECT2_LIBS@
+ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
+ # Don't try modifying collect2 (aka ld) in place--it might be linking this.
+@@ -3721,8 +3721,8 @@ install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype
+ 
+ # Install the compiler executables built during cross compilation.
+ install-common: native lang.install-common installdirs
+-	rm -f $(DESTDIR)$(libexecdir)/onnx.fdata
+-	cp $(srcdir)/onnx.fdata $(DESTDIR)$(libexecsubdir)/onnx.fdata
++	rm -f $(DESTDIR)$(libexecdir)/gcc/*.fdata
++	cp $(srcdir)/*.fdata $(DESTDIR)$(libexecdir)/gcc/
+ 	for file in $(COMPILERS); do \
+ 	  if [ -f $$file ] ; then \
+ 	    rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
+diff --git a/gcc/ai-optimizer.cc b/gcc/ai-optimizer.cc
+new file mode 100644
+index 000000000..c3d99dd85
+--- /dev/null
++++ b/gcc/ai-optimizer.cc
+@@ -0,0 +1,395 @@
++/* Lightweight AI Inference Framework.
++   Copyright (C) 2024-2024 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
++.  */
++
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include 
++#include "config.h"
++#include "system.h"
++#include "ai4c-infer.h"
++
++#define M_OPTION_SIZE  11
++#define M_MODE_SIZE  6
++#define NATIVE_TUNE_SIZE  128
++#define CATS_STRINGS_ROW  34
++#define CATS_STRINGS_COL  65
++#define CATS_STRINGS1_ROW  10
++#define CATS_STRINGS1_COL  65
++#define OFFSET_ROW  6
++#define SCALE_ROW  6
++#define UNITY_ROW  1
++#define COEFFICIENT_ROW  356
++#define COEFFICIENT_COL  10
++#define COEFFICIENT1_ROW  10
++#define COEFFICIENT1_COL  1
++#define INTERCEPTS_ROW  10
++#define INTERCEPTS1_ROW  1
++
++/* Intermediate computation results from the ONNX model.  */
++static char cats_strings[CATS_STRINGS_ROW][CATS_STRINGS_COL];
++static char cats_strings1[CATS_STRINGS1_ROW][CATS_STRINGS1_COL];
++static float offset[OFFSET_ROW];
++static float scale[SCALE_ROW];
++static float unity[UNITY_ROW];
++static float coefficient[COEFFICIENT_ROW][COEFFICIENT_COL];
++static float coefficient1[COEFFICIENT1_ROW][COEFFICIENT1_COL];
++static float intercepts[INTERCEPTS_ROW];
++static float intercepts1[INTERCEPTS1_ROW];
++
++/* Return an integer that represents the comparison result of the
++   two strings.  */
++
++static int
++compare_strings (const void *a, const void *b)
++{
++  const char *str_a = *(const char **)a;
++  const char *str_b = *(const char **)b;
++
++  int len = strlen (str_a) < strlen (str_b) ? strlen (str_a) : strlen (str_b);
++  for (int i = 0; i < len; i++)
++    {
++      char c1 = str_a[i];
++      char c2 = str_b[i];
++      if (ISUPPER (c1) && !ISUPPER (c2))
++	return 0;
++      else if (!ISUPPER (c1) && ISUPPER (c2))
++	return 1;
++      else if (c1 != c2)
++	return c1 < c2;
++    }
++  return strlen (str_a) > strlen (str_b);
++}
++
++/* Return the substring before the first underscore ('_') in the input
++   string.  */
++
++static void
++truncate_prefix (const char *str, char *result)
++{
++  const char *underscore_pos = strchr (str, '_');
++  if (underscore_pos == NULL)
++    {
++      strcpy (result, str);
++      return;
++    }
++
++  size_t len = underscore_pos - str;
++  strncpy (result, str, len + 1);
++  result[len + 1] = '\0';
++}
++
++
++static void
++preprocess (int argc1, const char **argv1, const char *mops,
++	    int argc2, int64_t *argv2, char (*in_options)[1024],
++	    int64_t *in_modes)
++{
++  strcpy (in_options[0], mops);
++
++  const char *output_option = "-o";
++  const char *marco_prefix = "-D";
++  const char *needle = "--param";
++  const char *flag_prefix = "-";
++  const char *default_option = "-default-option";
++  const int default_int_val = 0;
++  int m_size = 0;
++  for (int i = 0; i < argc1; i++)
++    {
++      if (strncmp (argv1[i], marco_prefix, 2) == 0)
++	m_size ++;
++    }
++
++  char *m_options[m_size];
++  char output_file[1024];
++  int m_index = 0;
++  for (int i = 0; i < argc1; i++)
++    {
++      if (strncmp (argv1[i], marco_prefix, 2) == 0)
++	{
++	  m_options[m_index] = (char *)argv1[i];
++	  m_index ++;
++	}
++      if (strcmp (argv1[i], output_option) == 0)
++	truncate_prefix (argv1[i + 1], output_file);
++    }
++
++  strcpy (in_options[1], output_file);
++  int in_options_size = 2;
++  qsort (m_options, m_size, sizeof (m_options[0]), compare_strings);
++  for (int i = 0; i < m_size && in_options_size < M_OPTION_SIZE; i++)
++    {
++      strcpy (in_options[in_options_size], m_options[i]);
++      in_options_size ++;
++    }
++
++  for (int i = 0; i < argc1 && in_options_size < M_OPTION_SIZE; i++)
++    {
++      if (strncmp (argv1[i], marco_prefix, 2) != 0
++	  && strcmp (argv1[i], output_option) != 0
++	  && strncmp (argv1[i], needle, 7) != 0
++	  && strncmp (argv1[i], flag_prefix, 1) == 0)
++	{
++	  strcpy (in_options[in_options_size], argv1[i]);
++	  in_options_size ++;
++	}
++    }
++
++  while (in_options_size < M_OPTION_SIZE)
++    {
++      strcpy (in_options[in_options_size], default_option);
++      in_options_size ++;
++    }
++
++  /* Use sha256 to encrypt the input.  */
++  char hash[65];
++  char input[64];
++  for (int i = 0; i < M_OPTION_SIZE; i++)
++    {
++      execute_sha256 (in_options[i], hash, sizeof (hash));
++      strcpy (in_options[i], hash);
++    }
++
++  for (int i = 0; i < argc2 && i < M_MODE_SIZE; i++)
++    {
++      if (i < argc2)
++	in_modes[i] = argv2[i];
++      else
++	in_modes[i] = default_int_val;
++    }
++}
++
++/* To read model parameter information from optimizer.fdata and store it into
++   the appropriate arrays.  */
++
++static void
++fill_node (const char *file_name)
++{
++  FILE *file = fopen (file_name, "rb");
++
++  if (!file)
++    {
++      perror ("Can not open file.");
++      return;
++    }
++
++   /* Read cats_strings from optimizer.fdata.  */
++  char hex_string[2];
++  for (int i = 0; i < CATS_STRINGS_ROW; i++)
++    {
++      for (int j = 0; j < CATS_STRINGS_COL - 1; j++)
++	{
++	  if (fscanf (file, "%2s", hex_string) != 1)
++	    {
++	      perror ("Can not read cats_strings from optimizer.fdata.");
++	      return;
++	    }
++	  cats_strings[i][j] = (unsigned char) strtol(hex_string, NULL, 16);
++	}
++      cats_strings[i][CATS_STRINGS_COL - 1] = '\0';
++    }
++
++  /* Read cats_strings1 from optimizer.fdata.  */
++  for (int i = 0; i < CATS_STRINGS1_ROW; i++)
++    {
++      for (int j = 0; j < CATS_STRINGS1_COL - 1; j++)
++	{
++	  if (fscanf (file, "%2s", hex_string) != 1)
++	    {
++	      perror ("Can not read cats_strings1 from optimizer.fdata.");
++	      return;
++	    }
++	  cats_strings1[i][j] = (unsigned char) strtol(hex_string, NULL, 16);
++	}
++      cats_strings1[i][CATS_STRINGS1_COL - 1] = '\0';
++    }
++
++  /* Read offset from optimizer.fdata.  */
++  for (int i = 0; i < OFFSET_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      offset[i] = result;
++    }
++
++  
++  /* Read scale from optimizer.fdata.  */
++  for (int i = 0; i < SCALE_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      scale[i] = result;
++    }
++
++  /* Read unity from optimizer.fdata.  */
++  for (int i = 0; i < UNITY_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      unity[i] = result;
++    }
++
++  /* Read coefficient from optimizer.fdata.  */
++  for (int i = 0; i < COEFFICIENT_ROW; i++)
++    for (int j = 0; j < COEFFICIENT_COL; j++)
++      {
++	float result = read_float_from_file (file);
++	coefficient[i][j] = result;
++      }
++
++  /* Read coefficient1 from optimizer.fdata.  */
++  for (int i = 0; i < COEFFICIENT1_ROW; i++)
++    for (int j = 0; j < COEFFICIENT1_COL; j++)
++      {
++	float result = read_float_from_file (file);
++	coefficient1[i][j] = result;
++      }
++
++  /* Read intercepts from optimizer.fdata.  */
++  for (int i = 0; i < INTERCEPTS_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      intercepts[i] = result;
++    }
++
++  /* Read intercepts1 from optimizer.fdata.  */
++  for (int i = 0; i < INTERCEPTS1_ROW; i++)
++    {
++      float result = read_float_from_file (file);
++      intercepts1[i] = result;
++    }
++
++  fclose (file);
++  return;
++}
++
++/* The process of model inference.  */
++
++static int
++graph_infer (int argc1, const char **argv1, const char *mops,
++             int argc2, int64_t *argv2)
++{
++  char *gcc_exec_prefix = getenv ("ONNX_FDATA_PATH");
++  if (gcc_exec_prefix == NULL)
++    return 0;
++  char native_file[512];
++
++  if (gcc_exec_prefix)
++    {
++      const char *onnx_fdata = "optimizer.fdata";
++      strncpy (native_file, gcc_exec_prefix, sizeof (native_file) - 1);
++      native_file[sizeof (native_file) - 1] = '\0';
++      char *last_slash = strrchr (native_file, '/');
++      if (last_slash)
++	strcpy (last_slash + 1, onnx_fdata);
++    }
++
++  if (access (native_file, F_OK) == 0)
++    fill_node (native_file);
++  else
++    return 0;
++
++  static int64_t in_modes[M_MODE_SIZE];
++  static char in_options[M_OPTION_SIZE][1024];
++
++  preprocess (argc1, argv1, mops, argc2, argv2, in_options, in_modes);
++
++  /* concat_result and encoder_out are intermediate computation results from
++     the ONNX model. concat_result is a 1 × 18 matrix, and encoder_out is a
++     1 × 12 matrix.  */
++
++  const int concat_out_size = 350;
++  float concat_result[concat_out_size];
++  const int encoder_out_size = 34;
++  const int encoder_last_size = 10;
++  int concat_size = 0;
++  const int size = encoder_out_size;
++
++  for (int i = 1; i < M_OPTION_SIZE; i++)
++    {
++      float encoder_out[size];
++      one_hot_encoder (in_options[i], cats_strings, encoder_out, size);
++      line_concat (encoder_out, size, concat_result, concat_size);
++      concat_size += size;
++    }
++
++  float encoder_out2[encoder_last_size];
++  one_hot_encoder (in_options[0], cats_strings1, encoder_out2,
++		   encoder_last_size);
++  line_concat (encoder_out2, encoder_last_size, concat_result, concat_size);
++  concat_size += encoder_last_size;
++
++  float variable[M_MODE_SIZE];
++  imputer (in_modes, M_MODE_SIZE, variable);
++  float variable1[M_MODE_SIZE];
++  scaler (variable, offset, scale, M_MODE_SIZE, variable1);
++
++  float transformed_column[concat_out_size + M_MODE_SIZE];
++  /* line_concat is used to stro*/
++  line_concat (variable1, M_MODE_SIZE, transformed_column, 0);
++  line_concat (concat_result, concat_out_size, transformed_column, 6);
++
++  /* This requires performing matrix multiplication between a 1 × 356 matrix
++     and an 356 × 10 matrix  */
++
++  const int m = 1, k = 356, n = 10;
++  float mul_result[n];
++  matmul (transformed_column, coefficient[0], m, k, n, mul_result);  
++
++  float add_result[n];
++  add (mul_result, intercepts, n, add_result);
++
++  float next_activations[n];
++  relu (add_result, n, next_activations);
++  
++  /* This requires performing matrix multiplication between a 1 × 10 matrix
++     and an 10 × 1 matrix  */
++
++  const int m2 = 1, k2 = 10, n2 = 1;
++  float mul_result1[n2];
++  matmul (next_activations, coefficient1[0], m2, k2, n2, mul_result1);
++
++  float add_result1[n2];
++  add (mul_result1, intercepts1, n2, add_result1);
++
++  float out_activations_result[n2];
++  sigmoid (add_result1, n2, out_activations_result);
++
++  float negative_class_proba[n2];
++  sub (unity, out_activations_result, n2, negative_class_proba);
++  const int prob_size = n2 + n2;
++  float probabilities[prob_size];
++  line_concat (negative_class_proba, n2, probabilities, 0);
++  line_concat (out_activations_result, n2, probabilities, n2);
++
++  int argmax_output = argmax (probabilities, prob_size);
++  return argmax_output;
++}
++
++int
++get_optimize_decision_from_optimizer (int argc, const char **argv,
++				      const char *mops, int argc2,
++				      int64_t *argv2)
++{
++  int model_pred = graph_infer (argc, argv, mops, argc2, argv2);
++  if (model_pred == 1)
++    {
++      putenv ("AI_INFER_LEVEL=1");
++    }
++  return model_pred;
++}
+diff --git a/gcc/ai4c-infer.cc b/gcc/ai4c-infer.cc
+index 99f7a6b45..42922e1ca 100644
+--- a/gcc/ai4c-infer.cc
++++ b/gcc/ai4c-infer.cc
+@@ -61,6 +61,12 @@ static int64_t optimize_result;
+ void
+ prepare_native_tune_str (const char *info)
+ {
++  if (info == NULL)
++    {
++      strcpy (native_tune, "=native+");
++      return;
++    }
++
+   gcc_assert (strlen (info) < NATIVE_TUNE_SIZE);
+   if (info)
+     strcpy (native_tune, info);
+@@ -83,7 +89,7 @@ set_cache_info (int prefetches, int l1_cache_size,
+ 
+ /* Read float from onnx.fdata.  */
+ 
+-float static
++float
+ read_float_from_file (FILE* file)
+ {
+   char hex_float[8];
+@@ -196,7 +202,7 @@ fill_node (const char *file_name)
+   return;
+ }
+ 
+-static void
++void
+ matmul (const float *lhs, const float *rhs, int m, int k, int n, float *out)
+ {
+   for (int i = 0; i < m; i++)
+@@ -212,7 +218,7 @@ matmul (const float *lhs, const float *rhs, int m, int k, int n, float *out)
+     }
+ }
+ 
+-static void
++void
+ add (const float *lhs, const float *rhs, int length, float *out)
+ {
+   for (int i = 0; i < length; i++)
+@@ -221,7 +227,7 @@ add (const float *lhs, const float *rhs, int length, float *out)
+     }
+ }
+ 
+-static void
++void
+ sub (const float *lhs, const float *rhs, int length, float *out)
+ {
+   for (int i = 0; i < length; i++)
+@@ -230,7 +236,7 @@ sub (const float *lhs, const float *rhs, int length, float *out)
+     }
+ }
+ 
+-static void
++void
+ sigmoid (const float *in, int length, float *out)
+ {
+   for (int i = 0; i < length; i++)
+@@ -239,7 +245,7 @@ sigmoid (const float *in, int length, float *out)
+     }
+ }
+ 
+-static void
++void
+ relu (const float *data, int length, float *out)
+ {
+   for (int i = 0; i < length; i++)
+@@ -255,14 +261,14 @@ relu (const float *data, int length, float *out)
+     }
+ }
+ 
+-static void
++void
+ line_concat (const float *in, int in_size, float *out, int out_size)
+ {
+   for (int i = 0; i < in_size; i++)
+     out[out_size + i] = in[i];
+ }
+ 
+-static void
++void
+ one_hot_encoder (const char *in, const char (*cats)[65], float *out,
+ 		 int out_size)
+ {
+@@ -279,14 +285,14 @@ one_hot_encoder (const char *in, const char (*cats)[65], float *out,
+     }
+ }
+ 
+-static void
++void
+ imputer (const int64_t *in, int size, float *out)
+ {
+   for (int i = 0; i < size; i++)
+     out[i] = in[i] * 1.0f;
+ }
+ 
+-static void
++void
+ scaler (const float *in, const float *offset, const float *scale, int size,
+ 	float *out)
+ {
+@@ -294,7 +300,7 @@ scaler (const float *in, const float *offset, const float *scale, int size,
+     out[i] = (in[i] - offset[i]) * scale[i];
+ }
+ 
+-static int
++int
+ argmax (const float *in, int in_size)
+ {
+   int out_idx = 0;
+@@ -327,7 +333,20 @@ preprocess (int argc, int64_t *argv, int64_t *in_modes)
+ static int
+ graph_infer (int argc, const char *argv, int argc2, int64_t *argv2)
+ {
+-  const char *file_name = getenv ("GCC_AI4C_ONNX_FDATA");
++  char *gcc_exec_prefix = getenv ("ONNX_FDATA_PATH");
++  if (gcc_exec_prefix == NULL)
++    return 0;
++  char file_name[512];
++
++  if (gcc_exec_prefix)
++    {
++      const char *onnx_fdata = "onnx.fdata";
++      strncpy (file_name, gcc_exec_prefix, sizeof (file_name) - 1);
++      file_name[sizeof (file_name) - 1] = '\0';
++      char *last_slash = strrchr (file_name, '/');
++      if (last_slash)
++	strcpy (last_slash + 1, onnx_fdata);
++    }
+ 
+   if (access (file_name, F_OK) == 0)
+     {
+@@ -401,7 +420,8 @@ graph_infer (int argc, const char *argv, int argc2, int64_t *argv2)
+   return argmax_output;
+ }
+ 
+-void execute_sha256 (const char *input, char *output, size_t output_size)
++void
++execute_sha256 (const char *input, char *output, size_t output_size)
+ {
+     char command[256];
+     snprintf (command, sizeof (command), "echo -n \"%s\" | sha256sum", input);
+diff --git a/gcc/ai4c-infer.h b/gcc/ai4c-infer.h
+index 7fb75900b..fa5156ab1 100644
+--- a/gcc/ai4c-infer.h
++++ b/gcc/ai4c-infer.h
+@@ -21,9 +21,25 @@
+ #ifndef AI4C_INFER_H
+ #define AI4C_INFER_H
+ 
++extern void matmul (const float *, const float *, int, int, int, float *);
++extern void add (const float *, const float *, int, float *);
++extern void sub (const float *, const float *, int, float *);
++extern void sigmoid (const float *, int, float *);
++extern void relu (const float *, int, float *);
++extern void line_concat (const float *, int, float *, int);
++extern void one_hot_encoder (const char *, const char (*)[65], float *, int);
++extern void imputer (const int64_t *, int, float *);		 
++extern void scaler (const float *, const float *, const float *, int, float *);
++extern int argmax (const float *, int);
++
++extern void
++execute_sha256 (const char *, char *, size_t);
++extern float read_float_from_file (FILE*);
++
+ extern int get_optimize_decision_from_ai4c ();
+-extern void set_cache_info (int prefetches, int l1_cache_size, 
+-			    int l1_cache_line_size, int l2_cache_size,
+-			    int prefetch_latency, int prefetch_distance_factor);
+-extern void prepare_native_tune_str (const char *info);
+-#endif /* AI4C_INFER_H */
+\ No newline at end of file
++extern int get_optimize_decision_from_optimizer (int, const char **,
++						 const char *, int ,
++						 int64_t *);
++extern void set_cache_info (int, int, int, int, int, int);
++extern void prepare_native_tune_str (const char *);
++#endif /* AI4C_INFER_H */
+diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
+index d1503c5a7..47c502e13 100644
+--- a/gcc/c-family/c-common.h
++++ b/gcc/c-family/c-common.h
+@@ -940,6 +940,8 @@ extern void set_compound_literal_name (tree decl);
+ 
+ extern tree build_va_arg (location_t, tree, tree);
+ 
++extern void deferred_opts_add_macro_front (const char *);
++
+ extern const unsigned int c_family_lang_mask;
+ extern unsigned int c_common_option_lang_mask (void);
+ extern void c_common_diagnostics_set_defaults (diagnostic_context *);
+diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
+index 744b54dc3..4cde773bf 100644
+--- a/gcc/c-family/c-opts.cc
++++ b/gcc/c-family/c-opts.cc
+@@ -94,6 +94,9 @@ static bool std_cxx_inc = true;
+ /* If the quote chain has been split by -I-.  */
+ static bool quote_chain_split;
+ 
++/* Size of deferred_opts.  */
++static size_t deferred_opts_size;
++
+ /* Number of deferred options.  */
+ static size_t deferred_count;
+ 
+@@ -145,6 +148,23 @@ static struct deferred_opt
+ extern const unsigned int 
+ c_family_lang_mask = (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX);
+ 
++/* Add macro to the front of deferred_opts.  */
++void
++deferred_opts_add_macro_front (const char *arg)
++{
++  /* Allocate a new vec and move elements back.  */
++  auto *new_opts = XNEWVEC (struct deferred_opt, deferred_opts_size + 1);
++  memcpy (new_opts + 1, deferred_opts,
++	  sizeof (struct deferred_opt) * deferred_opts_size);
++  XDELETEVEC (deferred_opts);
++  deferred_opts = new_opts;
++  deferred_opts_size++;
++  deferred_count++;
++
++  deferred_opts[0].code = OPT_D;
++  deferred_opts[0].arg = arg;
++}
++
+ /* Defer option CODE with argument ARG.  */
+ static void
+ defer_opt (enum opt_code code, const char *arg)
+@@ -251,6 +271,7 @@ c_common_init_options (unsigned int decoded_options_count,
+   cpp_opts->warn_dollars = 0;
+ 
+   deferred_opts = XNEWVEC (struct deferred_opt, decoded_options_count);
++  deferred_opts_size = decoded_options_count;
+ 
+   if (c_language == clk_c)
+     {
+diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
+index 2d2ac42c4..dd739288c 100644
+--- a/gcc/config/aarch64/aarch64-c.cc
++++ b/gcc/config/aarch64/aarch64-c.cc
+@@ -47,6 +47,21 @@ aarch64_def_or_undef (bool def_p, const char *macro, cpp_reader *pfile)
+     cpp_undef (pfile, macro);
+ }
+ 
++/* Reset the optimize option.
++   After checking the model result, this function can
++   reset the more appropriate options.  */
++static void
++reset_machine_option (struct gcc_options *opts)
++{
++  const char *ai_infer_level = getenv ("AI_INFER_LEVEL");
++  if (ai_infer_level)
++    {
++      auto *cpp_opts = cpp_get_options (parse_in);
++      cpp_opts->macro_use_commandline = 1;
++      deferred_opts_add_macro_front ("OBSTACK_CHUNK_SIZE=65536");
++    }
++}
++
+ /* Define the macros that we always expect to have on AArch64.  */
+ 
+ static void
+@@ -119,6 +134,7 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
+       cpp_opts->warn_variadic_macros = old_warn_variadic_macros;
+       cpp_opts->cpp_warn_c90_c99_compat = old_cpp_warn_c90_c99_compat;
+     }
++  reset_machine_option(&global_options);
+ }
+ 
+ /* Undefine/redefine macros that depend on the current backend state and may
+diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
+index 829e0da8f..debb15522 100644
+--- a/gcc/config/aarch64/aarch64.cc
++++ b/gcc/config/aarch64/aarch64.cc
+@@ -18771,6 +18771,7 @@ override_C_optimize_options (struct gcc_options *opts)
+   opts->x_semi_relayout_level = 14;
+   opts->x_flag_ipa_prefetch = 1;
+   opts->x_flag_ipa_ic = 1;
++  opts->x_flag_cmlt_arith = 1;
+ }
+ 
+ /* Check whether in CPP language or LTO with only CPP language.  */
+@@ -18872,23 +18873,28 @@ reset_machine_option (struct gcc_options *opts)
+   const char *ai_infer_level = getenv ("AI_INFER_LEVEL");
+   if (ai_infer_level)
+     {
++      char *collect_gcc = getenv("COLLECT_GCC");
++      const char* gcc_exec = basename(ASTRDUP(collect_gcc));
++      if (gcc_exec == NULL)
++	{
++	  return;
++	}
+       override_optimize_options_1 (opts);
+-      if (lang_c_p ())
++      if (strstr(gcc_exec, "gcc") != NULL)
+ 	{
+ 	  override_C_optimize_options (opts);
+ 	}
+-      else if (lang_cpp_p ())
++      else if (strstr(gcc_exec, "g++") != NULL)
+ 	{
+ 	  override_CPP_optimize_options (opts);
+ 	}
+-      else if (lang_GNU_Fortran ())
++      else if (strstr(gcc_exec, "gfortran") != NULL)
+ 	{
+ 	  override_Fortran_optimize_options (opts);
+ 	}
+     }
+ }
+ 
+-
+ /* STMT_COST is the cost calculated for STMT_INFO, which has cost kind KIND
+    and which when vectorized would operate on vector type VECTYPE.  Add the
+    cost of any embedded operations.  */
+@@ -20348,7 +20354,6 @@ aarch64_override_options_internal (struct gcc_options *opts)
+       && aarch64_tune_params.prefetch->default_opt_level >= 0
+       && opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level)
+     opts->x_flag_prefetch_loop_arrays = 1;
+-
+   reset_machine_option (opts);
+   aarch64_override_options_after_change_1 (opts);
+ }
+diff --git a/gcc/gcc.cc b/gcc/gcc.cc
+index 90f6dfe85..179d507f2 100644
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -5799,10 +5799,13 @@ do_self_spec (const char *spec)
+   do_spec_2 (spec, NULL);
+   do_spec_1 (" ", 0, NULL);
+ 
+-  const char* tune_native = eval_spec_function ("local_cpu_detect", "cpu", "");
++  const char* tune_native = NULL;
++#if defined (__x86_64__) || defined (__aarch64__)
++  tune_native = eval_spec_function ("local_cpu_detect", "cpu", "");
++#endif
+   if (tune_native == NULL)
+     {
+-      tune_native = "native";
++      tune_native = "=native+";
+     }
+   setenv ("GCC_AI4C_TUNE_INFO", tune_native, 1);
+ 
+@@ -8129,7 +8132,6 @@ driver::main (int argc, char **argv)
+   putenv_COLLECT_AS_OPTIONS (assembler_options);
+   putenv_COLLECT_GCC (argv[0]);
+   maybe_putenv_COLLECT_LTO_WRAPPER ();
+-  putenv_ONNX_FDATA ();
+   maybe_putenv_OFFLOAD_TARGETS ();
+   handle_unrecognized_options ();
+ 
+@@ -8187,6 +8189,9 @@ driver::expand_at_files (int *argc, char ***argv) const
+ void
+ driver::decode_argv (int argc, const char **argv)
+ {
++  const char* libexec_path = standard_libexec_prefix;
++  if (libexec_path)
++    setenv ("ONNX_FDATA_PATH", libexec_path, 1);
+   init_opts_obstack ();
+   init_options_struct (&global_options, &global_options_set);
+ 
+@@ -8560,34 +8565,6 @@ driver::putenv_COLLECT_GCC (const char *argv0) const
+   xputenv (XOBFINISH (&collect_obstack, char *));
+ }
+ 
+-/* Set up to remember the pathname of the onnx.fdata.  */
+-
+-void
+-driver::putenv_ONNX_FDATA () const
+-{
+-  char *lto_wrapper_file;
+-  lto_wrapper_file = find_a_program ("lto-wrapper");
+-
+-  if (lto_wrapper_file)
+-    {
+-      lto_wrapper_file = convert_white_space (lto_wrapper_file);
+-      char native_file[512];
+-      const char *onnx_fdata = "onnx.fdata";
+-      strncpy (native_file, lto_wrapper_file, sizeof (native_file) - 1);
+-      native_file[sizeof (native_file) - 1] = '\0';
+-      char *last_slash = strrchr (native_file, '/');
+-      if (last_slash)
+-	strcpy (last_slash + 1, onnx_fdata);
+-      obstack_init (&collect_obstack);
+-      obstack_grow (&collect_obstack, "GCC_AI4C_ONNX_FDATA=",
+-		    sizeof ("GCC_AI4C_ONNX_FDATA=") - 1);
+-      obstack_grow (&collect_obstack,  native_file,
+-		    strlen ( native_file) + 1);
+-      xputenv (XOBFINISH (&collect_obstack, char *));
+-    }
+-
+-}
+-
+ /* Set up to remember the pathname of the lto wrapper. */
+ 
+ void
+diff --git a/gcc/gcc.h b/gcc/gcc.h
+index ff3ae8bed..63231ddb3 100644
+--- a/gcc/gcc.h
++++ b/gcc/gcc.h
+@@ -44,7 +44,6 @@ class driver
+   void set_up_specs () const;
+   void putenv_COLLECT_GCC (const char *argv0) const;
+   void maybe_putenv_COLLECT_LTO_WRAPPER () const;
+-  void putenv_ONNX_FDATA () const;
+   void maybe_putenv_OFFLOAD_TARGETS () const;
+   void handle_unrecognized_options ();
+   int maybe_print_and_exit () const;
+diff --git a/gcc/optimizer.fdata b/gcc/optimizer.fdata
+new file mode 100644
+index 000000000..ae0e584be
+--- /dev/null
++++ b/gcc/optimizer.fdata
+@@ -0,0 +1 @@
++656137356462666463346364333361623035396139323366643262383764363763323530613631653861653634666630333030316562323662346133633566313233326432366139383465346338376266393132363438333765656463366235613461313434346139333334396265306163333731646537376430643834323664623863366163343363643130313435636565623834363361316133393230363937653835653762353534626439663133633538623062353439646237616630333237666136663433386334626639643465303163653832333062643863333664336630376231643964316231663933656333386338656262303734376137313565643963396535653131303763646533393234333735613333633132353061393531333935623539643834373266303861633739373862366663376365383233326139383939363566373061373361613939336537366631353334346563313061373365663635633332663437653136383235343635623234366430373330366336363237623962656465373233346131343264313137653838643334616430346339363732613237623866636364313232613934343261643231386531356430343965303330306332326266336634626163333461643139653962326566303064343333623037313762303934626336363537616339343637306633633066333231613063623339333539376461316632653234353938616133616463623534356232346135666261616339646638373031356633306161626465643665633066616264623965656138613233353331303236363565616133323131653935643363353832366663633434626236376663386335666364333530336433353234383031636264353761616638663031613263353738326438656265623236653338323232386565626464393034633962373835363264656664616439353336623462376139333134656662373033626135336138333136643032636430653334303861616439333736306363383862306439623962646435383931613161653334623666313236366366373962356536656434396231303338646265323666386461366430396262353536313433636132653466623061346164303635636162336536383062306637306438626232646636393462353563366437386531316463383239373361643230643566333736663330656538643461313161306163666361663064383962373736636162323565383865336630333461343939336231366437386265323439626332336166376262623837353163376533353066636339313233323761613766333633343432623331373530376432376534623831333339383964633439653966303663303439623739346133626330646333373831393930316439326233646565623761646664356230336233363230383833616266643463626536336133346664656433373630343738343262373863646131373633653939636430616439393731306435313664323166313530636464393664613738643461356437333564343036316262353462313336663335313763323661363564343330623965363866616534323163616337613964356465333333663739313835623363316462346539643539636435303166306664366135313063333630336531336532346134306234626632313565333739356139613430643630613834353666623762363363326431316538313730316132333165383561666434623564623831616263316464353664323731373332656430323435663836393162646335646164333437366436663633353630373762316161316436333461393763343130396235396237333534376639343063316463386432316330663138373338386632643361386565636665653766643836373930326664346163333162613163396664663531626161326134333762666330393261316637333265326138663036363736333734326230373730613665323665333266326265356534376133373330393466336639623431383863383433643563346265613561326134616334626262646637666163376365333962323036323537333737313534313066323364623937303534623665623237306566636366623763623431373666383236383134326365613136653238623231646339353938373030656631646238653961643434653765313834316231346231323563636633356131376538636666613866303638323362643436636638353665346166323633623861616639363862613835306234643961666662656334393366613066653061383333653965343633653837613263636530633863303861313363636361346132613431363962336539613463313366633934633761363761623039396365393263633638656134376162616631363838616238613137323032663864613035313363353335396432373530363233663234343136346339663435333834656630366537353336306137366434646264303466303633663630386363636337383066316631323836353135393134646139373035323637346164303965323536666335393864636364346433383564616435383862366464326130336536313934636139386438373462333162366230623165323533336263313430386430643661386261633061313631613639313232313734383136336464636231323130336231613131373336636238656635353635626666303535663331363332353338313363396334313631333034656133666365353561643830356565633137346638643739636136376432303761633436666465336232356236653164353163346461656165333038653266336161383966633961323462376262386430363536323932373263343731313562356139336265383765336139643837333966623265386131666561366161333138353261663139303338393733346335313934363761393137633266616431663436343236613231663865636236346133616662623761373633663830623231393063616534633032316538626436633731643261313866666339353836373133363939623966636239333637373764323863663964376134323134613133346335326162363334363334386666396666336534646565616264363966356566323465346538613762623864303766646338666264643466666537303263623162326539653435643130313061386235623631306232303139633962653661303038376162323666343263356465313035393535313531373665623537363237373934366266303434333463303562646535623762313565326631393061643033613838363963333933396162363834393636613136613036656435356339616665636134313034663335343465646335333738663063616330353634316466336438373835326638633037656234396239303730613338336332613839323837643561333235393366323531303032666436616435313137313166383433396531626137353932616538333330653164326438656166343339363262366264326632376564396434396333356565343733383137666333386462313164333630303936336137323863313634613031393931613164363237643262353162376133643935373036306336346161376563383862316365613139376535626535626234666331363163303835336362393535613530636234643633626364386566396132333232373733633230393865663664636334393131643133383736373833653261383661623632343237653937366164386564633433396130313166306430316134653864643263343835653438383687144d4395a52c41e3842b41b03f3743f207264565084e41e0fbdf3bd429b13da15eb33d7e47b93b309daa3890d2d93d0000803f04a59dba191d513e33226b3acb4c80be39e785bb0bb9f63c65cdfb38ac15eebd303d01bb4419f23a55cf06bc7ff1453cfd78433b0bf6febd9013433b3b6da33db673a03b2b9491bd7ac8e03b25dbe63b684e0dbcbb0a3ebdc44800bdbcc493bd93e601bd4b6484bd0a60f4bc60dceb3d70e9debcf709e2bcfbb3e83bbdf4023e0ae182bcd48370bd6b8bb5bc431600be698b0abde7c93bbd7d1e83bcc37df5bc6bc82abc8cb32c3d068300bdd32812be02a169bc1040c7be90c1b2bb666f10becbb08fbcf74b17bc1b1602baf138b43d5224843abfb0d4bd60cdbe3a82a4993c8ae4a63a8c9fa8bdc8a86b3afcabb83a4f68c93e8af795bed2d6ff3e5dc599bec525003f902e14bf7e73e93eea321d3e3bf3d13eb012e03e90fde23e313b7bbeef3fe23ec1eb88be7e3eea3e4d0431bfff85d93eaf825c3e333dc33e4d1ad93e44b8cf3e02d697bec0bbf93e84ba9cbe99cbea3ebef11dbf493be73e1640303d18f7ce3e3e59e63e4f3c0a3f3f3e73be1d3cdb3eda1a7dbe56e3d83e8f333abf6d5fcb3e7268383e67b9b13e156ac73e78c507be519081be4deef33e857f81be2959073fb3003ebfd134eb3ee775bf3e5ce8d63e5cf3e63ead860fbef58193bec791043ffaf29cbe689e063fe7772ebf8659fc3ecac0a33e0be3df3ea97afa3ee85f82bdaf0398be529dfe3ef1a39cbee6cdfa3e616738bf1314f43e2425023e5e10d23efe12ed3e3069b8be5e9d7abe7bc2f23ee6b27fbe498d143f2bf545bf934f013f53442a3f23dfe13ec02fe13e48d3cbbd07bc62be8851013f064a90be5f340e3f2a8f42bfa2bcf63e60cdef3ec14dde3e41c9de3ebc90113f286f3cbe86e5db3ed02474bef976ec3e177231bfd8f5e43e9cd5d93ee0fdc23e3c93cf3e6035c03e176199bedfb0f43ee0f39bbe9c8fe73eded525bf8412e33e7485393d99acca3ec677e13e8a5bc83e5ac5a1be2528fb3ec1b9a2be4bd1f03ed92417bf2ae7ea3e7ebcc63c3b37d23edcfee73eb381c6bb8e48d73b5463ca3abdb1b13a9904c23b8f9948393f7ecb3aea64a0bde43c883bde8ce03afdab793cb6d945bc09d0a33c5bd255bc5c04a03c14a8243d153aaa3c3cd991bc6a70913cc9a38a3ca956d6b9ddfa903c944948bbbb53903ce48761bb6e0a0abca78a8dbb728827bd1d7904bc7ea513bc9f89cfbbdab6b23c30c117bc6dbbae3c19b1d5badb1d90bbb6d427bcd329ddbc3f8f1dbc879137bcb972d63a89bc4c3b9619283b9b4b133a8c65e13b3901103d9c7e643bbf128fbdef865d3b7f258b3b033a123be896e9baee8caa3c4efb683c7998c33c4aed8b3d50a2ad3c7aff60bd678b973c45cca63c73d7c6baf325473b210f1c3c0ec3173bba9d463cf2b3583df487003ced3709bdbb3eeb3b5210f63b41eb303b9665293c7953a73bf34d5c3cab738b3c1f0cf03cd77a813b1d6947bdbf322c3b25a7c6397325e93acb3c953a2266d33ba8ea28bbf4e2d53b3da9383d0bcfd63b2cfa20bd251aa03b2a8ab53b03529c3cbbbdc9bc0e1b053d7c27c9bc955f0c3dd4f3323e0edd023d9f9a0bbd506e003d347a073d4c951bbb7989343c8fedaf3bf6a1233c00eeaf3b63dba43cfc7e533ac83606bdb09646bab2af50ba072e9dbb2548b93c7737debbb6e0a43c5b1e02bcff8d3fbd274eacbba96c3dbd3e8ceabbf3fb13bc5714203cc98936bc98db9d3c83d268bc0148a83c9736483dc820a43c9de221bdb90e983c2fe3943c3a5fd4ba81ef3b3c751c973b23fadd3b4f8b333b37b4b53cd044e53a88a81abd4a7aa7b99dc501bad8cda93aa7c572bcfba0d63cc1da86bc4d3bd73cf09e943c827ccd3c1b8956bd3883c23c8637bf3cab889fbbb5c2d13acb99fb3b4295273cc41dfc3b65be0e3d1dddd53becc235bdf19ca43bbbdec43bd1b8b23b4ac6afba5fd6943c218509bb2bc0763c48c8f73c62c3813c565f25bd1374443c26cb633c1fda053ddebcf13cd9f829bce620e43cf20079bbe584b7bb3ade37bc40043dbd140f3fbc183f64bcb6b97fbc4640e33cbeff89bc9ecce53c627f3bbc92a8a0bde11326bc9058073c296f68bc939699bc7bed253b46d30cba6da4803b995d9aba7292253ca565a43cb7b8d03bd50711bd21df8f3b9a02803b3f98f83933cbb1bb98a95c3ca09600bc14c1753c3184703d7760523cf2f390bdb6663a3c91c9433cc137633b6be27d3c997ecab9060da63c1600cd3bafce23bdae80dbba1ccb88bc058da2bb467e21bce8aab63edd089dbe4f78fa3e1fef9fbe16a1f23ee01a18bfc853ec3ed3a3433d9ce5d03e226ce63ed83484be140466be9106fa3eb0117dbeb6c3133f0fb33bbf9787053fe44c0c3fa01cdd3e379ce73ec6904b3e0ba483be3ef5f53eb7fd87be03c1053f8d4c2dbf6257f73e6866ba3efd92cd3e0945e23e59a1323e199391be37c4023f598595be7f81f63ebe6c2ebfc3e3f33e33fa323e77f7d43ed851f13e7b92053fde4a37be0ba8cb3e5e0d53be7047da3ef3a24bbfddabd73edf0dce3e3c6aac3e8810c63e1a6f9f3ef0b686be44eae93e0b2685bec4bfe73e164c3abf6067e33ec99f4f3ec58ebf3e6252d03ec3eff43ea926a7beb70f063fd659aabed093fd3e73c6cabe1c69fb3e3f861d3d4d3ce13e0a74fa3e4c35063f755379be2f12f43e7d848ebe2060043f9d9103bfaf5af83ef9b1043f8e7ac83ef721d53eaeff133fb67d2dbead28cc3efc3668befd33ea3ee1b941bfed13dd3ea8940e3fcfb9ab3e82fbc33e38e7e33ee37590be93efe83e41ac91be6fe2df3e66f21ebfe293d83e6b91573de8eabf3e3abcd63ea5db103f5b217cbe49c9d13ef7ac80beaa60d13eeaa93ebff204cd3efe974e3eac14b23ef978c33ec984cd3ec2d8a2be4c3dfc3e149ba5bec9f1f03e00f911bf3f4deb3ee781273b690cd33e1ccfe83e7ed9ce3bf7dd993be26ca43aa8abba3b4c8a1b3b2357313d7eb9d73a64e851bdaa101e3b6a432a3a1b5457bb665899bc7993fb3c83c150bc13abec3c749d863df737e23c2f3b11bd8b92d03c1dacdb3c072077bb17e3d1ba1ad1323c254dd93a8bd12e3c5ea3213d4f9b263c158d73bd8c5d013c0cde153cbed5d0bb31ff0d3c59f8ff3a5b2df23b29da083bc4561b3d0491673be76542bc74fd963960539eba288b47ba9f2eca3aa558a73bd043abba8049c33bd32eb63ce799e73b4296ccbccda17c3bd5eec53bfddd8f3c66733bbc6a5e943c11bd53bc14dda13c7fae023dd800a23c034b55bdc354943c0c158b3c9c59a4bb82b70f3ccb7c783b7df2123c6d74be3b126bdf3c3ac9463aeeab5abd4df224bb11bdc1389b6322bb232aa8391f7c863cf42d3ebbbb0f803c049f493da7cf3f3c6c9924bd33876e3ca5165b3c972233ba2a880bbc8a30893cb66825bc1a729e3c6624933d492f883ccd7243bd00c5733cf019833c0308c93bc72d3b3b88a5c43bb947243bf435f23b3916afbbdb18df3bd7685ebde8eeba3bdf2ba03b223b07bcea544fbc0669fd3c81fe8bbc1275f73c5e02723df0b1cb3c51ae5cbd1d3fe33c8980de3c71bd48bba6c40b3dfa96ce3c08c5663d3ccf6e3cc800143d2a08933c0cd93f3b508e9d3ce864d33ccbf2adbbc124033c9a36233bf554ed3b5729123bc4b9a4bbcd83b53ac16774bd3cb33a3afa121c3a7ad068bb01c4603ca49e9b397efa6c3c0395df3b0cea40bb160a703be9dad9bcca8f593b66b085bb8d35a2bbae80203ccd53a5bb30d02a3c432e18bb9795e63c58c982bb874772bd99d64fbb118faabb5d1820bc388044baea1e3d3c7837df3b2164373c1f98673df94f183cfc0d45bdf80b223c2b146a3c8cd5d739622b99bb01a62f3ca437eabbc703323c1cc9e83c66002b3c451f67bd9e4f1e3c61a0233c797bf8bb9576c33ae97c8a3cc5ac933b991b553c41f85e3dedd8523ccc9946bd22335f3cbfec273c24fb0bbbaa53023b8c62623c3f8dd3baa4fe833cf033123d0131633c92ef79bd43a24d3c61be0c3c8f4de1b94e9ed1ba1e811f3cf46e85bb7e115a3cf3d5ae3ceca73e3c3c0c41bd57df253cdcd2213c263b3ebc345d733c81be6f3c8aadee3c8a5d393cdf08703b7361813c7d5222bdde9ba83b5465c138af778e3b2e20b83c9a0c69bcfef7be3c44b00bbc850599bcf7406cbc56d64fbd1cc44ebc73e483bc1f71883e25ab7ebe1807003fd1c286beef68043fe1ad19bfd38af93eb4a0c43ed240dc3efb15e63e487f4c3e640b7fbe4907fd3e871b81befe66173fe60e1ebf5886fd3e6022093f8c18e23ebb31003f63cfe83e27805bbe22b0e83e84c37cbeb6d1f03ee10634bfa8a4da3e3d3fbf3e372dc53e6920cf3ed1e1703e1f888fbebced023f8e4692be6bf0043ff0b121bf525ef13e6ed0763ecddfd23e197eeb3efe3d8abd61ab74be3ce8023fb0d484bead74073fca504ebfad57e73ebd250f3fa009c83ef804dc3e00864abd678da3be815f083f71d7a9bea740083f6d2e1ebff19dff3e8968d23d832ee23eeba4fb3eb51bfb3d7b298fbeacc2fa3e6b4d91bef1b7f03e642645bfe625ea3e460e0a3e602ccf3e7c86e23e7754f7bd306785be01ad033fcc7297bec0ab093f2aa034bfa508033fe0570b3f4acdd73e4e7afb3efd2fb53e5b688ebe8e41f63e8fb791be0563f13e9af428bf8858e63e54962f3e22bec83eb4c5e03e184e94bd78de98be707c073fb7f19fbe0ecb043f9c5d33bf7316fa3efcba313eb5eddd3e5283f53e2e92ff3ec37d61be00ebe43e06528cbe7949fa3e66ab29bf108de43e9b95ef3e8eb3cb3e7a2cd03e26bb71bd334794be2725063f18a097bec754053ff6d52fbfa253ff3e6f3d8a3e9d30dd3e5391f23e376e12bbd12e833ce1a93d3b3c98593cf3155d3bdc9895bbd4d0b73a64e731bdd2869b3bbf23bdbb14175fbbeca5a03c6921c7bbdcd9db3ca82787bbae172cbd01edc4bb4409c2bc296076bbc0953cbc70712d3cfafa62bc047fb93c822e8cbcb852c33c62d2833da0b2bf3c085509bd7573ac3c61cdb13cbef44e3c54518b3c2d402abcfb4a8a3c4f8a1abcceead03c35e13bbce83d47bd35ec3cbca71f32bc3d365c3a71c946bc48e8cb3cae9072bc6483c53c7441ad3dc78ebc3c05a12ebd49a4b13cd1ebb93cb7e544bb8d0f963c7216a0bbba6ec13cffad77bba48636bd1dd90bbc591d06bd82f1d5ba9d3114bc55807b393f0345bbb84e4b3c4788cdbb1e8a423cd5c7873d8ff43b3c4e5a51bd1e82293c0147383ccfc8163bb605d53b54eb323c2549cc3bd62c3c3caf80223d556e1e3cb95c42bd3f9d413c7dd2243c6b08c03af82effb91db7853c0378a9ba0802793c2e6b783d346e5f3c093b80bdd148663c0d6e5e3cfc6844b9f2e1cf3a7d18613b3b8734b953bb413bbdbc943cf6a8323b88962dbda482133be6971d3b12ad30bbac4f143cd94ca43b87984c3cdbf16a3b9dc7b13ce8e6633a286b77bdf5c7373b162fa73bce6c1a3c33e88cbb4363093c1c049fbbc6b8373c95c3953ca57d343c76441ebdbfbb0f3c3f56013ccae5863a4ddc20bcfcc7c73cbafe29bc10149b3cee14873d03ae953cfa1e36bd2aa5863c7b79903c5c5125bceebc103c7d270f3b0b70023c42fc8b3ab278eb3c84d4fcb816012abdbfd66639ea10e4b8cc1e11bbed1c073b1c3b803bd21e9a3ac633b53b2f52083d9c50713becd382bd6714543bc395063b79e0ae3b7b9e4ebb2d0d253c44b83abb4d6a393c23814b3d6e861f3ce06cb6bcfe8e0a3c511f173ccfa56c3b873eec3a1c34e53b4381d0394e17d73b2c49ec3cd516cc3bb9c42bbdd3fa933bf49e793b20936a3b5043823961cf3e3ccc562cbaed9e403cbf96063d9c28353ccb3f5bbdf558163cdfc9fb3b5bf28d3cd425acbc618d163de421c1bc0a86163d09ec2e3edc5e083d3d898cbdbec3113dc213043d3d38c4b9466a44ba1efb2f3cce0f9c3bfaf92a3c5388693d991d113c7ce746bd74ed1b3c08d21a3c382fb03c5592a0bbccf6563c24ee8bbb5908563cd779163d06b5503c0580fdbc91d9423cc241493c356d15ba05fd523ca5611cbbc379493c66e7f33b0c1f073dc62fe0bbd3d455bd42683fbb482ec2bbf0d0a83ee99383be0eda033fa74082be4c841c3fe391f7beb6a2063fb386103f5f2feb3e6bafec3e53dfbd3e983a56be1528eb3e1f3085beb3fdf33e12fe3dbfed47dc3ed362e53eb34fc33e0b0ad33ef34e0dbefeac85becdbdf43e75bf95be249c133f67db35bf21d8013faf1a133fd964da3e7c4afb3e8408823e7fdb8bbe77f7013f8f1595be6804053fa32217bf4881fe3e6341823e55beda3ed8fff53e0002db3e85dd6bbe93cedf3e11ee68be5e26d43eb9f24cbff431cf3eca59693ed2afaf3e60d4c43e81bc54bd13eaa5be9661053f5ab0aabefc59023ffba229bf847c003f92e1f53d31bae03e5082f73e9e01b63e759a8ebe7133e73ea36590be9342db3e680d37bf872fd63e7d461d3d8813be3e0816d43e5d82d53efaca83be81e5e23e01ad87beb5c6d53e2bd731bf007cd03eca1deb3dc447b93e4013cf3e154eff3ea8fc75be08b8e23e116189be36dafd3e4dde22bf2458d63e2faead3e25c6c73e0a54d83ed91bf23e02e993be25bfec3eaf6e96be0defec3e48a621bfc4c4e43ef7ad213e4974ca3ecda6df3ea114383fdaf953beb966d23ef24e4dbe291ce93edef430bf7100c63eb01ccb3e95b4b93eda29b93e8a49ca3ecc00a4bedfa8fc3e2bb1a5be2fe1f03ec66f16bfd2b2eb3ee1e29d3c966ed33e198de93e1904c63a3ae604bcfeff653c5d0bfbbb80629b3c76985c3d60918a3cd08057bdd35c933ca83e6b3cb9d066bbb36d47bb05eb803c4bb4a1bb48c3823c9bcc033d9e47763c32a143bd3cb3613c960d683c8189d4ba9301293cbd3f263bef5a323cbab8a63a3d59e83b56dc643b234648bd7674be38ef94443a9df5abbbc5be603c02d2df3accaa403cb260ca3b856f0e3d2191ceb9dacf39bd1bf821bb5766d73bb84111bccc86c93aacf4613c8371e5ba12d1533cf7936e3d66c8023cadd91abd5d2e313ce4e92f3c223b19bc5ac9183b1caf983b0cc0a73a64a1153cd31c0c3d1b5d923bfa1f24bdbff1a33b73bd7b3b8bd9693cd6ba7bbc2d09db3c758c83bc3085003dd3330b3eda22d93cf0ae09bdc729d63caf83d93c05610cb9a04e24bc8d2d9a3c82923cbcaadca33cb17a873d11cb9c3cf6b041bd449f913c7196923ce771feba39f6edba18b3143c1d3807395c21113cd00b253dfff4303c962c50bde69c1e3c5710de3bdb3c8a3b096e2ebaec6b373cece9383b9de8433c3b4ce13cdad3143cce5928bd2b30253c4de61b3c3e5925bc0d53e5398ee9f83b50c71b3a51bde63bd55e813dfbd6bf3b938257bdb3e9943b152ab03bc25b1cbc98f59c3b75ed303b8ec63c3b464e713bbe07743dd60e2a3b004d1bbd36ec863bd63c1c3b6bdf53bb3c309539a8c8743b973cad39656aa33bbda3aa3cc2e08b3b98d705bdc680563bfab04a3bf73b01bcd76e913c604527bcaec1813c9c9ae3bbba0438bd285216bc94cc29bdfc310fbcaf4c42bc138f3cbc7c9d66ba60164a3cdf580bbbb5af403c7261863dcabb2f3cec056abdf8051e3c83f1283cb600b9ba0b9fb4baba50213c095a5039ac32513c8fb07e3cb9371f3c50a40cbdf843383cd969f33b1c34fbba0cff823cf9d281bb7aeb6c3ca95f09bbc72cc5bcb93379ba67f4d9bc132aa2bb94a6afbbc79f74baf9082b3c7c42053b4adac33b969a483b1dd779bce885103befd8c9bc60d7f13a8a93db3a7055c6bcf0cbd03cc67c75bcc196ce3cdfda89bc85e3a2bd8aaa95bc66897dbc339896bcc08298bcb27911bb4fe4b23b3c89513cd8bb8e3bc0df4a3c58980a3d549f0b3cc3ed54bd565c563b3c35843bef71a33ab4b026381dab4f3c8822eb3b9f5b2e3cee511d3d170a113ccff352bd2d41ee3b321aee3b6479c43cab76bb3c2a3315bc329aca3c2df32ebcfef9fdbb244a8cbcde3444bd365a57bc33fc79bcfe524f3eabe282bea97ffe3ee0ea87bed85a043f4be633bf908bf23eec11043fd4d8d53e307fe93e2094803e506d83bedcbde23e1b2f87bef844dc3ec77244bf0c1ad53e572e163e5088b83e047dce3e05f512bd894199bec01e053f30039bbed405013ff1cd35bf4e51fa3efd5b213ea77edc3e2ca4f33ef42bd93ef78591be6cf5f03e362e93be94a5e43ee31d24bf596be03e801dd13d9d6fc63ef969dd3ea28ec23e365070be2d14de3e2e1076bea661da3e850350bf606dcf3ef091723eaf36b53ee0aac93e73e2033f75f074bee398e83ed00681bedd7bfa3e5c7817bf1ec2ee3e2915ac3ecdbdc93eff25d93e57c8a13ed2bc91bec6adfa3e5af895be74e5fa3e9fe712bf1f7af83e8a3c543e818ed33e749dec3e1dfe373e30b09abe2467053f98de9bbee5e8f73e1c4120bf6ba9f43ecfc0c83dc7e6d73e8d40f43ecf2395bdb64287bec2c2003f7f378cbe3318063fc8053bbf5738f13e54fdb33ef711cf3e374fe33ee988ff3e3e2284be68f1e53e0abe89bee926e73e1ba927bf55aae23e50a6183e6633c33ee12bcf3e0df5713f4249f9bddd1fb53e513604be7ca4d73e8c1049bf475fd33eaac3353f74008d3e15f7913e0404a73e064991be01fa063fd0c293bedde4023f7f460abf9c81f93e9408353e1f18dc3e3858f73efcf3d8381165bb3a1ed4f13b66faadba6c05063c7346ec3cafeddc3b45fe41bdf10bd43bdc3fba3b9fbaa6badb92df3a26b8523cfb88553aaf90453c8a984e3d6898463c298d1fbd98062c3c9bfc163c1cba5ebb8ec0eb3b5b56e33ba93de83b953c6f3c42588d3b1f74293c44d641bdd26cf13b2f2f9c3b8eeacbb949b7b2bb1a118c3cad7ffdbb8701843c78c8823d01cd843cd9b152bd70f3683ce2ad813c7212ccbaec4bf7b9ca32633c53adf2ba37bf673ce368703dbf3ef93bc5774ebd734c0e3c2eafd43b1d1166ba9ac4243befb80c3cc95518380381fa3b0947f93c49f6f73b44c628bdd475d03b6e0df33b43ecf4bb5077083c5064b9bacd2e153c9732e3baf237133d999cdfba632885bd1b7666bb7f95a9baeec6babbe3e49e3b3735093c8ae9883b28a7ac3b56fd633b33ccbb3b570d0cbd10d3453b81ea883b829da43c0180e23c1dd790bc5b77dc3c925e67bcf0fbccbc8dd6b9bcfc2463bdf94980bce22cafbc902ba4bb28a314bb5766383ccac575bacba2123ce74f463ddd9c153cc43136bd77f4013c9d15143ca77fa6bb6cc6243b4b2b443b7c95ed3a29e8043c6fe59a3cf516b03bafeb2ebdae27933b25d6153b8d463aba796e2cbadb1b533c1c11c4bb5a7d803c19972a3d7808623c1fe637bd6fad573c4b5b2b3c6eb3733bdfd29cbb02e38c3c6401e0bb72e1973c02ab743da4fd933c87250dbd83eb5f3cb8d6773c7e4514bbe5a1113c1e4f013c77e4543cc590453b93870f3c78a337ba301f52bd5af99c3a853e65bb63e106bb8b42eb3bdbc01f3b0c81e83bfa8de0b91447893dd66b2b3a928a4dbd9da10cbbec6f0abb9e397abccf5c173c0f0c2f3be3d7f53b16b0293b53d0cb3c95db6f3ab36af1bca4769a3a01d4a0baad745a3b260265bcc3b99d3c7b6549bca87fa23c147e453df66d9f3cd7ba39bdd2049d3cfb239c3cc7bb673c45b3a1bc36a3313d580191bc70291a3d41f8493e28d1143dc25c08bd013f2a3d05af213d61f820bb113eaa3b27c4c03b56e3d53bbdbbe33bb0dc203bf4e3d03b491469bdfe07123bddd1063b179a0abb86a584bbb240a63c599fd5bb495f8b3c464f443db62c793cd51220bd4ccc823c5af24f3cbcef4fbb83b4cebb9c92663cb6c7fabbefac6c3ce308783d2d5c533c905d2cbd78ab3e3c3fbe4f3cfaea4dbb49ee5fbb25c5233cef6b833b531c3f3c66ab2f3d5edf4e3cbb9210bd9fbf0b3ccf49193c51fafe3e90c756be715adb3eed0d49be25c5ed3e64503abf318bd73e99b8e73e6b79af3e420fba3ee950be3e07008cbef683e93e99c88dbee548dc3eed4a3dbfacaad73e77d18a3df25bbf3e9445d63e5d96123eec65aabeec39073fe313acbed47c023fb3ef17bfa431fd3ed00cdf3cf490e03e6703f93e004bcb3ed5c6a1beb268fa3ef2aca3be1898ee3eb1f111bf6baee93e84cd133c8a79d13ecd3de73effab5bbd2daf95be81f8063f874ca1bebfdd083f8c9c25bf21f6023f4e4e653e042ae83e537ef43e40d452be2d4e56be66c0fa3e7ad486becfca143f22f03ebfcb79003f73ab523fb6d8d13eeacbf33ef57611bdec8a96be17ad033fc25a98be4623003f61133abff137f83e56b62b3e9665da3eab4cf13ea1339d3d765973be63fd003fa5225ebe73a4023f223e46bf07c0fa3e1742153f6e6ad33ea276e13e5393c33e41a99ebe5eeefb3e879fa0be8360ed3e320016bfef4ce93ece150c3d34b9d03e157ae83e7cc1313f72685dbec4c4d43e7bb05ebe9657f63e2b2d23bf46f4e73eea41023f2d3db33e3de6c33ec32ef93e79894cbec235dd3efa0c80beff1b023faf442fbf7df7da3ee041f53e6556ca3ece48d23ece5906be323b93bef7bd013fd4e195be642a053fc2c439bf42e8ff3e86ea6e3e9581d73ead4ced3ee3ffa53c7981c4bc2fe9fe3c2ca2d8bcd059093dc6c3193e81fa023df8b6b7bc09f2033d79b8ff3c49f32a39562805ba7df3053c165180bbbcd0123c40d1e33cb49be63b564903bda22ae43bf8dcd43b28edc73a4a1e723c347001bba98a5a3cc3bb9a3941c603bceecf38bbe8d652bd101354bbb677d0bb93ac88b9e093f03b2fe2a13ba98afa3b5485cc3b48564d3ce6af1c3b989844bd6033003b5990803bd374b63b69edd7bb278c9e3ce958ecbb98c2d53c827201bc0f529e3c174b88bdad15833c416b893c4daf89bbbb16193bab8f993b9dfc253a4927f73bcafa553d0de1d73b59cb48bd2bccdd3bf5f0803b81f4bbbb480843bb8bfe6b3c10542fbb2ca88f3cbf488b3de92c8d3ca05422bd97e1813c92924b3c9b449abba9f73e3cb3f69cb90173763c750248baaed0b7bc915b12bb4e7c54bd70120eba414ebbbb13b6993b035b9f3b9b30003cf3fd003cfe37133cd137a23cc222e73b4bdf9cbc3907bc3ba4779b3b15cbb83aebfbd0b92e3de83b42e793b910661a3cc1bdee3c18b10e3c708314bdc7bcb33b64f1c83be5300a3c7965a93b7086d53b11fb083b321bd33b4aa3073daa59923b88101abd06ea0e3b1fc62b3b2d4f58ba12d5ab3ba506cf3bd5bb263c3877c83bf6ba753d244e8f3bf1813abd39185d3bd2e57d3b8276f2ba6709933a02406b3b62d8003ccd922f3c6b14913cdfb9a23b101c0bbdc016893bdf0e533bc2afae3b475ceebb6daf9f3c1898fcbbcf1e963ca4eab23ced34983c43a94fbdf4b57e3c859b903cedb0c93b6632dcbb6a74473c1d207ebb69dc803cb0c53a3d2edb573cd72a26bd2792533c0be43b3c22f1a7bbcc598f3b4580393ccc597fbab1ad323c0d642d3db418fe3bcdbe1abd144c0b3c251e043c6ff7c038b3fc19bcf1758f3c170f13bc55fa873c7cb63e3d4697913c162a2abdd9b3793c797f703c46f85f3b6ca3ccbb876b933cbd24f1bbca59923cb7e1be3db0a5993c757365bd3f1a723c19e48e3c98150d3d5ce97d3c696698bbb0af533c1d515cbbccc11e3ce72cc6bb2b555ebdadf9c3bb1574dfbb3211dcba1085913c4c0e38bc0aff843caaf59ebb773309bd361dc0bbd991abbcc9284fbce6b04ebcb78f543b472d26bbe403883c90229aba79c2893c44025e3d09d63f3c71a104bd8af2273cf4af483c94822bbc54b8cc3bcfe0e739245baa3b7380fd3aefd9803dee35a638e80d49bd70861939e25276b9b3746b3df0cf99be4a85013fbc149cbeb2c9fa3e395836bf5a68ef3e65b7d33d6180d63e70b0ea3e84046d3e665891bee293f63eab5895bedc01ff3efa2324bf050bf33e3af05c3e5277dc3efa8eee3ead753b3ff22e34be1f33ce3e5ddc5abe523ce83e9a032fbf8f88cd3e50ebef3efc00bb3ed07dbf3ef885133f7b5159beb055e23e1aa26fbeb22fed3e1a3e2ebf16a2cd3e2a13b53e0f88b73e619dc53e6681f63e14e591be1b05fd3e1c5b92bef153f33ed4570abf29cee43e011e063ed901cd3e4469e43e2b3cf03ea30a66be5616d33e6ed568bea2f0de3e4bda41bf3da6d03ef1108a3e726eb93e0556bf3e1cddcc3ea1669abe0ef1f63e7bf39cbe8e07e83e905422bfe4c0e43eb492a13d2010cd3ec405e43ef1d1ae3dfa3394be6873093f6e5598be8ed40a3f25161bbfb5ab063f2bb9db3d4cf1ea3ee06ff43ea95a20beb6ad9dbeab13043fdc539abeaafa0a3fe7272fbf9e84f83e6e168d3e7781e53eece7f73ec8ce2abebc067bbee90ef93ed53186bea243093fbbe73fbf7e21f53eb51dff3e3b3adf3e6ec8e13e8c3b82bdb42460beab37f43ebfad94bed1b10f3f0c213cbf2383ed3eb8671a3fd463ec3e0cacf63eae35cfbdfc817bbe1854043fb85f94be2348163f22ea30bf9e4a023faf214c3f3f85fe3e6c9ef73e355a28ba4c46e53b017e753c1c87c03bb5cd5a3c2838803d14e5343c6861c3bcbc67133cc47ed33b35432f3be20f213c9bff823cdd53483c42cb7d3cd7ecc13c147a113cdcac96bdf93e433c01fb103cf2ec67b8032b1fbc76d99f3cabc747bc2974993c1376ac3da7358f3cafe934bd3fdb803c6c62943cbb5343bb2b6496bb8ec43b3c6236cbbbd0c62a3c28b4833d90e7243c73e35fbd115c123c48e9283c1a7d903b70063bbc1933853c7a7d1dbce9ad8b3c4fd20f3dc7d9813ca69f20bdbf14803c57ab7f3c9e6d093b7a2d093b4302ea3b71b3afba6f23163c5642c93c1d8bd13b0f0004bdba12ce3be107a73b50cd62bb92904b3bda05f33bf1b6e53a94a5033c7894953c81b8943b58933dbd97f2a43b48ce4b3bdcd3593ce3e559bb69ffcf3c759780bb8354c63c51a8f93d48128c3cfc8107bd7246b63cab7c943c5f9ddaba8bfc18bc714da03c576349bcf85d9b3ce84e9c3d2d09933cea4c18bd8afe8e3c2cea923c57ef41390ba48bba674fba3cb1264ebbce30be3c3bbaec3c138bd53c6f5990bd9be4c93ceac7883c02898cbae2e441ba0e1abd3bb2f5d83ae905473c4056493c4e330f3c28c50cbdd2b7283c5bfaed3b1f638c3abd2cb53bed0ee33b4416b63bef75073c7a38753cbd91b53b954528bd3e33883b5456a53beb300bbb350e223be1e5cd3b23ddb53a281be93b6eac4b3d0f77cb3b2d1da4bc19348d3b71add33b25c33abaff77a9bbb1ab9c3c42fa05bc597d893cd1002d3d5a22853c90a4dfbc0d71853ca7f58a3c6eb77d39743fb93bbbda9f3b16e8943be58d9b3b6730fb3ceab25c3b229453bd9aca833b4aa1a43b96f507bb02dadabb1dd25b3c73ad04bcb1f24c3c9b72693dab604a3ce904cdbc8ab0333cd192473c502a5eb932c9143c9b6c013cdd07263c16cf513c3848c03c8d37f23b10fe15bdfc5e6d3c77369e3b7d18ce3a9601d2bc8c6e113d1ef3d5bc8be0183db487b03d05ba0e3d330441bd93390a3d05830a3d7df54abb3c1eec39ffe3823b19d4643b0ca3993b4201613c87817a3be0aa11bd68463c3bee21413b569fd43acb4351bb32323e3c1130b6bba088403c54cb133d71f2583c650a7dbd366e293c536a023c74d3b7bb9c6d163c51feceb9dfeac93bc622dc3a1c951a3d5e7681bad78f20bdaf9843bae03ad3ba6f648bbb7558213c8c35003bacf80f3c9d37633adab56a3b47c2e8ba429780bd8bf9b53a6d12a4b995b337be64908ebe376e053fc7a194be0502013f392b41bfc7fdf13ee94f873e230fd93ea502ed3e751cfa3e23fc84be96cbe43e558f87becf28d63e7a5d37bf8666d23e3e12cd3da892ba3e2ecad13ef3b3e0bd481a99be552a0a3f85999bbec033043f8f732ebfdc82fd3eb766413ec4cee13e152afa3ed5fbc9bdf7a87cbea07f023f212e98be70b60c3f99f531bfe83c023f65bbea3e76d5e33ea863f63e10c643bdcae24bbece820a3feed88dbeb8a60e3f20903bbf721ff53eaff42b3fe856d93e8b80ff3e4c3d6c3e2ae494be964a023f5b0ba1be9672043f47cc11bf8f93fa3ee0cc2a3e33dada3e301eea3e83ade5bdd7eb92be2233f93e43ec95be8e2af33e1b4445bf0ddaea3ebdac2d3ef7d0ce3e1f51e73edee566be687674bea12d0b3f26429abe4c2a0e3fd4a73abfd5daf23e32f0c83e924def3e2284fe3ea24716bedacc96bed509083fde4e96bea6430a3f6d9a28bf534fff3ea56e833e002fe03ef2c5013f8a6cee3eb0698fbeb11df13ecbaf90be5aa5e03e8b8824bfa06fdd3eb118fb3daec7c53ee528df3eeebf65bed1b58bbebacd063f7390a2be63ab0a3f5ca425bf4a3d013fd665c13ec5fbe23e1b66033f7013da3ec0e782be5132e63e12f686bef829de3e8b6d2fbf4b60d63ef2c00f3e659ebd3ef7e6d13ee10ed03bc67f0f3c45741d3bb0daf33b5e39df3b5ea9953be727893ba42d13bd2afdae3b0be0f93bb1a2223c6d45e43c17da55bcd75a0e3d3c3315bcc99f73bdf2b34dbcadb347bd863263bc4a6e89bc65b616bc4244fd3b32023f3b1d43d13bef37a53b98fb123d971b1a3bf6eadabc30f15c3b3ace153b58fa5e3b7a05a4bb52f3323cc3bd98bb9696313c5b19993dd413293c2e094bbd4e47113cdadf233cafd7603b4c1ed6b8dc521f3c63c984bb2103193c7aae9c3d50640e3ced2c4ebdb62fed3b1a9b0e3c219f31394773703bfbc3bf3b7ef7813bfaafed3b08ff4f3c1a058e3b8a7247bdf9f8a73bf284e93afd4eca3b7be13b3c7d27bfbbfcc3413c4cf90dbb59ecb0bce6f836bb338985bd3d3a69bbb96002bc4396583adeb88e3babe9f53a68c2a83b90d7433be703523c6c20dc3ad1f31fbd4769b63a3f9c4b39cd774bb8cae544bc5967cb3c06f107bcd6d0d53cd829333d41a6b93cf5f544bd1104bd3c12a1c53c72fd99ba591fc43a7149c53b53dd633bf1c42d3c6eaf003d6568a83bf17a49bdca33c53bdc83f73b32946e39579123bb74dd2b3c8bc165bb2f85a23cfb398f3d7e6c2a3c843b5dbde50f0b3c67941a3ca7533abc59089d3c36c3babbc0f7a53c898721bc100554bdb9474abc4f55c7ba098932bcc25b5fbc6748a13c343f8bbc081a2a3d8a2591bc6225273d8a724b3ec527363d916a51bd51a1213d32c6133ddd415638a4aafcbbd6b8933c8247e3bbe3c0a13cd7cc673dfbb0663c007a6bbd67177f3cf1ad763c427fd03b7768a6bbba29a73ca4c80dbc9809b43c10f9783da206b63cd5b072bd0066893cb03c933c7f80143b1ac112bba4cc573c177680bb84c6723c20c1ef3cb47e433c100043bd006b2f3cbc46403cc9ffbf3ab881703b80e7f13bb2c8863b27b70d3cf15c393d0375343b1fe28dbdcab2cf3b4103e63b15fbe6399b7a28bcc41a9c3ce82757bc40cc913c12ca8d3de1278f3cb9e22dbd6ac1833c5c308d3c2693b2b9146a553bc2da3f3ca5c9b4ba5377503c22ac393d17be303ce29c5cbdb02e213c9cd6fc3b6307d33b70b6a1bb10d6843cd567acbbdba95c3c5583423d8129633ceadfbcbc3d8c4c3c02ee513c71f21d3ba86b813b0ff95b3ca70c603b11131b3c4dbddc3bc8ecfc3bc7910bbd621dc43b5b669b3bdd3236ba1c6a22bcc7db8d3c52901ebccc0d933c6402343d20a3803cd9a321bdbf9e6d3cd0b8783c6ff7febdd72f8fbeb78f093f69ac9bbe0b810c3f90f323bf600c003fcd33bf3e9193e83e0d03003f72ace63eaa6c84be1f57e53eefd186bee796de3e844839bff336d23e99aa073e2f92ba3e47c2d03edf4bcb3e5cd19abe3ee8f53eada49cbeeeaae83e374019bf233ee43e4746553db2d1cb3e233fe33e8726e93eeee48dbe66b8f03ea2bc8fbee768e13e522b26bf6932dd3e52e3b83dc097c43e93acdb3ed827c43e6d8d99bef31df53eb44e9cbec848e93e8dd125bf457fe33e54d1693d7e8fcc3ebf9ce13e4dea28be3b2f83beeca6033f080f8fbe69fb133f473d39bfb70afd3ef5fa323fd174d63e7598ea3e46f87cbe51e663bee731013f1c40a3bee01a083f662637bf387f063fa480163f9417da3ede77fa3e4d7ee43ecca487be8528f23efe458abe3bb1e33e7e172abfe295e03e86b4053e7d58c33ee5a1dd3ea22de53e812d8fbe8a61f13e0ac292be3492e63ee25826bf714ae03ec7a1eb3d285ec83e21a0db3efdb0db3edb2980be5ee4db3e3b6f83becb59dc3e61d743bf9e39d03e0572563ed04fb53e7303cd3ed31b053f1a1461be3b24ed3edb938dbe66d4f53e67e320bfa5f7dc3ebea2963ecf62c13e3c6bd43ef01eb43eb41c5dbecd55e83e46ee89be0a1a013f087d27bfd2fafa3eaca30b3f476cd63ecab1d93e7e9725bc0aa6923b86da413c0203193b5e7e673c7d50253df6e9363ca01e4fbd3481453cef6ad83b800e913cd1685d3c107bbdbb18eb313c57317fbb8e55233debb5bdbb863567bd2850bcbbad13d4bb915a783b3cd9aebb70534f3c4e62d13bafe06f3cc4473d3dd4005d3caa5922bdde91503c94ce323c6c72c9ba0449b33b0e88c93b4cb2603b033fe73bb935dd3c42e8e03b53f621bd5561983b2efc753bf430caba702d4bbb00841f3cfb49713acf192e3cac562e3d260b0f3ceabc30bd7b25f53ba67a013c87a3e2bbaaf2263c37417a3c7484b63c0fd47d3c83f36f3df7c9d53bdb981dbdf112963b2295473ccdf5c1bb65a4423c3e59caba46581c3c9d6edebad1f5babc6cce85bba5329abddd9e61bb5af783bbf23a0d3b800ec9bbcf327c3cfb47c0bb7adc703c76c75f3d7a92623c127c1cbdc5e2503cebc76d3c65cde53bae1696bc308ee23c4855aebcb7a5dd3c1be8ab3d7244da3cc1c500bd7f44ce3c439bdb3cd47314bc56d26fbcc8d1c83c2ec16fbcd1b9d63c500b953da937be3ca49477bdfddbb53cfacab83ceca2813aa65c283b462b443b001b303b5219883b9b2c69bcd1fa3b3b6a4157bd25cff33a86d1733b7638723ca39df8bc31f0463d30040cbdb2063c3d17f85e3e7fff3f3dc244cdbc03b6353d22542e3d1d7dafba2e2490ba394d413c37a186ba2f70383c4d72613d5156d73ba180f4bcc1d2143c78010d3c4a3125bbe706003df3418dbca9bd033d0efa2fbc06d36cbd8f558ebceb3734bd801486bc0cddb4bc406612bc4227823c76d9b2bb53197d3c3df981390c2a883cc7d35fbbce8969bd179ad8ba4928cbbbe034ec3ae66c83bba9e3313c9215cabbcacb4f3ceed13c3dda43483c768817bd7f9e373cde071f3c98165cbb49c9e23b0661753be990bd372c4fe93bdf4acb3c5385823b24b868bdfa2d5c3b1ed5863b0019fabcfbc00c3d48f179bcfe80fe3c86da8dbc39f5a3bdc936abbc0d3891bcd834b3bc837dc8bcd4ed0b39513a9cbbec06a13c93209cbb59daad3cf298bc3df1e5a73cecabb7bc324f923c1ba7a33c6b6d19393bc7093c3050a33a3b71bb3bbd4aaf3b9742ad3aeb0eea3a193e37bd3377a73b8e7ec53ae00107bbd15c83ba0c6ff63b3b5e7ebace75e43be425843d61f4d73b05e2e6bce263a93bc565dd3b5a00b0bb6f1083bcedb9ef3c5a57a1bc699eee3cdff4443d633de73c655e39bddcd2d83c8d39dc3cc398ca3e30f799be5f55f33e35739cbe2ad7e73ecbdf1ebf6f40e23ee2a67e3d5f78ca3e55f2df3e843761bece365dbefb42003f64bc77bef20d103f607440bff1b4f53eca680b3f8539df3e0234f43e937096bec00968be8efa083f20d277beea60163fddf130bf06b8fe3e82a3183fd38aee3e92c0f83e3bd408bef2924dbec2e4013f19ec5cbe02d80a3f419c52bff40afe3e84dc143fe2fdd83e29a5cf3ef803ca3e1fab9dbe42c6f83e51c09ebe1e74eb3ef50b12bf7624e73e8676123d7719cf3ecab8e53e5eb7c63e7f5d98be361cf83e2bd69bbe5d9fec3e885722bf52cfe53eda77783db381cc3e28c6e23e3374eb3e21d688bef36ff73e7ef38abe84aaf13e6be51fbfa438e73ecc10703e2cb9c53e5b45db3eac07f73ef8af6cbe561dea3eccd584bef612fd3e5af929bf0f33e13e1156af3ef905cd3e3e60d23e461ac53e17749bbe00ebf23efe389dbe19e5e73eeded1fbf2cebe23e24843d3d12e3ca3e9fa3e03ef894283e365371be2621e63e7c137cbeb5bb053ffb7c39bf5e23f13e8ffb1f3fba81c33e1a22d63e2c2152be8ad160bea9c9093fb7d78abe9693143f72bd2ebf65d9033fca360f3f29dee43e622edb3ed02b52be21f498bea13f063f359c9dbe4282013fedee39bf9a96f93ee155693e017ed83e3bc5f43e3c7cd23b157c01bc7e4d513c87f017bc8a814a3c50586f3d79f9433ca6121fbd1f83353c3356403c558cbc3a889492bbd9f87c3ceedacabb514c6c3c1c71883dfd31693cd94165bd84e1563c9c2c633c99e71d3c623cf63c0ff7fdbbdf43023d0695ebbbb0c997bdb63d0cbc5f589cbc72303abc9db459bc5bafa03bad5e10bb5660f73bdcc52abbeeef133c1acf313dcaa2f03b21c216bd7d90e73b8bf3fb3b22b61c3cc686603d2e8789bc1d2a543defbdd5bc95240dbec970debc8b5c97bc527ad5bce64df7bc0242da3a826aa5bb7dcf4c3c1f06bbbbed98533c0837513dd80e463c641a39bd29263c3c2701403cce511d3a4960b53a0770df3b01385d3bbcc5d63bffc119b880c9b63bd29235bd6979a53b089fa23bcb94933b23be4abb0bed663c91f3873bd52a493cf181853d41b23d3ca3f032bd3bca323c79ae443c160176bbdc7390b90c90ca3b9ed10cbbd19afc3ba719f13cda02be3b8d495bbdd26fcb3b986ab93b1ee9fe3aafca30bb53910f3c6571cbb894f9443c1a9b583d53d2233cba7468bd2218353cb656043c33f7823b443281395f5f713ceb62153ad8ba4d3cd4e85f3d2a3b2b3c583b81bd26e3e33b301c1c3ce4f8be3b592629bb97fa283cef297dbb3aea443c0713373d7b733e3c7a7d06bd943d173c1d9d123ccacd4fbb259aef3cac93523c7170c73c8fff193c819dc93c9f3aef3bd2ef42bd71560d3c9fcb3cbaa084ea3cf5eb293d313ea83ab2a47e3d4ea4713c639f9ebc53d7383cc9f23abc912fa6b9c37fbfba2f5c9c3cf2435bbce756093d8dba75bc7472133d8371153e8f580e3df2a9efbc49b90a3dc2dcda3c89499cba2e1a35bb57957f3c8f919bbbd3a7803ce376303d2a46583c823910bdd59b4b3c41db153ca3245c3b5846893cd9bdd33aed3a8a3cea89583bfc1ba3bc04d0e3b9daf306bd3ad9fdba4bd896bb9dcd6a3bd53faabb5a18553c33e7adbbb04c4a3ce84a643dfe4c3b3cdceb0cbd9119273c58862f3c070a24bb0d62643c955fc1bb466b4e3c78d2a5bb6c98b53c5af18bbb2d2c4fbd14b3d8bb4af60abcd7999f3be7722bbb5628843c9ef3c2bbca4aa23ce11ba43d9de27e3c3ecc54bd07aa7f3c3b3c753c50ed473d1cc8b03ca4ae6fbca0e0ab3c6f8e68bc0b89c2bc709672bc8e96efbcad4884bc197e8cbc88ad0abb1e84a2bbfa37913c4fed96bb095b813c7cdd893d585a803c22fd07bdb11f593c44bf623c8126713fe675cabf69320240baa8d3bf09da0e407fa3a3bfffd00340ba7c15c0ed5ef73ffc72f73f7e93713f0e20cabff9a00540fd5fbfbfd2331040ad5f9dbf1a5f0540e7b31cc07341fa3fccadfc3fbf516bbe49806b3f7352b2bf8ed8843fb13fdabf85b205306eefc8bfd21f6c3f5901abbf05c0a6bf7c29adbe5b6f7c3f1ec0d3bfb1228b3f86f0dfbf7abe103ea357d4bf9bf1743fea1da1bf818ca8bf62c7b7bd4cde883fe0f3dcbf631c903fda1f03c05974bb2e3a86dabf7ef1793f5253abbfc846c1bf90be6cbea4208d3f01acdabf48ff983f7c3f06c0a786392e77e1d3bf4598853f2839adbf0c11c8bf800f5cbe6546673f99f4b3bf94f88a3f65a8e3bf60833a30ce94ccbf7344703fb92d8dbfa461a3bf7c3cb0be6d96353f448baabf220c4a3f9221b7bf1d15b2306e6f9cbf8e9b3d3f29fe84bf77d187bf0ca1c2be4005593faa5dcabf4de9683f0d7dd0bf0e34ae304cdcbebfe07d543f528799bfaa14b0bf8e2dcebefab07d3f7cafd3bffcd1833f5f70efbf1131902ed667bebfbdae763f5632a8bfcf1aa9bfc9989040e9b06dc0f01eb6401a0570c03bf6ad40c896d7c03634aa40b06a80c00ab49840326aa840b13f71bf87ec15401fb2f0bf0caf3040caf509c018e9f63f3cb8f8bf8e1ded3f0322ebbf6ba5e3bf28a371bf
+\ No newline at end of file
+diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
+index 176041bfe..35db76b84 100644
+--- a/gcc/opts-common.cc
++++ b/gcc/opts-common.cc
+@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "diagnostic.h"
+ #include "spellcheck.h"
+ #include "opts-jobserver.h"
++#include "ai4c-infer.h"
+ 
+ static void prune_options (struct cl_decoded_option **, unsigned int *,
+ 			   unsigned int);
+@@ -992,71 +993,6 @@ opts_concat (const char *first, ...)
+   return newstr;
+ }
+ 
+-typedef int64_t (*run_ai_model_func)(int, const char **,
+-				     const char *, int, int64_t *);
+-#define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
+-#define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
+-#define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
+-
+-static int64_t
+-ai_infer_optimization (int argc, const char **argv,
+-		       const char *mcpu_option,
+-		       int argc_hw, int64_t *argv_hw)
+-{
+-  /* Load dependent AI-framework libraries.  */
+-  void *onnxruntime_lib_handle = NULL;
+-  const char *onnxruntime_lib_path = "libonnxruntime.so";
+-
+-  onnxruntime_lib_handle = dlopen (onnxruntime_lib_path,
+-				   RTLD_LAZY | RTLD_GLOBAL);
+-  if (!onnxruntime_lib_handle)
+-    {
+-      return -1;
+-    }
+-
+-  void *ai4c_lib_handle = NULL;
+-  const char *ai4c_lib_path = "libONNXRunner.so";
+-
+-  ai4c_lib_handle = dlopen (ai4c_lib_path, RTLD_LAZY | RTLD_GLOBAL);
+-  if (!ai4c_lib_handle)
+-    {
+-      return -1;
+-    }
+-
+-  /* Clear any existing error.  */
+-  dlerror ();
+-
+-  /* Run AI4Compiler model.  */
+-  if (ai4c_lib_handle == NULL || onnxruntime_lib_handle == NULL)
+-    {
+-      return -1;
+-    }
+-
+-  run_ai_model_func run_ai_model;
+-  PTR_UNION_TYPE (run_ai_model_func) run_ai_model_func_union;
+-  PTR_UNION_AS_VOID_PTR (run_ai_model_func_union)
+-    = dlsym (ai4c_lib_handle, "runONNXModelOptimizer");
+-  run_ai_model = PTR_UNION_AS_CAST_PTR (run_ai_model_func_union);
+-  if (!run_ai_model)
+-    {
+-      dlclose (ai4c_lib_handle);
+-      dlclose (onnxruntime_lib_handle);
+-      return -1;
+-    }
+-  int64_t model_pred = (*run_ai_model) (argc, argv,
+-					mcpu_option, argc_hw, argv_hw);
+-
+-  if (ai4c_lib_handle)
+-    dlclose (ai4c_lib_handle);
+-
+-  if (onnxruntime_lib_handle)
+-    dlclose (onnxruntime_lib_handle);
+-
+-  if (model_pred == 1)
+-    setenv ("AI_INFER_LEVEL", "1", 1);
+-  return model_pred;
+-}
+-
+ static int
+ handle_lto_option (unsigned int lang_mask,
+ 		   unsigned int num_decoded_options,
+@@ -1132,12 +1068,12 @@ handle_machine_option (unsigned int lang_mask,
+     global_options.x_param_l2_cache_size,
+     global_options.x_param_prefetch_latency,
+     global_options.x_param_ipa_prefetch_distance_factor};
+-  int64_t output_pred = ai_infer_optimization (
++  int64_t output_pred = get_optimize_decision_from_optimizer (
+ 			  argc, argv, "hip09", argc_hw, argv_hw);
++  if (output_pred == 1)
++    return output_pred;
+   if (output_pred != 1)
+-    {
+-      return ret;
+-    }
++    return ret;
+ 
+   return handle_lto_option (lang_mask, num_decoded_options,
+ 			    argc, argv, opt_array);
+diff --git a/gcc/opts-global.cc b/gcc/opts-global.cc
+index e684bc5e3..843ace666 100644
+--- a/gcc/opts-global.cc
++++ b/gcc/opts-global.cc
+@@ -312,7 +312,10 @@ decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
+ 		  global_options.x_param_prefetch_latency,
+ 		  global_options.x_param_ipa_prefetch_distance_factor);
+   const char *tune_native = getenv ("GCC_AI4C_TUNE_INFO");
+-  prepare_native_tune_str (tune_native);
++  if (tune_native != nullptr)
++    {
++      prepare_native_tune_str (tune_native);
++    }
+ 
+   struct cl_option_handlers handlers;
+ 
+-- 
+2.33.0
+
diff --git a/0327-Bugfix-Adjust-the-same-gate-to-use-struct-option.patch b/0327-Bugfix-Adjust-the-same-gate-to-use-struct-option.patch
new file mode 100644
index 0000000..6fd98ec
--- /dev/null
+++ b/0327-Bugfix-Adjust-the-same-gate-to-use-struct-option.patch
@@ -0,0 +1,81 @@
+From 861ddfd90d86215a573a7614f49d572f1e03be6f Mon Sep 17 00:00:00 2001
+From: huang-xiaoquan 
+Date: Mon, 16 Dec 2024 11:34:06 +0800
+Subject: [PATCH] [Bugfix] Adjust the same gate to use struct option
+
+---
+ gcc/gimple-ssa-warn-access.cc | 7 ++++++-
+ gcc/ipa-free-lang-data.cc     | 5 +++--
+ gcc/symbol-summary.h          | 8 +++++++-
+ 3 files changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
+index a24645783..3d80590ee 100644
+--- a/gcc/gimple-ssa-warn-access.cc
++++ b/gcc/gimple-ssa-warn-access.cc
+@@ -56,6 +56,9 @@
+ #include "attr-fnspec.h"
+ #include "pointer-query.h"
+ 
++/* Check whether in C language or LTO with only C language.  */
++extern bool lang_c_p (void);
++
+ /* Return true if tree node X has an associated location.  */
+ 
+ static inline location_t
+@@ -2198,7 +2201,9 @@ pass_waccess::gate (function *)
+      In pass waccess, it will traverse all SSA and cause ICE
+      when handling these unused SSA.  So temporarily disable
+      pass waccess when enable structure optimizations.  */
+-  if (flag_ipa_struct_reorg)
++  if (optimize >= 3 && flag_ipa_struct_reorg && !seen_error ()
++      && flag_lto_partition == LTO_PARTITION_ONE && lang_c_p ()
++      && (in_lto_p || flag_whole_program))
+     return false;
+ 
+   return (warn_free_nonheap_object
+diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc
+index 801e95cea..17e3f43b3 100644
+--- a/gcc/ipa-free-lang-data.cc
++++ b/gcc/ipa-free-lang-data.cc
+@@ -108,8 +108,9 @@ fld_simplified_type_name (tree type)
+   /* Simplify type will cause that struct A and struct A within
+      struct B are different type pointers, so skip it in structure
+      optimizations.  */
+-  if (flag_ipa_struct_reorg && lang_c_p ()
+-      && flag_lto_partition == LTO_PARTITION_ONE)
++  if (optimize >= 3 && flag_ipa_struct_reorg && !seen_error ()
++      && flag_lto_partition == LTO_PARTITION_ONE && lang_c_p ()
++      && (in_lto_p || flag_whole_program))
+     return TYPE_NAME (type);
+ 
+   if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
+diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
+index 4f896f4e4..06a1c7fff 100644
+--- a/gcc/symbol-summary.h
++++ b/gcc/symbol-summary.h
+@@ -21,6 +21,10 @@ along with GCC; see the file COPYING3.  If not see
+ #ifndef GCC_SYMBOL_SUMMARY_H
+ #define GCC_SYMBOL_SUMMARY_H
+ 
++#include "diagnostic.h"
++/* Check whether in C language or LTO with only C language.  */
++extern bool lang_c_p (void);
++
+ /* Base class for function_summary and fast_function_summary classes.  */
+ 
+ template 
+@@ -109,7 +113,9 @@ protected:
+ 			     : m_allocator.allocate ();
+     /* In structure optimizatons, we call memset to ensure that
+        the allocated memory is initialized to 0.  */
+-    if (flag_ipa_struct_reorg)
++    if (optimize >= 3 && flag_ipa_struct_reorg && !seen_error ()
++	&& flag_lto_partition == LTO_PARTITION_ONE && lang_c_p ()
++	&& (in_lto_p || flag_whole_program))
+       memset (allocated, 0, sizeof (T));
+     return allocated;
+   }
+-- 
+2.33.0
+
diff --git a/0328-Bugfix-if-split-Added-checking-for-ssa_name.patch b/0328-Bugfix-if-split-Added-checking-for-ssa_name.patch
new file mode 100644
index 0000000..840d32e
--- /dev/null
+++ b/0328-Bugfix-if-split-Added-checking-for-ssa_name.patch
@@ -0,0 +1,248 @@
+From e2896c73513cfb2dfd7c4796effef6ba06396f35 Mon Sep 17 00:00:00 2001
+From: Zinin Ivan WX1305386 
+Date: Fri, 13 Dec 2024 10:52:08 +0300
+Subject: [PATCH] [Bugfix][if-split] Added checking for ssa_name
+
+Added checking if part of OR complex condition is really an ssa
+name in necessary_complex_cond_p(). Besides, made var_n_cst
+structure, which replaced var_cst and cond_parts_defs structures.
+---
+ gcc/gimple-if-split.cc | 123 +++++++++++++++++++----------------------
+ 1 file changed, 56 insertions(+), 67 deletions(-)
+
+diff --git a/gcc/gimple-if-split.cc b/gcc/gimple-if-split.cc
+index 351515435..914b65d47 100644
+--- a/gcc/gimple-if-split.cc
++++ b/gcc/gimple-if-split.cc
+@@ -61,14 +61,14 @@ Example:
+ //-------------------------------------------------------------------------
+ /* Check if arg list of call got n.  */
+ bool
+-got_in_args_p (gimple* call, tree n)
++got_in_args_p (gimple *call, tree n)
+ {
+   unsigned num_args = gimple_call_num_args (call);
+ 
+   for (int i = 0; i < num_args; i++)
+     {
+       if (n == gimple_call_arg (call, i))
+-  return true;
++	return true;
+     }
+ 
+   return false;
+@@ -142,19 +142,24 @@ bb_got_necessary_call_p (basic_block bb, tree n, unsigned nesting)
+ //-------------------------------------------------------------------------
+ // Complex conditions
+ //-------------------------------------------------------------------------
+-/* Auxiliary struct which contains var and its constant of comaprison
+- * of expr: n == cst.  */
+-struct var_const
++/* Auxiliary struct which contains tree nodes of such statements:
++ * var = (n == cst). Actually in some cases var field can be not an ssa
++ * name and/or it's rhs can be not "comparison with constant"
++ * expression.  However, we need to fill var field of such structures
++ * in necessary_complex_cond_p () to build/change conditions in
++ * process_complex_cond ().  */
++struct var_n_const
+ {
++  tree var = NULL_TREE;
+   tree n = NULL_TREE;
+   tree cst = NULL_TREE;
+ };
+ 
+ /* Check if var_def stmt got this pattern:
+  *    var = (n == const);
+- * If it does, we need to set var_cst struct.  */
++ * If it does, we need to set n and cst in var_n_cst struct.  */
+ static bool
+-comp_with_const_p (gimple *var_def, var_const *var_cst)
++comp_with_const_p (gimple *var_def, var_n_const *var_n_cst)
+ {
+   if (gimple_expr_code (var_def) != EQ_EXPR)
+     return false;
+@@ -164,33 +169,24 @@ comp_with_const_p (gimple *var_def, var_const *var_cst)
+   if (TREE_CODE (var_def_rhs2) != INTEGER_CST)
+     return false;
+ 
+-  var_cst->n = gimple_assign_rhs1 (var_def);
+-  var_cst->cst = var_def_rhs2;
++  var_n_cst->n = gimple_assign_rhs1 (var_def);
++  var_n_cst->cst = var_def_rhs2;
+ 
+   return true;
+ }
+ 
+-/* Auxiliary struct which contains defenition of each part of
+- * complex condition, like:
+- *    a = ... <- a_def
+- *    b = ... <- b_def
+- *    c = a | b  <- complex_cond.  */
+-struct cond_parts_defs
+-{
+-  gimple *a_def = NULL;
+-  gimple *b_def = NULL;
+-};
+-
+ /* Check if cond got this pattern:
+  *    a = ...; <- a_def
+  *    b = ...; <- b_def
+- *    c = a | b;
++ *    c = a | b; <- c_def
+  *    if (c != 0)
+- * and a_def or b_def is comparison with constant.  If it does,
+- * we need to set a with a_def and b with b_def.  */
++ * and a_def or b_def is comparison with constant.
++ * If it does, we need to set a_var_n_cst and b_var_n_cst.
++ * Also set a_var_n_cst->var as gimple_assign_rhs1 (c_def),
++ * b_var_n_cst->var as gimple_assign_rhs2 (c_def).  */
+ static bool
+ necessary_complex_cond_p (const gimple *cond, basic_block then_bb,
+-			  cond_parts_defs *defs)
++			  var_n_const *a_var_n_cst, var_n_const *b_var_n_cst)
+ {
+   tree lhs = gimple_cond_lhs (cond);
+   tree rhs = gimple_cond_rhs (cond);
+@@ -207,27 +203,25 @@ necessary_complex_cond_p (const gimple *cond, basic_block then_bb,
+       || gimple_expr_code (c_def) != BIT_IOR_EXPR)
+     return false;
+ 
+-  tree a_var = gimple_assign_rhs1 (c_def);
+-  tree b_var = gimple_assign_rhs2 (c_def);
+-  gimple *a_def = SSA_NAME_DEF_STMT (a_var);
+-  gimple *b_def = SSA_NAME_DEF_STMT (b_var);
+-
+-  if (!a_def || !is_gimple_assign (a_def) || !b_def
+-      || !is_gimple_assign (b_def))
+-    return false;
+-
+-  var_const var_cst;
+-
+-  if (!(comp_with_const_p (a_def, &var_cst)
+-	&& bb_got_necessary_call_p (then_bb, var_cst.n, SCALAR_NESTING))
+-      && !(comp_with_const_p (b_def, &var_cst)
+-	   && bb_got_necessary_call_p (then_bb, var_cst.n, SCALAR_NESTING)))
+-    return false;
+-
+-  defs->a_def = a_def;
+-  defs->b_def = b_def;
+-
+-  return true;
++  bool result = false;
++
++  gimple *a_def;
++  a_var_n_cst->var = gimple_assign_rhs1 (c_def);
++  if (TREE_CODE (a_var_n_cst->var) == SSA_NAME
++      && (a_def = SSA_NAME_DEF_STMT (a_var_n_cst->var))
++      && is_gimple_assign (a_def) && comp_with_const_p (a_def, a_var_n_cst)
++      && bb_got_necessary_call_p (then_bb, a_var_n_cst->n, SCALAR_NESTING))
++    result = true;
++
++  gimple *b_def;
++  b_var_n_cst->var = gimple_assign_rhs2 (c_def);
++  if (TREE_CODE (b_var_n_cst->var) == SSA_NAME
++      && (b_def = SSA_NAME_DEF_STMT (b_var_n_cst->var))
++      && is_gimple_assign (b_def) && comp_with_const_p (b_def, b_var_n_cst)
++      && bb_got_necessary_call_p (then_bb, b_var_n_cst->n, SCALAR_NESTING))
++    result = true;
++
++  return result;
+ }
+ 
+ /* Check if our complex condition seems to be "necessary"
+@@ -253,11 +247,10 @@ process_complex_cond (basic_block cond_bb, basic_block then_bb,
+ 		      basic_block else_bb)
+ {
+   gimple *cond = last_stmt (cond_bb);
+-  cond_parts_defs defs;
++  var_n_const a_var_n_cst, b_var_n_cst;
+ 
+-  if (!can_duplicate_block_p (then_bb)
+-      || !single_succ_p (then_bb)
+-      || !necessary_complex_cond_p (cond, then_bb, &defs))
++  if (!can_duplicate_block_p (then_bb) || !single_succ_p (then_bb)
++      || !necessary_complex_cond_p (cond, then_bb, &a_var_n_cst, &b_var_n_cst))
+     return;
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+@@ -267,19 +260,16 @@ process_complex_cond (basic_block cond_bb, basic_block then_bb,
+       print_gimple_stmt (dump_file, cond, 0, TDF_NONE);
+     }
+ 
+-  var_const var_cst;
+-
+   /* Setting cond.  */
+-  if (comp_with_const_p (defs.a_def, &var_cst))
+-      /* Setting cond as: if (n == const).  */
+-      gimple_cond_set_condition (as_a (cond), EQ_EXPR, var_cst.n,
+-					var_cst.cst);
++  if (a_var_n_cst.n != NULL_TREE && a_var_n_cst.cst != NULL_TREE)
++    /* Setting cond as: if (n == const).  */
++    gimple_cond_set_condition (as_a (cond), EQ_EXPR, a_var_n_cst.n,
++			       a_var_n_cst.cst);
+   else
+     {
+       /* Setting cond as: if (a != 0).  */
+-      tree cond_lhs = gimple_assign_lhs (defs.a_def);
+-      gimple_cond_set_condition (as_a (cond), NE_EXPR, cond_lhs,
+-      					build_zero_cst (TREE_TYPE (cond_lhs)));
++      gimple_cond_set_condition (as_a (cond), NE_EXPR, a_var_n_cst.var,
++				 build_zero_cst (TREE_TYPE (a_var_n_cst.var)));
+     }
+   update_stmt (cond);
+ 
+@@ -290,19 +280,18 @@ process_complex_cond (basic_block cond_bb, basic_block then_bb,
+ 
+   /* Setting inner_cond.  */
+   gcond *inner_cond = NULL;
+-  if (comp_with_const_p (defs.b_def, &var_cst))
++  if (b_var_n_cst.n != NULL_TREE && b_var_n_cst.cst != NULL_TREE)
+     {
+-      /* Setting inner cond as: if (b == const).  */
+-      inner_cond = gimple_build_cond (EQ_EXPR, var_cst.n, var_cst.cst,
++      /* Setting inner cond as: if (n == const).  */
++      inner_cond = gimple_build_cond (EQ_EXPR, b_var_n_cst.n, b_var_n_cst.cst,
+ 				      NULL_TREE, NULL_TREE);
+     }
+   else
+     {
+       /* Setting inner cond as: if (b != 0).  */
+-      tree inner_cond_lhs = gimple_assign_lhs (defs.b_def);
+       inner_cond = gimple_build_cond (
+-	  NE_EXPR, inner_cond_lhs, build_zero_cst (TREE_TYPE (inner_cond_lhs)),
+-	  NULL_TREE, NULL_TREE);
++	  NE_EXPR, b_var_n_cst.var,
++	  build_zero_cst (TREE_TYPE (b_var_n_cst.var)), NULL_TREE, NULL_TREE);
+     }
+   gimple_stmt_iterator gsi = gsi_last_bb (inner_cond_bb);
+   gsi_insert_after (&gsi, inner_cond, GSI_NEW_STMT);
+@@ -362,7 +351,7 @@ make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
+   if (single_succ (then_bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
+     {
+       gcc_assert (gimple_code (last_stmt (then_bb)) == GIMPLE_RETURN);
+-      ret_val = gimple_return_retval (as_a(last_stmt (then_bb)));
++      ret_val = gimple_return_retval (as_a (last_stmt (then_bb)));
+ 
+       then_bb_succ_edge_flags = single_succ_edge (then_bb)->flags;
+     }
+@@ -373,7 +362,7 @@ make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
+    * if now merge_bb is pred of EXIT_BLOCK.  */
+   if (single_succ (merge_bb) == EXIT_BLOCK_PTR_FOR_FN (cfun))
+     {
+-      gimple* ret = gimple_build_return (ret_val);
++      gimple *ret = gimple_build_return (ret_val);
+       gimple_stmt_iterator gsi = gsi_last_bb (merge_bb);
+       gsi_insert_after (&gsi, ret, GSI_NEW_STMT);
+ 
+@@ -400,7 +389,7 @@ make_two_separate_calls (basic_block outer_cond_bb, basic_block inner_cond_bb,
+ 			   single_succ (merge_bb));
+ 
+   if (get_immediate_dominator (CDI_POST_DOMINATORS, outer_cond_bb) == then_bb)
+-     set_immediate_dominator (CDI_POST_DOMINATORS, outer_cond_bb, merge_bb);
++    set_immediate_dominator (CDI_POST_DOMINATORS, outer_cond_bb, merge_bb);
+ 
+   return then_bb1;
+ }
+-- 
+2.33.0
+
diff --git a/0329-Fixed-work-with-loops-in-process_complex_cond.patch b/0329-Fixed-work-with-loops-in-process_complex_cond.patch
new file mode 100644
index 0000000..510544a
--- /dev/null
+++ b/0329-Fixed-work-with-loops-in-process_complex_cond.patch
@@ -0,0 +1,90 @@
+From 66e1c68b47a1fd889e206be5572a2ba5d62afb4d Mon Sep 17 00:00:00 2001
+From: Zinin Ivan WX1305386 
+Date: Tue, 17 Dec 2024 22:07:36 +0800
+Subject: [PATCH] [if-split][BugFix]Fixed work with loops in
+ process_complex_cond()
+
+Signed-off-by: zhenyu--zhao_admin 
+---
+ gcc/gimple-if-split.cc        | 17 +++++++++++++++--
+ gcc/tree-loop-distribution.cc |  6 ++++++
+ gcc/tree-vect-loop.cc         |  4 ----
+ 3 files changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/gimple-if-split.cc b/gcc/gimple-if-split.cc
+index 914b65d4782..b535ffab1c3 100644
+--- a/gcc/gimple-if-split.cc
++++ b/gcc/gimple-if-split.cc
+@@ -262,9 +262,11 @@ process_complex_cond (basic_block cond_bb, basic_block then_bb,
+ 
+   /* Setting cond.  */
+   if (a_var_n_cst.n != NULL_TREE && a_var_n_cst.cst != NULL_TREE)
+-    /* Setting cond as: if (n == const).  */
+-    gimple_cond_set_condition (as_a (cond), EQ_EXPR, a_var_n_cst.n,
++    {
++      /* Setting cond as: if (n == const).  */
++      gimple_cond_set_condition (as_a (cond), EQ_EXPR, a_var_n_cst.n,
+ 			       a_var_n_cst.cst);
++    }
+   else
+     {
+       /* Setting cond as: if (a != 0).  */
+@@ -276,8 +278,19 @@ process_complex_cond (basic_block cond_bb, basic_block then_bb,
+   /* Creating inner_cond_bb.  */
+   edge then_e = find_edge (cond_bb, then_bb);
+   edge else_e = find_edge (cond_bb, else_bb);
++
++  bool inner_cond_bb_need_set_loop = false;
++  if (else_e->dest->loop_father != else_e->src->loop_father)
++	inner_cond_bb_need_set_loop = true;
++
+   basic_block inner_cond_bb = split_edge (else_e);
+ 
++  if (inner_cond_bb_need_set_loop)
++    {
++	remove_bb_from_loops (inner_cond_bb);
++	add_bb_to_loop (inner_cond_bb, cond_bb->loop_father);
++    }
++
+   /* Setting inner_cond.  */
+   gcond *inner_cond = NULL;
+   if (b_var_n_cst.n != NULL_TREE && b_var_n_cst.cst != NULL_TREE)
+diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
+index 8d118e98739..f7a4690246c 100644
+--- a/gcc/tree-loop-distribution.cc
++++ b/gcc/tree-loop-distribution.cc
+@@ -5265,10 +5265,16 @@ loop_distribution::execute (function *fun)
+ 
+ 	  bool destroy_p;
+ 	  int nb_generated_loops, nb_generated_calls;
++
++	  vect_slp_init ();
++
+ 	  nb_generated_loops
+ 	    = distribute_loop (loop, work_list, cd, &nb_generated_calls,
+ 			       &destroy_p, (!optimize_loop_for_speed_p (loop)
+ 					    || !flag_tree_loop_distribution));
++
++	  vect_slp_fini ();
++
+ 	  if (destroy_p)
+ 	    loops_to_be_destroyed.safe_push (loop);
+ 
+diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
+index f296e9415c4..7f75779519a 100644
+--- a/gcc/tree-vect-loop.cc
++++ b/gcc/tree-vect-loop.cc
+@@ -3016,10 +3016,6 @@ vect_analyze_loop (class loop *loop, vec_info_shared *shared,
+   opt_loop_vec_info first_loop_vinfo = opt_loop_vec_info::success (NULL);
+   /* Loop_vinfo for loop-distribution pass.  */
+   opt_loop_vec_info fail_loop_vinfo = opt_loop_vec_info::success (NULL);
+-  if (result_only_p)
+-  {
+-     vect_slp_init ();
+-  }
+   unsigned int mode_i = 0;
+   unsigned HOST_WIDE_INT simdlen = loop->simdlen;
+ 
+-- 
+Gitee
+
diff --git a/0330-bugfix-fix-typo-error.patch b/0330-bugfix-fix-typo-error.patch
new file mode 100644
index 0000000..4f12d79
--- /dev/null
+++ b/0330-bugfix-fix-typo-error.patch
@@ -0,0 +1,25 @@
+From 843b7577b5b255806978f338f6f99863693509d6 Mon Sep 17 00:00:00 2001
+From: Mingchuan Wu 
+Date: Wed, 18 Dec 2024 10:10:30 +0800
+Subject: [PATCH] [bugfix] fix typo error.
+
+---
+ gcc/opts-common.cc | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
+index 35db76b84..ee94723fc 100644
+--- a/gcc/opts-common.cc
++++ b/gcc/opts-common.cc
+@@ -1070,8 +1070,6 @@ handle_machine_option (unsigned int lang_mask,
+     global_options.x_param_ipa_prefetch_distance_factor};
+   int64_t output_pred = get_optimize_decision_from_optimizer (
+ 			  argc, argv, "hip09", argc_hw, argv_hw);
+-  if (output_pred == 1)
+-    return output_pred;
+   if (output_pred != 1)
+     return ret;
+ 
+-- 
+2.33.0
+
diff --git a/0331-fix-function-missing-return-value.patch b/0331-fix-function-missing-return-value.patch
new file mode 100644
index 0000000..003760b
--- /dev/null
+++ b/0331-fix-function-missing-return-value.patch
@@ -0,0 +1,25 @@
+From 8d8dff2b18de8149b4f9f03968abd1b6f4b8cc69 Mon Sep 17 00:00:00 2001
+From: rfwang07 
+Date: Sat, 21 Dec 2024 18:29:10 +0800
+Subject: [PATCH] fix: function missing return value
+
+---
+ gcc/final.cc | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/final.cc b/gcc/final.cc
+index e4bfceabc..0252250ba 100644
+--- a/gcc/final.cc
++++ b/gcc/final.cc
+@@ -4443,7 +4443,7 @@ dump_direct_callee_info_to_asm (basic_block bb, gcov_type call_count)
+ }
+ 
+ /* Dump the edge info into asm.    */
+-static int
++static void
+ dump_edge_jump_info_to_asm (basic_block bb, gcov_type bb_count)
+ {
+   edge e;
+-- 
+2.39.5 (Apple Git-154)
+
diff --git a/gcc.spec b/gcc.spec
new file mode 100644
index 0000000..0476c27
--- /dev/null
+++ b/gcc.spec
@@ -0,0 +1,4485 @@
+%global gcc_version 12.3.1
+%global gcc_major 12
+# Note, gcc_release must be integer, if you want to add suffixes to
+# %%{release}, append them after %%{gcc_release} on Release: line.
+%global gcc_release 63
+
+%global _unpackaged_files_terminate_build 0
+%global _performance_build 1
+# Hardening slows the compiler way too much.
+%undefine _hardened_build
+%undefine _auto_set_build_flags
+%undefine _annotated_build
+
+%global multilib_64_archs sparc64 ppc64 ppc64p7
+
+%global build_ada 0
+%global build_objc 1
+%global build_go 0
+%global build_d 0
+
+%ifarch %{ix86} x86_64 ia64 ppc64le aarch64
+%global build_libquadmath 1
+%else
+%global build_libquadmath 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 loongarch64 riscv64 sw_64
+%global build_libasan 1
+%else
+%global build_libasan 0
+%endif
+%ifarch x86_64 ppc64 ppc64le aarch64 s390x loongarch64 sw_64
+%global build_libtsan 1
+%else
+%global build_libtsan 0
+%endif
+%ifarch x86_64 ppc64 ppc64le aarch64 s390x loongarch64 sw_64
+%global build_liblsan 1
+%else
+%global build_liblsan 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 loongarch64 riscv64 sw_64
+%global build_libubsan 1
+%else
+%global build_libubsan 0
+%endif
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips} riscv64 loongarch64 sw_64
+%global build_libatomic 1
+%else
+%global build_libatomic 0
+%endif
+%ifarch %{ix86} x86_64 %{arm} alpha ppc ppc64 ppc64le ppc64p7 s390 s390x aarch64 loongarch64 sw_64
+%global build_libitm 1
+%else
+%global build_libitm 0
+%endif
+%global build_libstdcxx_docs 0
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 %{mips} loongarch64
+%global attr_ifunc 1
+%else
+%global attr_ifunc 0
+%endif
+%ifarch sparc64
+%global multilib_32_arch sparcv9
+%endif
+%ifarch ppc64 ppc64p7
+%global multilib_32_arch ppc
+%endif
+%ifarch x86_64
+%global multilib_32_arch i686
+%endif
+%ifarch riscv64
+%global _smp_mflags -j8
+%endif
+
+%global isl_enable 0
+%global check_enable 0
+
+Summary: Various compilers (C, C++, Objective-C, ...)
+Name: gcc
+Version: %{gcc_version}
+Release: %{gcc_release}
+# libgcc, libgfortran, libgomp, libstdc++ and crtstuff have
+# GCC Runtime Exception.
+License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD
+URL: https://gcc.gnu.org
+Source0: https://ftp.gnu.org/gnu/gcc/gcc-12.3.0/gcc-12.3.0.tar.xz
+
+BuildRequires: binutils >= 2.31
+BuildRequires: glibc-headers
+BuildRequires: libtool, zlib-devel, texinfo, gettext, flex, bison, sharutils
+BuildRequires: gmp-devel >= 4.1.2, mpfr-devel >= 3.1.0, libmpc-devel >= 0.8.1
+%if %{isl_enable}
+BuildRequires: isl >= 0.15.0, isl-devel >= 0.15.0
+%endif
+BuildRequires: gcc, gcc-c++, make, chrpath
+%if %{build_go}
+BuildRequires: hostname, procps
+%endif
+BuildRequires: gdb
+BuildRequires: glibc-devel >= 2.17
+%ifarch %{multilib_64_archs} sparcv9 ppc
+# Ensure glibc{,-devel} is installed for both multilib arches
+BuildRequires: /lib/libc.so.6 /usr/lib/libc.so /lib64/libc.so.6 /usr/lib64/libc.so
+%endif
+%if %{build_ada}
+# Ada requires Ada to build
+BuildRequires: gcc-gnat >= 3.1, libgnat >= 3.1
+%endif
+%if %{build_d}
+# D requires D to build
+BuildRequires: gcc-gdc >= 11.0.0, libgphobos-static >= 11.0.0
+%endif
+%ifarch ia64
+BuildRequires: libunwind >= 0.98
+%endif
+%if %{build_libstdcxx_docs}
+BuildRequires: doxygen >= 1.7.1
+BuildRequires: graphviz, dblatex, texlive-collection-latex, docbook5-style-xsl
+%endif
+Requires: cpp = %{version}-%{release}
+Requires: binutils >= 2.31
+Conflicts: gdb < 5.1-2
+Requires: glibc-devel >= 2.17
+Requires: libgcc >= %{version}-%{release}
+Requires: libgomp = %{version}-%{release}
+# lto-wrapper invokes make
+Requires: make
+%if !%{build_ada}
+Obsoletes: gcc-gnat < %{version}-%{release}
+%endif
+Obsoletes: gcc-java < %{version}-%{release}
+AutoReq: true
+Provides: bundled(libiberty)
+Provides: bundled(libbacktrace)
+Provides: bundled(libffi)
+Provides: gcc(major) = %{gcc_major}
+
+Patch1: 0001-Version-Set-version-to-12.3.1.patch
+Patch2: 0002-RISCV-Backport-inline-subword-atomic-patches.patch
+Patch3: 0003-CONFIG-Regenerate-configure-file.patch
+Patch4: 0004-libquadmath-Enable-libquadmath-on-kunpeng.patch
+Patch6: 0006-MULL64-1-3-Add-A-B-op-CST-B-match-and-simplify-optim.patch
+Patch7: 0007-MULL64-2-3-Fold-series-of-instructions-into-mul.patch
+Patch8: 0008-MULL64-3-3-Fold-series-of-instructions-into-umulh.patch
+Patch9: 0009-MULL64-Disable-mull64-transformation-by-default.patch
+Patch10: 0010-Version-Clear-DATESTAMP_s.patch
+Patch11: 0011-Add-attribute-hot-judgement-for-INLINE_HINT_known_ho.patch
+Patch12: 0012-Enable-small-loop-unrolling-for-O2.patch
+Patch13: 0013-i386-Only-enable-small-loop-unrolling-in-backend-PR-.patch
+Patch14: 0014-Array-widen-compare-Add-a-new-optimization-for-array.patch
+Patch15: 0015-Backport-Structure-reorganization-optimization.patch
+Patch16: 0016-CompleteStructRelayout-Complete-Structure-Relayout.patch
+Patch17: 0017-StructReorg-Some-bugfix-for-structure-reorganization.patch
+Patch18: 0018-ccmp-Add-another-optimization-opportunity-for-ccmp-i.patch
+Patch19: 0019-fp-model-Enable-fp-model-on-kunpeng.patch
+Patch20: 0020-simdmath-Enable-simdmath-on-kunpeng.patch
+Patch21: 0021-StructReorderFields-Structure-reorder-fields.patch
+Patch22: 0022-DFE-Add-Dead-Field-Elimination-in-Struct-Reorg.patch
+Patch23: 0023-PGO-kernel-Add-fkernel-pgo-option-to-support-PGO-ker.patch
+Patch24: 0024-Struct-Reorg-Refactoring-and-merge-reorder-fields-in.patch
+Patch25: 0025-AArch64-Rewrite-the-tsv110-option.patch
+Patch26: 0026-GOMP-Enabling-moutline-atomics-improves-libgomp-perf.patch
+Patch27: 0027-LoopElim-Redundant-loop-elimination-optimization.patch
+Patch28: 0028-Array-widen-compare-Fix-the-return-value-match-after.patch
+Patch29: 0029-Struct-Reorg-Add-Safe-Structure-Pointer-Compression.patch
+Patch30: 0030-Struct-Reorg-Add-unsafe-structure-pointer-compressio.patch
+Patch31: 0031-AutoBOLT-Support-saving-feedback-count-info-to-ELF-s.patch
+Patch32: 0032-AutoBOLT-Add-bolt-linker-plugin-2-3.patch
+Patch33: 0033-AutoBOLT-Enable-BOLT-linker-plugin-on-aarch64-3-3.patch
+Patch34: 0034-Autofdo-Enable-discrimibator-and-MCF-algorithm-on-Au.patch
+Patch35: 0035-Add-insn-defs-and-correct-costs-for-cmlt-generation.patch
+Patch36: 0036-rtl-ifcvt-introduce-rtl-ifcvt-enchancements.patch           
+Patch37: 0037-Perform-early-if-conversion-of-simple-arithmetic.patch      
+Patch38: 0038-Add-option-to-allow-matching-uaddsub-overflow-for-wi.patch  
+Patch39: 0039-Match-double-sized-mul-pattern.patch                        
+Patch40: 0040-Port-icp-patch-to-GCC-12.patch                              
+Patch41: 0041-Port-fixes-in-icp-to-GCC-12.patch
+Patch42: 0042-Add-split-complex-instructions-pass.patch                   
+Patch43: 0043-Extending-and-refactoring-of-pass_split_complex_inst.patch
+Patch44: 0044-Port-maxmin-patch-to-GCC-12.patch
+Patch45: 0045-Port-moving-minmask-pattern-to-gimple-to-GCC-12.patch
+Patch46: 0046-Add-new-pattern-to-pass-the-maxmin-tests.patch
+Patch47: 0047-AES-Implement-AES-pattern-matching.patch
+Patch48: 0048-crypto-accel-add-optimization-level-requirement-to-t.patch
+Patch49: 0049-Add-more-flexible-check-for-pointer-aliasing-during-.patch
+Patch50: 0050-Port-IPA-prefetch-to-GCC-12.patch
+Patch51: 0051-Port-fixes-for-IPA-prefetch-to-GCC-12.patch
+Patch52: 0052-Fix-fails-in-IPA-prefetch-src-openEuler-gcc-I96ID7.patch
+Patch53: 0053-struct-reorg-Add-Semi-Relayout.patch
+Patch54: 0054-Struct-Reorg-Bugfix-for-structure-pointer-compressio.patch
+Patch55: 0055-Struct-Reorg-Port-bugfixes-to-GCC-12.3.1.patch
+Patch56: 0056-Fix-bug-that-verifying-gimple-failed-when-reorg-leve.patch
+Patch57: 0057-AutoFdo-Fix-memory-leaks-in-autofdo.patch
+Patch86: 0086-Modfify-cost-calculation-for-dealing-with-equivalenc.patch
+Patch87: 0087-Add-cost-calculation-for-reg-equivalence-invariants.patch
+Patch88: 0088-BUGFIX-Fix-the-configure-file-of-BOLT.patch
+Patch89: 0089-StructReorderFields-Fix-gimple-call-not-rewritten.patch
+Patch90: 0090-double-sized-mul-testsuite-Add-march-armv8.2-a-for-d.patch
+Patch91: 0091-IPA-Bugfix-Fix-fails-in-IPA-prefetch-src-openEuler-g.patch
+Patch92: 0092-AES-Bugfix-Change-set_of-to-reg_set_p-and-add-check-.patch
+Patch93: 0093-fix-bugs-within-pointer-compression-and-DFE.patch
+Patch94: 0094-BUGFIX-AutoBOLT-function-miss-bind-type.patch
+Patch95: 0095-STABS-remove-gstabs-and-gxcoff-functionality.patch
+Patch96: 0096-Bugfix-Autofdo-use-PMU-sampling-set-num-eauals-den.patch
+Patch97: 0097-Improve-non-loop-disambiguation.patch
+Patch98: 0098-CHREC-multiplication-and-undefined-overflow.patch
+Patch99: 0099-Enable-Transposed-SLP.patch
+Patch100: 0100-Add-hip09-machine-discribtion.patch
+Patch101: 0101-Add-hip11-CPU-pipeline-scheduling.patch
+Patch102: 0102-Add-Crc32-Optimization-in-Gzip-For-crc32-algorithm-i.patch
+Patch103: 0103-SME-Remove-hip09-and-hip11-in-aarch64-cores.def-to-b.patch
+Patch104: 0104-Backport-SME-AArch64-Cleanup-CPU-option-processing-c.patch
+Patch105: 0105-Backport-SME-AArch64-Cleanup-option-processing-code.patch
+Patch106: 0106-Backport-SME-aarch64-Add-march-support-for-Armv9.1-A.patch
+Patch107: 0107-Backport-SME-Revert-aarch64-Define-__ARM_FEATURE_RCP.patch
+Patch108: 0108-Backport-SME-Revert-Ampere-1-and-Ampere-1A-core-defi.patch
+Patch109: 0109-Backport-SME-aarch64-Rename-AARCH64_ISA-architecture.patch
+Patch110: 0110-Backport-SME-aarch64-Rename-AARCH64_FL-architecture-.patch
+Patch111: 0111-Backport-SME-aarch64-Rename-AARCH64_FL_FOR_ARCH-macr.patch
+Patch112: 0112-Backport-SME-aarch64-Add-V-to-aarch64-arches.def-nam.patch
+Patch113: 0113-Backport-SME-aarch64-Small-config.gcc-cleanups.patch
+Patch114: 0114-Backport-SME-aarch64-Avoid-redundancy-in-aarch64-cor.patch
+Patch115: 0115-Backport-SME-aarch64-Remove-AARCH64_FL_RCPC8_4-PR107.patch
+Patch116: 0116-Backport-SME-aarch64-Fix-transitive-closure-of-featu.patch
+Patch117: 0117-Backport-SME-aarch64-Reorder-an-entry-in-aarch64-opt.patch
+Patch118: 0118-Backport-SME-aarch64-Simplify-feature-definitions.patch
+Patch119: 0119-Backport-SME-aarch64-Simplify-generation-of-.arch-st.patch
+Patch120: 0120-Backport-SME-aarch64-Avoid-std-string-in-static-data.patch
+Patch121: 0121-Backport-SME-aarch64-Tweak-constness-of-option-relat.patch
+Patch122: 0122-Backport-SME-aarch64-Make-more-use-of-aarch64_featur.patch
+Patch123: 0123-Backport-SME-aarch64-Tweak-contents-of-flags_on-off-.patch
+Patch124: 0124-Backport-SME-aarch64-Tweak-handling-of-mgeneral-regs.patch
+Patch125: 0125-Backport-SME-aarch64-Remove-redundant-TARGET_-checks.patch
+Patch126: 0126-Backport-SME-aarch64-Define-__ARM_FEATURE_RCPC.patch
+Patch127: 0127-Backport-SME-Add-Ampere-1-and-Ampere-1A-core-definit.patch
+Patch128: 0128-Backport-SME-aarch64-Fix-nosimd-handling-of-FPR-move.patch
+Patch129: 0129-Backport-SME-aarch64-Commonise-some-folding-code.patch
+Patch130: 0130-Backport-SME-aarch64-Add-a-Z-operand-modifier-for-SV.patch
+Patch131: 0131-Backport-SME-mode-switching-Remove-unused-bbnum-fiel.patch
+Patch132: 0132-Backport-SME-mode-switching-Tweak-the-macro-hook-doc.patch
+Patch133: 0133-Backport-SME-mode-switching-Add-note-problem.patch
+Patch134: 0134-Backport-SME-mode-switching-Avoid-quadractic-list-op.patch
+Patch135: 0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch
+Patch136: 0136-Backport-SME-mode-switching-Simplify-recording-of-tr.patch
+Patch137: 0137-Backport-SME-mode-switching-Tweak-entry-exit-handlin.patch
+Patch138: 0138-Backport-SME-mode-switching-Allow-targets-to-set-the.patch
+Patch139: 0139-Backport-SME-mode-switching-Pass-set-of-live-registe.patch
+Patch140: 0140-Backport-SME-mode-switching-Pass-the-set-of-live-reg.patch
+Patch141: 0141-Backport-SME-mode-switching-Use-1-based-edge-aux-fie.patch
+Patch142: 0142-Backport-SME-mode-switching-Add-a-target-configurabl.patch
+Patch143: 0143-Backport-SME-mode-switching-Add-a-backprop-hook.patch
+Patch144: 0144-Backport-SME-aarch64-Add-a-result_mode-helper-functi.patch
+Patch145: 0145-Backport-SME-rtl-Try-to-remove-EH-edges-after-pro-ep.patch
+Patch146: 0146-Backport-SME-Fix-PR-middle-end-107705-ICE-after-recl.patch
+Patch147: 0147-Backport-SME-function-Change-return-type-of-predicat.patch
+Patch148: 0148-Backport-SME-Allow-prologues-and-epilogues-to-be-ins.patch
+Patch149: 0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
+Patch150: 0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch
+Patch151: 0151-Backport-SME-Allow-targets-to-add-USEs-to-asms.patch
+Patch152: 0152-Backport-SME-New-compact-syntax-for-insn-and-insn_sp.patch
+Patch153: 0153-Backport-SME-recog-Improve-parser-for-pattern-new-co.patch
+Patch154: 0154-Backport-SME-recog-Support-space-in-cons.patch
+Patch155: 0155-Backport-SME-aarch64-Generalise-require_immediate_la.patch
+Patch156: 0156-Backport-SME-aarch64-Add-backend-support-for-DFP.patch
+Patch157: 0157-Backport-SME-aarch64-Vector-move-fixes-for-nosimd.patch
+Patch158: 0158-Backport-SME-aarch64-Simplify-output-template-emissi.patch
+Patch159: 0159-Backport-SME-Improve-immediate-expansion-PR106583.patch
+Patch160: 0160-Backport-SME-AArch64-Cleanup-move-immediate-code.patch
+Patch161: 0161-Backport-SME-AArch64-convert-some-patterns-to-compac.patch
+Patch162: 0162-Backport-SME-aarch64-Use-SVE-s-RDVL-instruction.patch
+Patch163: 0163-Backport-SME-aarch64-Make-AARCH64_FL_SVE-requirement.patch
+Patch164: 0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch
+Patch165: 0165-Backport-SME-aarch64-Add-sve_type-to-SVE-builtins-co.patch
+Patch166: 0166-Backport-SME-aarch64-Generalise-some-SVE-ACLE-error-.patch
+Patch167: 0167-Backport-SME-aarch64-Replace-vague-previous-argument.patch
+Patch168: 0168-Backport-SME-aarch64-Make-more-use-of-sve_type-in-AC.patch
+Patch169: 0169-Backport-SME-aarch64-Tweak-error-message-for-tuple-v.patch
+Patch170: 0170-Backport-SME-aarch64-Add-tuple-forms-of-svreinterpre.patch
+Patch171: 0171-Backport-SME-attribs-Use-existing-traits-for-excl_ha.patch
+Patch172: 0172-Backport-SME-Allow-target-attributes-in-non-gnu-name.patch
+Patch173: 0173-Backport-SME-aarch64-Fix-plugin-header-install.patch
+Patch174: 0174-Backport-SME-aarch64-Add-arm_streaming-_compatible-a.patch
+Patch175: 0175-Backport-SME-aarch64-Add-sme.patch
+Patch176: 0176-Backport-SME-aarch64-Add-r-m-and-m-r-alternatives-to.patch
+Patch177: 0177-Backport-SME-AArch64-Rewrite-simd-move-immediate-pat.patch
+Patch178: 0178-Backport-SME-AArch64-remove-test-comment-from-mov-mo.patch
+Patch179: 0179-Backport-SME-aarch64-Distinguish-streaming-compatibl.patch
+Patch180: 0180-Backport-SME-aarch64-Mark-relevant-SVE-instructions-.patch
+Patch181: 0181-Backport-SME-AArch64-Support-new-tbranch-optab.patch
+Patch182: 0182-Backport-SME-aarch64-Use-local-frame-vars-in-shrink-.patch
+Patch183: 0183-Backport-SME-aarch64-Avoid-a-use-of-callee_offset.patch
+Patch184: 0184-Backport-SME-aarch64-Explicitly-handle-frames-with-n.patch
+Patch185: 0185-Backport-SME-aarch64-Add-bytes_below_saved_regs-to-f.patch
+Patch186: 0186-Backport-SME-aarch64-Add-bytes_below_hard_fp-to-fram.patch
+Patch187: 0187-Backport-SME-aarch64-Robustify-stack-tie-handling.patch
+Patch188: 0188-Backport-SME-aarch64-Tweak-aarch64_save-restore_call.patch
+Patch189: 0189-Backport-SME-aarch64-Only-calculate-chain_offset-if-.patch
+Patch190: 0190-Backport-SME-aarch64-Rename-locals_offset-to-bytes_a.patch
+Patch191: 0191-Backport-SME-aarch64-Rename-hard_fp_offset-to-bytes_.patch
+Patch192: 0192-Backport-SME-aarch64-Tweak-frame_size-comment.patch
+Patch193: 0193-Backport-SME-aarch64-Measure-reg_offset-from-the-bot.patch
+Patch194: 0194-Backport-SME-aarch64-Simplify-top-of-frame-allocatio.patch
+Patch195: 0195-Backport-SME-aarch64-Minor-initial-adjustment-tweak.patch
+Patch196: 0196-Backport-SME-aarch64-Tweak-stack-clash-boundary-cond.patch
+Patch197: 0197-Backport-SME-aarch64-Put-LR-save-probe-in-first-16-b.patch
+Patch198: 0198-Backport-SME-aarch64-Simplify-probe-of-final-frame-a.patch
+Patch199: 0199-Backport-SME-aarch64-Explicitly-record-probe-registe.patch
+Patch200: 0200-Backport-SME-aarch64-Remove-below_hard_fp_saved_regs.patch
+Patch201: 0201-Backport-SME-aarch64-Make-stack-smash-canary-protect.patch
+Patch202: 0202-Backport-SME-Handle-epilogues-that-contain-jumps.patch
+Patch203: 0203-Backport-SME-aarch64-Use-vecs-to-store-register-save.patch
+Patch204: 0204-Backport-SME-aarch64-Put-LR-save-slot-first-in-more-.patch
+Patch205: 0205-Backport-SME-aarch64-Switch-PSTATE.SM-around-calls.patch
+Patch206: 0206-Backport-SME-aarch64-Add-support-for-SME-ZA-attribut.patch
+Patch207: 0207-Backport-SME-aarch64-Add-a-register-class-for-w12-w1.patch
+Patch208: 0208-Backport-SME-aarch64-Add-a-VNx1TI-mode.patch
+Patch209: 0209-Backport-SME-aarch64-Generalise-unspec_based_functio.patch
+Patch210: 0210-Backport-SME-aarch64-Generalise-_m-rules-for-SVE-int.patch
+Patch211: 0211-Backport-SME-aarch64-Add-support-for-arm_sme.h.patch
+Patch212: 0212-Backport-SME-aarch64-Add-support-for-__arm_locally_s.patch
+Patch213: 0213-Backport-SME-aarch64-Handle-PSTATE.SM-across-abnorma.patch
+Patch214: 0214-Backport-SME-aarch64-Enforce-inlining-restrictions-f.patch
+Patch215: 0215-Backport-SME-aarch64-Update-sibcall-handling-for-SME.patch
+Patch216: 0216-Backport-SME-libgcc-aarch64-Configure-check-for-.var.patch
+Patch217: 0217-Backport-SME-libgcc-aarch64-Configure-check-for-__ge.patch
+Patch218: 0218-Backport-SME-libgcc-aarch64-Add-SME-runtime-support.patch
+Patch219: 0219-Backport-SME-libgcc-aarch64-Add-SME-unwinder-support.patch
+Patch220: 0220-Backport-SME-libgcc-Fix-config.in.patch
+Patch221: 0221-Backport-SME-aarch64-Add-funwind-tables-to-some-test.patch
+Patch222: 0222-Backport-SME-aarch64-Skip-some-SME-register-save-tes.patch
+Patch223: 0223-Backport-SME-Add-OPTIONS_H_EXTRA-to-GTFILES.patch
+Patch224: 0224-Backport-SME-aarch64-Add-V1DI-mode.patch
+Patch225: 0225-Backport-SME-Allow-md-iterators-to-include-other-ite.patch
+Patch226: 0226-Backport-SME-riscv-Add-support-for-strlen-inline-exp.patch
+Patch227: 0227-Backport-SME-attribs-Add-overloads-with-namespace-na.patch
+Patch228: 0228-Backport-SME-vec-Add-array_slice-constructors-from-n.patch
+Patch229: 0229-Backport-SME-A-couple-of-va_gc_atomic-tweaks.patch
+Patch230: 0230-Backport-SME-middle-end-Fix-issue-of-poly_uint16-1-1.patch
+Patch231: 0231-SME-Add-missing-header-file-in-aarch64.cc.patch
+Patch232: 0232-Backport-SME-c-Add-support-for-__extension__.patch
+Patch233: 0233-Backport-SME-lra-Updates-of-biggest-mode-for-hard-re.patch
+Patch234: 0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch
+Patch235: 0235-Backport-SME-aarch64-Update-sizeless-tests-for-recen.patch
+Patch236: 0236-Backport-SME-attribs-Namespace-aware-lookup_attribut.patch
+Patch237: 0237-Backport-SME-c-family-ICE-with-gnu-nocf_check-PR1069.patch
+Patch238: 0238-Backport-SME-AArch64-Fix-assert-in-aarch64_move_imm-.patch
+Patch239: 0239-Backport-SME-testsuite-Only-run-fcf-protection-test-.patch
+Patch240: 0240-Backport-SME-Fix-PRs-106764-106765-and-107307-all-IC.patch
+Patch241: 0241-Backport-SME-aarch64-Remove-expected-error-for-compo.patch
+Patch242: 0242-Backport-SME-aarch64-Remove-redundant-builtins-code.patch
+Patch243: 0243-Backport-SME-AArch64-Fix-Armv9-a-warnings-that-get-e.patch
+Patch244: 0244-Backport-SME-Canonicalize-X-Y-as-X-Y-in-match.pd-whe.patch
+Patch245: 0245-Backport-SME-middle-end-Add-new-tbranch-optab-to-add.patch
+Patch246: 0246-Backport-SME-explow-Allow-dynamic-allocations-after-.patch
+Patch247: 0247-Backport-SME-PR105169-Fix-references-to-discarded-se.patch
+Patch248: 0248-Backport-SME-RISC-V-autovec-Verify-that-GET_MODE_NUN.patch
+Patch249: 0249-Backport-SME-Add-operator-to-gimple_stmt_iterator-an.patch
+Patch250: 0250-Backport-SME-tree-optimization-110221-SLP-and-loop-m.patch
+Patch251: 0251-SME-Adapt-some-testsuites.patch
+Patch252: 0252-SME-Fix-error-by-backported-patches-and-IPA-prefetch.patch
+Patch253: 0253-aarch64-Fix-return-register-handling-in-untyped_call.patch
+Patch254: 0254-aarch64-Fix-loose-ldpstp-check.patch
+Patch255: 0255-x86-Add-a-new-option-mdaz-ftz-to-enable-FTZ-and-DAZ-.patch
+Patch256: 0256-Explicitly-view_convert_expr-mask-to-signed-type-whe.patch
+Patch257: 0257-Make-option-mvzeroupper-independent-of-optimization-.patch
+Patch258: 0258-i386-Sync-tune_string-with-arch_string-for-target-at.patch
+Patch259: 0259-Refine-maskloadmn-pattern-with-UNSPEC_MASKLOAD.patch
+Patch260: 0260-Refine-maskstore-patterns-with-UNSPEC_MASKMOV.patch
+Patch261: 0261-x86-Update-model-values-for-Alderlake-and-Rocketlake.patch
+Patch262: 0262-Workaround-possible-CPUID-bug-in-Sandy-Bridge.patch
+Patch263: 0263-Software-mitigation-Disable-gather-generation-in-vec.patch
+Patch264: 0264-Support-m-no-gather-m-no-scatter-to-enable-disable-v.patch
+Patch265: 0265-Remove-constraint-modifier-for-fcmaddcph-fmaddcph-fc.patch
+Patch266: 0266-Disparage-slightly-for-the-alternative-which-move-DF.patch
+Patch267: 0267-Fix-wrong-code-due-to-vec_merge-pcmp-to-blendvb-spli.patch
+Patch268: 0268-Don-t-assume-it-s-AVX_U128_CLEAN-after-call_insn-who.patch
+Patch269: 0269-Disable-FMADD-in-chains-for-Zen4-and-generic.patch
+Patch270: 0270-Initial-Raptorlake-Support.patch
+Patch271: 0271-Initial-Meteorlake-Support.patch
+Patch272: 0272-Support-Intel-AMX-FP16-ISA.patch
+Patch273: 0273-Support-Intel-prefetchit0-t1.patch
+Patch274: 0274-Initial-Granite-Rapids-Support.patch
+Patch275: 0275-Support-Intel-AMX-COMPLEX.patch
+Patch276: 0276-i386-Add-AMX-COMPLEX-to-Granite-Rapids.patch
+Patch277: 0277-Initial-Granite-Rapids-D-Support.patch
+Patch278: 0278-Correct-Granite-Rapids-D-documentation.patch
+Patch279: 0279-i386-Remove-Meteorlake-s-family_model.patch
+Patch280: 0280-x86-Update-model-values-for-Alderlake-Rocketlake-and.patch
+Patch281: 0281-x86-Update-model-values-for-Raptorlake.patch
+Patch282: 0282-Fix-target_clone-arch-graniterapids-d.patch
+Patch283: 0283-i386-Change-prefetchi-output-template.patch
+Patch284: 0284-i386-Add-non-optimize-prefetchi-intrins.patch
+Patch285: 0285-SME-Recover-hip09-and-hip11-in-aarch64-cores.def.patch
+Patch286: 0286-Try-to-use-AI-model-to-guide-optimization.patch
+Patch287: 0287-Add-dynamic-memory-access-checks.patch
+Patch288: 0288-Enable-macro-use-commandline.patch
+Patch289: 0289-tree-ssa-loop-crc.cc-TARGET_CRC32-may-be-not-defined.patch
+Patch290: 0290-Add-ipa-prefetch-test-for-gcc-s-case.patch
+Patch291: 0291-Fix-settings-for-wide-operations-tests.patch
+Patch292: 0292-Fix-errors-in-ipa-prefetch-IAORPF-and-IAOSJ0.patch
+Patch293: 0293-Fix-error-with-stmts-insertion-in-ipa-prefetch-for-I.patch
+Patch294: 0294-Fix-errors-in-ipa-prefetch-IAO50J-and-IAO5H7.patch
+Patch295: 0295-Fix-error-with-grouped_load-merge-in-slp-transpose-v.patch
+Patch296: 0296-Fix-error-in-slp-transpose-vectorize-for-IAQFM3.patch
+Patch297: 0297-Fix-grouped-load-merging-error-in-SLP-transpose-vectorization.patch
+Patch298: 0298-Mark-prefetch-builtin-as-willreturn.patch
+Patch299: 0299-Backport-Disallow-pointer-operands-for-and-partly-PR.patch
+Patch300: 0300-Remove-erroneous-pattern-from-gimple-ifcvt.patch
+Patch301: 0301-Add-required-check-for-iteration-through-uses.patch
+Patch302: 0302-Added-param-for-optimization-for-merging-bb-s-with-c.patch
+Patch303: 0303-Add-generation-of-stream-in-functions-for-pre-versio.patch
+Patch304: 0304-Add-multi-version-lto-symbol-parse-cross-lto-units-i.patch
+Patch305: 0305-Backport-varasm-Handle-private-COMDAT-function-symbo.patch
+Patch306: 0306-RISC-V-Install-libstdc-libcc1-etc-to-lib64-instead-o.patch
+Patch307: 0307-Set-fallback-value-for-print-multi-os-directory.patch
+Patch308: 0308-Fix-enum-INPUT-MIDDLE-FINAL-aes_stage.patch
+Patch309: 0309-CSPGO-Add-context-sensitive-PGO.patch
+Patch310: 0310-CFGO-Add-cfgo-pgo-optimization.patch
+Patch311: 0311-PATCH-Add-if-split-optimization-pass.patch
+Patch312: 0312-Add-late-slp-vectorization-pass-with-additional-chec.patch
+Patch313: 0313-Add-tracer-transformation-for-static-probabilities.patch
+Patch314: 0314-bugfix-Modify-the-hip09-tune-flags.patch
+Patch315: 0315-Bugfix-Add-no-var-recored-check-for-ssa_name-in-stru.patch
+Patch316: 0316-Use-ai-ability-to-guide-optimization.patch
+Patch317: 0317-Bugfix-set-default-value-when-tune_native-is-NULL.patch
+Patch318: 0318-add-flag-flto-try.patch 
+Patch319: 0319-CSPGO-fix-bugs-when-using-cspgo.patch
+Patch320: 0320-if-split-fix-bugs.patch
+Patch321: 0321-Struct-reorg-Avoid-doing-struct-split-and-reorder_fi.patch
+Patch322: 0322-Bugfix-Create-POINTER_PLUS_EXPR-for-REFERENCE_TYPE.patch
+Patch323: 0323-Bugfix-replace-tmp-pattern-split.patch
+Patch324: 0324-bugfix-fix-vector-costs-for-hip09.patch
+Patch325: 0325-gcc-opts-common.cc-Fix-build-with-clang.patch
+Patch326: 0326-BUGFIX-Fix-build-error-on-risv_64.patch
+Patch327: 0327-Bugfix-Adjust-the-same-gate-to-use-struct-option.patch
+Patch328: 0328-Bugfix-if-split-Added-checking-for-ssa_name.patch
+Patch329: 0329-Fixed-work-with-loops-in-process_complex_cond.patch
+Patch330: 0330-bugfix-fix-typo-error.patch
+Patch331: 0331-fix-function-missing-return-value.patch
+
+# Part 1001-1999
+%ifarch sw_64
+Patch1001: 0001-Sw64-Port-add-configure-support-for-sw64.patch
+Patch1002: 0002-Sw64-Port-add-gcc-compiler.patch
+Patch1003: 0003-Sw64-Port-add-multi-prefetch-support-for-sw64.patch
+Patch1004: 0004-Sw64-Port-update-gcc-testsuite-for-sw64.patch
+Patch1005: 0005-Sw64-Port-libatomic.patch
+Patch1006: 0006-Sw64-Port-libgcc.patch
+Patch1007: 0007-Sw64-Port-libffi.patch
+Patch1008: 0008-Sw64-Port-libgfortran.patch
+Patch1009: 0009-Sw64-Port-libgo.patch
+Patch1010: 0010-Sw64-Port-libgomp.patch
+Patch1011: 0011-Sw64-Port-libitm.patch
+Patch1012: 0012-Sw64-Port-libstdc.patch
+Patch1013: 0013-Sw64-Port-set-raise-FPE-when-DivbyZero-on-Sw_64.patch
+Patch1014: 0014-Sw64-Port-add-lex-builtin-support-in-libcpp.patch
+Patch1015: 0015-Sw64-Port-libsanitizer.patch
+Patch1016: 0016-libsanitizer-fix-isoc23-function-interception.patch
+Patch1017: 0017-Sw64-Port-Fix-target-explicit_mask.patch
+%endif
+
+# Part 3000 ~ 4999
+%ifarch loongarch64
+Patch3001: loongarch-add-alternatives-for-idiv-insns-to-improve.patch
+Patch3002: loongarch-avoid-unnecessary-sign-extend-after-32-bit.patch
+Patch3003: LoongArch-Subdivision-symbol-type-add-SYMBOL_PCREL-s.patch
+Patch3004: LoongArch-Support-split-symbol.patch
+Patch3005: LoongArch-Modify-the-output-message-string-of-the-wa.patch
+Patch3006: LoongArch-adjust-the-default-of-mexplicit-relocs-by-.patch
+Patch3007: LoongArch-document-m-no-explicit-relocs.patch
+Patch3008: LoongArch-Define-the-macro-ASM_PREFERRED_EH_DATA_FOR.patch
+Patch3009: LoongArch-Provide-fmin-fmax-RTL-pattern.patch
+Patch3010: LoongArch-Get-__tls_get_addr-address-through-got-tab.patch
+Patch3011: LoongArch-Add-support-code-model-extreme.patch
+Patch3012: LoongArch-Add-new-code-model-medium.patch
+Patch3013: LoongArch-Avoid-RTL-flag-check-failure-in-loongarch_.patch
+Patch3014: LoongArch-add-model-attribute.patch
+Patch3015: LoongArch-testsuite-refine-__tls_get_addr-tests-with.patch
+Patch3016: LoongArch-add-mdirect-extern-access-option.patch
+Patch3017: LoongArch-Fix-pr106828-by-define-hook-TARGET_ASAN_SH.patch
+Patch3018: LoongArch-Prepare-static-PIE-support.patch
+Patch3019: LoongArch-Libitm-add-LoongArch-support.patch
+Patch3020: LoongArch-Fixed-a-typo-in-the-comment-information-of.patch
+Patch3021: LoongArch-Use-UNSPEC-for-fmin-fmax-RTL-pattern-PR105.patch
+Patch3022: LoongArch-Fixed-a-bug-in-the-loongarch-architecture-.patch
+Patch3023: LoongArch-implement-count_-leading-trailing-_zeros.patch
+Patch3024: Libvtv-Add-loongarch-support.patch
+Patch3025: LoongArch-Add-fcopysign-instructions.patch
+Patch3026: LoongArch-fix-signed-overflow-in-loongarch_emit_int_.patch
+Patch3027: LoongArch-Rename-frint_-fmt-to-rint-mode-2.patch
+Patch3028: LoongArch-Add-ftint-rm-rp-.-w-l-.-s-d-instructions.patch
+Patch3029: LoongArch-Add-fscaleb.-s-d-instructions-as-ldexp-sf-.patch
+Patch3030: LoongArch-Add-flogb.-s-d-instructions-and-expand-log.patch
+Patch3031: LoongArch-Add-prefetch-instructions.patch
+Patch3032: LoongArch-Optimize-immediate-load.patch
+Patch3033: LoongArch-Optimize-the-implementation-of-stack-check.patch
+Patch3034: LoongArch-Fixed-a-compilation-failure-with-c-in-inli.patch
+Patch3035: LoongArch-Don-t-add-crtfastmath.o-for-shared.patch
+Patch3036: LoongArch-Generate-bytepick.-wd-for-suitable-bit-ope.patch
+Patch3037: LoongArch-Change-the-value-of-macro-TRY_EMPTY_VM_SPA.patch
+Patch3038: LoongArch-testsuite-Disable-stack-protector-for-some.patch
+Patch3039: LoongArch-Add-built-in-functions-description-of-Loon.patch
+Patch3040: LoongArch-Remove-the-definition-of-the-macro-LOGICAL.patch
+Patch3041: LoongArch-Optimize-additions-with-immediates.patch
+Patch3042: LoongArch-Improve-GAR-store-for-va_list.patch
+Patch3043: LoongArch-Improve-cpymemsi-expansion-PR109465.patch
+Patch3044: LoongArch-Fix-MUSL_DYNAMIC_LINKER.patch
+Patch3045: LoongArch-Enable-shrink-wrapping.patch
+Patch3046: LoongArch-Change-the-default-value-of-LARCH_CALL_RAT.patch
+Patch3047: LoongArch-Set-default-alignment-for-functions-and-la.patch
+Patch3048: LoongArch-Avoid-non-returning-indirect-jumps-through.patch
+Patch3049: Loongarch-Fix-plugin-header-missing-install.patch
+Patch3050: libffi-Backport-of-LoongArch-support-for-libffi.patch
+Patch3051: LoongArch-Remove-redundant-sign-extension-instructio.patch
+Patch3052: LoongArch-Enable-free-starting-at-O2.patch
+Patch3053: LoongArch-Fix-bug-in-loongarch_emit_stack_tie-PR1104.patch
+Patch3054: LoongArch-Implement-128-bit-floating-point-functions.patch
+Patch3056: LoongArch-Optimize-switch-with-sign-extended-index.patch
+Patch3057: LoongArch-Support-storing-floating-point-zero-into-M.patch
+Patch3058: LoongArch-improved-target-configuration-interface.patch
+Patch3059: LoongArch-define-preprocessing-macros-__loongarch_-a.patch
+Patch3060: LoongArch-add-new-configure-option-with-strict-align.patch
+Patch3061: LoongArch-support-loongarch-elf-target.patch
+Patch3062: LoongArch-initial-ada-support-on-linux.patch
+Patch3063: LoongArch-Add-Loongson-SX-base-instruction-support.patch
+Patch3064: LoongArch-Add-Loongson-SX-directive-builtin-function.patch
+Patch3065: LoongArch-Add-Loongson-ASX-base-instruction-support.patch
+Patch3066: LoongArch-Add-Loongson-ASX-directive-builtin-functio.patch
+Patch3067: LoongArch-Fix-unintentionally-breakage-in-r14-3665.patch
+Patch3068: LoongArch-Use-bstrins-instruction-for-a-mask-and-a-m.patch
+Patch3069: LoongArch-Adjust-C-multilib-header-layout.patch
+Patch3070: LoongArch-Fix-unintentional-bash-ism-in-r14-3665.patch
+Patch3071: LoongArch-Enable-fsched-pressure-by-default-at-O1-an.patch
+Patch3072: LoongArch-Use-LSX-and-LASX-for-block-move.patch
+Patch3073: LoongArch-Slightly-simplify-loongarch_block_move_str.patch
+Patch3074: LoongArch-Optimized-multiply-instruction-generation.patch
+Patch3075: LoongArch-Fix-up-memcpy-vec-3.c-test-case.patch
+Patch3076: LoongArch-Add-tests-of-mstrict-align-option.patch
+Patch3077: LoongArch-Add-testsuite-framework-for-Loongson-SX-AS.patch
+Patch3078: LoongArch-Add-tests-for-Loongson-SX-builtin-function.patch
+Patch3079: LoongArch-Add-tests-for-SX-vector-floating-point-ins.patch
+Patch3080: LoongArch-Add-tests-for-SX-vector-addition-instructi.patch
+Patch3081: LoongArch-Add-tests-for-SX-vector-subtraction-instru.patch
+Patch3082: LoongArch-Add-tests-for-SX-vector-addition-vsadd-ins.patch
+Patch3083: LoongArch-Add-tests-for-the-SX-vector-multiplication.patch
+Patch3084: LoongArch-Add-tests-for-SX-vector-vavg-vavgr-instruc.patch
+Patch3085: LoongArch-Add-tests-for-SX-vector-vmax-vmaxi-vmin-vm.patch
+Patch3086: LoongArch-Add-tests-for-SX-vector-vexth-vextl-vldi-v.patch
+Patch3087: LoongArch-Add-tests-for-SX-vector-vabsd-vmskgez-vmsk.patch
+Patch3088: LoongArch-Add-tests-for-SX-vector-vdiv-vmod-instruct.patch
+Patch3089: LoongArch-Add-tests-for-SX-vector-vsll-vslli-vsrl-vs.patch
+Patch3090: LoongArch-Add-tests-for-SX-vector-vrotr-vrotri-vsra-.patch
+Patch3091: LoongArch-Add-tests-for-SX-vector-vssran-vssrani-vss.patch
+Patch3092: LoongArch-Add-tests-for-SX-vector-vbitclr-vbitclri-v.patch
+Patch3093: LoongArch-Add-tests-for-SX-vector-floating-point-ari.patch
+Patch3094: LoongArch-Add-tests-for-SX-vector-vfrstp-vfrstpi-vse.patch
+Patch3095: LoongArch-Add-tests-for-SX-vector-vfcmp-instructions.patch
+Patch3096: LoongArch-Add-tests-for-SX-vector-handling-and-shuff.patch
+Patch3097: LoongArch-Add-tests-for-SX-vector-vand-vandi-vandn-v.patch
+Patch3098: LoongArch-Add-tests-for-SX-vector-vfmadd-vfnmadd-vld.patch
+Patch3099: LoongArch-Add-tests-for-ASX-vector-xvadd-xvadda-xvad.patch
+Patch3100: LoongArch-Add-tests-for-ASX-vector-xvhadd-xvhaddw-xv.patch
+Patch3101: LoongArch-Add-tests-for-ASX-vector-subtraction-instr.patch
+Patch3102: LoongArch-Add-tests-for-ASX-vector-xvmul-xvmod-xvdiv.patch
+Patch3103: LoongArch-Add-tests-for-ASX-vector-xvmax-xvmaxi-xvmi.patch
+Patch3104: LoongArch-Add-tests-for-ASX-vector-xvldi-xvmskgez-xv.patch
+Patch3105: LoongArch-Add-tests-for-ASX-vector-xvand-xvandi-xvan.patch
+Patch3106: LoongArch-Add-tests-for-ASX-vector-xvsll-xvsrl-instr.patch
+Patch3107: LoongArch-Add-tests-for-ASX-vector-xvextl-xvsra-xvsr.patch
+Patch3108: LoongArch-Add-tests-for-ASX-vector-xvbitclr-xvbitclr.patch
+Patch3109: LoongArch-Add-tests-for-ASX-builtin-functions.patch
+Patch3110: LoongArch-Add-tests-for-ASX-xvldrepl-xvstelm-instruc.patch
+Patch3111: LoongArch-Add-tests-for-ASX-vector-floating-point-op.patch
+Patch3112: LoongArch-Add-tests-for-ASX-vector-floating-point-co.patch
+Patch3113: LoongArch-Add-tests-for-ASX-vector-comparison-and-se.patch
+Patch3114: LoongArch-Add-tests-for-ASX-vector-xvfnmadd-xvfrstp-.patch
+Patch3115: LoongArch-Add-tests-for-ASX-vector-xvabsd-xvavg-xvav.patch
+Patch3116: LoongArch-Add-tests-for-ASX-vector-xvfcmp-caf-ceq-cl.patch
+Patch3117: LoongArch-Add-tests-for-ASX-vector-xvfcmp-saf-seq-sl.patch
+Patch3118: LoongArch-Add-tests-for-ASX-vector-xvext2xv-xvexth-x.patch
+Patch3119: LoongArch-Add-tests-for-ASX-vector-xvpackev-xvpackod.patch
+Patch3120: LoongArch-Add-tests-for-ASX-vector-xvssrln-xvssrlni-.patch
+Patch3121: LoongArch-Add-tests-for-ASX-vector-xvssran-xvssrani-.patch
+Patch3122: LoongArch-Fix-bug-of-optab-di3_fake.patch
+Patch3123: LoongArch-Change-the-value-of-branch_cost-from-2-to-.patch
+Patch3124: libsanitizer-add-LoongArch-support.patch
+Patch3125: LoongArch-fix-error-building.patch
+Patch3126: libjccjit-do-not-link-objects-contained-same-element.patch
+Patch3127: LoongArch-Use-finer-grained-DBAR-hints.patch
+Patch3128: LoongArch-Add-LA664-support.patch
+Patch3129: LoongArch-Fix-internal-error-running-gcc-march-nativ.patch
+Patch3130: LoongArch-Fix-lsx-vshuf.c-and-lasx-xvshuf_b.c-tests-.patch
+# -- Update to master, lastest commit: 60e99901aef8e7efd4d60adf9f82021fcbd1101f
+Patch3131: 0001-LoongArch-Reimplement-multilib-build-option-handling.patch
+Patch3132: 0002-LoongArch-Check-whether-binutils-supports-the-relax-.patch
+Patch3133: 0003-Modify-gas-uleb128-support-test.patch
+Patch3134: 0004-LoongArch-Optimizations-of-vector-construction.patch
+Patch3135: 0005-LoongArch-Replace-UNSPEC_FCOPYSIGN-with-copysign-RTL.patch
+Patch3136: 0006-LoongArch-Adjust-makefile-dependency-for-loongarch-h.patch
+Patch3137: 0007-LoongArch-Enable-vect.exp-for-LoongArch.-PR111424.patch
+Patch3138: 0008-LoongArch-Delete-macro-definition-ASM_OUTPUT_ALIGN_W.patch
+Patch3139: 0009-LoongArch-Fix-vec_initv32qiv16qi-template-to-avoid-I.patch
+Patch3140: 0010-LoongArch-Use-fcmp.caf.s-instead-of-movgr2cf-for-zer.patch
+Patch3141: 0011-LoongArch-Implement-avg-and-sad-standard-names.patch
+Patch3142: 0012-LoongArch-Implement-vec_widen-standard-names.patch
+Patch3143: 0013-LoongArch-Implement-the-new-vector-cost-model-framew.patch
+Patch3144: 0014-LoongArch-Define-macro-CLEAR_INSN_CACHE.patch
+Patch3145: 0015-LoongArch-Add-enum-style-mexplicit-relocs-option.patch
+Patch3146: 0016-LoongArch-Use-explicit-relocs-for-GOT-access-when-me.patch
+Patch3147: 0017-LoongArch-Use-explicit-relocs-for-TLS-access-with-me.patch
+Patch3148: 0018-LoongArch-Use-explicit-relocs-for-addresses-only-use.patch
+Patch3149: 0019-LoongArch-Implement-__builtin_thread_pointer-for-TLS.patch
+Patch3150: 0020-LoongArch-Fix-vfrint-releated-comments-in-lsxintrin..patch
+Patch3151: 0021-LoongArch-Enable-vcond_mask_mn-expanders-for-SF-DF-m.patch
+Patch3152: 0022-LoongArch-Define-HAVE_AS_TLS-to-0-if-it-s-undefined-.patch
+Patch3153: 0023-LoongArch-Fix-instruction-name-typo-in-lsx_vreplgr2v.patch
+Patch3154: 0024-LoongArch-Use-simplify_gen_subreg-instead-of-gen_rtx.patch
+Patch3155: 0025-LoongArch-Optimize-single-used-address-with-mexplici.patch
+Patch3156: 0026-LoongArch-Disable-relaxation-if-the-assembler-don-t-.patch
+Patch3157: 0027-LoongArch-Remove-redundant-barrier-instructions-befo.patch
+Patch3158: 0028-LoongArch-Fix-scan-assembler-times-of-lasx-lsx-test-.patch
+Patch3159: 0029-LoongArch-Increase-cost-of-vector-aligned-store-load.patch
+Patch3160: 0030-LoongArch-Implement-C-LT-Z_DEFINED_VALUE_AT_ZERO.patch
+Patch3161: 0031-LoongArch-Handle-vectorized-copysign-x-1-expansion-e.patch
+Patch3162: 0032-LoongArch-Add-code-generation-support-for-call36-fun.patch
+Patch3163: 0033-LoongArch-Implement-atomic-operations-using-LoongArc.patch
+Patch3164: 0034-LoongArch-atomic_load-and-atomic_store-are-implement.patch
+Patch3165: 0035-LoongArch-genopts-Add-infrastructure-to-generate-cod.patch
+Patch3166: 0036-LoongArch-Add-evolution-features-of-base-ISA-revisio.patch
+Patch3167: 0037-LoongArch-Take-the-advantage-of-mdiv32-if-it-s-enabl.patch
+Patch3168: 0038-LoongArch-Don-t-emit-dbar-0x700-if-mld-seq-sa.patch
+Patch3169: 0039-LoongArch-Add-fine-grained-control-for-LAM_BH-and-LA.patch
+Patch3170: 0040-LoongArch-Fix-mexplict-relocs-none-mcmodel-medium-pr.patch
+Patch3171: 0041-LoongArch-Modify-MUSL_DYNAMIC_LINKER.patch
+Patch3172: 0042-LoongArch-Fix-libgcc-build-failure-when-libc-is-not-.patch
+Patch3173: 0043-LoongArch-Optimize-LSX-vector-shuffle-on-floating-po.patch
+Patch3174: 0044-LoongArch-Optimize-the-loading-of-immediate-numbers-.patch
+Patch3175: 0045-LoongArch-Fix-runtime-error-in-a-gcc-build-with-with.patch
+Patch3176: 0046-LoongArch-Fix-usage-of-LSX-and-LASX-frint-ftint-inst.patch
+Patch3177: 0047-LoongArch-Use-standard-pattern-name-and-RTX-code-for.patch
+Patch3178: 0048-LoongArch-Use-standard-pattern-name-and-RTX-code-for.patch
+Patch3179: 0049-LoongArch-Remove-lrint_allow_inexact.patch
+Patch3180: 0050-LoongArch-Use-LSX-for-scalar-FP-rounding-with-explic.patch
+Patch3181: 0051-LoongArch-Remove-duplicate-definition-of-CLZ_DEFINED.patch
+Patch3182: 0052-LoongArch-Added-vectorized-hardware-inspection-for-t.patch
+Patch3183: 0053-LoongArch-Accelerate-optimization-of-scalar-signed-u.patch
+Patch3184: 0054-LoongArch-Optimize-vector-constant-extract-even-odd-.patch
+Patch3185: 0055-LoongArch-Add-intrinsic-function-descriptions-for-LS.patch
+Patch3186: 0056-LoongArch-Switch-loongarch-def-from-C-to-C-to-make-i.patch
+Patch3187: 0057-LoongArch-Remove-the-definition-of-ISA_BASE_LA64V110.patch
+Patch3188: 0058-LoongArch-Add-support-for-xorsign.patch
+Patch3189: 0059-LoongArch-Add-support-for-LoongArch-V1.1-approximate.patch
+Patch3190: 0060-LoongArch-Use-standard-pattern-name-for-xvfrsqrt-vfr.patch
+Patch3191: 0061-LoongArch-Redefine-pattern-for-xvfrecip-vfrecip-inst.patch
+Patch3192: 0062-LoongArch-New-options-mrecip-and-mrecip-with-ffast-m.patch
+Patch3193: 0063-LoongArch-Vectorized-loop-unrolling-is-disable-for-d.patch
+Patch3194: 0064-LoongArch-Fix-lsx-vshuf.c-and-lasx-xvshuf_b.c-tests-.patch
+Patch3195: 0065-LoongArch-Fix-ICE-and-use-simplify_gen_subreg-instea.patch
+Patch3196: 0066-LoongArch-Fix-eh_return-epilogue-for-normal-returns.patch
+Patch3197: 0067-LoongArch-Allow-mcmodel-extreme-and-model-attribute-.patch
+Patch3198: 0068-LoongArch-Fix-warnings-building-libgcc.patch
+Patch3199: 0069-LoongArch-testsuite-Remove-XFAIL-in-vect-ftint-no-in.patch
+Patch3200: 0070-LoongArch-Include-rtl.h-for-COSTS_N_INSNS-instead-of.patch
+Patch3201: 0071-LoongArch-Fix-instruction-costs-PR112936.patch
+Patch3202: 0072-LoongArch-Add-alslsi3_extend.patch
+Patch3203: 0073-LoongArch-Add-support-for-D-frontend.patch
+Patch3204: 0074-libruntime-Add-fiber-context-switch-code-for-LoongAr.patch
+Patch3205: 0075-LoongArch-Fix-FP-vector-comparsons-PR113034.patch
+Patch3206: 0076-LoongArch-Use-force_reg-instead-of-gen_reg_rtx-emit_.patch
+Patch3207: 0077-LoongArch-Clean-up-vec_init-expander.patch
+Patch3208: 0078-LoongArch-Fix-incorrect-code-generation-for-sad-patt.patch
+Patch3209: 0079-LoongArch-Modify-the-check-type-of-the-vector-builti.patch
+Patch3210: 0080-LoongArch-extend.texi-Fix-typos-in-LSX-intrinsics.patch
+Patch3211: 0081-LoongArch-Fix-builtin-function-prototypes-for-LASX-i.patch
+Patch3212: 0082-LoongArch-Add-asm-modifiers-to-the-LSX-and-LASX-dire.patch
+Patch3213: 0083-LoongArch-Implement-FCCmode-reload-and-cstore-ANYF-m.patch
+Patch3214: 0084-LoongArch-Add-sign_extend-pattern-for-32-bit-rotate-.patch
+Patch3215: 0085-LoongArch-Fixed-bug-in-bstrins_-mode-_for_ior_mask-t.patch
+Patch3216: 0086-LoongArch-Fix-insn-output-of-vec_concat-templates-fo.patch
+Patch3217: 0087-LoongArch-Fix-ICE-when-passing-two-same-vector-argum.patch
+Patch3218: 0088-LoongArch-Expand-left-rotate-to-right-rotate-with-ne.patch
+Patch3219: 0089-LoongArch-Fix-infinite-secondary-reloading-of-FCCmod.patch
+Patch3220: 0090-LoongArch-Replace-mexplicit-relocs-auto-simple-used-.patch
+Patch3221: 0091-LoongArch-Fix-the-format-of-bstrins_-mode-_for_ior_m.patch
+Patch3222: 0092-LoongArch-Added-TLS-Le-Relax-support.patch
+Patch3223: 0093-LoongArch-Provide-fmin-fmax-RTL-pattern-for-vectors.patch
+Patch3224: 0094-LoongArch-Merge-constant-vector-permuatation-impleme.patch
+Patch3225: 0095-LoongArch-testsuite-Fix-FAIL-in-lasx-xvstelm.c-file.patch
+Patch3226: 0096-LoongArch-testsuite-Modify-the-test-behavior-of-the-.patch
+Patch3227: 0097-LoongArch-testsuite-Delete-the-default-run-behavior-.patch
+Patch3228: 0098-LoongArch-testsuite-Added-additional-vectorization-m.patch
+Patch3229: 0099-LoongArch-testsuite-Give-up-the-detection-of-the-gcc.patch
+Patch3230: 0100-LoongArch-Fixed-the-problem-of-incorrect-judgment-of.patch
+Patch3231: 0101-LoongArch-Improve-lasx_xvpermi_q_-LASX-mode-insn-pat.patch
+Patch3232: 0102-LoongArch-Implement-vec_init-M-N-where-N-is-a-LSX-ve.patch
+Patch3233: 0103-LoongArch-Handle-ISA-evolution-switches-along-with-o.patch
+Patch3234: 0104-LoongArch-Rename-ISA_BASE_LA64V100-to-ISA_BASE_LA64.patch
+Patch3235: 0105-LoongArch-Use-enums-for-constants.patch
+Patch3236: 0106-LoongArch-Simplify-mexplicit-reloc-definitions.patch
+Patch3237: 0107-LoongArch-testsuite-Add-loongarch-support-to-slp-21..patch
+Patch3238: 0108-LoongArch-Optimized-some-of-the-symbolic-expansion-i.patch
+Patch3239: 0109-LoongArch-Implement-option-save-restore.patch
+Patch3240: 0110-LoongArch-Redundant-sign-extension-elimination-optim.patch
+Patch3241: 0111-LoongArch-Redundant-sign-extension-elimination-optim.patch
+Patch3242: 0112-LoongArch-Assign-the-u-attribute-to-the-mem-to-which.patch
+Patch3243: 0113-LoongArch-testsuite-Fix-fail-in-gen-vect-2-25-.c-fil.patch
+Patch3244: 0114-LoongArch-Remove-constraint-z-from-movsi_internal.patch
+Patch3245: 0115-LoongArch-doc-Add-attribute-descriptions-defined-in-.patch
+Patch3246: 0116-LoongArch-Disable-explicit-reloc-for-TLS-LD-GD-with-.patch
+Patch3247: 0117-LoongArch-testsuite-Disable-stack-protector-for-got-.patch
+Patch3248: 0118-LoongArch-Disable-TLS-type-symbols-from-generating-n.patch
+Patch3249: 0119-LoongArch-Remove-vec_concatz-mode-pattern.patch
+Patch3250: 0120-LoongArch-Optimize-implementation-of-single-precisio.patch
+Patch3251: 0121-LoongArch-Define-LOGICAL_OP_NON_SHORT_CIRCUIT.patch
+Patch3252: 0122-LoongArch-Split-vec_selects-of-bottom-elements-into-.patch
+Patch3253: 0123-LoongArch-Modify-the-address-calculation-logic-for-o.patch
+Patch3254: 0124-LoongArch-Merge-template-got_load_tls_-ld-gd-le-ie.patch
+Patch3255: 0125-LoongArch-Add-the-macro-implementation-of-mcmodel-ex.patch
+Patch3256: 0126-LoongArch-Enable-explicit-reloc-for-extreme-TLS-GD-L.patch
+Patch3257: 0127-LoongArch-Added-support-for-loading-__get_tls_addr-s.patch
+Patch3258: 0128-LoongArch-Don-t-split-the-instructions-containing-re.patch
+Patch3259: 0129-LoongArch-Adjust-cost-of-vector_stmt-that-match-mult.patch
+Patch3260: 0130-LoongArch-Fix-incorrect-return-type-for-frecipe-frsq.patch
+Patch3261: 0131-LoongArch-Fix-an-ODR-violation.patch
+Patch3262: 0132-LoongArch-testsuite-Fix-gcc.dg-vect-vect-reduc-mul_-.patch
+Patch3263: 0133-LoongArch-Avoid-out-of-bounds-access-in-loongarch_sy.patch
+Patch3264: 0134-LoongArch-Fix-wrong-LSX-FP-vector-negation.patch
+Patch3265: 0135-LoongArch-Fix-wrong-return-value-type-of-__iocsrrd_h.patch
+Patch3266: 0136-LoongArch-Remove-redundant-symbol-type-conversions-i.patch
+Patch3267: 0137-LoongArch-When-checking-whether-the-assembler-suppor.patch
+Patch3268: 0138-LoongArch-Don-t-falsely-claim-gold-supported-in-topl.patch
+Patch3269: 0139-LoongArch-NFC-Deduplicate-crc-instruction-defines.patch
+Patch3270: 0140-LoongArch-Remove-unneeded-sign-extension-after-crc-c.patch
+Patch3271: 0141-LoongArch-Allow-s9-as-a-register-alias.patch
+Patch3272: 0142-LoongArch-testsuite-Rewrite-x-vfcmp-d-f-.c-to-avoid-.patch
+Patch3273: 0143-LoongArch-Use-lib-instead-of-lib64-as-the-library-se.patch
+Patch3274: 0144-LoongArch-testsuite-Fix-problems-with-incorrect-resu.patch
+Patch3275: 0145-LoongArch-Fixed-an-issue-with-the-implementation-of-.patch
+Patch3276: 0146-LoongArch-testsuite-Add-compilation-options-to-the-r.patch
+Patch3277: 0147-LoongArch-Emit-R_LARCH_RELAX-for-TLS-IE-with-non-ext.patch
+Patch3278: 0148-LoongArch-Remove-unused-and-incorrect-sge-u-_-X-mode.patch
+Patch3279: 0149-LoongArch-Remove-masking-process-for-operand-3-of-xv.patch
+Patch3280: 0150-LoongArch-Fix-C23-.-functions-returning-large-aggreg.patch
+Patch3281: 0151-LoongArch-Remove-unused-useless-definitions.patch
+Patch3282: 0152-LoongArch-Change-loongarch_expand_vec_cmp-s-return-t.patch
+Patch3283: 0153-LoongArch-Combine-UNITS_PER_FP_REG-and-UNITS_PER_FPR.patch
+Patch3284: 0154-LoongArch-Fix-a-typo-PR-114407.patch
+Patch3285: 0155-testsuite-Add-a-test-case-for-negating-FP-vectors-co.patch
+Patch3286: 0156-LoongArch-Add-descriptions-of-the-compilation-option.patch
+Patch3287: 0157-LoongArch-Split-loongarch_option_override_internal-i.patch
+Patch3288: 0158-LoongArch-Regenerate-loongarch.opt.urls.patch
+Patch3289: 0159-LoongArch-Add-support-for-TLS-descriptors.patch
+Patch3290: 0160-LoongArch-Fix-missing-plugin-header.patch
+Patch3291: 0161-LoongArch-Remove-unused-code.patch
+Patch3292: 0162-LoongArch-Set-default-alignment-for-functions-jumps-.patch
+Patch3293: 0163-LoongArch-Enable-switchable-target.patch
+Patch3294: 0164-LoongArch-Define-ISA-versions.patch
+Patch3295: 0165-LoongArch-Define-builtin-macros-for-ISA-evolutions.patch
+Patch3296: 0166-LoongArch-Add-constraints-for-bit-string-operation-d.patch
+Patch3297: 0167-LoongArch-Guard-REGNO-with-REG_P-in-loongarch_expand.patch
+Patch3298: 0168-LoongArch-Fix-mode-size-comparision-in-loongarch_exp.patch
+Patch3299: 0169-LoongArch-Use-bstrins-for-value-1u-const.patch
+Patch3300: 0170-LoongArch-Tweak-IOR-rtx_cost-for-bstrins.patch
+Patch3301: 0171-LoongArch-NFC-Dedup-and-sort-the-comment-in-loongarc.patch
+Patch3302: 0172-LoongArch-Fix-explicit-relocs-extreme-tls-desc.c-tes.patch
+Patch3303: 0173-LoongArch-Define-loongarch_insn_cost-and-set-the-cos.patch
+Patch3304: 0174-LoongArch-TFmode-is-not-allowed-to-be-stored-in-the-.patch
+Patch3305: 0175-LoongArch-Remove-unreachable-codes.patch
+Patch3306: 0176-LoongArch-Organize-the-code-related-to-split-move-an.patch
+Patch3307: 0177-LoongArch-Expand-some-SImode-operations-through-si3_.patch
+Patch3308: 0178-LoongArch-Relax-ins_zero_bitmask_operand-and-remove-.patch
+Patch3309: 0179-LoongArch-Rework-bswap-hi-si-di-2-definition.patch
+Patch3310: 0180-testsuite-fix-dg-do-preprocess-typo.patch
+Patch3311: 0181-LoongArch-Remove-gawk-extension-from-a-generator-scr.patch
+Patch3312: 0182-LoongArch-Use-iorn-and-andn-standard-pattern-names.patch
+Patch3313: 0183-LoongArch-Drop-vcond-u-expanders.patch
+Patch3314: 0184-LoongArch-Provide-ashr-lshr-and-ashl-RTL-pattern-for.patch
+Patch3315: 0185-LoongArch-Implement-scalar-isinf-isnormal-and-isfini.patch
+Patch3316: 0186-LoongArch-Add-support-to-annotate-tablejump.patch
+Patch3317: 0187-LoongArch-Fix-up-r15-4130.patch
+Patch3318: 0188-libphobos-Update-build-scripts-for-LoongArch64.patch
+Patch3319: 0189-LoongArch-fix-building-errors.patch
+Patch3320: 0190-tree-optimization-110702-avoid-zero-based-memory-ref.patch
+Patch3321: 0191-LoongArch-Change-OSDIR-for-distribution.patch
+Patch3322: Fix-indentation-and-numbering-errors.diff
+Patch3323: LoongArch-Allow-attributes-in-non-gnu-namespaces.diff
+%endif
+
+# On ARM EABI systems, we do want -gnueabi to be part of the
+# target triple.
+%ifnarch %{arm}
+%global _gnu %{nil}
+%else
+%global _gnu -gnueabi
+%endif
+%ifarch sparcv9
+%global gcc_target_platform sparc64-%{_vendor}-%{_target_os}
+%endif
+%ifarch ppc ppc64p7
+%global gcc_target_platform ppc64-%{_vendor}-%{_target_os}
+%endif
+%ifnarch sparcv9 ppc ppc64p7
+%global gcc_target_platform %{_target_platform}
+%endif
+
+%if %{build_go}
+# Avoid stripping these libraries and binaries.
+%global __os_install_post \
+chmod 644 %{buildroot}%{_prefix}/%{_lib}/libgo.so.21.* \
+chmod 644 %{buildroot}%{_prefix}/bin/go.gcc \
+chmod 644 %{buildroot}%{_prefix}/bin/gofmt.gcc \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json \
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet \
+%__os_install_post \
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgo.so.21.* \
+chmod 755 %{buildroot}%{_prefix}/bin/go.gcc \
+chmod 755 %{buildroot}%{_prefix}/bin/gofmt.gcc \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json \
+chmod 755 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet \
+%{nil}
+%endif
+
+%description
+The gcc package contains the GNU Compiler Collection version 12.
+You'll need this package in order to compile C code.
+
+%package -n libgcc
+Summary: GCC version 12 shared support library
+Autoreq: false
+%if !%{build_ada}
+Obsoletes: libgnat < %{version}-%{release}
+%endif
+Obsoletes: libgcj < %{version}-%{release}
+Obsoletes: libgcj-devel < %{version}-%{release}
+Obsoletes: libgcj-src < %{version}-%{release}
+%ifarch %{ix86} x86_64
+Obsoletes: libcilkrts
+Obsoletes: libcilkrts-static
+Obsoletes: libmpx
+Obsoletes: libmpx-static
+%endif
+
+%description -n libgcc
+This package contains GCC shared support library which is needed
+e.g. for exception handling support.
+
+%package c++
+Summary: C++ support for GCC
+Requires: gcc = %{version}-%{release}
+Requires: libstdc++ = %{version}-%{release}
+Requires: libstdc++-devel = %{version}-%{release}
+Provides: gcc-g++ = %{version}-%{release}
+Provides: g++ = %{version}-%{release}
+Autoreq: true
+
+%description c++
+This package adds C++ support to the GNU Compiler Collection.
+It includes support for most of the current C++ specification,
+including templates and exception handling.
+
+%package -n libstdc++
+Summary: GNU Standard C++ Library
+Autoreq: true
+Requires: glibc >= 2.10.90-7
+
+%description -n libstdc++
+The libstdc++ package contains a rewritten standard compliant GCC Standard
+C++ Library.
+
+%package -n libstdc++-devel
+Summary: Header files and libraries for C++ development
+Requires: libstdc++%{?_isa} = %{version}-%{release}
+Autoreq: true
+
+%description -n libstdc++-devel
+This is the GNU implementation of the standard C++ libraries.  This
+package includes the header files and libraries needed for C++
+development. This includes rewritten implementation of STL.
+
+%package -n libstdc++-static
+Summary: Static libraries for the GNU standard C++ library
+Requires: libstdc++-devel = %{version}-%{release}
+Autoreq: true
+
+%description -n libstdc++-static
+Static libraries for the GNU standard C++ library.
+
+%package -n libstdc++-docs
+Summary: Documentation for the GNU standard C++ library
+Autoreq: true
+
+%description -n libstdc++-docs
+Manual, doxygen generated API information and Frequently Asked Questions
+for the GNU standard C++ library.
+
+%package objc
+Summary: Objective-C support for GCC
+Requires: gcc = %{version}-%{release}
+Requires: libobjc = %{version}-%{release}
+Autoreq: true
+
+%description objc
+gcc-objc provides Objective-C support for the GCC.
+Mainly used on systems running NeXTSTEP, Objective-C is an
+object-oriented derivative of the C language.
+
+%package objc++
+Summary: Objective-C++ support for GCC
+Requires: gcc-c++ = %{version}-%{release}, gcc-objc = %{version}-%{release}
+Autoreq: true
+
+%description objc++
+gcc-objc++ package provides Objective-C++ support for the GCC.
+
+%package -n libobjc
+Summary: Objective-C runtime
+Autoreq: true
+
+%description -n libobjc
+This package contains Objective-C shared library which is needed to run
+Objective-C dynamically linked programs.
+
+%package gfortran
+Summary: Fortran support
+Requires: gcc = %{version}-%{release}
+Requires: libgfortran = %{version}-%{release}
+%if %{build_libquadmath}
+Requires: libquadmath = %{version}-%{release}
+Requires: libquadmath-devel = %{version}-%{release}
+%endif
+Provides: gcc-fortran = %{version}-%{release}
+Provides: gfortran = %{version}-%{release}
+Autoreq: true
+
+%description gfortran
+The gcc-gfortran package provides support for compiling Fortran
+programs with the GNU Compiler Collection.
+
+%package -n libgfortran
+Summary: Fortran runtime
+Autoreq: true
+%if %{build_libquadmath}
+Requires: libquadmath = %{version}-%{release}
+%endif
+
+%description -n libgfortran
+This package contains Fortran shared library which is needed to run
+Fortran dynamically linked programs.
+
+%package -n libgfortran-static
+Summary: Static Fortran libraries
+Requires: libgfortran = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+%if %{build_libquadmath}
+Requires: libquadmath-static = %{version}-%{release}
+%endif
+
+%description -n libgfortran-static
+This package contains static Fortran libraries.
+
+%package gdc
+Summary: D support
+Requires: gcc = %{version}-%{release}
+Requires: libgphobos = %{version}-%{release}
+Provides: gcc-d = %{version}-%{release}
+Provides: gdc = %{version}-%{release}
+Autoreq: true
+
+%description gdc
+The gcc-gdc package provides support for compiling D
+programs with the GNU Compiler Collection.
+
+%package -n libgphobos
+Summary: D runtime
+Autoreq: true
+
+%description -n libgphobos
+This package contains D shared library which is needed to run
+D dynamically linked programs.
+
+%package -n libgphobos-static
+Summary: Static D libraries
+Requires: libgphobos = %{version}-%{release}
+Requires: gcc-gdc = %{version}-%{release}
+
+%description -n libgphobos-static
+This package contains static D libraries.
+
+%package -n libgomp
+Summary: GCC OpenMP v4.5 shared support library
+
+%description -n libgomp
+This package contains GCC shared support library which is needed
+for OpenMP v4.5 support.
+
+%package gdb-plugin
+Summary: GCC plugin for GDB
+Requires: gcc = %{version}-%{release}
+
+%description gdb-plugin
+This package contains GCC plugin for GDB C expression evaluation.
+
+%package -n libgccjit
+Summary: Library for embedding GCC inside programs and libraries
+Requires: gcc = %{version}-%{release}
+
+%description -n libgccjit
+This package contains shared library with GCC JIT front-end.
+
+%package -n libgccjit-devel
+Summary: Support for embedding GCC inside programs and libraries
+BuildRequires: python3-sphinx
+Requires: libgccjit = %{version}-%{release}
+
+%description -n libgccjit-devel
+This package contains header files and documentation for GCC JIT front-end.
+
+%package -n libquadmath
+Summary: GCC __float128 shared support library
+
+%description -n libquadmath
+This package contains GCC shared support library which is needed
+for __float128 math support and for Fortran REAL*16 support.
+
+%package -n libquadmath-devel
+Summary: GCC __float128 support
+Requires: libquadmath = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+
+%description -n libquadmath-devel
+This package contains headers for building Fortran programs using
+REAL*16 and programs using __float128 math.
+
+%package -n libquadmath-static
+Summary: Static libraries for __float128 support
+Requires: libquadmath-devel = %{version}-%{release}
+
+%description -n libquadmath-static
+This package contains static libraries for building Fortran programs
+using REAL*16 and programs using __float128 math.
+
+%package -n libitm
+Summary: The GNU Transactional Memory library
+
+%description -n libitm
+This package contains the GNU Transactional Memory library
+which is a GCC transactional memory support runtime library.
+
+%package -n libitm-devel
+Summary: The GNU Transactional Memory support
+Requires: libitm = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+
+%description -n libitm-devel
+This package contains headers and support files for the
+GNU Transactional Memory library.
+
+%package -n libitm-static
+Summary: The GNU Transactional Memory static library
+Requires: libitm-devel = %{version}-%{release}
+
+%description -n libitm-static
+This package contains GNU Transactional Memory static libraries.
+
+%package -n libatomic
+Summary: The GNU Atomic library
+
+%description -n libatomic
+This package contains the GNU Atomic library
+which is a GCC support runtime library for atomic operations not supported
+by hardware.
+
+%package -n libatomic-static
+Summary: The GNU Atomic static library
+Requires: libatomic = %{version}-%{release}
+
+%description -n libatomic-static
+This package contains GNU Atomic static libraries.
+
+%package -n libasan
+Summary: The Address Sanitizer runtime library
+
+%description -n libasan
+This package contains the Address Sanitizer library
+which is used for -fsanitize=address instrumented programs.
+
+%package -n libasan-static
+Summary: The Address Sanitizer static library
+Requires: libasan = %{version}-%{release}
+
+%description -n libasan-static
+This package contains Address Sanitizer static runtime library.
+
+%package -n libtsan
+Summary: The Thread Sanitizer runtime library
+
+%description -n libtsan
+This package contains the Thread Sanitizer library
+which is used for -fsanitize=thread instrumented programs.
+
+%package -n libtsan-static
+Summary: The Thread Sanitizer static library
+Requires: libtsan = %{version}-%{release}
+
+%description -n libtsan-static
+This package contains Thread Sanitizer static runtime library.
+
+%package -n libubsan
+Summary: The Undefined Behavior Sanitizer runtime library
+
+%description -n libubsan
+This package contains the Undefined Behavior Sanitizer library
+which is used for -fsanitize=undefined instrumented programs.
+
+%package -n libubsan-static
+Summary: The Undefined Behavior Sanitizer static library
+Requires: libubsan = %{version}-%{release}
+
+%description -n libubsan-static
+This package contains Undefined Behavior Sanitizer static runtime library.
+
+%package -n liblsan
+Summary: The Leak Sanitizer runtime library
+
+%description -n liblsan
+This package contains the Leak Sanitizer library
+which is used for -fsanitize=leak instrumented programs.
+
+%package -n liblsan-static
+Summary: The Leak Sanitizer static library
+Requires: liblsan = %{version}-%{release}
+
+%description -n liblsan-static
+This package contains Leak Sanitizer static runtime library.
+
+%package -n cpp
+Summary: The C Preprocessor
+Requires: filesystem >= 3
+Provides: /lib/cpp
+Autoreq: true
+
+%description -n cpp
+Cpp is the GNU C-Compatible Compiler Preprocessor.
+Cpp is a macro processor which is used automatically
+by the C compiler to transform your program before actual
+compilation. It is called a macro processor because it allows
+you to define macros, abbreviations for longer
+constructs.
+
+The C preprocessor provides four separate functionalities: the
+inclusion of header files (files of declarations that can be
+substituted into your program); macro expansion (you can define macros,
+and the C preprocessor will replace the macros with their definitions
+throughout the program); conditional compilation (using special
+preprocessing directives, you can include or exclude parts of the
+program according to various conditions); and line control (if you use
+a program to combine or rearrange source files into an intermediate
+file which is then compiled, you can use line control to inform the
+compiler about where each source line originated).
+
+You should install this package if you are a C programmer and you use
+macros.
+
+%package gnat
+Summary: Ada 83, 95, 2005 and 2012 support for GCC
+Requires: gcc = %{version}-%{release}
+Requires: libgnat = %{version}-%{release}, libgnat-devel = %{version}-%{release}
+Autoreq: true
+
+%description gnat
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+development tools, the documents and Ada compiler.
+
+%package -n libgnat
+Summary: GNU Ada 83, 95, 2005 and 2012 runtime shared libraries
+Autoreq: true
+
+%description -n libgnat
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+shared libraries, which are required to run programs compiled with the GNAT.
+
+%package -n libgnat-devel
+Summary: GNU Ada 83, 95, 2005 and 2012 libraries
+Autoreq: true
+
+%description -n libgnat-devel
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+libraries, which are required to compile with the GNAT.
+
+%package -n libgnat-static
+Summary: GNU Ada 83, 95, 2005 and 2012 static libraries
+Requires: libgnat-devel = %{version}-%{release}
+Autoreq: true
+
+%description -n libgnat-static
+GNAT is a GNU Ada 83, 95, 2005 and 2012 front-end to GCC. This package includes
+static libraries.
+
+%package go
+Summary: Go support
+Requires: gcc = %{version}-%{release}
+Requires: libgo = %{version}-%{release}
+Requires: libgo-devel = %{version}-%{release}
+Requires(post): %{_sbindir}/update-alternatives
+Requires(postun): %{_sbindir}/update-alternatives
+Provides: gccgo = %{version}-%{release}
+Autoreq: true
+
+%description go
+The gcc-go package provides support for compiling Go programs
+with the GNU Compiler Collection.
+
+%package -n libgo
+Summary: Go runtime
+Autoreq: true
+
+%description -n libgo
+This package contains Go shared library which is needed to run
+Go dynamically linked programs.
+
+%package -n libgo-devel
+Summary: Go development libraries
+Requires: libgo = %{version}-%{release}
+Autoreq: true
+
+%description -n libgo-devel
+This package includes libraries and support files for compiling
+Go programs.
+
+%package -n libgo-static
+Summary: Static Go libraries
+Requires: libgo = %{version}-%{release}
+Requires: gcc = %{version}-%{release}
+
+%description -n libgo-static
+This package contains static Go libraries.
+
+%package plugin-devel
+Summary: Support for compiling GCC plugins
+Requires: gcc = %{version}-%{release}
+Requires: gmp-devel >= 4.1.2-8, mpfr-devel >= 3.1.0, libmpc-devel >= 0.8.1
+
+%description plugin-devel
+This package contains header files and other support files
+for compiling GCC plugins.  The GCC plugin ABI is currently
+not stable, so plugins must be rebuilt any time GCC is updated.
+
+%prep
+%setup -q -n gcc-12.3.0
+
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
+%patch -P4 -p1
+%patch -P6 -p1
+%patch -P7 -p1
+%patch -P8 -p1
+%patch -P9 -p1
+%patch -P10 -p1
+%patch -P11 -p1
+%patch -P12 -p1
+%patch -P13 -p1
+%patch -P14 -p1
+%patch -P15 -p1
+%patch -P16 -p1
+%patch -P17 -p1
+%patch -P18 -p1
+%patch -P19 -p1
+%patch -P20 -p1
+%patch -P21 -p1
+%patch -P22 -p1
+%patch -P23 -p1
+%patch -P24 -p1
+%patch -P25 -p1
+%patch -P26 -p1
+%patch -P27 -p1
+%patch -P28 -p1
+%patch -P29 -p1
+%patch -P30 -p1
+%patch -P31 -p1
+%patch -P32 -p1
+%patch -P33 -p1
+%patch -P34 -p1
+%patch -P35 -p1
+%patch -P36 -p1
+%patch -P37 -p1
+%patch -P38 -p1
+%patch -P39 -p1
+%patch -P40 -p1
+%patch -P41 -p1
+%patch -P42 -p1
+%patch -P43 -p1
+%patch -P44 -p1
+%patch -P45 -p1
+%patch -P46 -p1
+%patch -P47 -p1
+%patch -P48 -p1
+%patch -P49 -p1
+%patch -P50 -p1
+%patch -P51 -p1
+%patch -P52 -p1
+%patch -P53 -p1
+%patch -P54 -p1
+%patch -P55 -p1
+%patch -P56 -p1
+%patch -P57 -p1
+%patch -P86 -p1
+%patch -P87 -p1
+%patch -P88 -p1
+%patch -P89 -p1
+%patch -P90 -p1
+%patch -P91 -p1
+%patch -P92 -p1
+%patch -P93 -p1
+%patch -P94 -p1
+%patch -P95 -p1
+%patch -P96 -p1
+%patch -P97 -p1
+%patch -P98 -p1
+%patch -P99 -p1
+%patch -P100 -p1
+%patch -P101 -p1
+%patch -P102 -p1
+%patch -P103 -p1
+%patch -P104 -p1
+%patch -P105 -p1
+%patch -P106 -p1
+%patch -P107 -p1
+%patch -P108 -p1
+%patch -P109 -p1
+%patch -P110 -p1
+%patch -P111 -p1
+%patch -P112 -p1
+%patch -P113 -p1
+%patch -P114 -p1
+%patch -P115 -p1
+%patch -P116 -p1
+%patch -P117 -p1
+%patch -P118 -p1
+%patch -P119 -p1
+%patch -P120 -p1
+%patch -P121 -p1
+%patch -P122 -p1
+%patch -P123 -p1
+%patch -P124 -p1
+%patch -P125 -p1
+%patch -P126 -p1
+%patch -P127 -p1
+%patch -P128 -p1
+%patch -P129 -p1
+%patch -P130 -p1
+%patch -P131 -p1
+%patch -P132 -p1
+%patch -P133 -p1
+%patch -P134 -p1
+%patch -P135 -p1
+%patch -P136 -p1
+%patch -P137 -p1
+%patch -P138 -p1
+%patch -P139 -p1
+%patch -P140 -p1
+%patch -P141 -p1
+%patch -P142 -p1
+%patch -P143 -p1
+%patch -P144 -p1
+%patch -P145 -p1
+%patch -P146 -p1
+%patch -P147 -p1
+%patch -P148 -p1
+%patch -P149 -p1
+%patch -P150 -p1
+%patch -P151 -p1
+%patch -P152 -p1
+%patch -P153 -p1
+%patch -P154 -p1
+%patch -P155 -p1
+%patch -P156 -p1
+%patch -P157 -p1
+%patch -P158 -p1
+%patch -P159 -p1
+%patch -P160 -p1
+%patch -P161 -p1
+%patch -P162 -p1
+%patch -P163 -p1
+%patch -P164 -p1
+%patch -P165 -p1
+%patch -P166 -p1
+%patch -P167 -p1
+%patch -P168 -p1
+%patch -P169 -p1
+%patch -P170 -p1
+%patch -P171 -p1
+%patch -P172 -p1
+%patch -P173 -p1
+%patch -P174 -p1
+%patch -P175 -p1
+%patch -P176 -p1
+%patch -P177 -p1
+%patch -P178 -p1
+%patch -P179 -p1
+%patch -P180 -p1
+%patch -P181 -p1
+%patch -P182 -p1
+%patch -P183 -p1
+%patch -P184 -p1
+%patch -P185 -p1
+%patch -P186 -p1
+%patch -P187 -p1
+%patch -P188 -p1
+%patch -P189 -p1
+%patch -P190 -p1
+%patch -P191 -p1
+%patch -P192 -p1
+%patch -P193 -p1
+%patch -P194 -p1
+%patch -P195 -p1
+%patch -P196 -p1
+%patch -P197 -p1
+%patch -P198 -p1
+%patch -P199 -p1
+%patch -P200 -p1
+%patch -P201 -p1
+%patch -P202 -p1
+%patch -P203 -p1
+%patch -P204 -p1
+%patch -P205 -p1
+%patch -P206 -p1
+%patch -P207 -p1
+%patch -P208 -p1
+%patch -P209 -p1
+%patch -P210 -p1
+%patch -P211 -p1
+%patch -P212 -p1
+%patch -P213 -p1
+%patch -P214 -p1
+%patch -P215 -p1
+%patch -P216 -p1
+%patch -P217 -p1
+%patch -P218 -p1
+%patch -P219 -p1
+%patch -P220 -p1
+%patch -P221 -p1
+%patch -P222 -p1
+%patch -P223 -p1
+%patch -P224 -p1
+%patch -P225 -p1
+%patch -P226 -p1
+%patch -P227 -p1
+%patch -P228 -p1
+%patch -P229 -p1
+%patch -P230 -p1
+%patch -P231 -p1
+%patch -P232 -p1
+%patch -P233 -p1
+%patch -P234 -p1
+%patch -P235 -p1
+%patch -P236 -p1
+%patch -P237 -p1
+%patch -P238 -p1
+%patch -P239 -p1
+%patch -P240 -p1
+%patch -P241 -p1
+%patch -P242 -p1
+%patch -P243 -p1
+%patch -P244 -p1
+%patch -P245 -p1
+%patch -P246 -p1
+%patch -P247 -p1
+%patch -P248 -p1
+%patch -P249 -p1
+%patch -P250 -p1
+%patch -P251 -p1
+%patch -P252 -p1
+%patch -P253 -p1
+%patch -P254 -p1
+%patch -P255 -p1
+%patch -P256 -p1
+%patch -P257 -p1
+%patch -P258 -p1
+%patch -P259 -p1
+%patch -P260 -p1
+%patch -P261 -p1
+%patch -P262 -p1
+%patch -P263 -p1
+%patch -P264 -p1
+%patch -P265 -p1
+%patch -P266 -p1
+%patch -P267 -p1
+%patch -P268 -p1
+%patch -P269 -p1
+%patch -P270 -p1
+%patch -P271 -p1
+%patch -P272 -p1
+%patch -P273 -p1
+%patch -P274 -p1
+%patch -P275 -p1
+%patch -P276 -p1
+%patch -P277 -p1
+%patch -P278 -p1
+%patch -P279 -p1
+%patch -P280 -p1
+%patch -P281 -p1
+%patch -P282 -p1
+%patch -P283 -p1
+%patch -P284 -p1
+%patch -P285 -p1
+%patch -P286 -p1
+%patch -P287 -p1
+%patch -P288 -p1
+%patch -P289 -p1
+%patch -P290 -p1
+%patch -P291 -p1
+%patch -P292 -p1
+%patch -P293 -p1
+%patch -P294 -p1
+%patch -P295 -p1
+%patch -P296 -p1
+%patch -P297 -p1
+%patch -P298 -p1
+%patch -P299 -p1
+%patch -P300 -p1
+%patch -P301 -p1
+%patch -P302 -p1
+%patch -P303 -p1
+%patch -P304 -p1
+%patch -P305 -p1
+%patch -P306 -p1
+%patch -P307 -p1
+%patch -P308 -p1
+%patch -P309 -p1
+%patch -P310 -p1
+%patch -P311 -p1
+%patch -P312 -p1
+%patch -P313 -p1
+%patch -P314 -p1
+%patch -P315 -p1
+%patch -P316 -p1
+%patch -P317 -p1
+%patch -P318 -p1
+%patch -P319 -p1
+%patch -P320 -p1
+%patch -P321 -p1
+%patch -P322 -p1
+%patch -P323 -p1
+%patch -P324 -p1
+%patch -P325 -p1
+%patch -P326 -p1
+%patch -P327 -p1
+%patch -P328 -p1
+%patch -P329 -p1
+%patch -P330 -p1
+%patch -P331 -p1
+
+%ifarch sw_64
+%patch -P1001 -p1
+%patch -P1002 -p1
+%patch -P1003 -p1
+%patch -P1004 -p1
+%patch -P1005 -p1
+%patch -P1006 -p1
+%patch -P1007 -p1
+%patch -P1008 -p1
+%patch -P1009 -p1
+%patch -P1010 -p1
+%patch -P1011 -p1
+%patch -P1012 -p1
+%patch -P1013 -p1
+%patch -P1014 -p1
+%patch -P1015 -p1
+%patch -P1016 -p1
+%patch -P1017 -p1
+%endif
+
+%ifarch loongarch64
+%patch -P3001 -p1
+%patch -P3002 -p1
+%patch -P3003 -p1
+%patch -P3004 -p1
+%patch -P3005 -p1
+%patch -P3006 -p1
+%patch -P3007 -p1
+%patch -P3008 -p1
+%patch -P3009 -p1
+%patch -P3010 -p1
+%patch -P3011 -p1
+%patch -P3012 -p1
+%patch -P3013 -p1
+%patch -P3014 -p1
+%patch -P3015 -p1
+%patch -P3016 -p1
+%patch -P3017 -p1
+%patch -P3018 -p1
+%patch -P3019 -p1
+%patch -P3020 -p1
+%patch -P3021 -p1
+%patch -P3022 -p1
+%patch -P3023 -p1
+%patch -P3024 -p1
+%patch -P3025 -p1
+%patch -P3026 -p1
+%patch -P3027 -p1
+%patch -P3028 -p1
+%patch -P3029 -p1
+%patch -P3030 -p1
+%patch -P3031 -p1
+%patch -P3032 -p1
+%patch -P3033 -p1
+%patch -P3034 -p1
+%patch -P3035 -p1
+%patch -P3036 -p1
+%patch -P3037 -p1
+%patch -P3038 -p1
+%patch -P3039 -p1
+%patch -P3040 -p1
+%patch -P3041 -p1
+%patch -P3042 -p1
+%patch -P3043 -p1
+%patch -P3044 -p1
+%patch -P3045 -p1
+%patch -P3046 -p1
+%patch -P3047 -p1
+%patch -P3048 -p1
+%patch -P3049 -p1
+%patch -P3050 -p1
+%patch -P3051 -p1
+%patch -P3052 -p1
+%patch -P3053 -p1
+%patch -P3054 -p1
+%patch -P3056 -p1
+%patch -P3057 -p1
+%patch -P3058 -p1
+%patch -P3059 -p1
+%patch -P3060 -p1
+%patch -P3061 -p1
+%patch -P3062 -p1
+%patch -P3063 -p1
+%patch -P3064 -p1
+%patch -P3065 -p1
+%patch -P3066 -p1
+%patch -P3067 -p1
+%patch -P3068 -p1
+%patch -P3069 -p1
+%patch -P3070 -p1
+%patch -P3071 -p1
+%patch -P3072 -p1
+%patch -P3073 -p1
+%patch -P3074 -p1
+%patch -P3075 -p1
+%patch -P3076 -p1
+%patch -P3077 -p1
+%patch -P3078 -p1
+%patch -P3079 -p1
+%patch -P3080 -p1
+%patch -P3081 -p1
+%patch -P3082 -p1
+%patch -P3083 -p1
+%patch -P3084 -p1
+%patch -P3085 -p1
+%patch -P3086 -p1
+%patch -P3087 -p1
+%patch -P3088 -p1
+%patch -P3089 -p1
+%patch -P3090 -p1
+%patch -P3091 -p1
+%patch -P3092 -p1
+%patch -P3093 -p1
+%patch -P3094 -p1
+%patch -P3095 -p1
+%patch -P3096 -p1
+%patch -P3097 -p1
+%patch -P3098 -p1
+%patch -P3099 -p1
+%patch -P3100 -p1
+%patch -P3101 -p1
+%patch -P3102 -p1
+%patch -P3103 -p1
+%patch -P3104 -p1
+%patch -P3105 -p1
+%patch -P3106 -p1
+%patch -P3107 -p1
+%patch -P3108 -p1
+%patch -P3109 -p1
+%patch -P3110 -p1
+%patch -P3111 -p1
+%patch -P3112 -p1
+%patch -P3113 -p1
+%patch -P3114 -p1
+%patch -P3115 -p1
+%patch -P3116 -p1
+%patch -P3117 -p1
+%patch -P3118 -p1
+%patch -P3119 -p1
+%patch -P3120 -p1
+%patch -P3121 -p1
+%patch -P3122 -p1
+%patch -P3123 -p1
+%patch -P3124 -p1
+%patch -P3125 -p1
+%patch -P3126 -p1
+%patch -P3127 -p1
+%patch -P3128 -p1
+%patch -P3129 -p1
+%patch -P3130 -p1
+#--
+%patch -P3131 -p1
+%patch -P3132 -p1
+%patch -P3133 -p1
+%patch -P3134 -p1
+%patch -P3135 -p1
+%patch -P3136 -p1
+%patch -P3137 -p1
+%patch -P3138 -p1
+%patch -P3139 -p1
+%patch -P3140 -p1
+%patch -P3141 -p1
+%patch -P3142 -p1
+%patch -P3143 -p1
+%patch -P3144 -p1
+%patch -P3145 -p1
+%patch -P3146 -p1
+%patch -P3147 -p1
+%patch -P3148 -p1
+%patch -P3149 -p1
+%patch -P3150 -p1
+%patch -P3151 -p1
+%patch -P3152 -p1
+%patch -P3153 -p1
+%patch -P3154 -p1
+%patch -P3155 -p1
+%patch -P3156 -p1
+%patch -P3157 -p1
+%patch -P3158 -p1
+%patch -P3159 -p1
+%patch -P3160 -p1
+%patch -P3161 -p1
+%patch -P3162 -p1
+%patch -P3163 -p1
+%patch -P3164 -p1
+%patch -P3165 -p1
+%patch -P3166 -p1
+%patch -P3167 -p1
+%patch -P3168 -p1
+%patch -P3169 -p1
+%patch -P3170 -p1
+%patch -P3171 -p1
+%patch -P3172 -p1
+%patch -P3173 -p1
+%patch -P3174 -p1
+%patch -P3175 -p1
+%patch -P3176 -p1
+%patch -P3177 -p1
+%patch -P3178 -p1
+%patch -P3179 -p1
+%patch -P3180 -p1
+%patch -P3181 -p1
+%patch -P3182 -p1
+%patch -P3183 -p1
+%patch -P3184 -p1
+%patch -P3185 -p1
+%patch -P3186 -p1
+%patch -P3187 -p1
+%patch -P3188 -p1
+%patch -P3189 -p1
+%patch -P3190 -p1
+%patch -P3191 -p1
+%patch -P3192 -p1
+%patch -P3193 -p1
+%patch -P3194 -p1
+%patch -P3195 -p1
+%patch -P3196 -p1
+%patch -P3197 -p1
+%patch -P3198 -p1
+%patch -P3199 -p1
+%patch -P3200 -p1
+%patch -P3201 -p1
+%patch -P3202 -p1
+%patch -P3203 -p1
+%patch -P3204 -p1
+%patch -P3205 -p1
+%patch -P3206 -p1
+%patch -P3207 -p1
+%patch -P3208 -p1
+%patch -P3209 -p1
+%patch -P3210 -p1
+%patch -P3211 -p1
+%patch -P3212 -p1
+%patch -P3213 -p1
+%patch -P3214 -p1
+%patch -P3215 -p1
+%patch -P3216 -p1
+%patch -P3217 -p1
+%patch -P3218 -p1
+%patch -P3219 -p1
+%patch -P3220 -p1
+%patch -P3221 -p1
+%patch -P3222 -p1
+%patch -P3223 -p1
+%patch -P3224 -p1
+%patch -P3225 -p1
+%patch -P3226 -p1
+%patch -P3227 -p1
+%patch -P3228 -p1
+%patch -P3229 -p1
+%patch -P3230 -p1
+%patch -P3231 -p1
+%patch -P3232 -p1
+%patch -P3233 -p1
+%patch -P3234 -p1
+%patch -P3235 -p1
+%patch -P3236 -p1
+%patch -P3237 -p1
+%patch -P3238 -p1
+%patch -P3239 -p1
+%patch -P3240 -p1
+%patch -P3241 -p1
+%patch -P3242 -p1
+%patch -P3243 -p1
+%patch -P3244 -p1
+%patch -P3245 -p1
+%patch -P3246 -p1
+%patch -P3247 -p1
+%patch -P3248 -p1
+%patch -P3249 -p1
+%patch -P3250 -p1
+%patch -P3251 -p1
+%patch -P3252 -p1
+%patch -P3253 -p1
+%patch -P3254 -p1
+%patch -P3255 -p1
+%patch -P3256 -p1
+%patch -P3257 -p1
+%patch -P3258 -p1
+%patch -P3259 -p1
+%patch -P3260 -p1
+%patch -P3261 -p1
+%patch -P3262 -p1
+%patch -P3263 -p1
+%patch -P3264 -p1
+%patch -P3265 -p1
+%patch -P3266 -p1
+%patch -P3267 -p1
+%patch -P3268 -p1
+%patch -P3269 -p1
+%patch -P3270 -p1
+%patch -P3271 -p1
+%patch -P3272 -p1
+%patch -P3273 -p1
+%patch -P3274 -p1
+%patch -P3275 -p1
+%patch -P3276 -p1
+%patch -P3277 -p1
+%patch -P3278 -p1
+%patch -P3279 -p1
+%patch -P3280 -p1
+%patch -P3281 -p1
+%patch -P3282 -p1
+%patch -P3283 -p1
+%patch -P3284 -p1
+%patch -P3285 -p1
+%patch -P3286 -p1
+%patch -P3287 -p1
+%patch -P3288 -p1
+%patch -P3289 -p1
+%patch -P3290 -p1
+%patch -P3291 -p1
+%patch -P3292 -p1
+%patch -P3293 -p1
+%patch -P3294 -p1
+%patch -P3295 -p1
+%patch -P3296 -p1
+%patch -P3297 -p1
+%patch -P3298 -p1
+%patch -P3299 -p1
+%patch -P3300 -p1
+%patch -P3301 -p1
+%patch -P3302 -p1
+%patch -P3303 -p1
+%patch -P3304 -p1
+%patch -P3305 -p1
+%patch -P3306 -p1
+%patch -P3307 -p1
+%patch -P3308 -p1
+%patch -P3309 -p1
+%patch -P3310 -p1
+%patch -P3311 -p1
+%patch -P3312 -p1
+%patch -P3313 -p1
+%patch -P3314 -p1
+%patch -P3315 -p1
+%patch -P3316 -p1
+%patch -P3317 -p1
+%patch -P3318 -p1
+%patch -P3319 -p1
+%patch -P3320 -p1
+%patch -P3321 -p1
+%patch -P3322 -p1
+%patch -P3323 -p1
+%endif
+
+echo '%{_vendor} %{version}-%{release}' > gcc/DEV-PHASE
+
+cp -a libstdc++-v3/config/cpu/i{4,3}86/atomicity.h
+
+./contrib/gcc_update --touch
+
+LC_ALL=C sed -i -e 's/\xa0/ /' gcc/doc/options.texi
+
+sed -i -e 's/Common Driver Var(flag_report_bug)/& Init(1)/' gcc/common.opt
+sed -i -e 's/context->report_bug = false;/context->report_bug = true;/' gcc/diagnostic.cc
+
+%build
+
+export CONFIG_SITE=NONE
+
+CC=gcc
+CXX=g++
+OPT_FLAGS=`echo %{optflags}|sed -e 's/-flto=auto//g;s/-flto//g;s/-ffat-lto-objects//g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-m64//g;s/-m32//g;s/-m31//g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mfpmath=sse/-mfpmath=sse -msse2/g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/ -pipe / /g'`
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-Werror=format-security/ /g'`
+%ifarch sparc
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mcpu=ultrasparc/-mtune=ultrasparc/g;s/-mcpu=v[78]//g'`
+%endif
+%ifarch %{ix86}
+OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-march=i.86//g'`
+%endif
+OPT_FLAGS=`echo "$OPT_FLAGS" | sed -e 's/[[:blank:]]\+/ /g'`
+case "$OPT_FLAGS" in
+  *-fasynchronous-unwind-tables*)
+    sed -i -e 's/-fno-exceptions /-fno-exceptions -fno-asynchronous-unwind-tables /' \
+      libgcc/Makefile.in
+    ;;
+esac
+
+rm -rf obj-%{gcc_target_platform}
+mkdir obj-%{gcc_target_platform}
+cd obj-%{gcc_target_platform}
+
+enablelgo=
+enablelada=
+enablelobjc=
+enableld=
+%if %{build_objc}
+enablelobjc=,objc,obj-c++
+%endif
+%if %{build_ada}
+enablelada=,ada
+%endif
+%if %{build_go}
+enablelgo=,go
+%endif
+%if %{build_d}
+enableld=,d
+%endif
+
+CONFIGURE_OPTS="\
+	--prefix=%{_prefix} --mandir=%{_mandir} --infodir=%{_infodir} \
+	--with-bugurl=https://gitee.com/src-openeuler/gcc/issues \
+	--enable-shared --enable-threads=posix --enable-checking=release\
+%ifarch aarch64
+	--enable-multilib \
+%else
+	--disable-multilib \
+%endif
+	--with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions \
+	--enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only \
+	--enable-libstdcxx-backtrace \
+%ifnarch %{mips}
+	--with-linker-hash-style=gnu \
+%endif
+	--enable-plugin --enable-initfini-array \
+%if %{isl_enable}
+	--with-isl \
+%else
+	--without-isl \
+%endif
+%if %{attr_ifunc}
+	--enable-gnu-indirect-function \
+%endif
+%ifarch %{arm}
+	--disable-sjlj-exceptions \
+%endif
+%ifarch aarch64
+	--with-multilib-list=lp64 \
+        --enable-bolt
+%endif
+%ifarch %{ix86} x86_64
+	--enable-cet \
+	--with-tune=generic \
+%endif
+%ifarch %{ix86}
+	--with-arch=x86-64 \
+%endif
+%ifarch x86_64
+	--with-arch_64=x86-64-v3 \
+%endif
+%ifarch riscv64
+	--with-arch=rv64gc --with-abi=lp64d --disable-libquadmath \
+%endif
+%ifnarch sparc sparcv9 ppc
+	--build=%{gcc_target_platform} \
+%endif
+%ifarch loongarch64
+	   --with-arch=loongarch64 --with-abi=lp64d \
+	   --disable-libquadmath --disable-multilib --enable-tls \
+	   --enable-default-pie
+%endif
+%ifarch sw_64
+	--with-cpu=sw6b --disable-libquadmath --disable-multilib \
+	--enable-tls
+%endif
+	"
+
+# Add Secure Compilation Options
+OPT_FLAGS="$OPT_FLAGS -O2 -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector-strong -fPIE -Wl,-z,relro,-z,now"
+OPT_LDFLAGS="$OPT_LDFLAGS -Wl,-z,relro,-z,now"
+
+# Disable bootstrap for saving compilation time
+export extra_ldflags_libobjc="-Wl,-z,relro,-z,now"
+export FCFLAGS="$OPT_FLAGS"
+CC="$CC" CXX="$CXX" \
+	CFLAGS="$OPT_FLAGS" \
+	CXXFLAGS="`echo " $OPT_FLAGS " | sed 's/ -Wall / /g;s/ -fexceptions / /g' \
+		  | sed 's/ -Wformat-security / -Wformat -Wformat-security /'`" \
+	LDFLAGS="$OPT_LDFLAGS" \
+	CFLAGS_FOR_TARGET="$OPT_FLAGS" \
+	CXXFLAGS_FOR_TARGET="$OPT_FLAGS" \
+	XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" GCJFLAGS="$OPT_FLAGS" \
+	../configure --disable-bootstrap --disable-libgcj --without-cloog\
+	--enable-languages=c,c++,fortran${enablelobjc}${enablelada}${enablelgo}${enableld},lto \
+	$CONFIGURE_OPTS
+
+%ifarch sparc sparcv9 sparc64
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now
+%else
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" LDFLAGS_FOR_TARGET=-Wl,-z,relro,-z,now
+%endif
+
+CC="`%{gcc_target_platform}/libstdc++-v3/scripts/testsuite_flags --build-cc`"
+CXX="`%{gcc_target_platform}/libstdc++-v3/scripts/testsuite_flags --build-cxx` `%{gcc_target_platform}/libstdc++-v3/scripts/testsuite_flags --build-includes`"
+
+# Build libgccjit separately, so that normal compiler binaries aren't -fpic
+# unnecessarily.
+mkdir objlibgccjit
+cd objlibgccjit
+CC="$CC" CXX="$CXX" \
+	CFLAGS="$OPT_FLAGS" \
+	CXXFLAGS="`echo " $OPT_FLAGS " | sed 's/ -Wall / /g;s/ -fexceptions / /g' \
+		  | sed 's/ -Wformat-security / -Wformat -Wformat-security /'`" \
+	LDFLAGS="$OPT_LDFLAGS" \
+	CFLAGS_FOR_TARGET="$OPT_FLAGS" \
+	CXXFLAGS_FOR_TARGET="$OPT_FLAGS" \
+	XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" GCJFLAGS="$OPT_FLAGS" \
+	../../configure --disable-bootstrap --enable-host-shared \
+	--enable-languages=jit $CONFIGURE_OPTS
+make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" all-gcc
+cp -a gcc/libgccjit.so* ../gcc/
+cd ../gcc/
+ln -sf xgcc %{gcc_target_platform}-gcc-%{gcc_major}
+cp -a Makefile{,.orig}
+sed -i -e '/^CHECK_TARGETS/s/$/ check-jit/' Makefile
+touch -r Makefile.orig Makefile
+rm Makefile.orig
+make jit.sphinx.html
+make jit.sphinx.install-html jit_htmldir=`pwd`/../../rpm.doc/libgccjit-devel/html
+cd ..
+
+# Make generated man pages even if Pod::Man is not new enough
+perl -pi -e 's/head3/head2/' ../contrib/texi2pod.pl
+for i in ../gcc/doc/*.texi; do
+  cp -a $i $i.orig; sed 's/ftable/table/' $i.orig > $i
+done
+make -C gcc generated-manpages
+for i in ../gcc/doc/*.texi; do mv -f $i.orig $i; done
+
+# Make generated doxygen pages.
+%if %{build_libstdcxx_docs}
+cd %{gcc_target_platform}/libstdc++-v3
+make doc-html-doxygen
+make doc-man-doxygen
+cd ../..
+%endif
+
+# Copy various doc files here and there
+cd ..
+mkdir -p rpm.doc/gfortran rpm.doc/objc rpm.doc/gdc rpm.doc/libphobos
+mkdir -p rpm.doc/go rpm.doc/libgo rpm.doc/libquadmath rpm.doc/libitm
+mkdir -p rpm.doc/changelogs/{gcc/cp,gcc/ada,gcc/jit,libstdc++-v3,libobjc,libgomp,libcc1,libatomic,libsanitizer}
+
+for i in {gcc,gcc/cp,gcc/ada,gcc/jit,libstdc++-v3,libobjc,libgomp,libcc1,libatomic,libsanitizer}/ChangeLog*; do
+	cp -p $i rpm.doc/changelogs/$i
+done
+
+(cd gcc/fortran; for i in ChangeLog*; do
+	cp -p $i ../../rpm.doc/gfortran/$i
+done)
+(cd libgfortran; for i in ChangeLog*; do
+	cp -p $i ../rpm.doc/gfortran/$i.libgfortran
+done)
+%if %{build_objc}
+(cd libobjc; for i in README*; do
+	cp -p $i ../rpm.doc/objc/$i.libobjc
+done)
+%endif
+%if %{build_d}
+(cd gcc/d; for i in ChangeLog*; do
+	cp -p $i ../../rpm.doc/gdc/$i.gdc
+done)
+(cd libphobos; for i in ChangeLog*; do
+	cp -p $i ../rpm.doc/libphobos/$i.libphobos
+done
+cp -a src/LICENSE*.txt libdruntime/LICENSE.txt ../rpm.doc/libphobos/)
+%endif
+%if %{build_libquadmath}
+(cd libquadmath; for i in ChangeLog* COPYING.LIB; do
+	cp -p $i ../rpm.doc/libquadmath/$i.libquadmath
+done)
+%endif
+%if %{build_libitm}
+(cd libitm; for i in ChangeLog*; do
+	cp -p $i ../rpm.doc/libitm/$i.libitm
+done)
+%endif
+%if %{build_go}
+(cd gcc/go; for i in README* ChangeLog*; do
+	cp -p $i ../../rpm.doc/go/$i
+done)
+(cd libgo; for i in LICENSE* PATENTS* README; do
+	cp -p $i ../rpm.doc/libgo/$i.libgo
+done)
+%endif
+
+rm -f rpm.doc/changelogs/gcc/ChangeLog.[1-9]
+find rpm.doc -name \*ChangeLog\* | xargs bzip2 -9
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}
+
+# RISC-V ABI wants to install everything in /lib64/lp64d or /usr/lib64/lp64d.
+# Make these be symlinks to /lib64 or /usr/lib64 respectively. See:
+# https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/DRHT5YTPK4WWVGL3GIN5BF2IKX2ODHZ3/
+%ifarch riscv64
+for d in %{buildroot}%{_libdir} %{buildroot}/%{_lib} \
+	  %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib} \
+	  %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/%{_lib}; do
+  mkdir -p $d
+  (cd $d && ln -sf . lp64d)
+done
+%endif
+
+cd obj-%{gcc_target_platform}
+
+TARGET_PLATFORM=%{gcc_target_platform}
+
+# There are some MP bugs in libstdc++ Makefiles
+make -C %{gcc_target_platform}/libstdc++-v3
+
+make prefix=%{buildroot}%{_prefix} mandir=%{buildroot}%{_mandir} \
+  infodir=%{buildroot}%{_infodir} install
+%if %{build_ada}
+chmod 644 %{buildroot}%{_infodir}/gnat*
+%endif
+
+FULLPATH=%{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+FULLEPATH=%{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+
+# fix some things
+ln -sf gcc %{buildroot}%{_prefix}/bin/cc
+rm -f %{buildroot}%{_prefix}/lib/cpp
+ln -sf ../bin/cpp %{buildroot}/%{_prefix}/lib/cpp
+ln -sf gfortran %{buildroot}%{_prefix}/bin/f95
+rm -f %{buildroot}%{_infodir}/dir
+gzip -9 %{buildroot}%{_infodir}/*.info*
+ln -sf gcc %{buildroot}%{_prefix}/bin/gnatgcc
+mkdir -p %{buildroot}%{_fmoddir}
+
+%if %{build_go}
+mv %{buildroot}%{_prefix}/bin/go{,.gcc}
+mv %{buildroot}%{_prefix}/bin/gofmt{,.gcc}
+ln -sf /etc/alternatives/go %{buildroot}%{_prefix}/bin/go
+ln -sf /etc/alternatives/gofmt %{buildroot}%{_prefix}/bin/gofmt
+%endif
+
+cxxconfig="`find %{gcc_target_platform}/libstdc++-v3/include -name c++config.h`"
+for i in `find %{gcc_target_platform}/[36]*/libstdc++-v3/include -name c++config.h 2>/dev/null`; do
+  if ! diff -up $cxxconfig $i; then
+    cat > %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/bits/c++config.h <
+#if __WORDSIZE == 32
+%ifarch %{multilib_64_archs}
+`cat $(find %{gcc_target_platform}/32/libstdc++-v3/include -name c++config.h)`
+%else
+`cat $(find %{gcc_target_platform}/libstdc++-v3/include -name c++config.h)`
+%endif
+#else
+%ifarch %{multilib_64_archs}
+`cat $(find %{gcc_target_platform}/libstdc++-v3/include -name c++config.h)`
+%else
+`cat $(find %{gcc_target_platform}/64/libstdc++-v3/include -name c++config.h)`
+%endif
+#endif
+#endif
+EOF
+    break
+  fi
+done
+
+for f in `find %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/ -name c++config.h`; do
+  for i in 1 2 4 8; do
+    sed -i -e 's/#define _GLIBCXX_ATOMIC_BUILTINS_'$i' 1/#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_'$i'\
+&\
+#endif/' $f
+  done
+done
+
+# Nuke bits/*.h.gch dirs
+# 1) there is no bits/*.h header installed, so when gch file can't be
+#    used, compilation fails
+# 2) sometimes it is hard to match the exact options used for building
+#    libstdc++-v3 or they aren't desirable
+# 3) there are multilib issues, conflicts etc. with this
+# 4) it is huge
+# People can always precompile on their own whatever they want, but
+# shipping this for everybody is unnecessary.
+rm -rf %{buildroot}%{_prefix}/include/c++/%{gcc_major}/%{gcc_target_platform}/bits/*.h.gch
+
+%if %{build_libstdcxx_docs}
+libstdcxx_doc_builddir=%{gcc_target_platform}/libstdc++-v3/doc/doxygen
+mkdir -p ../rpm.doc/libstdc++-v3
+cp -r -p ../libstdc++-v3/doc/html ../rpm.doc/libstdc++-v3/html
+cp -r -p $libstdcxx_doc_builddir/html ../rpm.doc/libstdc++-v3/html/api
+mkdir -p %{buildroot}%{_mandir}/man3
+cp -r -p $libstdcxx_doc_builddir/man/man3/* %{buildroot}%{_mandir}/man3/
+find ../rpm.doc/libstdc++-v3 -name \*~ | xargs rm
+%endif
+
+%ifarch sparcv9 sparc64
+ln -f %{buildroot}%{_prefix}/bin/%{gcc_target_platform}-gcc \
+  %{buildroot}%{_prefix}/bin/sparc-%{_vendor}-%{_target_os}-gcc
+%endif
+%ifarch ppc ppc64 ppc64p7
+ln -f %{buildroot}%{_prefix}/bin/%{gcc_target_platform}-gcc \
+  %{buildroot}%{_prefix}/bin/ppc-%{_vendor}-%{_target_os}-gcc
+%endif
+
+FULLLSUBDIR=
+%ifarch sparcv9 ppc
+FULLLSUBDIR=lib32
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+FULLLSUBDIR=lib64
+%endif
+if [ -n "$FULLLSUBDIR" ]; then
+  FULLLPATH=$FULLPATH/$FULLLSUBDIR
+  mkdir -p $FULLLPATH
+else
+  FULLLPATH=$FULLPATH
+fi
+
+find %{buildroot} -name \*.la | xargs rm -f
+
+mv %{buildroot}%{_prefix}/%{_lib}/libgfortran.spec $FULLPATH/
+%if %{build_d}
+mv %{buildroot}%{_prefix}/%{_lib}/libgphobos.spec $FULLPATH/
+%endif
+%if %{build_libitm}
+mv %{buildroot}%{_prefix}/%{_lib}/libitm.spec $FULLPATH/
+%endif
+%if %{build_libasan}
+mv %{buildroot}%{_prefix}/%{_lib}/libsanitizer.spec $FULLPATH/
+%endif
+
+mkdir -p %{buildroot}/%{_lib}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgcc_s.so.1 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}.so.1
+chmod 755 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}.so.1
+ln -sf libgcc_s-%{gcc_major}.so.1 %{buildroot}/%{_lib}/libgcc_s.so.1
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64p7 ppc64le %{arm} aarch64 riscv64 loongarch64 sw_64
+rm -f $FULLPATH/libgcc_s.so
+echo '/* GNU ld script
+   Use the shared library, but some functions are only in
+   the static library, so try that secondarily.  */
+OUTPUT_FORMAT('`gcc -Wl,--print-output-format -nostdlib -r -o /dev/null`')
+GROUP ( /%{_lib}/libgcc_s.so.1 libgcc.a )' > $FULLPATH/libgcc_s.so
+%else
+ln -sf /%{_lib}/libgcc_s.so.1 $FULLPATH/libgcc_s.so
+%endif
+%ifarch sparcv9 ppc
+%ifarch ppc
+rm -f $FULLPATH/64/libgcc_s.so
+echo '/* GNU ld script
+   Use the shared library, but some functions are only in
+   the static library, so try that secondarily.  */
+OUTPUT_FORMAT('`gcc -m64 -Wl,--print-output-format -nostdlib -r -o /dev/null`')
+GROUP ( /lib64/libgcc_s.so.1 libgcc.a )' > $FULLPATH/64/libgcc_s.so
+%else
+ln -sf /lib64/libgcc_s.so.1 $FULLPATH/64/libgcc_s.so
+%endif
+%endif
+%ifarch %{multilib_64_archs}
+%ifarch x86_64 ppc64 ppc64p7
+rm -f $FULLPATH/64/libgcc_s.so
+echo '/* GNU ld script
+   Use the shared library, but some functions are only in
+   the static library, so try that secondarily.  */
+OUTPUT_FORMAT('`gcc -m32 -Wl,--print-output-format -nostdlib -r -o /dev/null`')
+GROUP ( /lib/libgcc_s.so.1 libgcc.a )' > $FULLPATH/32/libgcc_s.so
+%else
+ln -sf /lib/libgcc_s.so.1 $FULLPATH/32/libgcc_s.so
+%endif
+%endif
+
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.spec $FULLPATH/
+
+%if %{build_ada}
+mv -f $FULLPATH/adalib/libgnarl-*.so %{buildroot}%{_prefix}/%{_lib}/
+mv -f $FULLPATH/adalib/libgnat-*.so %{buildroot}%{_prefix}/%{_lib}/
+rm -f $FULLPATH/adalib/libgnarl.so* $FULLPATH/adalib/libgnat.so*
+%endif
+
+mkdir -p %{buildroot}%{_prefix}/libexec/getconf
+if gcc/xgcc -B gcc/ -E -P -dD -xc /dev/null | grep '__LONG_MAX__.*\(2147483647\|0x7fffffff\($\|[LU]\)\)'; then
+  ln -sf POSIX_V6_ILP32_OFF32 %{buildroot}%{_prefix}/libexec/getconf/default
+else
+  ln -sf POSIX_V6_LP64_OFF64 %{buildroot}%{_prefix}/libexec/getconf/default
+fi
+
+mkdir -p %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++*gdb.py* \
+      %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/
+pushd ../libstdc++-v3/python
+for i in `find . -name \*.py`; do
+  touch -r $i %{buildroot}%{_prefix}/share/gcc-%{gcc_major}/python/$i
+done
+touch -r hook.in %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/libstdc++*gdb.py
+popd
+for f in `find %{buildroot}%{_prefix}/share/gcc-%{gcc_major}/python/ \
+	       %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/ -name \*.py`; do
+  r=${f/$RPM_BUILD_ROOT/}
+  %{__python3} -c 'import py_compile; py_compile.compile("'$f'", dfile="'$r'")'
+  %{__python3} -O -c 'import py_compile; py_compile.compile("'$f'", dfile="'$r'")'
+done
+
+rm -f $FULLEPATH/libgccjit.so
+cp -a objlibgccjit/gcc/libgccjit.so* %{buildroot}%{_prefix}/%{_lib}/
+cp -a ../gcc/jit/libgccjit*.h %{buildroot}%{_prefix}/include/
+/usr/bin/install -c -m 644 objlibgccjit/gcc/doc/libgccjit.info %{buildroot}/%{_infodir}/
+gzip -9 %{buildroot}/%{_infodir}/libgccjit.info
+
+pushd $FULLPATH
+if [ "%{_lib}" = "lib" ]; then
+%if %{build_objc}
+ln -sf ../../../libobjc.so.4 libobjc.so
+%endif
+ln -sf ../../../libstdc++.so.6.*[0-9] libstdc++.so
+ln -sf ../../../libgfortran.so.5.* libgfortran.so
+ln -sf ../../../libgomp.so.1.* libgomp.so
+%if %{build_go}
+ln -sf ../../../libgo.so.21.* libgo.so
+%endif
+%if %{build_libquadmath}
+ln -sf ../../../libquadmath.so.0.* libquadmath.so
+%endif
+%if %{build_d}
+ln -sf ../../../libgdruntime.so.3.* libgdruntime.so
+ln -sf ../../../libgphobos.so.3.* libgphobos.so
+%endif
+%if %{build_libitm}
+ln -sf ../../../libitm.so.1.* libitm.so
+%endif
+%if %{build_libatomic}
+ln -sf ../../../libatomic.so.1.* libatomic.so
+%endif
+%if %{build_libasan}
+ln -sf ../../../libasan.so.8.* libasan.so
+mv ../../../libasan_preinit.o libasan_preinit.o
+%endif
+%if %{build_libubsan}
+ln -sf ../../../libubsan.so.1.* libubsan.so
+%endif
+%ifarch loongarch64 sw_64
+%if %{build_libtsan}
+rm -f libtsan.so
+echo 'INPUT ( %{_prefix}/%{_lib}/'`echo ../../../../%{_lib}/libtsan.so.2.* | sed 's,^.*libt,libt,'`' )' > libtsan.so
+mv ../../../../%{_lib}/libtsan_preinit.o libtsan_preinit.o
+%endif
+%if %{build_liblsan}
+rm -f liblsan.so
+echo 'INPUT ( %{_prefix}/%{_lib}/'`echo ../../../../%{_lib}/liblsan.so.0.* | sed 's,^.*libl,libl,'`' )' > liblsan.so
+mv ../../../../%{_lib}/liblsan_preinit.o liblsan_preinit.o
+%endif
+%endif
+else
+%if %{build_objc}
+ln -sf ../../../../%{_lib}/libobjc.so.4 libobjc.so
+%endif
+ln -sf ../../../../%{_lib}/libstdc++.so.6.*[0-9] libstdc++.so
+ln -sf ../../../../%{_lib}/libgfortran.so.5.* libgfortran.so
+ln -sf ../../../../%{_lib}/libgomp.so.1.* libgomp.so
+%if %{build_go}
+ln -sf ../../../../%{_lib}/libgo.so.21.* libgo.so
+%endif
+%if %{build_libquadmath}
+ln -sf ../../../../%{_lib}/libquadmath.so.0.* libquadmath.so
+%endif
+%if %{build_d}
+ln -sf ../../../../%{_lib}/libgdruntime.so.3.* libgdruntime.so
+ln -sf ../../../../%{_lib}/libgphobos.so.3.* libgphobos.so
+%endif
+%if %{build_libitm}
+ln -sf ../../../../%{_lib}/libitm.so.1.* libitm.so
+%endif
+%if %{build_libatomic}
+ln -sf ../../../../%{_lib}/libatomic.so.1.* libatomic.so
+%endif
+%if %{build_libasan}
+ln -sf ../../../../%{_lib}/libasan.so.8.* libasan.so
+mv ../../../../%{_lib}/libasan_preinit.o libasan_preinit.o
+%endif
+%if %{build_libubsan}
+ln -sf ../../../../%{_lib}/libubsan.so.1.* libubsan.so
+%endif
+%if %{build_libtsan}
+rm -f libtsan.so
+echo 'INPUT ( %{_prefix}/%{_lib}/'`echo ../../../../%{_lib}/libtsan.so.2.* | sed 's,^.*libt,libt,'`' )' > libtsan.so
+mv ../../../../%{_lib}/libtsan_preinit.o libtsan_preinit.o
+%endif
+%if %{build_liblsan}
+rm -f liblsan.so
+echo 'INPUT ( %{_prefix}/%{_lib}/'`echo ../../../../%{_lib}/liblsan.so.0.* | sed 's,^.*libl,libl,'`' )' > liblsan.so
+mv ../../../../%{_lib}/liblsan_preinit.o liblsan_preinit.o
+%endif
+fi
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++fs.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++_libbacktrace.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libsupc++.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgfortran.*a $FULLLPATH/
+%if %{build_objc}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libobjc.*a .
+%endif
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgomp.*a .
+%if %{build_libquadmath}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libquadmath.*a $FULLLPATH/
+%endif
+%if %{build_d}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgdruntime.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgphobos.*a $FULLLPATH/
+%endif
+%if %{build_libitm}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libitm.*a $FULLLPATH/
+%endif
+%if %{build_libatomic}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libatomic.*a $FULLLPATH/
+%endif
+%if %{build_libasan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libasan.*a $FULLLPATH/
+%endif
+%if %{build_libubsan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libubsan.*a $FULLLPATH/
+%endif
+%if %{build_libtsan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libtsan.*a $FULLPATH/
+%endif
+%if %{build_liblsan}
+mv -f %{buildroot}%{_prefix}/%{_lib}/liblsan.*a $FULLPATH/
+%endif
+%if %{build_go}
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgo.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgobegin.*a $FULLLPATH/
+mv -f %{buildroot}%{_prefix}/%{_lib}/libgolibbegin.*a $FULLLPATH/
+%endif
+
+%if %{build_ada}
+%ifarch sparcv9 ppc
+rm -rf $FULLPATH/64/ada{include,lib}
+%endif
+%ifarch %{multilib_64_archs}
+rm -rf $FULLPATH/32/ada{include,lib}
+%endif
+if [ "$FULLPATH" != "$FULLLPATH" ]; then
+mv -f $FULLPATH/ada{include,lib} $FULLLPATH/
+pushd $FULLLPATH/adalib
+if [ "%{_lib}" = "lib" ]; then
+ln -sf ../../../../../libgnarl-*.so libgnarl.so
+ln -sf ../../../../../libgnarl-*.so libgnarl-12.so
+ln -sf ../../../../../libgnat-*.so libgnat.so
+ln -sf ../../../../../libgnat-*.so libgnat-12.so
+else
+ln -sf ../../../../../../%{_lib}/libgnarl-*.so libgnarl.so
+ln -sf ../../../../../../%{_lib}/libgnarl-*.so libgnarl-12.so
+ln -sf ../../../../../../%{_lib}/libgnat-*.so libgnat.so
+ln -sf ../../../../../../%{_lib}/libgnat-*.so libgnat-12.so
+fi
+popd
+else
+pushd $FULLPATH/adalib
+if [ "%{_lib}" = "lib" ]; then
+ln -sf ../../../../libgnarl-*.so libgnarl.so
+ln -sf ../../../../libgnarl-*.so libgnarl-12.so
+ln -sf ../../../../libgnat-*.so libgnat.so
+ln -sf ../../../../libgnat-*.so libgnat-12.so
+else
+ln -sf ../../../../../%{_lib}/libgnarl-*.so libgnarl.so
+ln -sf ../../../../../%{_lib}/libgnarl-*.so libgnarl-12.so
+ln -sf ../../../../../%{_lib}/libgnat-*.so libgnat.so
+ln -sf ../../../../../%{_lib}/libgnat-*.so libgnat-12.so
+fi
+popd
+fi
+%endif
+
+%ifarch sparcv9 ppc
+%if %{build_objc}
+ln -sf ../../../../../lib64/libobjc.so.4 64/libobjc.so
+%endif
+ln -sf ../`echo ../../../../lib/libstdc++.so.6.*[0-9] | sed s~/lib/~/lib64/~` 64/libstdc++.so
+ln -sf ../`echo ../../../../lib/libgfortran.so.5.* | sed s~/lib/~/lib64/~` 64/libgfortran.so
+ln -sf ../`echo ../../../../lib/libgomp.so.1.* | sed s~/lib/~/lib64/~` 64/libgomp.so
+%if %{build_go}
+rm -f libgo.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libgo.so.21.* | sed 's,^.*libg,libg,'`' )' > libgo.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgo.so.21.* | sed 's,^.*libg,libg,'`' )' > 64/libgo.so
+%endif
+%if %{build_libquadmath}
+rm -f libquadmath.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > libquadmath.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > 64/libquadmath.so
+%endif
+%if %{build_d}
+rm -f libgdruntime.so libgphobos.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libgdruntime.so.3.* | sed 's,^.*libg,libg,'`' )' > libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgdruntime.so.3.* | sed 's,^.*libg,libg,'`' )' > 64/libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libgphobos.so.3.* | sed 's,^.*libg,libg,'`' )' > libgphobos.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libgphobos.so.3.* | sed 's,^.*libg,libg,'`' )' > 64/libgphobos.so
+%endif
+%if %{build_libitm}
+rm -f libitm.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > libitm.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > 64/libitm.so
+%endif
+%if %{build_libatomic}
+rm -f libatomic.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > libatomic.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > 64/libatomic.so
+%endif
+%if %{build_libasan}
+rm -f libasan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libasan.so.8.* | sed 's,^.*liba,liba,'`' )' > libasan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libasan.so.8.* | sed 's,^.*liba,liba,'`' )' > 64/libasan.so
+mv ../../../../lib64/libasan_preinit.o 64/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+rm -f libubsan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > libubsan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > 64/libubsan.so
+%endif
+ln -sf lib32/libgfortran.a libgfortran.a
+ln -sf ../lib64/libgfortran.a 64/libgfortran.a
+%if %{build_objc}
+mv -f %{buildroot}%{_prefix}/lib64/libobjc.*a 64/
+%endif
+mv -f %{buildroot}%{_prefix}/lib64/libgomp.*a 64/
+ln -sf lib32/libstdc++.a libstdc++.a
+ln -sf ../lib64/libstdc++.a 64/libstdc++.a
+ln -sf lib32/libstdc++fs.a libstdc++fs.a
+ln -sf ../lib64/libstdc++fs.a 64/libstdc++fs.a
+ln -sf lib32/libstdc++_libbacktrace.a libstdc++_libbacktrace.a
+ln -sf ../lib64/libstdc++_libbacktrace.a 64/libstdc++_libbacktrace.a
+ln -sf lib32/libsupc++.a libsupc++.a
+ln -sf ../lib64/libsupc++.a 64/libsupc++.a
+%if %{build_libquadmath}
+ln -sf lib32/libquadmath.a libquadmath.a
+ln -sf ../lib64/libquadmath.a 64/libquadmath.a
+%endif
+%if %{build_d}
+ln -sf lib32/libgdruntime.a libgdruntime.a
+ln -sf ../lib64/libgdruntime.a 64/libgdruntime.a
+ln -sf lib32/libgphobos.a libgphobos.a
+ln -sf ../lib64/libgphobos.a 64/libgphobos.a
+%endif
+%if %{build_libitm}
+ln -sf lib32/libitm.a libitm.a
+ln -sf ../lib64/libitm.a 64/libitm.a
+%endif
+%if %{build_libatomic}
+ln -sf lib32/libatomic.a libatomic.a
+ln -sf ../lib64/libatomic.a 64/libatomic.a
+%endif
+%if %{build_libasan}
+ln -sf lib32/libasan.a libasan.a
+ln -sf ../lib64/libasan.a 64/libasan.a
+%endif
+%if %{build_libubsan}
+ln -sf lib32/libubsan.a libubsan.a
+ln -sf ../lib64/libubsan.a 64/libubsan.a
+%endif
+%if %{build_go}
+ln -sf lib32/libgo.a libgo.a
+ln -sf ../lib64/libgo.a 64/libgo.a
+ln -sf lib32/libgobegin.a libgobegin.a
+ln -sf ../lib64/libgobegin.a 64/libgobegin.a
+ln -sf lib32/libgolibbegin.a libgolibbegin.a
+ln -sf ../lib64/libgolibbegin.a 64/libgolibbegin.a
+%endif
+%if %{build_ada}
+ln -sf lib32/adainclude adainclude
+ln -sf ../lib64/adainclude 64/adainclude
+ln -sf lib32/adalib adalib
+ln -sf ../lib64/adalib 64/adalib
+%endif
+%endif
+%ifarch %{multilib_64_archs}
+mkdir -p 32
+%if %{build_objc}
+ln -sf ../../../../libobjc.so.4 32/libobjc.so
+%endif
+ln -sf ../`echo ../../../../lib64/libstdc++.so.6.*[0-9] | sed s~/../lib64/~/~` 32/libstdc++.so
+ln -sf ../`echo ../../../../lib64/libgfortran.so.5.* | sed s~/../lib64/~/~` 32/libgfortran.so
+ln -sf ../`echo ../../../../lib64/libgomp.so.1.* | sed s~/../lib64/~/~` 32/libgomp.so
+%if %{build_go}
+rm -f libgo.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libgo.so.21.* | sed 's,^.*libg,libg,'`' )' > libgo.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgo.so.21.* | sed 's,^.*libg,libg,'`' )' > 32/libgo.so
+%endif
+%if %{build_libquadmath}
+rm -f libquadmath.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > libquadmath.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libquadmath.so.0.* | sed 's,^.*libq,libq,'`' )' > 32/libquadmath.so
+%endif
+%if %{build_d}
+rm -f libgdruntime.so libgphobos.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libgdruntime.so.3.* | sed 's,^.*libg,libg,'`' )' > libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgdruntime.so.3.* | sed 's,^.*libg,libg,'`' )' > 32/libgdruntime.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libgphobos.so.3.* | sed 's,^.*libg,libg,'`' )' > libgphobos.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libgphobos.so.3.* | sed 's,^.*libg,libg,'`' )' > 32/libgphobos.so
+%endif
+%if %{build_libitm}
+rm -f libitm.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > libitm.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libitm.so.1.* | sed 's,^.*libi,libi,'`' )' > 32/libitm.so
+%endif
+%if %{build_libatomic}
+rm -f libatomic.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > libatomic.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libatomic.so.1.* | sed 's,^.*liba,liba,'`' )' > 32/libatomic.so
+%endif
+%if %{build_libasan}
+rm -f libasan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libasan.so.8.* | sed 's,^.*liba,liba,'`' )' > libasan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libasan.so.8.* | sed 's,^.*liba,liba,'`' )' > 32/libasan.so
+mv ../../../../lib/libasan_preinit.o 32/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+rm -f libubsan.so
+echo 'INPUT ( %{_prefix}/lib64/'`echo ../../../../lib64/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > libubsan.so
+echo 'INPUT ( %{_prefix}/lib/'`echo ../../../../lib64/libubsan.so.1.* | sed 's,^.*libu,libu,'`' )' > 32/libubsan.so
+%endif
+%if %{build_objc}
+mv -f %{buildroot}%{_prefix}/lib/libobjc.*a 32/
+%endif
+mv -f %{buildroot}%{_prefix}/lib/libgomp.*a 32/
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+ln -sf ../lib32/libgfortran.a 32/libgfortran.a
+ln -sf lib64/libgfortran.a libgfortran.a
+ln -sf ../lib32/libstdc++.a 32/libstdc++.a
+ln -sf lib64/libstdc++.a libstdc++.a
+ln -sf ../lib32/libstdc++fs.a 32/libstdc++fs.a
+ln -sf lib64/libstdc++fs.a libstdc++fs.a
+ln -sf ../lib32/libstdc++_libbacktrace.a 32/libstdc++_libbacktrace.a
+ln -sf lib64/libstdc++_libbacktrace.a libstdc++_libbacktrace.a
+ln -sf ../lib32/libsupc++.a 32/libsupc++.a
+ln -sf lib64/libsupc++.a libsupc++.a
+%if %{build_libquadmath}
+ln -sf ../lib32/libquadmath.a 32/libquadmath.a
+ln -sf lib64/libquadmath.a libquadmath.a
+%endif
+%if %{build_d}
+ln -sf ../lib32/libgdruntime.a 32/libgdruntime.a
+ln -sf lib64/libgdruntime.a libgdruntime.a
+ln -sf ../lib32/libgphobos.a 32/libgphobos.a
+ln -sf lib64/libgphobos.a libgphobos.a
+%endif
+%if %{build_libitm}
+ln -sf ../lib32/libitm.a 32/libitm.a
+ln -sf lib64/libitm.a libitm.a
+%endif
+%if %{build_libatomic}
+ln -sf ../lib32/libatomic.a 32/libatomic.a
+ln -sf lib64/libatomic.a libatomic.a
+%endif
+%if %{build_libasan}
+ln -sf ../lib32/libasan.a 32/libasan.a
+ln -sf lib64/libasan.a libasan.a
+%endif
+%if %{build_libubsan}
+ln -sf ../lib32/libubsan.a 32/libubsan.a
+ln -sf lib64/libubsan.a libubsan.a
+%endif
+%if %{build_go}
+ln -sf ../lib32/libgo.a 32/libgo.a
+ln -sf lib64/libgo.a libgo.a
+ln -sf ../lib32/libgobegin.a 32/libgobegin.a
+ln -sf lib64/libgobegin.a libgobegin.a
+ln -sf ../lib32/libgolibbegin.a 32/libgolibbegin.a
+ln -sf lib64/libgolibbegin.a libgolibbegin.a
+%endif
+%if %{build_ada}
+ln -sf ../lib32/adainclude 32/adainclude
+ln -sf lib64/adainclude adainclude
+ln -sf ../lib32/adalib 32/adalib
+ln -sf lib64/adalib adalib
+%endif
+%else
+%ifarch %{multilib_64_archs}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgfortran.a 32/libgfortran.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libstdc++.a 32/libstdc++.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libstdc++fs.a 32/libstdc++fs.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libstdc++_libbacktrace.a 32/libstdc++_libbacktrace.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libsupc++.a 32/libsupc++.a
+%if %{build_libquadmath}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libquadmath.a 32/libquadmath.a
+%endif
+%if %{build_d}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgdruntime.a 32/libgdruntime.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgphobos.a 32/libgphobos.a
+%endif
+%if %{build_libitm}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libitm.a 32/libitm.a
+%endif
+%if %{build_libatomic}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libatomic.a 32/libatomic.a
+%endif
+%if %{build_libasan}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libasan.a 32/libasan.a
+%endif
+%if %{build_libubsan}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libubsan.a 32/libubsan.a
+%endif
+%if %{build_go}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgo.a 32/libgo.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgobegin.a 32/libgobegin.a
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/libgolibbegin.a 32/libgolibbegin.a
+%endif
+%if %{build_ada}
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/adainclude 32/adainclude
+ln -sf ../../../%{multilib_32_arch}-%{_vendor}-%{_target_os}/%{gcc_major}/adalib 32/adalib
+%endif
+%endif
+%endif
+
+# If we are building a debug package then copy all of the static archives
+# into the debug directory to keep them as unstripped copies.
+%if 0%{?_enable_debug_packages}
+for d in . $FULLLSUBDIR; do
+  mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/$d
+  for f in `find $d -maxdepth 1 -a \
+		\( -name libasan.a -o -name libatomic.a \
+		-o -name libcaf_single.a \
+		-o -name libgcc.a -o -name libgcc_eh.a \
+		-o -name libgcov.a -o -name libgfortran.a \
+		-o -name libgo.a -o -name libgobegin.a \
+		-o -name libgolibbegin.a -o -name libgomp.a \
+		-o -name libitm.a -o -name liblsan.a \
+		-o -name libobjc.a -o -name libgdruntime.a -o -name libgphobos.a \
+		-o -name libquadmath.a -o -name libstdc++.a \
+		-o -name libstdc++fs.a -o -name libstdc++_libbacktrace.a -o -name libsupc++.a \
+		-o -name libtsan.a -o -name libubsan.a \) -a -type f`; do
+    cp -a $f $RPM_BUILD_ROOT%{_prefix}/lib/debug%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/$d/
+  done
+done
+%endif
+
+# Strip debug info from Fortran/ObjC/Java static libraries
+strip -g `find . \( -name libgfortran.a -o -name libobjc.a -o -name libgomp.a \
+		    -o -name libgcc.a -o -name libgcov.a -o -name libquadmath.a \
+		    -o -name libgdruntime.a -o -name libgphobos.a \
+		    -o -name libitm.a -o -name libgo.a -o -name libcaf\*.a \
+		    -o -name libatomic.a -o -name libasan.a -o -name libtsan.a \
+		    -o -name libubsan.a -o -name liblsan.a -o -name libcc1.a \) \
+		 -a -type f`
+popd
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgfortran.so.5.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgomp.so.1.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libcc1.so.0.*
+%if %{build_libquadmath}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libquadmath.so.0.*
+%endif
+%if %{build_d}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgdruntime.so.3.*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgphobos.so.3.*
+%endif
+%if %{build_libitm}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libitm.so.1.*
+%endif
+%if %{build_libatomic}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libatomic.so.1.*
+%endif
+%if %{build_libasan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libasan.so.8.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/libasan.so.8.*
+%endif
+%if %{build_libubsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libubsan.so.1.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/libubsan.so.1.*
+%endif
+%if %{build_libtsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libtsan.so.2.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/libtsan.so.2.*
+%endif
+%if %{build_liblsan}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/liblsan.so.0.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/liblsan.so.0.*
+%endif
+%ifarch aarch64
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libhwasan.so.0.*
+chrpath -d %{buildroot}%{_prefix}/%{_lib}/libhwasan.so.0.*
+%endif
+%if %{build_go}
+# Avoid stripping these libraries and binaries.
+chmod 644 %{buildroot}%{_prefix}/%{_lib}/libgo.so.21.*
+chmod 644 %{buildroot}%{_prefix}/bin/go.gcc
+chmod 644 %{buildroot}%{_prefix}/bin/gofmt.gcc
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json
+chmod 644 %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet
+%endif
+%if %{build_objc}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libobjc.so.4.*
+%endif
+
+%if %{build_ada}
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgnarl*so*
+chmod 755 %{buildroot}%{_prefix}/%{_lib}/libgnat*so*
+%endif
+
+mv $FULLPATH/include-fixed/syslimits.h $FULLPATH/include/syslimits.h
+mv $FULLPATH/include-fixed/limits.h $FULLPATH/include/limits.h
+for h in `find $FULLPATH/include -name \*.h`; do
+  if grep -q 'It has been auto-edited by fixincludes from' $h; then
+    rh=`grep -A2 'It has been auto-edited by fixincludes from' $h | tail -1 | sed 's|^.*"\(.*\)".*$|\1|'`
+    diff -up $rh $h || :
+    rm -f $h
+  fi
+done
+
+cat > %{buildroot}%{_prefix}/bin/c89 <<"EOF"
+#!/bin/sh
+fl="-std=c89"
+for opt; do
+  case "$opt" in
+    -ansi|-std=c89|-std=iso9899:1990) fl="";;
+    -std=*) echo "`basename $0` called with non ANSI/ISO C option $opt" >&2
+	    exit 1;;
+  esac
+done
+exec gcc $fl ${1+"$@"}
+EOF
+cat > %{buildroot}%{_prefix}/bin/c99 <<"EOF"
+#!/bin/sh
+fl="-std=c99"
+for opt; do
+  case "$opt" in
+    -std=c99|-std=iso9899:1999) fl="";;
+    -std=*) echo "`basename $0` called with non ISO C99 option $opt" >&2
+	    exit 1;;
+  esac
+done
+exec gcc $fl ${1+"$@"}
+EOF
+chmod 755 %{buildroot}%{_prefix}/bin/c?9
+
+cd ..
+%find_lang %{name}
+%find_lang cpplib
+
+# Remove binaries we will not be including, so that they don't end up in
+# gcc-debuginfo
+rm -f %{buildroot}%{_prefix}/%{_lib}/{libffi*,libiberty.a} || :
+rm -f $FULLEPATH/install-tools/{mkheaders,fixincl}
+rm -f %{buildroot}%{_prefix}/lib/{32,64}/libiberty.a
+rm -f %{buildroot}%{_prefix}/%{_lib}/libssp*
+rm -f %{buildroot}%{_prefix}/%{_lib}/libvtv* || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gfortran || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gccgo || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcj || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-ar || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-nm || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-ranlib || :
+rm -f %{buildroot}%{_prefix}/bin/%{_target_platform}-gdc || :
+
+%ifarch %{multilib_64_archs}
+# Remove libraries for the other arch on multilib arches
+rm -f %{buildroot}%{_prefix}/lib/lib*.so*
+rm -f %{buildroot}%{_prefix}/lib/lib*.a
+rm -f %{buildroot}/lib/libgcc_s*.so*
+%if %{build_go}
+rm -rf %{buildroot}%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%ifnarch sparc64 ppc64 ppc64p7
+ln -sf %{multilib_32_arch}-%{_vendor}-%{_target_os} %{buildroot}%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%else
+%ifarch sparcv9 ppc
+rm -f %{buildroot}%{_prefix}/lib64/lib*.so*
+rm -f %{buildroot}%{_prefix}/lib64/lib*.a
+rm -f %{buildroot}/lib64/libgcc_s*.so*
+%if %{build_go}
+rm -rf %{buildroot}%{_prefix}/lib64/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%endif
+
+rm -f %{buildroot}%{mandir}/man3/ffi*
+
+# Help plugins find out nvra.
+echo gcc-%{version}-%{release}.%{_arch} > $FULLPATH/rpmver
+
+# Add symlink to lto plugin in the binutils plugin directory.
+%{__mkdir_p} %{buildroot}%{_libdir}/bfd-plugins/
+ln -s ../../libexec/gcc/%{gcc_target_platform}/%{gcc_major}/liblto_plugin.so \
+  %{buildroot}%{_libdir}/bfd-plugins/
+
+%ifarch aarch64
+    if [ -e %{buildroot}%{_prefix}/bin/gcc ]; then strip -s %{buildroot}%{_prefix}/bin/gcc; fi
+    if [ -e %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-12 ]; then strip -s %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-12; fi
+%endif
+%ifarch x86_64
+    if [ -e %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc ]; then strip -s %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc; fi
+    if [ -e %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-12 ]; then strip -s %{buildroot}%{_prefix}/bin/%{_target_platform}-gcc-12; fi
+%endif
+
+# Remove installed but unpacked files.
+# If any file is useful in the future, remove it from here.
+if [ -f %{buildroot}%{_prefix}/bin/gnatgcc ]; then rm -f %{buildroot}%{_prefix}/bin/gnatgcc; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libasan.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libasan.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libasan.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libasan.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libatomic.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libatomic.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libgcc_s.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libgcc_s.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libgfortran.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libgfortran.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libgomp.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libgomp.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libitm.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libitm.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/liblsan.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/liblsan.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libobjc.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libobjc.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libquadmath.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libquadmath.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libstdc++.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libstdc++.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libtsan.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libtsan.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libubsan.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libubsan.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libhwasan.a ]; then  rm -f %{buildroot}%{_prefix}/lib64/libhwasan.a; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libhwasan.so ]; then  rm -f %{buildroot}%{_prefix}/lib64/libhwasan.so; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libhwasan.so.0 ]; then  rm -f %{buildroot}%{_prefix}/lib64/libhwasan.so.0; fi
+if [ -f %{buildroot}%{_prefix}/lib64/libhwasan.so.0.0.0 ]; then  rm -f %{buildroot}%{_prefix}/lib64/libhwasan.so.0.0.0; fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/README ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/README;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/pthread.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/pthread.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/X11/Xw32defs.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/X11/Xw32defs.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/slang.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/slang.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/slang/slang.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include-fixed/slang/slang.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/ssp.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/ssp.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/stdio.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/stdio.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/string.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/string.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/unistd.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ssp/unistd.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/fixinc_list ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/fixinc_list;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/gsyslimits.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/gsyslimits.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/include/README ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/include/README;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/include/limits.h ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/include/limits.h;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/macro_list ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/macro_list;
+fi
+
+if [ -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/mkheaders.conf ];
+then
+  rm -f %{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/mkheaders.conf;
+fi
+
+if [ -f %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/fixinc.sh ];
+then
+  rm -f %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/fixinc.sh;
+fi
+
+if [ -f %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/mkinstalldirs ];
+then
+  rm -f %{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/install-tools/mkinstalldirs;
+fi
+
+if [ -f %{buildroot}%{_prefix}/share/locale/de/LC_MESSAGES/libstdc++.mo ];
+then
+  rm -f %{buildroot}%{_prefix}/share/locale/de/LC_MESSAGES/libstdc++.mo;
+fi
+
+if [ -f %{buildroot}%{_prefix}/share/locale/fr/LC_MESSAGES/libstdc++.mo ];
+then
+  rm -f %{buildroot}%{_prefix}/share/locale/fr/LC_MESSAGES/libstdc++.mo;
+fi
+
+%check
+cd obj-%{gcc_target_platform}
+
+# run the tests.
+%if %{check_enable}
+LC_ALL=C make %{?_smp_mflags} -k check ALT_CC_UNDER_TEST=gcc ALT_CXX_UNDER_TEST=g++ \
+     RUNTESTFLAGS="--target_board=unix/'{,-fstack-protector-strong}'" || :
+echo ====================TESTING=========================
+( LC_ALL=C ../contrib/test_summary || : ) 2>&1 | sed -n '/^cat.*EOF/,/^EOF/{/^cat.*EOF/d;/^EOF/d;/^LAST_UPDATED:/d;p;}'
+echo ====================TESTING END=====================
+mkdir testlogs-%{_target_platform}-%{version}-%{release}
+for i in `find . -name \*.log | grep -F testsuite/ | grep -v 'config.log\|acats.*/tests/'`; do
+  ln $i testlogs-%{_target_platform}-%{version}-%{release}/ || :
+done
+tar cf - testlogs-%{_target_platform}-%{version}-%{release} | xz -9e \
+  | uuencode testlogs-%{_target_platform}.tar.xz || :
+rm -rf testlogs-%{_target_platform}-%{version}-%{release}
+%endif
+
+%post go
+%{_sbindir}/update-alternatives --install \
+  %{_prefix}/bin/go go %{_prefix}/bin/go.gcc 92 \
+  --slave %{_prefix}/bin/gofmt gofmt %{_prefix}/bin/gofmt.gcc
+
+%preun go
+if [ $1 = 0 ]; then
+  %{_sbindir}/update-alternatives --remove go %{_prefix}/bin/go.gcc
+fi
+
+# Because glibc Prereq's libgcc and /sbin/ldconfig
+# comes from glibc, it might not exist yet when
+# libgcc is installed
+%post -n libgcc -p 
+if posix.access ("/sbin/ldconfig", "x") then
+  local pid = posix.fork ()
+  if pid == 0 then
+    posix.exec ("/sbin/ldconfig")
+  elseif pid ~= -1 then
+    posix.wait (pid)
+  end
+end
+
+%postun -n libgcc -p 
+if posix.access ("/sbin/ldconfig", "x") then
+  local pid = posix.fork ()
+  if pid == 0 then
+    posix.exec ("/sbin/ldconfig")
+  elseif pid ~= -1 then
+    posix.wait (pid)
+  end
+end
+
+%ldconfig_scriptlets -n libstdc++
+
+%ldconfig_scriptlets -n libobjc
+
+%ldconfig_scriptlets -n libgfortran
+
+%ldconfig_scriptlets -n libgphobos
+
+%ldconfig_scriptlets -n libgnat
+
+%ldconfig_scriptlets -n libgomp
+
+%ldconfig_scriptlets gdb-plugin
+
+%ldconfig_scriptlets -n libgccjit
+
+%ldconfig_scriptlets -n libquadmath
+
+%ldconfig_scriptlets -n libitm
+
+%ldconfig_scriptlets -n libatomic
+
+%ldconfig_scriptlets -n libasan
+
+%ldconfig_scriptlets -n libubsan
+
+%ldconfig_scriptlets -n libtsan
+
+%ldconfig_scriptlets -n liblsan
+
+%ldconfig_scriptlets -n libgo
+
+%files -f %{name}.lang
+%{_prefix}/bin/cc
+%{_prefix}/bin/c89
+%{_prefix}/bin/c99
+%{_prefix}/bin/gcc
+%{_prefix}/bin/gcov
+%{_prefix}/bin/gcov-tool
+%{_prefix}/bin/gcov-dump
+%{_prefix}/bin/gcc-ar
+%{_prefix}/bin/gcc-nm
+%{_prefix}/bin/gcc-ranlib
+%{_prefix}/bin/lto-dump
+%ifarch ppc
+%{_prefix}/bin/%{_target_platform}-gcc
+%endif
+%ifarch sparc64 sparcv9
+%{_prefix}/bin/sparc-%{_vendor}-%{_target_os}-gcc
+%endif
+%ifarch ppc64 ppc64p7
+%{_prefix}/bin/ppc-%{_vendor}-%{_target_os}-gcc
+%endif
+%{_prefix}/bin/%{gcc_target_platform}-gcc*
+%{_mandir}/man1/gcc.1*
+%{_mandir}/man1/gcov.1*
+%{_mandir}/man1/gcov-tool.1*
+%{_mandir}/man1/gcov-dump.1*
+%{_mandir}/man1/lto-dump.1*
+%{_mandir}/man7/*
+%{_infodir}/gcc*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/lto1
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/lto-wrapper
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/liblto_plugin.so*
+%{_libdir}/bfd-plugins/liblto_plugin.so
+%{_prefix}/libexec/gcc/onnx.fdata
+%{_prefix}/libexec/gcc/optimizer.fdata
+%ifarch aarch64
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/libbolt_plugin.so*
+%endif
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/rpmver
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stddef.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdarg.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdfix.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/varargs.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/float.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/limits.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdbool.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/iso646.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/syslimits.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/unwind.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/omp.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/openacc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/acc_prof.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdint.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdint-gcc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdalign.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdnoreturn.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/stdatomic.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/gcov.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/simdmath.h
+%ifarch %{ix86} x86_64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/emmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/tmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ammintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/smmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/nmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/wmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/immintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/x86intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/fma4intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xopintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/lwpintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/popcntintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/tbmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ia32intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmi2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/f16cintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/fmaintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/lzcntintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/rtmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xtestintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/adxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/prfchwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/rdseedintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/fxsrintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsaveintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsaveoptintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512cdintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512erintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512fintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512pfintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/shaintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mm_malloc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mm3dnow.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cpuid.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cross-stdarg.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512bwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512dqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512ifmaintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512ifmavlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmivlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vlbwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vldqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/clflushoptintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/clwbintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mwaitxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsavecintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xsavesintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/clzerointrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pkuintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx5124fmapsintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx5124vnniwintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vpopcntdqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/sgxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/gfniintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cetintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cet.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmi2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vbmi2vlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vnniintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vnnivlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vaesintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vpclmulqdqintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vpopcntdqvlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512bitalgintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pconfigintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/wbnoinvdintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/movdirintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/waitpkgintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/cldemoteintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512bf16vlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512bf16intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/enqcmdintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vp2intersectintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512vp2intersectvlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/serializeintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/tsxldtrkintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amxtileintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amxint8intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amxbf16intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amxfp16intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amxcomplexintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/x86gprintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/uintrintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/hresetintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/keylockerintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/prfchiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avxvnniintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mwaitintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512fp16intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/avx512fp16vlintrin.h
+%endif
+%ifarch ia64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ia64intrin.h
+%endif
+%ifarch ppc ppc64 ppc64le ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ppc-asm.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/altivec.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ppu_intrinsics.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/si2vmx.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/spu2vmx.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vec_types.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmxlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmi2intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/bmiintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/xmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mm_malloc.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/emmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/x86intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/pmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/tmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/smmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/amo.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/nmmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/immintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/x86gprintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/rs6000-vecdefines.h
+%endif
+%ifarch %{arm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/unwind-arm-common.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/mmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_neon.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_acle.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_cmse.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_fp16.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_bf16.h
+%endif
+%ifarch aarch64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_neon.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_acle.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_fp16.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_bf16.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_sve.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/arm_sme.h
+%endif
+%ifarch loongarch64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/larchintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/loongarch/loongarch-protos.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/loongarch/loongarch-opts.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/loongarch/loongarch-str.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/loongarch/loongarch-def.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/loongarch/loongarch-tune.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/loongarch/loongarch-driver.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/lsxintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/lasxintrin.h
+%endif
+%ifarch sparc sparcv9 sparc64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/visintrin.h
+%endif
+%ifarch s390 s390x
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/s390intrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/htmxlintrin.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/vecintrin.h
+%endif
+%ifarch sw_64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/sw_64/sw_64-protos.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include/config/sw_64/sw_64.h
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/sanitizer
+%endif
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/collect2
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/crt*.o
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcov.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcc_eh.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgcc_s.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgomp.spec
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgomp.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgomp.so
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.spec
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libsanitizer.spec
+%endif
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/crt*.o
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcov.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcc_eh.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgcc_s.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgomp.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgomp.so
+%if %{build_libquadmath}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libquadmath.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libquadmath.so
+%endif
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libitm.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libitm.so
+%endif
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libatomic.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libasan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libubsan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libubsan.so
+%endif
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/crt*.o
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcov.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcc_eh.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgcc_s.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgomp.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgomp.so
+%if %{build_libquadmath}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libquadmath.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libquadmath.so
+%endif
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libitm.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libitm.so
+%endif
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libatomic.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libasan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libubsan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libubsan.so
+%endif
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%if %{build_libquadmath}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.so
+%endif
+%if %{build_libitm}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.so
+%endif
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.so
+%endif
+%else
+%if %{build_libatomic}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.so
+%endif
+%if %{build_libasan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan_preinit.o
+%endif
+%if %{build_libubsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.so
+%endif
+%endif
+%if %{build_libtsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libtsan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libtsan_preinit.o
+%endif
+%if %{build_liblsan}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/liblsan.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/liblsan_preinit.o
+%endif
+%{_prefix}/libexec/getconf/default
+%doc gcc/README* rpm.doc/changelogs/gcc/ChangeLog* 
+%{!?_licensedir:%global license %%doc}
+%license gcc/COPYING* COPYING.RUNTIME
+
+%files -n cpp -f cpplib.lang
+%{_prefix}/lib/cpp
+%{_prefix}/bin/cpp
+%{_mandir}/man1/cpp.1*
+%{_infodir}/cpp*
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1
+
+%files -n libgcc
+/%{_lib}/libgcc_s-%{gcc_major}.so.1
+/%{_lib}/libgcc_s.so.1
+%{!?_licensedir:%global license %%doc}
+%license gcc/COPYING* COPYING.RUNTIME
+
+%files c++
+%{_prefix}/bin/%{gcc_target_platform}-*++
+%{_prefix}/bin/g++
+%{_prefix}/bin/c++
+%{_mandir}/man1/g++.1*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1plus
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/g++-mapper-server
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libstdc++_libbacktrace.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libsupc++.a
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libstdc++_libbacktrace.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libsupc++.a
+%endif
+%ifarch sparcv9 ppc %{multilib_64_archs}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.so
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++_libbacktrace.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libsupc++.a
+%endif
+%doc rpm.doc/changelogs/gcc/cp/ChangeLog*
+
+%files -n libstdc++
+%{_prefix}/%{_lib}/libstdc++.so.6*
+%dir %{_datadir}/gdb
+%dir %{_datadir}/gdb/auto-load
+%dir %{_datadir}/gdb/auto-load/%{_prefix}
+%dir %{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/
+# Package symlink to keep compatibility
+%ifarch riscv64
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/lp64d
+%endif
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/libstdc*gdb.py*
+%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/__pycache__
+%dir %{_prefix}/share/gcc-%{gcc_major}
+%dir %{_prefix}/share/gcc-%{gcc_major}/python
+%{_prefix}/share/gcc-%{gcc_major}/python/libstdcxx
+
+%files -n libstdc++-devel
+%dir %{_prefix}/include/c++
+%{_prefix}/include/c++/%{gcc_major}
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifnarch sparcv9 ppc %{multilib_64_archs}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.so
+%endif
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libstdc++_libbacktrace.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libstdc++_libbacktrace.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++fs.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++_libbacktrace.a
+%endif
+%doc rpm.doc/changelogs/libstdc++-v3/ChangeLog* libstdc++-v3/README*
+
+%files -n libstdc++-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libsupc++.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libsupc++.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libstdc++.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libsupc++.a
+%endif
+
+%if %{build_libstdcxx_docs}
+%files -n libstdc++-docs
+%{_mandir}/man3/*
+%doc rpm.doc/libstdc++-v3/html
+%endif
+
+%if %{build_objc}
+%files objc
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/objc
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1obj
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libobjc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libobjc.so
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libobjc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libobjc.so
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libobjc.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libobjc.so
+%endif
+%doc rpm.doc/objc/*
+%doc libobjc/THREADS* rpm.doc/changelogs/libobjc/ChangeLog*
+
+%files objc++
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cc1objplus
+
+%files -n libobjc
+%{_prefix}/%{_lib}/libobjc.so.4*
+%endif
+
+%files gfortran
+%{_prefix}/bin/gfortran
+%{_prefix}/bin/f95
+%{_mandir}/man1/gfortran.1*
+%{_infodir}/gfortran*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/ISO_Fortran_binding.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib.f90
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/omp_lib_kinds.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc.f90
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc_kinds.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/openacc_lib.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/ieee_arithmetic.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/ieee_exceptions.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/ieee_features.mod
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/finclude/simdmath_f.h
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/f951
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.spec
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libcaf_single.a
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.a
+%endif
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.so
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libcaf_single.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgfortran.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgfortran.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/finclude
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libcaf_single.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgfortran.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgfortran.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/finclude
+%endif
+%dir %{_fmoddir}
+%doc rpm.doc/gfortran/*
+
+%files -n libgfortran
+%{_prefix}/%{_lib}/libgfortran.so.5*
+
+%files -n libgfortran-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgfortran.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgfortran.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgfortran.a
+%endif
+
+%if %{build_d}
+%files gdc
+%{_prefix}/bin/gdc
+%{_mandir}/man1/gdc.1*
+%{_infodir}/gdc*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/d
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/d21
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgphobos.spec
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgdruntime.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgphobos.a
+%endif
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgdruntime.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgphobos.so
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgdruntime.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgphobos.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgdruntime.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgphobos.so
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgdruntime.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgphobos.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgdruntime.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgphobos.so
+%endif
+%doc rpm.doc/gdc/*
+
+%files -n libgphobos
+%{_prefix}/%{_lib}/libgdruntime.so.3*
+%{_prefix}/%{_lib}/libgphobos.so.3*
+%doc rpm.doc/libphobos/*
+
+%files -n libgphobos-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgdruntime.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgphobos.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgdruntime.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgphobos.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgdruntime.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgphobos.a
+%endif
+%endif
+
+%if %{build_ada}
+%files gnat
+%{_prefix}/bin/gnat
+%{_prefix}/bin/gnat[^i]*
+%{_infodir}/gnat*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/ada_target_properties
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/ada_target_properties
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib
+%endif
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/ada_target_properties
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/gnat1
+%doc rpm.doc/changelogs/gcc/ada/ChangeLog*
+
+%files -n libgnat
+%{_prefix}/%{_lib}/libgnat-*.so
+%{_prefix}/%{_lib}/libgnarl-*.so
+
+%files -n libgnat-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnat.a
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnarl.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnat.a
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnarl.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adainclude
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnat.a
+%exclude %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnarl.a
+%endif
+
+%files -n libgnat-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnat.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/adalib/libgnarl.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnat.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/adalib/libgnarl.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnat.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/adalib/libgnarl.a
+%endif
+%endif
+
+%files -n libgomp
+%{_prefix}/%{_lib}/libgomp.so.1*
+%{_infodir}/libgomp.info*
+%doc rpm.doc/changelogs/libgomp/ChangeLog*
+
+%if %{build_libquadmath}
+%files -n libquadmath
+%{_prefix}/%{_lib}/libquadmath.so.0*
+%{_infodir}/libquadmath.info*
+%{!?_licensedir:%global license %%doc}
+%license rpm.doc/libquadmath/COPYING*
+
+%files -n libquadmath-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/quadmath.h
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include/quadmath_weak.h
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.so
+%endif
+%doc rpm.doc/libquadmath/ChangeLog*
+
+%files -n libquadmath-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libquadmath.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libquadmath.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libquadmath.a
+%endif
+%endif
+
+%if %{build_libitm}
+%files -n libitm
+%{_prefix}/%{_lib}/libitm.so.1*
+%{_infodir}/libitm.info*
+
+%files -n libitm-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/include
+#%%{_prefix}/lib/gcc/%%{gcc_target_platform}/%%{gcc_major}/include/itm.h
+#%%{_prefix}/lib/gcc/%%{gcc_target_platform}/%%{gcc_major}/include/itm_weak.h
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.so
+%endif
+%doc rpm.doc/libitm/ChangeLog*
+
+%files -n libitm-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libitm.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libitm.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libitm.a
+%endif
+%endif
+
+%if %{build_libatomic}
+%files -n libatomic
+%{_prefix}/%{_lib}/libatomic.so.1*
+
+%files -n libatomic-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libatomic.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libatomic.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libatomic.a
+%endif
+%doc rpm.doc/changelogs/libatomic/ChangeLog*
+%endif
+
+%if %{build_libasan}
+%files -n libasan
+%{_prefix}/%{_lib}/libasan.so.8*
+
+%files -n libasan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libasan.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libasan.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libasan.a
+%endif
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_libubsan}
+%files -n libubsan
+%{_prefix}/%{_lib}/libubsan.so.1*
+
+%files -n libubsan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libubsan.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libubsan.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libubsan.a
+%endif
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_libtsan}
+%files -n libtsan
+%{_prefix}/%{_lib}/libtsan.so.2*
+
+%files -n libtsan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libtsan.a
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_liblsan}
+%files -n liblsan
+%{_prefix}/%{_lib}/liblsan.so.0*
+
+%files -n liblsan-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/liblsan.a
+%doc rpm.doc/changelogs/libsanitizer/ChangeLog*
+%{!?_licensedir:%global license %%doc}
+%license libsanitizer/LICENSE.TXT
+%endif
+
+%if %{build_go}
+%files go
+%ghost %{_prefix}/bin/go
+%attr(755,root,root) %{_prefix}/bin/go.gcc
+%{_prefix}/bin/gccgo
+%ghost %{_prefix}/bin/gofmt
+%attr(755,root,root) %{_prefix}/bin/gofmt.gcc
+%{_mandir}/man1/gccgo.1*
+%{_mandir}/man1/go.1*
+%{_mandir}/man1/gofmt.1*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/go1
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/cgo
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/buildid
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/test2json
+%attr(755,root,root) %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/vet
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgo.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgo.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/64/libgolibbegin.a
+%endif
+%ifarch %{multilib_64_archs}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgo.so
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgo.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/32/libgolibbegin.a
+%endif
+%ifarch sparcv9 ppc %{multilib_64_archs}
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.so
+%endif
+%ifarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgolibbegin.a
+%endif
+%doc rpm.doc/go/*
+
+%files -n libgo
+%attr(755,root,root) %{_prefix}/%{_lib}/libgo.so.21*
+%doc rpm.doc/libgo/*
+
+%files -n libgo-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/%{_lib}/go
+%dir %{_prefix}/%{_lib}/go/%{gcc_major}
+%{_prefix}/%{_lib}/go/%{gcc_major}/%{gcc_target_platform}
+%ifarch %{multilib_64_archs}
+%ifnarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/go
+%dir %{_prefix}/lib/go/%{gcc_major}
+%{_prefix}/lib/go/%{gcc_major}/%{gcc_target_platform}
+%endif
+%endif
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgolibbegin.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgolibbegin.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgobegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgolibbegin.a
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.so
+%endif
+
+%files -n libgo-static
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%ifarch sparcv9 ppc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib32/libgo.a
+%endif
+%ifarch sparc64 ppc64 ppc64p7
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/lib64/libgo.a
+%endif
+%ifnarch sparcv9 sparc64 ppc ppc64 ppc64p7
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/libgo.a
+%endif
+%endif
+
+%files -n libgccjit
+%{_prefix}/%{_lib}/libgccjit.so.*
+%doc rpm.doc/changelogs/gcc/jit/ChangeLog*
+
+%files -n libgccjit-devel
+%{_prefix}/%{_lib}/libgccjit.so
+%{_prefix}/include/libgccjit*.h
+%{_infodir}/libgccjit.info*
+%doc rpm.doc/libgccjit-devel/*
+%doc gcc/jit/docs/examples
+
+%files plugin-devel
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/gtype.state
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/include
+%dir %{_prefix}/libexec/gcc
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}
+%dir %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}
+%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
+
+%files gdb-plugin
+%{_prefix}/%{_lib}/libcc1.so*
+%dir %{_prefix}/lib/gcc
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}
+%dir %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/libcc1plugin.so*
+%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin/libcp1plugin.so*
+%doc rpm.doc/changelogs/libcc1/ChangeLog*
+
+%changelog
+* Sat Dec 21 2024 rfwang07  - 12.3.1-63
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC:Fix function missing return value.
+
+* Wed Dec 18 2024 Mingchuan Wu  - 12.3.1-62
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC: Sync patches from openeuler/gcc.
+
+* Mon Dec 16 2024 huzife <634763349@qq.com> - 12.3.1-61
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC:Add checking for ssa_name in if-split
+
+* Mon Dec 16 2024 huang-xiaoquan  - 12.3.1-60
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC:Adjust the same gate to use struct option.
+
+* Wed Dec 11 2024 Zhenyu Zhao  - 12.3.1-59
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC: Sync patches from openeuler/gcc.
+
+* Tue Dec 10 2024 huzife <634763349@qq.com> - 12.3.1-58
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC: Fix bugs in cmlt, replace tmp pattern split.
+
+* Mon Dec 09 2024 liyancheng <412998149@qq.com> - 12.3.1-57
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC: Fix bugs in strcut-reorg and ipa-prefetch.
+
+* Sat Dec 07 2024 huzife <634763349@qq.com> - 12.3.1-56
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC: Fix bugs for if-split.
+
+* Wed Dec 04 2024 liyancheng <412998149@qq.com> - 12.3.1-55
+- Type:Bugfix
+- ID:NA
+- SUG:NA
+- DESC: Fix bugs for cspgo.
+
+* Wed Dec 04 2024 Zhenyu Zhao  - 12.3.1-54
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patches from openeuler/gcc.
+
+* Wed Dec 04 2024 Zhenyu Zhao  - 12.3.1-53
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patches from openeuler/gcc.
+
+* Wed Dec 04 2024 Zhenyu Zhao  - 12.3.1-52
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Bugfix add no var recored check for ssa_name in struct reorg.
+
+* Wed Dec 04 2024 Mingchuan Wu  - 12.3.1-51
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync [late-SLP], [tracer-opt], [bugfix4hip09] patches from openeuler/gcc.
+
+* Thu Nov 28 2024 swcompiler  - 12.3.1-50
+- Type: Sw64
+- DESC:
+- Add sw64 architecture support.
+
+* Wed Nov 27 2024 liyancheng <412998149@qq.com> - 12.3.1-49
+- Type: Sync
+- DESC: Add if split optimization
+
+* Wed Nov 27 2024 Peng Fan  - 12.3.1-48
+- Type: BUGFIX
+- DESC:
+- LoongArch: Allow attributes in non-gnu namespaces.
+
+* Wed Nov 27 2024 liyancheng <412998149@qq.com> - 12.3.1-47
+- Type: Sync
+- DESC: Add cfgo-pgo optimization
+
+* Wed Nov 27 2024 liyancheng <412998149@qq.com> - 12.3.1-46
+- Type: Sync
+- DESC: Add context sensitive PGO
+
+* Mon Nov 25 2024 Peng Fan  - 12.3.1-45
+- Type: BUGFIX
+- DESC:
+- Fix indentation and numbering errors in makefile.
+
+* Thu Nov 21 2024 jchzhou  - 12.3.1-44
+- Type: Sync
+- DESC: Sync patches for fixing building issues with clang
+- Source: https://gitee.com/openeuler/gcc/pulls/239
+
+* Thu Nov 21 2024 YunQiang Su  - 12.3.1-43
+- Type: Sync
+- DESC: RISC-V: Install libstdc++/libcc1 etc to /lib64 instead of lib
+
+* Thu Nov 21 2024 Feiyang Liu  - 12.3.1-42
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:Sync backport patch varasm-Handle-private-COMDAT from upstream.
+
+* Thu Nov 21 2024 liyancheng <412998149@qq.com> - 12.3.1-41
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Multi-version lto symbol parse and lto units ipa-inline extension
+
+* Thu Nov 21 2024 liyancheng <412998149@qq.com> - 12.3.1-40
+- Type:bugfix
+- ID:NA
+- SUG:NA
+- DESC:Add missing header file for x86
+
+* Thu Nov 21 2024 huangzifeng  - 12.3.1-39
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patches from openeuler/gcc
+
+* Thu Nov 21 2024 huangzifeng  - 12.3.1-38
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patches from branch openEuler-24.09
+
+* Wed Nov 20 2024 Hu,Lin1  - 12.3.1-37
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC: Sync some patch from src-openEuler/gcc's openeuler-24.09
+
+* Tue Nov 19 2024 eastb233  - 12.3.1-36
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Recover CVE-2023-4039
+
+* Mon Nov 18 2024 eastb233  - 12.3.1-35
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Apply SME patches
+
+* Mon Nov 18 2024 eastb233  - 12.3.1-34
+- Type:Revert
+- ID:NA
+- SUG:NA
+- DESC:Revert CVE-2023-4039 to apply SME patches
+
+* Tue Nov 5 2024 Peng Fan  - 12.3.1-33
+- Type: Sync
+- DESC:
+- LoongArch: Sync patch from upstream
+- Tweaks OSDIR are consistent with most other distributions.
+
+* Fri Sep 20 2024 fuanan  - 12.3.1-32
+- Type:Sync
+- ID:NA
+- SUG:NA
+- DESC:Sync patch for CVE-2023-4039
+
+* Thu Jul 11 2024 huyubiao  - 12.3.1-31
+- Type:SPEC
+- ID:NA
+- SUG:NA
+- DESC:disable isl
+
+* Fri May 17 2024 Zhenyu Zhao  - 12.3.1-30
+- Type: Sync
+- DESC: Sync bug fix patch from openeuler/gcc
+
+* Sat May 11 2024 tiancheng-bao  - 12.3.1-29
+- Type: Sync
+- DESC: Sync bug fix patch from openeuler/gcc
+
+* Mon Apr 29 2024 huang-xiaoquan  - 12.3.1-28
+- Type: BUGFIX
+- DESC: StructReorderFields-Fix-gimple-call-not-rewritten.
+
+* Fri Apr 26 2024 Zhenyu Zhao  - 12.3.1-27
+- Type: BUGFIX
+- DESC: Update the configure file for BOLT.
+
+* Fri Apr 26 2024 Zheng Chenhui  - 12.3.1-26
+- Type: Revert
+- DESC: Revert Intel patches.
+
+* Wed Apr 24 2024 Wang Ding  - 12.3.1-25
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Tue Apr 23 2024 laokz  - 12.3.1-24
+- Type: SPEC
+- DESC: riscv64 enable libasan, libusan package
+
+* Mon Apr 22 2024 Peng Fan  - 12.3.1-23
+- DESC: Add LoongArch 3A6000 support
+
+* Fri Apr 12 2024 Zhengchen Hui  - 12.3.1-22
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Thu Apr 11 2024 Zhengchen Hui  - 12.3.1-21
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Thu Apr 11 2024 Zhenyu Zhao  - 12.3.1-20
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Mon Apr 1 2024 Peng Fan  12.3.1-19
+- Type: SPEC
+- DESC: fix libcc1 file path for LoongArch.
+
+* Wed Mar 27 2024 Peng Fan  12.3.1-18
+- Type: Sync
+- DESC: Sync patch from gcc upstream
+- LoongArch: support libsanitizer
+- separate LoongArch's patch
+
+* Mon Jan 15 2024 laokz  12.3.1-17
+- Type: SPEC
+- DESC: riscv64 -march default to rv64gc
+
+* Mon Sep 11 2023 dingguangya  12.3.1-16
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Thu Sep 07 2023 zhaozhenyu  12.3.1-15
+- Type: SPEC
+- DESC: Enable Strip for aarch64 and x86_64 
+
+* Wed Sep 06 2023 eastb233  12.3.1-14
+- Type: Bugfix
+- DESC: Package simdmath.h and simdmath_f.h
+
+* Tue Sep 05 2023 liyancheng <412998149@qq.com> 12.3.1-13
+- Type: Bugfix
+- DESC: Remove installed but unpacked files
+
+* Tue Sep 05 2023 zhaozhenyu  12.3.1-12
+- Type: SPEC
+- DESC: Enable Strip for gcc
+
+* Tue Sep 05 2023 huangxiaoquan  12.3.1-11
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Mon Sep 04 2023 dingguangya  12.3.1-10
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Tue Aug 29 2023 huangxiaoquan  12.3.1-9
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc part 2
+
+* Tue Aug 29 2023 huangxiaoquan  12.3.1-8
+- Type: Sync
+- DESC: Sync patch from openeuler/gcc
+
+* Fri Aug 11 2023 Hongyu Wang  12.3.1-7
+- Type:Sync
+- i386: Only enable small loop unrolling in backend [PR 107692].
+
+* Fri Aug 11 2023 Hongyu Wang  12.3.1-6
+- Type:Sync
+- Enable small loop unrolling for O2.
+
+* Fri Aug 11 2023 Cui,Lili  12.3.1-5
+- Type:Sync
+- Add attribute hot judgement for INLINE_HINT_known_hot hint.
+
+* Mon Jul 17 2023 huangxiaoquan  12.3.1-4
+- Type:SPEC
+- DESC:Enable libquadmath on kunpeng
+
+* Fri Jul 14 2023 huangxiaoquan  12.3.1-3
+- Type:Sync
+- DESC:Enable libquadmath on kunpeng
+
+* Tue Jul 11 2023 huangxiaoquan  12.3.1-2
+- Type:SPEC
+- DESC:Set version to 12.3.1
+
+* Tue Jun 13 2023 huangxiaoquan  12.3.0-1
+- Type:Init
+- DESC:Init GCC 12.3.0 repository
diff --git a/sources b/sources
new file mode 100644
index 0000000..5ef5751
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+58a863b2a50e4d42eacc20fec419bc3b  gcc-12.3.0.tar.xz
-- 
cgit v1.2.3